diff options
Diffstat (limited to 'arch')
1943 files changed, 71407 insertions, 27962 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 975dd22a2dbd..de5200eb55d1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -17,6 +17,15 @@ config CPU_MITIGATIONS def_bool y endif +# +# Selected by architectures that need custom DMA operations for e.g. legacy +# IOMMUs not handled by dma-iommu. Drivers must never select this symbol. +# +config ARCH_HAS_DMA_OPS + depends on HAS_DMA + select DMA_OPS_HELPERS + bool + menu "General architecture-dependent options" config ARCH_HAS_SUBPAGE_FAULTS @@ -126,6 +135,7 @@ config KPROBES_ON_FTRACE config UPROBES def_bool n depends on ARCH_SUPPORTS_UPROBES + select TASKS_TRACE_RCU help Uprobes is the user-space counterpart to kprobes: they enable instrumentation applications (such as 'perf probe') @@ -826,6 +836,36 @@ config CFI_CLANG https://clang.llvm.org/docs/ControlFlowIntegrity.html +config CFI_ICALL_NORMALIZE_INTEGERS + bool "Normalize CFI tags for integers" + depends on CFI_CLANG + depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS_CLANG + help + This option normalizes the CFI tags for integer types so that all + integer types of the same size and signedness receive the same CFI + tag. + + The option is separate from CONFIG_RUST because it affects the ABI. + When working with build systems that care about the ABI, it is + convenient to be able to turn on this flag first, before Rust is + turned on. + + This option is necessary for using CFI with Rust. If unsure, say N. + +config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_CLANG + def_bool y + depends on $(cc-option,-fsanitize=kcfi -fsanitize-cfi-icall-experimental-normalize-integers) + # With GCOV/KASAN we need this fix: https://github.com/llvm/llvm-project/pull/104826 + depends on CLANG_VERSION >= 190103 || (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS) + +config HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC + def_bool y + depends on HAVE_CFI_ICALL_NORMALIZE_INTEGERS_CLANG + depends on RUSTC_VERSION >= 107900 + # With GCOV/KASAN we need this fix: https://github.com/rust-lang/rust/pull/129373 + depends on (RUSTC_LLVM_VERSION >= 190103 && RUSTC_VERSION >= 108200) || \ + (!GCOV_KERNEL && !KASAN_GENERIC && !KASAN_SW_TAGS) + config CFI_PERMISSIVE bool "Use CFI in permissive mode" depends on CFI_CLANG @@ -862,7 +902,7 @@ config HAVE_CONTEXT_TRACKING_USER_OFFSTACK Architecture neither relies on exception_enter()/exception_exit() nor on schedule_user(). Also preempt_schedule_notrace() and preempt_schedule_irq() can't be called in a preemptible section - while context tracking is CONTEXT_USER. This feature reflects a sane + while context tracking is CT_STATE_USER. This feature reflects a sane entry implementation where the following requirements are met on critical entry code, ie: before user_exit() or after user_enter(): @@ -1489,7 +1529,7 @@ config HAVE_SPARSE_SYSCALL_NR entries at 4000, 5000 and 6000 locations. This option turns on syscall related optimizations for a given architecture. -config ARCH_HAS_VDSO_DATA +config ARCH_HAS_VDSO_TIME_DATA bool config HAVE_STATIC_CALL diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 50ff06d5b799..109a4cddcd13 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -4,12 +4,12 @@ config ALPHA default y select ARCH_32BIT_USTAT_F_TINODE select ARCH_HAS_CURRENT_STACK_POINTER + select ARCH_HAS_DMA_OPS if PCI select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO select ARCH_NO_PREEMPT select ARCH_NO_SG_CHAIN select ARCH_USE_CMPXCHG_LOCKREF - select DMA_OPS if PCI select FORCE_PCI select PCI_DOMAINS if PCI select PCI_SYSCALL if PCI diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h index 91d4a4d9258c..ae1b96479d0c 100644 --- a/arch/alpha/include/asm/cmpxchg.h +++ b/arch/alpha/include/asm/cmpxchg.h @@ -3,17 +3,232 @@ #define _ALPHA_CMPXCHG_H /* - * Atomic exchange routines. + * Atomic exchange. + * Since it can be used to implement critical sections + * it must clobber "memory" (also for interrupts in UP). */ -#define ____xchg(type, args...) __arch_xchg ## type ## _local(args) -#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args) -#include <asm/xchg.h> +static inline unsigned long +____xchg_u8(volatile char *m, unsigned long val) +{ + unsigned long ret, tmp, addr64; + + __asm__ __volatile__( + " andnot %4,7,%3\n" + " insbl %1,%4,%1\n" + "1: ldq_l %2,0(%3)\n" + " extbl %2,%4,%0\n" + " mskbl %2,%4,%2\n" + " or %1,%2,%2\n" + " stq_c %2,0(%3)\n" + " beq %2,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) + : "r" ((long)m), "1" (val) : "memory"); + + return ret; +} + +static inline unsigned long +____xchg_u16(volatile short *m, unsigned long val) +{ + unsigned long ret, tmp, addr64; + + __asm__ __volatile__( + " andnot %4,7,%3\n" + " inswl %1,%4,%1\n" + "1: ldq_l %2,0(%3)\n" + " extwl %2,%4,%0\n" + " mskwl %2,%4,%2\n" + " or %1,%2,%2\n" + " stq_c %2,0(%3)\n" + " beq %2,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) + : "r" ((long)m), "1" (val) : "memory"); + + return ret; +} + +static inline unsigned long +____xchg_u32(volatile int *m, unsigned long val) +{ + unsigned long dummy; + + __asm__ __volatile__( + "1: ldl_l %0,%4\n" + " bis $31,%3,%1\n" + " stl_c %1,%2\n" + " beq %1,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (val), "=&r" (dummy), "=m" (*m) + : "rI" (val), "m" (*m) : "memory"); + + return val; +} + +static inline unsigned long +____xchg_u64(volatile long *m, unsigned long val) +{ + unsigned long dummy; + + __asm__ __volatile__( + "1: ldq_l %0,%4\n" + " bis $31,%3,%1\n" + " stq_c %1,%2\n" + " beq %1,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (val), "=&r" (dummy), "=m" (*m) + : "rI" (val), "m" (*m) : "memory"); + + return val; +} + +/* This function doesn't exist, so you'll get a linker error + if something tries to do an invalid xchg(). */ +extern void __xchg_called_with_bad_pointer(void); + +static __always_inline unsigned long +____xchg(volatile void *ptr, unsigned long x, int size) +{ + return + size == 1 ? ____xchg_u8(ptr, x) : + size == 2 ? ____xchg_u16(ptr, x) : + size == 4 ? ____xchg_u32(ptr, x) : + size == 8 ? ____xchg_u64(ptr, x) : + (__xchg_called_with_bad_pointer(), x); +} + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ + +static inline unsigned long +____cmpxchg_u8(volatile char *m, unsigned char old, unsigned char new) +{ + unsigned long prev, tmp, cmp, addr64; + + __asm__ __volatile__( + " andnot %5,7,%4\n" + " insbl %1,%5,%1\n" + "1: ldq_l %2,0(%4)\n" + " extbl %2,%5,%0\n" + " cmpeq %0,%6,%3\n" + " beq %3,2f\n" + " mskbl %2,%5,%2\n" + " or %1,%2,%2\n" + " stq_c %2,0(%4)\n" + " beq %2,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) + : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); + + return prev; +} + +static inline unsigned long +____cmpxchg_u16(volatile short *m, unsigned short old, unsigned short new) +{ + unsigned long prev, tmp, cmp, addr64; + + __asm__ __volatile__( + " andnot %5,7,%4\n" + " inswl %1,%5,%1\n" + "1: ldq_l %2,0(%4)\n" + " extwl %2,%5,%0\n" + " cmpeq %0,%6,%3\n" + " beq %3,2f\n" + " mskwl %2,%5,%2\n" + " or %1,%2,%2\n" + " stq_c %2,0(%4)\n" + " beq %2,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) + : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); + + return prev; +} + +static inline unsigned long +____cmpxchg_u32(volatile int *m, int old, int new) +{ + unsigned long prev, cmp; + + __asm__ __volatile__( + "1: ldl_l %0,%5\n" + " cmpeq %0,%3,%1\n" + " beq %1,2f\n" + " mov %4,%1\n" + " stl_c %1,%2\n" + " beq %1,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r"(prev), "=&r"(cmp), "=m"(*m) + : "r"((long) old), "r"(new), "m"(*m) : "memory"); + + return prev; +} + +static inline unsigned long +____cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) +{ + unsigned long prev, cmp; + + __asm__ __volatile__( + "1: ldq_l %0,%5\n" + " cmpeq %0,%3,%1\n" + " beq %1,2f\n" + " mov %4,%1\n" + " stq_c %1,%2\n" + " beq %1,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r"(prev), "=&r"(cmp), "=m"(*m) + : "r"((long) old), "r"(new), "m"(*m) : "memory"); + + return prev; +} + +/* This function doesn't exist, so you'll get a linker error + if something tries to do an invalid cmpxchg(). */ +extern void __cmpxchg_called_with_bad_pointer(void); + +static __always_inline unsigned long +____cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, + int size) +{ + return + size == 1 ? ____cmpxchg_u8(ptr, old, new) : + size == 2 ? ____cmpxchg_u16(ptr, old, new) : + size == 4 ? ____cmpxchg_u32(ptr, old, new) : + size == 8 ? ____cmpxchg_u64(ptr, old, new) : + (__cmpxchg_called_with_bad_pointer(), old); +} #define xchg_local(ptr, x) \ ({ \ __typeof__(*(ptr)) _x_ = (x); \ - (__typeof__(*(ptr))) __arch_xchg_local((ptr), (unsigned long)_x_,\ + (__typeof__(*(ptr))) ____xchg((ptr), (unsigned long)_x_, \ sizeof(*(ptr))); \ }) @@ -21,7 +236,7 @@ ({ \ __typeof__(*(ptr)) _o_ = (o); \ __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ + (__typeof__(*(ptr))) ____cmpxchg((ptr), (unsigned long)_o_, \ (unsigned long)_n_, \ sizeof(*(ptr))); \ }) @@ -32,12 +247,6 @@ cmpxchg_local((ptr), (o), (n)); \ }) -#undef ____xchg -#undef ____cmpxchg -#define ____xchg(type, args...) __arch_xchg ##type(args) -#define ____cmpxchg(type, args...) __cmpxchg ##type(args) -#include <asm/xchg.h> - /* * The leading and the trailing memory barriers guarantee that these * operations are fully ordered. @@ -48,7 +257,7 @@ __typeof__(*(ptr)) _x_ = (x); \ smp_mb(); \ __ret = (__typeof__(*(ptr))) \ - __arch_xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ + ____xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ smp_mb(); \ __ret; \ }) @@ -59,7 +268,7 @@ __typeof__(*(ptr)) _o_ = (o); \ __typeof__(*(ptr)) _n_ = (n); \ smp_mb(); \ - __ret = (__typeof__(*(ptr))) __cmpxchg((ptr), \ + __ret = (__typeof__(*(ptr))) ____cmpxchg((ptr), \ (unsigned long)_o_, (unsigned long)_n_, sizeof(*(ptr)));\ smp_mb(); \ __ret; \ @@ -71,6 +280,4 @@ arch_cmpxchg((ptr), (o), (n)); \ }) -#undef ____cmpxchg - #endif /* _ALPHA_CMPXCHG_H */ diff --git a/arch/alpha/include/asm/page.h b/arch/alpha/include/asm/page.h index 70419e6be1a3..261af54fd601 100644 --- a/arch/alpha/include/asm/page.h +++ b/arch/alpha/include/asm/page.h @@ -4,11 +4,7 @@ #include <linux/const.h> #include <asm/pal.h> - -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #ifndef __ASSEMBLY__ diff --git a/arch/alpha/include/asm/xchg.h b/arch/alpha/include/asm/xchg.h deleted file mode 100644 index 7adb80c6746a..000000000000 --- a/arch/alpha/include/asm/xchg.h +++ /dev/null @@ -1,246 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ALPHA_CMPXCHG_H -#error Do not include xchg.h directly! -#else -/* - * xchg/xchg_local and cmpxchg/cmpxchg_local share the same code - * except that local version do not have the expensive memory barrier. - * So this file is included twice from asm/cmpxchg.h. - */ - -/* - * Atomic exchange. - * Since it can be used to implement critical sections - * it must clobber "memory" (also for interrupts in UP). - */ - -static inline unsigned long -____xchg(_u8, volatile char *m, unsigned long val) -{ - unsigned long ret, tmp, addr64; - - __asm__ __volatile__( - " andnot %4,7,%3\n" - " insbl %1,%4,%1\n" - "1: ldq_l %2,0(%3)\n" - " extbl %2,%4,%0\n" - " mskbl %2,%4,%2\n" - " or %1,%2,%2\n" - " stq_c %2,0(%3)\n" - " beq %2,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) - : "r" ((long)m), "1" (val) : "memory"); - - return ret; -} - -static inline unsigned long -____xchg(_u16, volatile short *m, unsigned long val) -{ - unsigned long ret, tmp, addr64; - - __asm__ __volatile__( - " andnot %4,7,%3\n" - " inswl %1,%4,%1\n" - "1: ldq_l %2,0(%3)\n" - " extwl %2,%4,%0\n" - " mskwl %2,%4,%2\n" - " or %1,%2,%2\n" - " stq_c %2,0(%3)\n" - " beq %2,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) - : "r" ((long)m), "1" (val) : "memory"); - - return ret; -} - -static inline unsigned long -____xchg(_u32, volatile int *m, unsigned long val) -{ - unsigned long dummy; - - __asm__ __volatile__( - "1: ldl_l %0,%4\n" - " bis $31,%3,%1\n" - " stl_c %1,%2\n" - " beq %1,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (val), "=&r" (dummy), "=m" (*m) - : "rI" (val), "m" (*m) : "memory"); - - return val; -} - -static inline unsigned long -____xchg(_u64, volatile long *m, unsigned long val) -{ - unsigned long dummy; - - __asm__ __volatile__( - "1: ldq_l %0,%4\n" - " bis $31,%3,%1\n" - " stq_c %1,%2\n" - " beq %1,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=&r" (val), "=&r" (dummy), "=m" (*m) - : "rI" (val), "m" (*m) : "memory"); - - return val; -} - -/* This function doesn't exist, so you'll get a linker error - if something tries to do an invalid xchg(). */ -extern void __xchg_called_with_bad_pointer(void); - -static __always_inline unsigned long -____xchg(, volatile void *ptr, unsigned long x, int size) -{ - switch (size) { - case 1: - return ____xchg(_u8, ptr, x); - case 2: - return ____xchg(_u16, ptr, x); - case 4: - return ____xchg(_u32, ptr, x); - case 8: - return ____xchg(_u64, ptr, x); - } - __xchg_called_with_bad_pointer(); - return x; -} - -/* - * Atomic compare and exchange. Compare OLD with MEM, if identical, - * store NEW in MEM. Return the initial value in MEM. Success is - * indicated by comparing RETURN with OLD. - */ - -static inline unsigned long -____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new) -{ - unsigned long prev, tmp, cmp, addr64; - - __asm__ __volatile__( - " andnot %5,7,%4\n" - " insbl %1,%5,%1\n" - "1: ldq_l %2,0(%4)\n" - " extbl %2,%5,%0\n" - " cmpeq %0,%6,%3\n" - " beq %3,2f\n" - " mskbl %2,%5,%2\n" - " or %1,%2,%2\n" - " stq_c %2,0(%4)\n" - " beq %2,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) - : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); - - return prev; -} - -static inline unsigned long -____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new) -{ - unsigned long prev, tmp, cmp, addr64; - - __asm__ __volatile__( - " andnot %5,7,%4\n" - " inswl %1,%5,%1\n" - "1: ldq_l %2,0(%4)\n" - " extwl %2,%5,%0\n" - " cmpeq %0,%6,%3\n" - " beq %3,2f\n" - " mskwl %2,%5,%2\n" - " or %1,%2,%2\n" - " stq_c %2,0(%4)\n" - " beq %2,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) - : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); - - return prev; -} - -static inline unsigned long -____cmpxchg(_u32, volatile int *m, int old, int new) -{ - unsigned long prev, cmp; - - __asm__ __volatile__( - "1: ldl_l %0,%5\n" - " cmpeq %0,%3,%1\n" - " beq %1,2f\n" - " mov %4,%1\n" - " stl_c %1,%2\n" - " beq %1,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r"(prev), "=&r"(cmp), "=m"(*m) - : "r"((long) old), "r"(new), "m"(*m) : "memory"); - - return prev; -} - -static inline unsigned long -____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new) -{ - unsigned long prev, cmp; - - __asm__ __volatile__( - "1: ldq_l %0,%5\n" - " cmpeq %0,%3,%1\n" - " beq %1,2f\n" - " mov %4,%1\n" - " stq_c %1,%2\n" - " beq %1,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r"(prev), "=&r"(cmp), "=m"(*m) - : "r"((long) old), "r"(new), "m"(*m) : "memory"); - - return prev; -} - -/* This function doesn't exist, so you'll get a linker error - if something tries to do an invalid cmpxchg(). */ -extern void __cmpxchg_called_with_bad_pointer(void); - -static __always_inline unsigned long -____cmpxchg(, volatile void *ptr, unsigned long old, unsigned long new, - int size) -{ - switch (size) { - case 1: - return ____cmpxchg(_u8, ptr, old, new); - case 2: - return ____cmpxchg(_u16, ptr, old, new); - case 4: - return ____cmpxchg(_u32, ptr, old, new); - case 8: - return ____cmpxchg(_u64, ptr, old, new); - } - __cmpxchg_called_with_bad_pointer(); - return old; -} - -#endif diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index e94f621903fe..251b73c5481e 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -140,6 +140,12 @@ #define SO_PASSPIDFD 76 #define SO_PEERPIDFD 77 +#define SO_DEVMEM_LINEAR 78 +#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR +#define SO_DEVMEM_DMABUF 79 +#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF +#define SO_DEVMEM_DONTNEED 80 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index e5f881bc8288..86185021f75a 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -152,7 +152,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd, long __user *, basep) { int error; - struct fd arg = fdget_pos(fd); + CLASS(fd_pos, arg)(fd); struct osf_dirent_callback buf = { .ctx.actor = osf_filldir, .dirent = dirent, @@ -160,16 +160,15 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd, .count = count }; - if (!arg.file) + if (fd_empty(arg)) return -EBADF; - error = iterate_dir(arg.file, &buf.ctx); + error = iterate_dir(fd_file(arg), &buf.ctx); if (error >= 0) error = buf.error; if (count != buf.count) error = count - buf.count; - fdput_pos(arg); return error; } @@ -1229,7 +1228,7 @@ arch_get_unmapped_area_1(unsigned long addr, unsigned long len, unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { unsigned long limit; diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 74720667fe09..c59d53d6d3f3 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -502,3 +502,7 @@ 570 common lsm_set_self_attr sys_lsm_set_self_attr 571 common lsm_list_modules sys_lsm_list_modules 572 common mseal sys_mseal +573 common setxattrat sys_setxattrat +574 common getxattrat sys_getxattrat +575 common listxattrat sys_listxattrat +576 common removexattrat sys_removexattrat diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 6afae65e9a8b..a9a38c80c4a7 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -22,7 +22,7 @@ #include <asm/gentrap.h> #include <linux/uaccess.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/sysinfo.h> #include <asm/hwrpb.h> #include <asm/mmu_context.h> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index fd0b0a0d4686..5b2488142041 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -13,6 +13,7 @@ config ARC select ARCH_HAS_SETUP_DMA_OPS select ARCH_HAS_SYNC_DMA_FOR_CPU select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select ARCH_NEED_CMPXCHG_1_EMU select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC select ARCH_32BIT_OFF_T select BUILDTIME_TABLE_SORT @@ -553,7 +554,7 @@ config ARC_BUILTIN_DTB_NAME string "Built in DTB" help Set the name of the DTB to embed in the vmlinux binary - Leaving it blank selects the minimal "skeleton" dtb + Leaving it blank selects the "nsim_700" dtb. endmenu # "ARC Architecture Configuration" diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig index 89720d6d7e0d..319bbe270322 100644 --- a/arch/arc/configs/axs101_defconfig +++ b/arch/arc/configs/axs101_defconfig @@ -66,6 +66,7 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_DRM=m diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig index 73ec01ed0492..8c1f1a111a17 100644 --- a/arch/arc/configs/axs103_defconfig +++ b/arch/arc/configs/axs103_defconfig @@ -66,6 +66,7 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_FB=y diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index 4da0f626fa9d..75cab9f25b5b 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -66,6 +66,7 @@ CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y # CONFIG_HWMON is not set CONFIG_DRM=m diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig index 1a68e4beebca..5aba3d850fa2 100644 --- a/arch/arc/configs/tb10x_defconfig +++ b/arch/arc/configs/tb10x_defconfig @@ -60,6 +60,7 @@ CONFIG_SERIAL_8250_DW=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_GPIO_SYSFS=y # CONFIG_HWMON is not set diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h index e138fde067de..58045c898340 100644 --- a/arch/arc/include/asm/cmpxchg.h +++ b/arch/arc/include/asm/cmpxchg.h @@ -8,6 +8,7 @@ #include <linux/build_bug.h> #include <linux/types.h> +#include <linux/cmpxchg-emu.h> #include <asm/barrier.h> #include <asm/smp.h> @@ -46,6 +47,9 @@ __typeof__(*(ptr)) _prev_; \ \ switch(sizeof((_p_))) { \ + case 1: \ + _prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \ + break; \ case 4: \ _prev_ = __cmpxchg(_p_, _o_, _n_); \ break; \ @@ -65,8 +69,6 @@ __typeof__(*(ptr)) _prev_; \ unsigned long __flags; \ \ - BUILD_BUG_ON(sizeof(_p_) != 4); \ - \ /* \ * spin lock/unlock provide the needed smp_mb() before/after \ */ \ diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 4fdb7350636c..f57cb5a6b624 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -9,7 +9,7 @@ #include <linux/types.h> #include <asm/byteorder.h> #include <asm/page.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #ifdef CONFIG_ISA_ARCV2 #include <asm/barrier.h> diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index 9febf5bc3de6..4ae2db59d494 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h @@ -14,6 +14,7 @@ typedef struct { unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */ } mm_context_t; +struct pt_regs; extern void do_tlb_overlap_fault(unsigned long, unsigned long, struct pt_regs *); #endif diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h deleted file mode 100644 index cf5a02382e0e..000000000000 --- a/arch/arc/include/asm/unaligned.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) - */ - -#ifndef _ASM_ARC_UNALIGNED_H -#define _ASM_ARC_UNALIGNED_H - -/* ARC700 can't handle unaligned Data accesses. */ - -#include <asm-generic/unaligned.h> -#include <asm/ptrace.h> - -#ifdef CONFIG_ARC_EMUL_UNALIGNED -int misaligned_fixup(unsigned long address, struct pt_regs *regs, - struct callee_regs *cregs); -#else -static inline int -misaligned_fixup(unsigned long address, struct pt_regs *regs, - struct callee_regs *cregs) -{ - /* Not fixed */ - return 1; -} -#endif - -#endif /* _ASM_ARC_UNALIGNED_H */ diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h index 7fd9e741b527..4606a326af5c 100644 --- a/arch/arc/include/uapi/asm/page.h +++ b/arch/arc/include/uapi/asm/page.h @@ -14,7 +14,7 @@ /* PAGE_SHIFT determines the page size */ #ifdef __KERNEL__ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT +#include <vdso/page.h> #else /* * Default 8k @@ -24,11 +24,10 @@ * not available */ #define PAGE_SHIFT 13 +#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */ +#define PAGE_MASK (~(PAGE_SIZE-1)) #endif -#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */ #define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */ -#define PAGE_MASK (~(PAGE_SIZE-1)) - #endif /* _UAPI__ASM_ARC_PAGE_H */ diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 4c9e61457b2f..cc6ac7d128aa 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -62,7 +62,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) const struct machine_desc *mdesc; unsigned long dt_root; - if (!early_init_dt_scan(dt)) + if (!early_init_dt_scan(dt, __pa(dt))) return NULL; mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach); diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index a19751e824fb..8d2ea2cbd98b 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -18,8 +18,9 @@ #include <linux/kgdb.h> #include <asm/entry.h> #include <asm/setup.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/kprobes.h> +#include "unaligned.h" void die(const char *str, struct pt_regs *regs, unsigned long address) { diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c index 99a9b92ed98d..d2f5ceaaed1b 100644 --- a/arch/arc/kernel/unaligned.c +++ b/arch/arc/kernel/unaligned.c @@ -12,6 +12,7 @@ #include <linux/ptrace.h> #include <linux/uaccess.h> #include <asm/disasm.h> +#include "unaligned.h" #ifdef CONFIG_CPU_BIG_ENDIAN #define BE 1 diff --git a/arch/arc/kernel/unaligned.h b/arch/arc/kernel/unaligned.h new file mode 100644 index 000000000000..5244453bb85f --- /dev/null +++ b/arch/arc/kernel/unaligned.h @@ -0,0 +1,16 @@ +struct pt_regs; +struct callee_regs; + +#ifdef CONFIG_ARC_EMUL_UNALIGNED +int misaligned_fixup(unsigned long address, struct pt_regs *regs, + struct callee_regs *cregs); +#else +static inline int +misaligned_fixup(unsigned long address, struct pt_regs *regs, + struct callee_regs *cregs) +{ + /* Not fixed */ + return 1; +} +#endif + diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index 9270d0a713c3..d8969dab12d4 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -19,7 +19,7 @@ #include <linux/uaccess.h> #include <linux/ptrace.h> #include <asm/sections.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/unwind.h> extern char __start_unwind[], __end_unwind[]; diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c index 69a915297155..2185afe8d59f 100644 --- a/arch/arc/mm/mmap.c +++ b/arch/arc/mm/mmap.c @@ -23,7 +23,8 @@ */ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, + unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 54b2bb817a7f..202397be76d8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -10,6 +10,7 @@ config ARM select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DEBUG_VIRTUAL if MMU select ARCH_HAS_DMA_ALLOC if MMU + select ARCH_HAS_DMA_OPS select ARCH_HAS_DMA_WRITE_COMBINE if !ARM_DMA_MEM_BUFFERABLE select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FORTIFY_SOURCE @@ -54,7 +55,6 @@ config ARM select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS select DMA_DECLARE_COHERENT select DMA_GLOBAL_POOL if !MMU - select DMA_OPS select DMA_NONCOHERENT_MMAP if MMU select EDAC_SUPPORT select EDAC_ATOMIC_SCRUB @@ -64,6 +64,7 @@ config ARM select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_IRQ_IPI if SMP select GENERIC_CPU_AUTOPROBE + select GENERIC_CPU_DEVICES select GENERIC_EARLY_IOREMAP select GENERIC_IDLE_POLL_SETUP select GENERIC_IRQ_MULTI_HANDLER @@ -117,7 +118,7 @@ config ARM select HAVE_KERNEL_XZ select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M select HAVE_KRETPROBES if HAVE_KPROBES - select HAVE_LD_DEAD_CODE_DATA_ELIMINATION + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD) select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL @@ -1597,6 +1598,9 @@ config ATAGS_PROC config ARCH_SUPPORTS_CRASH_DUMP def_bool y +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config AUTO_ZRELADDR bool "Auto calculation of the decompressed kernel image address" if !ARCH_MULTIPLATFORM default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 71afdd98ddf2..aafebf145738 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -183,7 +183,6 @@ machine-$(CONFIG_ARCH_CLPS711X) += clps711x machine-$(CONFIG_ARCH_DAVINCI) += davinci machine-$(CONFIG_ARCH_DIGICOLOR) += digicolor machine-$(CONFIG_ARCH_DOVE) += dove -machine-$(CONFIG_ARCH_EP93XX) += ep93xx machine-$(CONFIG_ARCH_EXYNOS) += exynos machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge machine-$(CONFIG_ARCH_GEMINI) += gemini diff --git a/arch/arm/boot/dts/amlogic/meson8b-ec100.dts b/arch/arm/boot/dts/amlogic/meson8b-ec100.dts index 3da47349eaaf..49890eb12781 100644 --- a/arch/arm/boot/dts/amlogic/meson8b-ec100.dts +++ b/arch/arm/boot/dts/amlogic/meson8b-ec100.dts @@ -34,8 +34,6 @@ gpio-keys { compatible = "gpio-keys-polled"; - #address-cells = <1>; - #size-cells = <0>; poll-interval = <100>; pal-switch { diff --git a/arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi b/arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi index 26783d053ac7..40f7515aa068 100644 --- a/arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi +++ b/arch/arm/boot/dts/arm/arm-realview-eb-mp.dtsi @@ -103,7 +103,7 @@ }; /* PMU with one IRQ line per core */ - pmu: pmu@0 { + pmu: pmu { compatible = "arm,arm11mpcore-pmu"; interrupt-parent = <&intc>; interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts index ce35748f3d25..db1b6793cd2c 100644 --- a/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts +++ b/arch/arm/boot/dts/arm/arm-realview-pb11mp.dts @@ -92,7 +92,7 @@ <0x1f000100 0x100>; }; - L2: cache-controller { + L2: cache-controller@1f002000 { compatible = "arm,l220-cache"; reg = <0x1f002000 0x1000>; interrupt-parent = <&intc_tc11mp>; diff --git a/arch/arm/boot/dts/arm/arm-realview-pba8.dts b/arch/arm/boot/dts/arm/arm-realview-pba8.dts index d3238c252b59..d2e0082245f9 100644 --- a/arch/arm/boot/dts/arm/arm-realview-pba8.dts +++ b/arch/arm/boot/dts/arm/arm-realview-pba8.dts @@ -40,7 +40,7 @@ }; }; - pmu: pmu@0 { + pmu: pmu { compatible = "arm,cortex-a8-pmu"; interrupt-parent = <&intc>; interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts b/arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts index 85d3968fbb91..507ad7ac4974 100644 --- a/arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts +++ b/arch/arm/boot/dts/arm/arm-realview-pbx-a9.dts @@ -97,7 +97,7 @@ interrupts = <1 14 0xf04>; }; - pmu: pmu@0 { + pmu: pmu { compatible = "arm,cortex-a9-pmu"; interrupt-parent = <&intc>; interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile index e51c6d203725..c4f064e4b073 100644 --- a/arch/arm/boot/dts/aspeed/Makefile +++ b/arch/arm/boot/dts/aspeed/Makefile @@ -17,6 +17,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-bytedance-g220a.dtb \ aspeed-bmc-delta-ahe50dc.dtb \ aspeed-bmc-facebook-bletchley.dtb \ + aspeed-bmc-facebook-catalina.dtb \ aspeed-bmc-facebook-cmm.dtb \ aspeed-bmc-facebook-elbert.dtb \ aspeed-bmc-facebook-fuji.dtb \ @@ -32,8 +33,10 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-facebook-yamp.dtb \ aspeed-bmc-facebook-yosemitev2.dtb \ aspeed-bmc-facebook-yosemite4.dtb \ + aspeed-bmc-ibm-blueridge.dtb \ aspeed-bmc-ibm-bonnell.dtb \ aspeed-bmc-ibm-everest.dtb \ + aspeed-bmc-ibm-fuji.dtb \ aspeed-bmc-ibm-rainier.dtb \ aspeed-bmc-ibm-rainier-1s4u.dtb \ aspeed-bmc-ibm-rainier-4u.dtb \ diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts index 8ab5f301f926..31c5d319aa0a 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtjade.dts @@ -49,6 +49,11 @@ */ i2c80 = &nvme_m2_0; i2c81 = &nvme_m2_1; + + /* + * i2c bus 82 assigned to OCP slot + */ + i2c82 = &ocpslot; }; chosen { @@ -420,6 +425,17 @@ reg = <0x70>; i2c-mux-idle-disconnect; + ocpslot: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + ocpslot_temp: temperature-sensor@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + }; + nvmeslot_0_7: i2c@3 { #address-cells = <1>; #size-cells = <0>; @@ -672,10 +688,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &pwm_tacho { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts index 3c8925034a8c..0295f5adcfbc 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ampere-mtmitchell.dts @@ -16,6 +16,32 @@ serial8 = &uart9; /* + * I2C temperature alias port + */ + i2c20 = &i2c4_bus70_chn0; + i2c21 = &i2c4_bus70_chn1; + i2c22 = &i2c4_bus70_chn2; + i2c23 = &i2c4_bus70_chn3; + + /* + * i2c bus 30-31 assigned to OCP slot 0-1 + */ + i2c30 = &ocpslot_0; + i2c31 = &ocpslot_1; + + /* + * i2c bus 32-33 assigned to Riser slot 0-1 + */ + i2c32 = &i2c_riser0; + i2c33 = &i2c_riser1; + + /* + * i2c bus 38-39 assigned to FRU on Riser slot 0-1 + */ + i2c38 = &i2c_riser0_chn_0; + i2c39 = &i2c_riser1_chn_0; + + /* * I2C NVMe alias port */ i2c100 = &backplane_0; @@ -87,6 +113,37 @@ }; }; + leds { + compatible = "gpio-leds"; + /* + * Use gpio-leds to configure GPIOW5 (bmc-ready) pin to be reseted when + * watchdog timeout. + */ + led-bmc-ready { + gpios = <&gpio0 ASPEED_GPIO(W, 5) (GPIO_ACTIVE_HIGH | GPIO_TRANSITORY)>; + }; + + led-sw-heartbeat { + gpios = <&gpio0 ASPEED_GPIO(N, 3) GPIO_ACTIVE_HIGH>; + }; + + led-identify { + gpios = <&gpio0 ASPEED_GPIO(S, 3) GPIO_ACTIVE_HIGH>; + }; + + led-fault { + gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>; + }; + + led-fan-fault { + gpios = <&gpio_expander1 0 GPIO_ACTIVE_HIGH>; + }; + + led-psu-fault { + gpios = <&gpio_expander1 1 GPIO_ACTIVE_HIGH>; + }; + }; + voltage_mon_reg: voltage-mon-regulator { compatible = "regulator-fixed"; regulator-name = "ltc2497_reg"; @@ -515,6 +572,80 @@ #size-cells = <0>; reg = <0x70>; i2c-mux-idle-disconnect; + + ocpslot_0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + ocpslot_0_temp: temperature-sensor@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + }; + + ocpslot_1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; + + ocpslot_1_temp: temperature-sensor@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + }; + + i2c_riser0: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + + i2c-mux@72 { + compatible = "nxp,pca9546"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x72>; + i2c-mux-idle-disconnect; + + i2c_riser0_chn_0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; + }; + }; + }; + + i2c_riser1: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + i2c-mux@72 { + compatible = "nxp,pca9546"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x72>; + i2c-mux-idle-disconnect; + + i2c_riser1_chn_0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; + }; + }; + }; }; }; @@ -790,6 +921,10 @@ }; }; +&i2c10 { + status = "okay"; +}; + &i2c11 { status = "okay"; ssif-bmc@10 { @@ -812,6 +947,25 @@ }; }; +&i2c15 { + status = "okay"; + gpio_expander1: gpio-expander@22 { + compatible = "nxp,pca9535"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = + "fan-fault","psu-fault", + "","", + "","", + "","", + "","", + "","", + "","", + "",""; + }; +}; + &adc0 { status = "okay"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts index 7c6af7f226e7..29c68c37e7f5 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-arm-stardragon4800-rep2.dts @@ -200,10 +200,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &gpio { pin_gpio_c7 { gpio-hog; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-spc621d8hm3.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-spc621d8hm3.dts index 555485871e7a..c4097e4f2ca4 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-spc621d8hm3.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-spc621d8hm3.dts @@ -110,11 +110,15 @@ compatible = "st,24c128", "atmel,24c128"; reg = <0x50>; pagesize = <16>; - #address-cells = <1>; - #size-cells = <1>; - eth0_macaddress: macaddress@3f80 { - reg = <0x3f80 6>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eth0_macaddress: macaddress@3f80 { + reg = <0x3f80 6>; + }; }; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-x570d4u.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-x570d4u.dts index 8dee4faa9e07..0943e0bf1305 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-x570d4u.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-asrock-x570d4u.dts @@ -254,10 +254,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &vhub { status = "okay"; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts new file mode 100644 index 000000000000..82835e96317d --- /dev/null +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-catalina.dts @@ -0,0 +1,1110 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2021 Facebook Inc. +/dts-v1/; + +#include "aspeed-g6.dtsi" +#include <dt-bindings/gpio/aspeed-gpio.h> +#include <dt-bindings/usb/pd.h> +#include <dt-bindings/leds/leds-pca955x.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/i2c/i2c.h> + +/ { + model = "Facebook Catalina BMC"; + compatible = "facebook,catalina-bmc", "aspeed,ast2600"; + + aliases { + serial0 = &uart1; + serial2 = &uart3; + serial3 = &uart4; + serial4 = &uart5; + i2c16 = &i2c1mux0ch0; + i2c17 = &i2c1mux0ch1; + i2c18 = &i2c1mux0ch2; + i2c19 = &i2c1mux0ch3; + i2c20 = &i2c1mux0ch4; + i2c21 = &i2c1mux0ch5; + i2c22 = &i2c1mux0ch6; + i2c23 = &i2c1mux0ch7; + i2c24 = &i2c0mux0ch0; + i2c25 = &i2c0mux0ch1; + i2c26 = &i2c0mux0ch2; + i2c27 = &i2c0mux0ch3; + i2c28 = &i2c0mux1ch0; + i2c29 = &i2c0mux1ch1; + i2c30 = &i2c0mux1ch2; + i2c31 = &i2c0mux1ch3; + i2c32 = &i2c0mux2ch0; + i2c33 = &i2c0mux2ch1; + i2c34 = &i2c0mux2ch2; + i2c35 = &i2c0mux2ch3; + i2c36 = &i2c0mux3ch0; + i2c37 = &i2c0mux3ch1; + i2c38 = &i2c0mux3ch2; + i2c39 = &i2c0mux3ch3; + i2c40 = &i2c0mux4ch0; + i2c41 = &i2c0mux4ch1; + i2c42 = &i2c0mux4ch2; + i2c43 = &i2c0mux4ch3; + i2c44 = &i2c0mux5ch0; + i2c45 = &i2c0mux5ch1; + i2c46 = &i2c0mux5ch2; + i2c47 = &i2c0mux5ch3; + i2c48 = &i2c30mux0ch0; + i2c49 = &i2c30mux0ch1; + i2c50 = &i2c30mux0ch2; + i2c51 = &i2c30mux0ch3; + i2c52 = &i2c30mux0ch4; + i2c53 = &i2c30mux0ch5; + i2c54 = &i2c30mux0ch6; + i2c55 = &i2c30mux0ch7; + }; + + chosen { + stdout-path = "serial4:57600n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>, + <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>, + <&adc1 2>; + }; + + spi1_gpio: spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>; + num-chipselects = <1>; + + tpm@0 { + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + spi-max-frequency = <33000000>; + reg = <0>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + label = "bmc_heartbeat_amber"; + gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + + led-1 { + label = "fp_id_amber"; + default-state = "off"; + gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>; + }; + + led-2 { + label = "bmc_ready_noled"; + gpios = <&gpio0 ASPEED_GPIO(B, 3) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>; + }; + + led-3 { + label = "bmc_ready_cpld_noled"; + gpios = <&gpio0 ASPEED_GPIO(P, 5) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>; + }; + }; + + p1v8_bmc_aux: regulator-p1v8-bmc-aux { + compatible = "regulator-fixed"; + regulator-name = "p1v8_bmc_aux"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + p2v5_bmc_aux: regulator-p2v5-bmc-aux { + compatible = "regulator-fixed"; + regulator-name = "p2v5_bmc_aux"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; +}; + +&uart1 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&uart5 { + status = "okay"; +}; + +&mac3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ncsi4_default>; + use-ncsi; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "bmc"; + spi-max-frequency = <50000000>; +#include "openbmc-flash-layout-128.dtsi" + }; + flash@1 { + status = "okay"; + m25p,fast-read; + label = "alt-bmc"; + spi-max-frequency = <50000000>; + }; +}; + +&i2c0 { + status = "okay"; + + i2c-mux@71 { + compatible = "nxp,pca9546"; + reg = <0x71>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux0ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux0ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + i2c0mux0ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c0mux0ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; + + i2c-mux@72 { + compatible = "nxp,pca9546"; + reg = <0x72>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux1ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux1ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // IO Mezz 0 IOEXP + io_expander7: gpio@20 { + compatible = "nxp,pca9535"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; + + // IO Mezz 0 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + }; + i2c0mux1ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + i2c-mux@70 { + compatible = "nxp,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c30mux0ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c30mux0ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + i2c30mux0ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c30mux0ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + i2c30mux0ch4: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + }; + i2c30mux0ch5: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + }; + i2c30mux0ch6: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + // HDD FRU EEPROM + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + }; + i2c30mux0ch7: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + + power-sensor@40 { + compatible = "ti,ina230"; + reg = <0x40>; + shunt-resistor = <2000>; + }; + power-sensor@41 { + compatible = "ti,ina230"; + reg = <0x41>; + shunt-resistor = <2000>; + }; + power-sensor@44 { + compatible = "ti,ina230"; + reg = <0x44>; + shunt-resistor = <2000>; + }; + power-sensor@45 { + compatible = "ti,ina230"; + reg = <0x45>; + shunt-resistor = <2000>; + }; + }; + }; + }; + i2c0mux1ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; + + i2c-mux@73 { + compatible = "nxp,pca9546"; + reg = <0x73>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux2ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux2ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + i2c0mux2ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c0mux2ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; + + i2c-mux@75 { + compatible = "nxp,pca9546"; + reg = <0x75>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux3ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux3ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + i2c0mux3ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c0mux3ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; + + i2c-mux@76 { + compatible = "nxp,pca9546"; + reg = <0x76>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux4ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux4ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // IO Mezz 1 IOEXP + io_expander8: gpio@21 { + compatible = "nxp,pca9535"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + }; + + // IO Mezz 1 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + }; + i2c0mux4ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c0mux4ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; + + i2c-mux@77 { + compatible = "nxp,pca9546"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c0mux5ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + i2c0mux5ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + i2c0mux5ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + }; + i2c0mux5ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + }; + }; +}; + +&i2c1 { + status = "okay"; + i2c-mux@70 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + i2c-mux-idle-disconnect; + + i2c1mux0ch0: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <500>; + }; + power-sensor@42 { + compatible = "ti,ina238"; + reg = <0x42>; + shunt-resistor = <500>; + }; + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <500>; + }; + }; + i2c1mux0ch1: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + }; + power-sensor@43 { + compatible = "ti,ina238"; + reg = <0x43>; + }; + }; + i2c1mux0ch2: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + }; + i2c1mux0ch3: i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + }; + i2c1mux0ch4: i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4>; + + power-monitor@42 { + compatible = "lltc,ltc4287"; + reg = <0x42>; + shunt-resistor-micro-ohms = <200>; + }; + power-monitor@43 { + compatible = "lltc,ltc4287"; + reg = <0x43>; + shunt-resistor-micro-ohms = <200>; + }; + }; + i2c1mux0ch5: i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x5>; + + // PDB FRU EEPROM + eeprom@54 { + compatible = "atmel,24c64"; + reg = <0x54>; + }; + + // PDB TEMP SENSOR + temperature-sensor@4f { + compatible = "ti,tmp75"; + reg = <0x4f>; + }; + }; + i2c1mux0ch6: i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x6>; + + // PDB IOEXP + io_expander5: gpio@27 { + compatible = "nxp,pca9554"; + reg = <0x27>; + gpio-controller; + #gpio-cells = <2>; + }; + + // OSFP IOEXP + io_expander6: gpio@25 { + compatible = "nxp,pca9555"; + reg = <0x25>; + gpio-controller; + #gpio-cells = <2>; + }; + + // OSFP FRU EEPROM + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + }; + i2c1mux0ch7: i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x7>; + + // FIO FRU EEPROM + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + + // FIO TEMP SENSOR + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; + }; + }; +}; + +&i2c2 { + status = "okay"; + + // Module 0 IOEXP + io_expander0: gpio@20 { + compatible = "nxp,pca9555"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(B, 4) IRQ_TYPE_LEVEL_LOW>; + }; + + // Module 1 IOEXP + io_expander1: gpio@21 { + compatible = "nxp,pca9555"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(B, 4) IRQ_TYPE_LEVEL_LOW>; + }; + + // HMC IOEXP + io_expander2: gpio@27 { + compatible = "nxp,pca9555"; + reg = <0x27>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(B, 4) IRQ_TYPE_LEVEL_LOW>; + }; + + // Module 0 EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + // Module 1 EEPROM + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; + + // BMC IOEXP on Module 0 + io_expander3: gpio@21 { + compatible = "nxp,pca9555"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + }; + + rtc@6f { + compatible = "nuvoton,nct3018y"; + reg = <0x6f>; + }; +}; + +&i2c7 { + status = "okay"; +}; + +&i2c8 { + status = "okay"; +}; + +&i2c9 { + status = "okay"; + + // SCM CPLD IOEXP + io_expander4: gpio@4f { + compatible = "nxp,pca9555"; + reg = <0x4f>; + gpio-controller; + #gpio-cells = <2>; + }; + + // SCM TEMP SENSOR + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; + + // SCM FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + // BSM FRU EEPROM + eeprom@56 { + compatible = "atmel,24c64"; + reg = <0x56>; + }; +}; + +&i2c10 { + status = "okay"; + + // OCP NIC0 TEMP + temperature-sensor@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + + // OCP NIC0 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; +}; + +&i2c11 { + status = "okay"; + + ssif-bmc@10 { + compatible = "ssif-bmc"; + reg = <0x10>; + }; +}; + +&i2c12 { + status = "okay"; + + // Module 1 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; +}; + +&i2c13 { + status = "okay"; + + // Module 0 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + // Left CBC FRU EEPROM + eeprom@54 { + compatible = "atmel,24c02"; + reg = <0x54>; + }; + + // Right CBC FRU EEPROM + eeprom@55 { + compatible = "atmel,24c02"; + reg = <0x55>; + }; + + // HMC FRU EEPROM + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; + }; +}; + +&i2c14 { + status = "okay"; + + // PDB CPLD IOEXP 0x10 + io_expander9: gpio@10 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x10>; + gpio-controller; + #gpio-cells = <2>; + }; + + // PDB CPLD IOEXP 0x11 + io_expander10: gpio@11 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x11>; + gpio-controller; + #gpio-cells = <2>; + }; + + // PDB CPLD IOEXP 0x12 + io_expander11: gpio@12 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x12>; + gpio-controller; + #gpio-cells = <2>; + }; + + // PDB CPLD IOEXP 0x13 + io_expander12: gpio@13 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x13>; + gpio-controller; + #gpio-cells = <2>; + }; + + // PDB CPLD IOEXP 0x14 + io_expander13: gpio@14 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x14>; + gpio-controller; + #gpio-cells = <2>; + }; + + // PDB CPLD IOEXP 0x15 + io_expander14: gpio@15 { + compatible = "nxp,pca9555"; + interrupt-parent = <&gpio0>; + interrupts = <ASPEED_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; + reg = <0x15>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&i2c15 { + status = "okay"; + + // OCP NIC1 TEMP + temperature-sensor@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + + // OCP NIC1 FRU EEPROM + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; +}; + +&adc0 { + vref-supply = <&p1v8_bmc_aux>; + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default + &pinctrl_adc2_default &pinctrl_adc3_default + &pinctrl_adc4_default &pinctrl_adc5_default + &pinctrl_adc6_default &pinctrl_adc7_default>; +}; + +&adc1 { + vref-supply = <&p2v5_bmc_aux>; + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc10_default>; +}; + +&ehci0 { + status = "okay"; +}; + +&wdt1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdtrst1_default>; + aspeed,reset-type = "soc"; + aspeed,external-signal; + aspeed,ext-push-pull; + aspeed,ext-active-high; + aspeed,ext-pulse-duration = <256>; +}; + +&pinctrl { + pinctrl_ncsi3_default: ncsi3_default { + function = "RMII3"; + groups = "NCSI3"; + }; + + pinctrl_ncsi4_default: ncsi4_default { + function = "RMII4"; + groups = "NCSI4"; + }; +}; + +&gpio0 { + gpio-line-names = + /*A0-A7*/ "","","","","","","","", + /*B0-B7*/ "BATTERY_DETECT","PRSNT1_HPM_SCM_N", + "BMC_I2C1_FPGA_ALERT_L","BMC_READY", + "IOEXP_INT_L","FM_ID_LED", + "","", + /*C0-C7*/ "","","","", + "PMBUS_REQ_N","PSU_FW_UPDATE_REQ_N", + "","BMC_I2C_SSIF_ALERT_L", + /*D0-D7*/ "","","","","","","","", + /*E0-E7*/ "","","","","","","","", + /*F0-F7*/ "","","","","","","","", + /*G0-G7*/ "","","","","","", + "FM_DEBUG_PORT_PRSNT_N","FM_BMC_DBP_PRESENT_N", + /*H0-H7*/ "PWR_BRAKE_L","RUN_POWER_EN", + "SHDN_FORCE_L","SHDN_REQ_L", + "","","","", + /*I0-I7*/ "","","","", + "","FLASH_WP_STATUS", + "FM_PDB_HEALTH_N","RUN_POWER_PG", + /*J0-J7*/ "","","","","","","","", + /*K0-K7*/ "","","","","","","","", + /*L0-L7*/ "","","","","","","","", + /*M0-M7*/ "PCIE_EP_RST_EN","BMC_FRU_WP", + "SCM_HPM_STBY_RST_N","SCM_HPM_STBY_EN", + "STBY_POWER_PG_3V3","TH500_SHDN_OK_L","","", + /*N0-N7*/ "LED_POSTCODE_0","LED_POSTCODE_1", + "LED_POSTCODE_2","LED_POSTCODE_3", + "LED_POSTCODE_4","LED_POSTCODE_5", + "LED_POSTCODE_6","LED_POSTCODE_7", + /*O0-O7*/ "HMC_I2C3_FPGA_ALERT_L","FPGA_READY_HMC", + "CHASSIS_AC_LOSS_L","BSM_PRSNT_R_N", + "PSU_SMB_ALERT_L","FM_TPM_PRSNT_0_N", + "","USBDBG_IPMI_EN_L", + /*P0-P7*/ "PWR_BTN_BMC_N","IPEX_CABLE_PRSNT_L", + "ID_RST_BTN_BMC_N","RST_BMC_RSTBTN_OUT_N", + "host0-ready","BMC_READY_CPLD","","BMC_HEARTBEAT_N", + /*Q0-Q7*/ "IRQ_PCH_TPM_SPI_N","USB_OC0_REAR_R_N", + "UART_MUX_SEL","I2C_MUX_RESET_L", + "RSVD_NV_PLT_DETECT","SPI_TPM_INT_L", + "CPU_JTAG_MUX_SELECT","THERM_BB_OVERT_L", + /*R0-R7*/ "THERM_BB_WARN_L","SPI_BMC_FPGA_INT_L", + "CPU_BOOT_DONE","PMBUS_GNT_L", + "CHASSIS_PWR_BRK_L","PCIE_WAKE_L", + "PDB_THERM_OVERT_L","HMC_I2C2_FPGA_ALERT_L", + /*S0-S7*/ "","","SYS_BMC_PWRBTN_R_N","FM_TPM_PRSNT_1_N", + "FM_BMC_DEBUG_SW_N","UID_LED_N", + "SYS_FAULT_LED_N","RUN_POWER_FAULT_L", + /*T0-T7*/ "","","","","","","","", + /*U0-U7*/ "","","","","","","","", + /*V0-V7*/ "L2_RST_REQ_OUT_L","L0L1_RST_REQ_OUT_L", + "BMC_ID_BEEP_SEL","BMC_I2C0_FPGA_ALERT_L", + "SMB_BMC_TMP_ALERT","PWR_LED_N", + "SYS_RST_OUT_L","IRQ_TPM_SPI_N", + /*W0-W7*/ "","","","","","","","", + /*X0-X7*/ "","","","","","","","", + /*Y0-Y7*/ "","RST_BMC_SELF_HW", + "FM_FLASH_LATCH_N","BMC_EMMC_RST_N", + "","","","", + /*Z0-Z7*/ "","","","","","","",""; +}; + +&io_expander0 { + gpio-line-names = + "FPGA_THERM_OVERT_L","FPGA_READY_BMC", + "HMC_BMC_DETECT","HMC_PGOOD", + "","BMC_SELF_PWR_CYCLE", + "FPGA_EROT_FATAL_ERROR_L","WP_HW_EXT_CTRL_L", + "EROT_FPGA_RST_L","FPGA_EROT_RECOVERY_L", + "BMC_EROT_FPGA_SPI_MUX_SEL","USB2_HUB_RESET_L", + "NCSI_CS1_SEL","SGPIO_EN_L", + "B2B_IOEXP_INT_L","I2C_BUS_MUX_RESET_L"; +}; + +&io_expander1 { + gpio-line-names = + "SEC_FPGA_THERM_OVERT_L","SEC_FPGA_READY_BMC", + "","", + "","", + "SEC_FPGA_EROT_FATAL_ERROR_L","SEC_WP_HW_EXT_CTRL_L", + "SEC_EROT_FPGA_RST_L","SEC_FPGA_EROT_RECOVERY_L", + "SEC_BMC_EROT_FPGA_SPI_MUX_SEL","", + "","", + "","SEC_I2C_BUS_MUX_RESET_L"; +}; + +&io_expander2 { + gpio-line-names = + "HMC_PRSNT_L","HMC_READY", + "HMC_EROT_FATAL_ERROR_L","I2C_MUX_SEL", + "HMC_EROT_SPI_MUX_SEL","HMC_EROT_RECOVERY_L", + "HMC_EROT_RST_L","GLOBAL_WP_HMC", + "FPGA_RST_L","USB2_HUB_RST", + "CPU_UART_MUX_SEL","", + "","","",""; +}; + +&io_expander3 { + gpio-line-names = + "RTC_MUX_SEL","PCI_MUX_SEL","TPM_MUX_SEL","FAN_MUX-SEL", + "SGMII_MUX_SEL","DP_MUX_SEL","UPHY3_USB_SEL","NCSI_MUX_SEL", + "BMC_PHY_RST","RTC_CLR_L","BMC_12V_CTRL","PS_RUN_IO0_PG", + "","","",""; +}; + +&io_expander4 { + gpio-line-names = + "stby_power_en_cpld","stby_power_gd_cpld","","", + "","","","", + "","","","", + "","","",""; +}; + +&io_expander5 { + gpio-line-names = + "JTAG_MUX_SEL","IOX_BMC_RESET","","", + "","","",""; +}; + +&io_expander6 { + gpio-line-names = + "OSFP_PHASE_ID0","OSFP_PHASE_ID1", + "OSFP_PHASE_ID2","OSFP_PHASE_ID3", + "","","","", + "OSFP_BOARD_ID0","OSFP_BOARD_ID1", + "OSFP_BOARD_ID2","PWRGD_P3V3_N1", + "PWRGD_P3V3_N2","","",""; +}; + +&io_expander7 { + gpio-line-names = + "RST_CX7_0","RST_CX7_1", + "CX0_SSD0_PRSNT_L","CX1_SSD1_PRSNT_L", + "CX_BOOT_CMPLT_CX0","CX_BOOT_CMPLT_CX1", + "CX_TWARN_CX0_L","CX_TWARN_CX1_L", + "CX_OVT_SHDN_CX0","CX_OVT_SHDN_CX1", + "FNP_L_CX0","FNP_L_CX1", + "","MCU_GPIO","MCU_RST_N","MCU_RECOVERY_N"; +}; + +&io_expander8 { + gpio-line-names = + "SEC_RST_CX7_0","SEC_RST_CX7_1", + "SEC_CX0_SSD0_PRSNT_L","SEC_CX1_SSD1_PRSNT_L", + "SEC_CX_BOOT_CMPLT_CX0","SEC_CX_BOOT_CMPLT_CX1", + "SEC_CX_TWARN_CX0_L","SEC_CX_TWARN_CX1_L", + "SEC_CX_OVT_SHDN_CX0","SEC_CX_OVT_SHDN_CX1", + "SEC_FNP_L_CX0","SEC_FNP_L_CX1", + "","SEC_MCU_GPIO","SEC_MCU_RST_N","SEC_MCU_RECOVERY_N"; +}; + +&io_expander9 { + gpio-line-names = + "LEAK3_DETECT_R","LEAK1_DETECT_R", + "LEAK2_DETECT_R","LEAK0_DETECT_R", + "CHASSIS3_LEAK_Q_N_PLD","CHASSIS1_LEAK_Q_N_PLD", + "CHASSIS2_LEAK_Q_N_PLD","CHASSIS0_LEAK_Q_N_PLD", + "P12V_AUX_FAN_ALERT_PLD_N","P12V_AUX_FAN_OC_PLD_N", + "P12V_AUX_FAN_FAULT_PLD_N","LEAK_DETECT_RMC_N_R", + "RSVD_RMC_GPIO3_R","SMB_RJ45_FIO_TMP_ALERT", + "",""; +}; + +&io_expander10 { + gpio-line-names = + "FM_P12V_NIC1_FLTB_R_N","FM_P3V3_NIC1_FAULT_R_N", + "OCP_V3_2_PWRBRK_FROM_HOST_ISO_PLD_N", + "P12V_AUX_NIC1_SENSE_ALERT_R_N", + "FM_P12V_NIC0_FLTB_R_N","FM_P3V3_NIC0_FAULT_R_N", + "OCP_SFF_PWRBRK_FROM_HOST_ISO_PLD_N", + "P12V_AUX_NIC0_SENSE_ALERT_R_N", + "P12V_AUX_PSU_SMB_ALERT_R_L","P12V_SCM_SENSE_ALERT_R_N", + "NODEB_PSU_SMB_ALERT_R_L","NODEA_PSU_SMB_ALERT_R_L", + "P52V_SENSE_ALERT_PLD_N","P48V_HS2_FAULT_N_PLD", + "P48V_HS1_FAULT_N_PLD",""; +}; + +&io_expander11 { + gpio-line-names = + "FAN_7_PRESENT_N","FAN_6_PRESENT_N", + "FAN_5_PRESENT_N","FAN_4_PRESENT_N", + "FAN_3_PRESENT_N","FAN_2_PRESENT_N", + "FAN_1_PRESENT_N","FAN_0_PRESENT_N", + "PRSNT_CHASSIS3_LEAK_CABLE_R_N","PRSNT_CHASSIS1_LEAK_CABLE_R_N", + "PRSNT_CHASSIS2_LEAK_CABLE_R_N","PRSNT_CHASSIS0_LEAK_CABLE_R_N", + "PRSNT_RJ45_FIO_N_R","PRSNT_HDDBD_POWER_CABLE_N", + "PRSNT_OSFP_POWER_CABLE_N",""; +}; + +&io_expander12 { + gpio-line-names = + "RST_OCP_V3_1_R_N","NIC0_PERST_N", + "OCP_SFF_PERST_FROM_HOST_ISO_PLD_N","OCP_SFF_MAIN_PWR_EN", + "FM_OCP_SFF_PWR_GOOD_PLD","OCP_SFF_AUX_PWR_PLD_EN_R", + "HP_LVC3_OCP_V3_1_PWRGD_PLD","HP_OCP_V3_1_HSC_PWRGD_PLD_R", + "RST_OCP_V3_2_R_N","NIC1_PERST_N", + "OCP_V3_2_PERST_FROM_HOST_ISO_PLD_N","OCP_V3_2_MAIN_PWR_EN", + "FM_OCP_V3_2_PWR_GOOD_PLD","OCP_V3_2_AUX_PWR_PLD_EN_R", + "HP_LVC3_OCP_V3_2_PWRGD_PLD","HP_OCP_V3_2_HSC_PWRGD_PLD_R"; +}; + +&io_expander13 { + gpio-line-names = + "NODEA_NODEB_PWOK_PLD_ISO_R","PWR_EN_NICS", + "PWRGD_P12V_AUX_FAN_PLD","P12V_AUX_FAN_EN_PLD", + "PWRGD_P3V3_AUX_PLD","PWRGD_P12V_AUX_PLD_ISO_R", + "FM_MAIN_PWREN_FROM_RMC_R","FM_MAIN_PWREN_RMC_EN_ISO_R", + "PWRGD_RMC_R","PWRGD_P12V_AUX_FAN_PLD", + "P12V_AUX_FAN_EN_PLD","FM_SYS_THROTTLE_N", + "HP_LVC3_OCP_V3_2_PRSNT2_PLD_N","HP_LVC3_OCP_V3_1_PRSNT2_PLD_N", + "",""; +}; + +&io_expander14 { + gpio-line-names = + "","","","","","","","", + "FM_BOARD_BMC_SKU_ID3","FM_BOARD_BMC_SKU_ID2", + "FM_BOARD_BMC_SKU_ID1","FM_BOARD_BMC_SKU_ID0", + "FAB_BMC_REV_ID2","FAB_BMC_REV_ID1", + "FAB_BMC_REV_ID0",""; +}; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts index 998598c15fd0..49914a4a179f 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-greatlakes.dts @@ -201,7 +201,7 @@ &i2c12 { status = "okay"; temperature-sensor@4f { - compatible = "lm75"; + compatible = "national,lm75"; reg = <0x4f>; }; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-harma.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-harma.dts index c118d473a76f..cf3f807a38fe 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-harma.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-harma.dts @@ -20,10 +20,6 @@ i2c21 = &imux21; i2c22 = &imux22; i2c23 = &imux23; - i2c24 = &imux24; - i2c25 = &imux25; - i2c26 = &imux26; - i2c27 = &imux27; i2c28 = &imux28; i2c29 = &imux29; i2c30 = &imux30; @@ -70,19 +66,19 @@ }; }; - spi_gpio: spi-gpio { + spi_gpio: spi { status = "okay"; compatible = "spi-gpio"; #address-cells = <1>; #size-cells = <0>; - gpio-sck = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; - gpio-mosi = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; - gpio-miso = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>; + sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>; num-chipselects = <1>; cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>; - tpmdev@0 { + tpm@0 { compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; spi-max-frequency = <33000000>; reg = <0>; @@ -137,7 +133,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rmii4_default>; use-ncsi; - mellanox,multi-host; }; &rtc { @@ -198,6 +193,35 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; &i2c1 { @@ -224,6 +248,35 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; &i2c3 { @@ -276,11 +329,15 @@ reg = <0x49>; }; - power-monitor@22 { - compatible = "lltc,ltc4286"; - reg = <0x22>; - adi,vrange-low-enable; - shunt-resistor-micro-ohms = <500>; + power-monitor@44 { + compatible = "lltc,ltc4287"; + reg = <0x44>; + shunt-resistor-micro-ohms = <250>; + }; + + power-monitor@40 { + compatible = "infineon,xdp710"; + reg = <0x40>; }; }; @@ -321,6 +378,14 @@ &i2c9 { status = "okay"; + mctp-controller; + multi-master; + + mctp@10 { + compatible = "mctp-i2c-controller"; + reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>; + }; + gpio@30 { compatible = "nxp,pca9555"; reg = <0x30>; @@ -340,33 +405,6 @@ "","","",""; }; - i2c-mux@71 { - compatible = "nxp,pca9546"; - reg = <0x71>; - #address-cells = <1>; - #size-cells = <0>; - - imux24: i2c@0 { - #address-cells = <1>; - #size-cells = <0>; - reg = <0>; - }; - imux25: i2c@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - }; - imux26: i2c@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - }; - imux27: i2c@3 { - #address-cells = <1>; - #size-cells = <0>; - reg = <3>; - }; - }; // PTTV FRU eeprom@52 { compatible = "atmel,24c64"; @@ -376,6 +414,31 @@ &i2c11 { status = "okay"; + + gpio@30 { + compatible = "nxp,pca9555"; + reg = <0x30>; + gpio-controller; + #gpio-cells = <2>; + }; + gpio@31 { + compatible = "nxp,pca9555"; + reg = <0x31>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "","","","", + "","","presence-cmm","", + "","","","", + "","","",""; + }; + + // Aegis FRU + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; }; &i2c12 { @@ -399,6 +462,30 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; + power-monitor@61 { + compatible = "isil,isl69260"; + reg = <0x61>; + }; + power-monitor@62 { + compatible = "isil,isl69260"; + reg = <0x62>; + }; + power-monitor@63 { + compatible = "isil,isl69260"; + reg = <0x63>; + }; + power-monitor@64 { + compatible = "infineon,xdpe152c4"; + reg = <0x64>; + }; + power-monitor@66 { + compatible = "infineon,xdpe152c4"; + reg = <0x66>; + }; + power-monitor@68 { + compatible = "infineon,xdpe152c4"; + reg = <0x68>; + }; }; imux29: i2c@1 { #address-cells = <1>; @@ -497,13 +584,14 @@ /*O0-O7*/ "","","","","","","","", /*P0-P7*/ "power-button","power-host-control", "reset-button","","led-power","","","", - /*Q0-Q7*/ "","","","","","","","", + /*Q0-Q7*/ "","","","","","power-chassis-control","","", /*R0-R7*/ "","","","","","","","", /*S0-S7*/ "","","","","","","","", /*T0-T7*/ "","","","","","","","", /*U0-U7*/ "","","","","","","led-identify-gate","", /*V0-V7*/ "","","","", - "rtc-battery-voltage-read-enable","","","", + "rtc-battery-voltage-read-enable","", + "power-chassis-good","", /*W0-W7*/ "","","","","","","","", /*X0-X7*/ "","","","","","","","", /*Y0-Y7*/ "","","","","","","","", @@ -521,7 +609,6 @@ &sgpiom0 { status = "okay"; - max-ngpios = <128>; ngpios = <128>; bus-frequency = <2000000>; gpio-line-names = diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva.dts index 942e53d5c714..41e2246cfbd1 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-minerva.dts @@ -11,7 +11,8 @@ compatible = "facebook,minerva-cmc", "aspeed,ast2600"; aliases { - serial5 = &uart5; + serial4 = &uart5; + serial5 = &uart6; /* * PCA9548 (2-0077) provides 8 channels connecting to * 6 pcs of FCB (Fan Controller Board). @@ -22,6 +23,8 @@ i2c19 = &imux19; i2c20 = &imux20; i2c21 = &imux21; + + spi1 = &spi_gpio; }; chosen { @@ -43,11 +46,54 @@ leds { compatible = "gpio-leds"; - led-fan-fault { - label = "led-fan-fault"; + led-0 { + label = "bmc_heartbeat_amber"; + gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + + led-1 { + label = "fp_id_amber"; + default-state = "off"; + gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>; + }; + + led-2 { + label = "power_blue"; + default-state = "off"; + gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>; + }; + + led-3 { + label = "fan_status_led"; gpios = <&leds_gpio 9 GPIO_ACTIVE_HIGH>; default-state = "off"; }; + + led-4 { + label = "fan_fault_led_n"; + gpios = <&leds_gpio 10 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + spi_gpio: spi { + status = "okay"; + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>; + num-chipselects = <1>; + cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>; + + tpm@0 { + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + spi-max-frequency = <33000000>; + reg = <0>; + }; }; }; @@ -77,6 +123,10 @@ }; }; +&mdio3 { + status = "okay"; +}; + &fmc { status = "okay"; flash@0 { @@ -94,10 +144,6 @@ }; }; -&rtc { - status = "okay"; -}; - &sgpiom0 { status = "okay"; ngpios = <128>; @@ -119,14 +165,15 @@ shunt-resistor = <1000>; }; - power-monitor@67 { - compatible = "adi,ltc2945"; - reg = <0x67>; + power-monitor@44 { + compatible = "lltc,ltc4287"; + reg = <0x44>; + shunt-resistor-micro-ohms = <2000>; }; - power-monitor@68 { - compatible = "adi,ltc2945"; - reg = <0x68>; + power-monitor@43 { + compatible = "infineon,xdp710"; + reg = <0x43>; }; leds_gpio: gpio@19 { @@ -145,9 +192,9 @@ reg = <0x4b>; }; - temperature-sensor@48 { + temperature-sensor@4f { compatible = "ti,tmp75"; - reg = <0x48>; + reg = <0x4f>; }; eeprom@54 { @@ -182,6 +229,35 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; imux17: i2c@1 { @@ -200,6 +276,35 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; imux18: i2c@2 { @@ -218,6 +323,35 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; imux19: i2c@3 { @@ -236,9 +370,38 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; - imux20: i2c@4 { + imux20: i2c@5 { #address-cells = <1>; #size-cells = <0>; reg = <4>; @@ -254,9 +417,37 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; - imux21: i2c@5 { + imux21: i2c@4 { #address-cells = <1>; #size-cells = <0>; reg = <5>; @@ -272,6 +463,34 @@ #address-cells = <1>; #size-cells = <0>; }; + + power-sensor@40 { + compatible = "ti,ina238"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + power-sensor@41 { + compatible = "ti,ina238"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + + power-sensor@44 { + compatible = "ti,ina238"; + reg = <0x44>; + shunt-resistor = <1000>; + }; + + power-sensor@45 { + compatible = "ti,ina238"; + reg = <0x45>; + shunt-resistor = <1000>; + }; + temperature-sensor@4b { + compatible = "ti,tmp75"; + reg = <0x4b>; + }; }; }; }; @@ -302,14 +521,16 @@ &i2c9 { status = "okay"; -}; -&i2c10 { - status = "okay"; -}; + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; -&i2c11 { - status = "okay"; + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; }; &i2c12 { @@ -338,6 +559,11 @@ compatible = "atmel,24c128"; reg = <0x50>; }; + + eeprom@56 { + compatible = "atmel,24c64"; + reg = <0x56>; + }; }; &adc0 { @@ -355,6 +581,10 @@ pinctrl-0 = <&pinctrl_adc10_default>; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -381,12 +611,12 @@ /*N0-N7*/ "","","","","","","","", /*O0-O7*/ "","","","","","","","", /*P0-P7*/ "","","","","","","","", - /*Q0-Q7*/ "","","","","","","","", + /*Q0-Q7*/ "","","","","","power-chassis-control","","", /*R0-R7*/ "","","","","","","","", - /*S0-S7*/ "","","","","","","","", + /*S0-S7*/ "","","","","","","","host0-ready", /*T0-T7*/ "","","","","","","","", /*U0-U7*/ "","","","","","","","", - /*V0-V7*/ "","","","","BAT_DETECT","","","", + /*V0-V7*/ "","","","","BAT_DETECT","","power-chassis-good","", /*W0-W7*/ "","","","","","","","", /*X0-X7*/ "","","BLADE_UART_SEL3","","","","","", /*Y0-Y7*/ "","","","","","","","", @@ -397,118 +627,118 @@ gpio-line-names = /*"input pin","output pin"*/ /*A0 - A7*/ - "PRSNT_MTIA_BLADE0_N","PWREN_MTIA_BLADE0_EN", - "PRSNT_MTIA_BLADE1_N","PWREN_MTIA_BLADE1_EN", - "PRSNT_MTIA_BLADE2_N","PWREN_MTIA_BLADE2_EN", - "PRSNT_MTIA_BLADE3_N","PWREN_MTIA_BLADE3_EN", - "PRSNT_MTIA_BLADE4_N","PWREN_MTIA_BLADE4_EN", - "PRSNT_MTIA_BLADE5_N","PWREN_MTIA_BLADE5_EN", - "PRSNT_MTIA_BLADE6_N","PWREN_MTIA_BLADE6_EN", - "PRSNT_MTIA_BLADE7_N","PWREN_MTIA_BLADE7_EN", + "PRSNT_MTIA_BLADE0_N","PWREN_MTIA_BLADE0_EN_N", + "PRSNT_MTIA_BLADE1_N","PWREN_MTIA_BLADE1_EN_N", + "PRSNT_MTIA_BLADE2_N","PWREN_MTIA_BLADE2_EN_N", + "PRSNT_MTIA_BLADE3_N","PWREN_MTIA_BLADE3_EN_N", + "PRSNT_MTIA_BLADE4_N","PWREN_MTIA_BLADE4_EN_N", + "PRSNT_MTIA_BLADE5_N","PWREN_MTIA_BLADE5_EN_N", + "PRSNT_MTIA_BLADE6_N","PWREN_MTIA_BLADE6_EN_N", + "PRSNT_MTIA_BLADE7_N","PWREN_MTIA_BLADE7_EN_N", /*B0 - B7*/ - "PRSNT_MTIA_BLADE8_N","PWREN_MTIA_BLADE8_EN", - "PRSNT_MTIA_BLADE9_N","PWREN_MTIA_BLADE9_EN", - "PRSNT_MTIA_BLADE10_N","PWREN_MTIA_BLADE10_EN", - "PRSNT_MTIA_BLADE11_N","PWREN_MTIA_BLADE11_EN", - "PRSNT_MTIA_BLADE12_N","PWREN_MTIA_BLADE12_EN", - "PRSNT_MTIA_BLADE13_N","PWREN_MTIA_BLADE13_EN", - "PRSNT_MTIA_BLADE14_N","PWREN_MTIA_BLADE14_EN", - "PRSNT_MTIA_BLADE15_N","PWREN_MTIA_BLADE15_EN", + "PRSNT_MTIA_BLADE8_N","PWREN_MTIA_BLADE8_EN_N", + "PRSNT_MTIA_BLADE9_N","PWREN_MTIA_BLADE9_EN_N", + "PRSNT_MTIA_BLADE10_N","PWREN_MTIA_BLADE10_EN_N", + "PRSNT_MTIA_BLADE11_N","PWREN_MTIA_BLADE11_EN_N", + "PRSNT_MTIA_BLADE12_N","PWREN_MTIA_BLADE12_EN_N", + "PRSNT_MTIA_BLADE13_N","PWREN_MTIA_BLADE13_EN_N", + "PRSNT_MTIA_BLADE14_N","PWREN_MTIA_BLADE14_EN_N", + "PRSNT_MTIA_BLADE15_N","PWREN_MTIA_BLADE15_EN_N", /*C0 - C7*/ - "PRSNT_NW_BLADE0_N","PWREN_NW_BLADE0_EN", - "PRSNT_NW_BLADE1_N","PWREN_NW_BLADE1_EN", - "PRSNT_NW_BLADE2_N","PWREN_NW_BLADE2_EN", - "PRSNT_NW_BLADE3_N","PWREN_NW_BLADE3_EN", - "PRSNT_NW_BLADE4_N","PWREN_NW_BLADE4_EN", - "PRSNT_NW_BLADE5_N","PWREN_NW_BLADE5_EN", - "PRSNT_FCB_TOP_0_N","PWREN_MTIA_BLADE0_HSC_EN", - "PRSNT_FCB_TOP_1_N","PWREN_MTIA_BLADE1_HSC_EN", + "PRSNT_NW_BLADE0_N","PWREN_NW_BLADE0_EN_N", + "PRSNT_NW_BLADE1_N","PWREN_NW_BLADE1_EN_N", + "PRSNT_NW_BLADE2_N","PWREN_NW_BLADE2_EN_N", + "PRSNT_NW_BLADE3_N","PWREN_NW_BLADE3_EN_N", + "PRSNT_NW_BLADE4_N","PWREN_NW_BLADE4_EN_N", + "PRSNT_NW_BLADE5_N","PWREN_NW_BLADE5_EN_N", + "PRSNT_FCB_TOP_0_N","PWREN_MTIA_BLADE0_HSC_EN_N", + "PRSNT_FCB_TOP_1_N","PWREN_MTIA_BLADE1_HSC_EN_N", /*D0 - D7*/ - "PRSNT_FCB_MIDDLE_0_N","PWREN_MTIA_BLADE2_HSC_EN", - "PRSNT_FCB_MIDDLE_1_N","PWREN_MTIA_BLADE3_HSC_EN", - "PRSNT_FCB_BOTTOM_0_N","PWREN_MTIA_BLADE4_HSC_EN", - "PRSNT_FCB_BOTTOM_1_N","PWREN_MTIA_BLADE5_HSC_EN", - "PWRGD_MTIA_BLADE0_PWROK_L_BUF","PWREN_MTIA_BLADE6_HSC_EN", - "PWRGD_MTIA_BLADE1_PWROK_L_BUF","PWREN_MTIA_BLADE7_HSC_EN", - "PWRGD_MTIA_BLADE2_PWROK_L_BUF","PWREN_MTIA_BLADE8_HSC_EN", - "PWRGD_MTIA_BLADE3_PWROK_L_BUF","PWREN_MTIA_BLADE9_HSC_EN", + "PRSNT_FCB_MIDDLE_0_N","PWREN_MTIA_BLADE2_HSC_EN_N", + "PRSNT_FCB_MIDDLE_1_N","PWREN_MTIA_BLADE3_HSC_EN_N", + "PRSNT_FCB_BOTTOM_1_N","PWREN_MTIA_BLADE4_HSC_EN_N", + "PRSNT_FCB_BOTTOM_0_N","PWREN_MTIA_BLADE5_HSC_EN_N", + "PWRGD_MTIA_BLADE0_PWROK_N","PWREN_MTIA_BLADE6_HSC_EN_N", + "PWRGD_MTIA_BLADE1_PWROK_N","PWREN_MTIA_BLADE7_HSC_EN_N", + "PWRGD_MTIA_BLADE2_PWROK_N","PWREN_MTIA_BLADE8_HSC_EN_N", + "PWRGD_MTIA_BLADE3_PWROK_N","PWREN_MTIA_BLADE9_HSC_EN_N", /*E0 - E7*/ - "PWRGD_MTIA_BLADE4_PWROK_L_BUF","PWREN_MTIA_BLADE10_HSC_EN", - "PWRGD_MTIA_BLADE5_PWROK_L_BUF","PWREN_MTIA_BLADE11_HSC_EN", - "PWRGD_MTIA_BLADE6_PWROK_L_BUF","PWREN_MTIA_BLADE12_HSC_EN", - "PWRGD_MTIA_BLADE7_PWROK_L_BUF","PWREN_MTIA_BLADE13_HSC_EN", - "PWRGD_MTIA_BLADE8_PWROK_L_BUF","PWREN_MTIA_BLADE14_HSC_EN", - "PWRGD_MTIA_BLADE9_PWROK_L_BUF","PWREN_MTIA_BLADE15_HSC_EN", - "PWRGD_MTIA_BLADE10_PWROK_L_BUF","PWREN_NW_BLADE0_HSC_EN", - "PWRGD_MTIA_BLADE11_PWROK_L_BUF","PWREN_NW_BLADE1_HSC_EN", + "PWRGD_MTIA_BLADE4_PWROK_N","PWREN_MTIA_BLADE10_HSC_EN_N", + "PWRGD_MTIA_BLADE5_PWROK_N","PWREN_MTIA_BLADE11_HSC_EN_N", + "PWRGD_MTIA_BLADE6_PWROK_N","PWREN_MTIA_BLADE12_HSC_EN_N", + "PWRGD_MTIA_BLADE7_PWROK_N","PWREN_MTIA_BLADE13_HSC_EN_N", + "PWRGD_MTIA_BLADE8_PWROK_N","PWREN_MTIA_BLADE14_HSC_EN_N", + "PWRGD_MTIA_BLADE9_PWROK_N","PWREN_MTIA_BLADE15_HSC_EN_N", + "PWRGD_MTIA_BLADE10_PWROK_N","PWREN_NW_BLADE0_HSC_EN_N", + "PWRGD_MTIA_BLADE11_PWROK_N","PWREN_NW_BLADE1_HSC_EN_N", /*F0 - F7*/ - "PWRGD_MTIA_BLADE12_PWROK_L_BUF","PWREN_NW_BLADE2_HSC_EN", - "PWRGD_MTIA_BLADE13_PWROK_L_BUF","PWREN_NW_BLADE3_HSC_EN", - "PWRGD_MTIA_BLADE14_PWROK_L_BUF","PWREN_NW_BLADE4_HSC_EN", - "PWRGD_MTIA_BLADE15_PWROK_L_BUF","PWREN_NW_BLADE5_HSC_EN", - "PWRGD_NW_BLADE0_PWROK_L_BUF","PWREN_FCB_TOP_L_EN", - "PWRGD_NW_BLADE1_PWROK_L_BUF","PWREN_FCB_TOP_R_EN", - "PWRGD_NW_BLADE2_PWROK_L_BUF","PWREN_FCB_MIDDLE_L_EN", - "PWRGD_NW_BLADE3_PWROK_L_BUF","PWREN_FCB_MIDDLE_R_EN", + "PWRGD_MTIA_BLADE12_PWROK_N","PWREN_NW_BLADE2_HSC_EN_N", + "PWRGD_MTIA_BLADE13_PWROK_N","PWREN_NW_BLADE3_HSC_EN_N", + "PWRGD_MTIA_BLADE14_PWROK_N","PWREN_NW_BLADE4_HSC_EN_N", + "PWRGD_MTIA_BLADE15_PWROK_N","PWREN_NW_BLADE5_HSC_EN_N", + "PWRGD_NW_BLADE0_PWROK_N","PWREN_FCB_TOP_0_EN_N", + "PWRGD_NW_BLADE1_PWROK_N","PWREN_FCB_TOP_1_EN_N", + "PWRGD_NW_BLADE2_PWROK_N","PWREN_FCB_MIDDLE_0_EN_N", + "PWRGD_NW_BLADE3_PWROK_N","PWREN_FCB_MIDDLE_1_EN_N", /*G0 - G7*/ - "PWRGD_NW_BLADE4_PWROK_L_BUF","PWREN_FCB_BOTTOM_L_EN", - "PWRGD_NW_BLADE5_PWROK_L_BUF","PWREN_FCB_BOTTOM_R_EN", - "PWRGD_FCB_TOP_0_PWROK_L_BUF","FM_CMM_AC_CYCLE_N", - "PWRGD_FCB_TOP_1_PWROK_L_BUF","MGMT_SFP_TX_DIS", - "PWRGD_FCB_MIDDLE_0_PWROK_L_BUF","", - "PWRGD_FCB_MIDDLE_1_PWROK_L_BUF","RST_I2CRST_MTIA_BLADE0_1_N", - "PWRGD_FCB_BOTTOM_0_PWROK_L_BUF","RST_I2CRST_MTIA_BLADE2_3_N", - "PWRGD_FCB_BOTTOM_1_PWROK_L_BUF","RST_I2CRST_MTIA_BLADE4_5_N", + "PWRGD_NW_BLADE4_PWROK_N","PWREN_FCB_BOTTOM_1_EN_N", + "PWRGD_NW_BLADE5_PWROK_N","PWREN_FCB_BOTTOM_0_EN_N", + "PWRGD_FCB_TOP_0_PWROK_N","FM_CMM_AC_CYCLE_N", + "PWRGD_FCB_TOP_1_PWROK_N","MGMT_SFP_TX_DIS", + "PWRGD_FCB_MIDDLE_0_PWROK_N","FM_MDIO_SW_SEL", + "PWRGD_FCB_MIDDLE_1_PWROK_N","FM_P24V_SMPWR_EN", + "PWRGD_FCB_BOTTOM_1_PWROK_N","", + "PWRGD_FCB_BOTTOM_0_PWROK_N","", /*H0 - H7*/ - "LEAK_DETECT_MTIA_BLADE0_N_BUF","RST_I2CRST_MTIA_BLADE6_7_N", - "LEAK_DETECT_MTIA_BLADE1_N_BUF","RST_I2CRST_MTIA_BLADE8_9_N", - "LEAK_DETECT_MTIA_BLADE2_N_BUF","RST_I2CRST_MTIA_BLADE10_11_N", - "LEAK_DETECT_MTIA_BLADE3_N_BUF","RST_I2CRST_MTIA_BLADE12_13_N", - "LEAK_DETECT_MTIA_BLADE4_N_BUF","RST_I2CRST_MTIA_BLADE14_15_N", - "LEAK_DETECT_MTIA_BLADE5_N_BUF","RST_I2CRST_NW_BLADE0_1_2_N", - "LEAK_DETECT_MTIA_BLADE6_N_BUF","RST_I2CRST_NW_BLADE3_4_5_N", - "LEAK_DETECT_MTIA_BLADE7_N_BUF","RST_I2CRST_FCB_N", + "LEAK_DETECT_MTIA_BLADE0_N","", + "LEAK_DETECT_MTIA_BLADE1_N","", + "LEAK_DETECT_MTIA_BLADE2_N","", + "LEAK_DETECT_MTIA_BLADE3_N","", + "LEAK_DETECT_MTIA_BLADE4_N","", + "LEAK_DETECT_MTIA_BLADE5_N","", + "LEAK_DETECT_MTIA_BLADE6_N","", + "LEAK_DETECT_MTIA_BLADE7_N","", /*I0 - I7*/ - "LEAK_DETECT_MTIA_BLADE8_N_BUF","RST_I2CRST_FCB_B_L_N", - "LEAK_DETECT_MTIA_BLADE9_N_BUF","RST_I2CRST_FCB_B_R_N", - "LEAK_DETECT_MTIA_BLADE10_N_BUF","RST_I2CRST_FCB_M_L_N", - "LEAK_DETECT_MTIA_BLADE11_N_BUF","RST_I2CRST_FCB_M_R_N", - "LEAK_DETECT_MTIA_BLADE12_N_BUF","RST_I2CRST_FCB_T_L_N", - "LEAK_DETECT_MTIA_BLADE13_N_BUF","RST_I2CRST_FCB_T_R_N", - "LEAK_DETECT_MTIA_BLADE14_N_BUF","BMC_READY", - "LEAK_DETECT_MTIA_BLADE15_N_BUF","wFM_88E6393X_BIN_UPDATE_EN_N", + "LEAK_DETECT_MTIA_BLADE8_N","RST_I2CRST_FCB_BOTTOM_1_N", + "LEAK_DETECT_MTIA_BLADE9_N","RST_I2CRST_FCB_BOTTOM_0_N", + "LEAK_DETECT_MTIA_BLADE10_N","RST_I2CRST_FCB_MIDDLE_0_N", + "LEAK_DETECT_MTIA_BLADE11_N","RST_I2CRST_FCB_MIDDLE_1_N", + "LEAK_DETECT_MTIA_BLADE12_N","RST_I2CRST_FCB_TOP_0_N", + "LEAK_DETECT_MTIA_BLADE13_N","RST_I2CRST_FCB_TOP_1_N", + "LEAK_DETECT_MTIA_BLADE14_N","BMC_READY", + "LEAK_DETECT_MTIA_BLADE15_N","FM_88E6393X_BIN_UPDATE_EN_N", /*J0 - J7*/ - "LEAK_DETECT_NW_BLADE0_N_BUF","WATER_VALVE_CLOSED_N", - "LEAK_DETECT_NW_BLADE1_N_BUF","", - "LEAK_DETECT_NW_BLADE2_N_BUF","", - "LEAK_DETECT_NW_BLADE3_N_BUF","", - "LEAK_DETECT_NW_BLADE4_N_BUF","", - "LEAK_DETECT_NW_BLADE5_N_BUF","", - "MTIA_BLADE0_STATUS_LED","", - "MTIA_BLADE1_STATUS_LED","", + "LEAK_DETECT_NW_BLADE0_N","WATER_VALVE_CLOSED_N", + "LEAK_DETECT_NW_BLADE1_N","", + "LEAK_DETECT_NW_BLADE2_N","", + "LEAK_DETECT_NW_BLADE3_N","", + "LEAK_DETECT_NW_BLADE4_N","", + "LEAK_DETECT_NW_BLADE5_N","", + "PWRGD_MTIA_BLADE0_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE1_HSC_PWROK_N","", /*K0 - K7*/ - "MTIA_BLADE2_STATUS_LED","", - "MTIA_BLADE3_STATUS_LED","", - "MTIA_BLADE4_STATUS_LED","", - "MTIA_BLADE5_STATUS_LED","", - "MTIA_BLADE6_STATUS_LED","", - "MTIA_BLADE7_STATUS_LED","", - "MTIA_BLADE8_STATUS_LED","", - "MTIA_BLADE9_STATUS_LED","", + "PWRGD_MTIA_BLADE2_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE3_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE4_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE5_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE6_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE7_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE8_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE9_HSC_PWROK_N","", /*L0 - L7*/ - "MTIA_BLADE10_STATUS_LED","", - "MTIA_BLADE11_STATUS_LED","", - "MTIA_BLADE12_STATUS_LED","", - "MTIA_BLADE13_STATUS_LED","", - "MTIA_BLADE14_STATUS_LED","", - "MTIA_BLADE15_STATUS_LED","", - "NW_BLADE0_STATUS_LED","", - "NW_BLADE1_STATUS_LED","", + "PWRGD_MTIA_BLADE10_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE11_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE12_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE13_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE14_HSC_PWROK_N","", + "PWRGD_MTIA_BLADE15_HSC_PWROK_N","", + "PWRGD_NW_BLADE0_HSC_PWROK_N","", + "PWRGD_NW_BLADE1_HSC_PWROK_N","", /*M0 - M7*/ - "NW_BLADE2_STATUS_LED","", - "NW_BLADE3_STATUS_LED","", - "NW_BLADE4_STATUS_LED","", - "NW_BLADE5_STATUS_LED","", + "PWRGD_NW_BLADE2_HSC_PWROK_N","", + "PWRGD_NW_BLADE3_HSC_PWROK_N","", + "PWRGD_NW_BLADE4_HSC_PWROK_N","", + "PWRGD_NW_BLADE5_HSC_PWROK_N","", "RPU_READY","", "IT_GEAR_RPU_LINK_N","", "IT_GEAR_LEAK","", @@ -516,28 +746,28 @@ /*N0 - N7*/ "VALVE_STS0","", "VALVE_STS1","", - "VALVE_STS2","", - "VALVE_STS3","", - "CR_TOGGLE_BOOT_BUF_N","", - "CMM_LC_RDY_LED_N","", - "CMM_LC_UNRDY_LED_N","", + "PCA9555_IRQ0_N","", + "PCA9555_IRQ1_N","", + "CR_TOGGLE_BOOT_N","", + "IRQ_FCB_TOP0_N","", + "IRQ_FCB_TOP1_N","", "CMM_CABLE_CARTRIDGE_PRSNT_BOT_N","", /*O0 - O7*/ "CMM_CABLE_CARTRIDGE_PRSNT_TOP_N","", "BOT_BCB_CABLE_PRSNT_N","", "TOP_BCB_CABLE_PRSNT_N","", - "CHASSIS0_LEAK_Q_N","", - "CHASSIS1_LEAK_Q_N","", - "LEAK0_DETECT","", - "LEAK1_DETECT","", - "MGMT_SFP_PRSNT_N","", + "IRQ_FCB_MID0_N","", + "IRQ_FCB_MID1_N","", + "CHASSIS_LEAK0_DETECT_N","", + "CHASSIS_LEAK1_DETECT_N","", + "VALVE_RMON_A_1","", /*P0 - P7*/ - "MGMT_SFP_TX_FAULT","", - "MGMT_SFP_RX_LOS","", - "","", - "","", - "","", - "","", - "","", - "",""; + "VALVE_RMON_A_2","", + "VALVE_RMON_B_1","", + "VALVE_RMON_B_2","", + "RPU_READY_SPARE","", + "IT_GEAR_LEAK_SPARE","", + "IT_GEAR_RPU_LINK_SPARE_N","", + "IRQ_FCB_BOT0_N","", + "IRQ_FCB_BOT0_N",""; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge-4u.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge-4u.dts new file mode 100644 index 000000000000..839aad4ddd91 --- /dev/null +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge-4u.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright 2024 IBM Corp. +/dts-v1/; + +#include "aspeed-bmc-ibm-blueridge.dts" + +/ { + model = "Blueridge 4U"; +}; + +&i2c3 { + power-supply@6a { + compatible = "ibm,cffps"; + reg = <0x6a>; + }; + + power-supply@6b { + compatible = "ibm,cffps"; + reg = <0x6b>; + }; +}; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge.dts new file mode 100644 index 000000000000..dfe5cc3edb52 --- /dev/null +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-blueridge.dts @@ -0,0 +1,1686 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright 2024 IBM Corp. +/dts-v1/; + +#include <dt-bindings/gpio/aspeed-gpio.h> +#include <dt-bindings/i2c/i2c.h> +#include <dt-bindings/leds/leds-pca955x.h> +#include "aspeed-g6.dtsi" +#include "ibm-power11-quad.dtsi" + +/ { + model = "Blueridge 2U"; + compatible = "ibm,blueridge-bmc", "aspeed,ast2600"; + + aliases { + serial4 = &uart5; + i2c16 = &i2c2mux0; + i2c17 = &i2c2mux1; + i2c18 = &i2c2mux2; + i2c19 = &i2c2mux3; + i2c20 = &i2c4mux0chn0; + i2c21 = &i2c4mux0chn1; + i2c22 = &i2c4mux0chn2; + i2c23 = &i2c5mux0chn0; + i2c24 = &i2c5mux0chn1; + i2c25 = &i2c6mux0chn0; + i2c26 = &i2c6mux0chn1; + i2c27 = &i2c6mux0chn2; + i2c28 = &i2c6mux0chn3; + i2c29 = &i2c11mux0chn0; + i2c30 = &i2c11mux0chn1; + }; + + chosen { + stdout-path = &uart5; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: region@b3d00000 { + reg = <0xb3d00000 0x100000>; + no-map; + }; + + ramoops@b3e00000 { + compatible = "ramoops"; + reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */ + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x8000>; + pmsg-size = <0x8000>; + max-reason = <3>; /* KMSG_DUMP_EMERG */ + }; + + /* LPC FW cycle bridge region requires natural alignment */ + flash_memory: region@b4000000 { + reg = <0xb4000000 0x04000000>; /* 64M */ + no-map; + }; + + /* VGA region is dictated by hardware strapping */ + vga_memory: region@bf000000 { + compatible = "shared-dma-pool"; + reg = <0xbf000000 0x01000000>; /* 16M */ + no-map; + }; + }; + + i2c-mux { + compatible = "i2c-mux-gpio"; + #address-cells = <1>; + #size-cells = <0>; + i2c-parent = <&i2c2>; + idle-state = <0>; + mux-gpios = <&gpio0 ASPEED_GPIO(G, 4) GPIO_ACTIVE_HIGH>, + <&gpio0 ASPEED_GPIO(G, 5) GPIO_ACTIVE_HIGH>; + + i2c2mux0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2mux1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2mux2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2mux3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + leds { + compatible = "gpio-leds"; + + /* BMC Card fault LED at the back */ + led-bmc-ingraham0 { + gpios = <&gpio0 ASPEED_GPIO(H, 1) GPIO_ACTIVE_LOW>; + }; + + /* Enclosure ID LED at the back */ + led-rear-enc-id0 { + gpios = <&gpio0 ASPEED_GPIO(H, 2) GPIO_ACTIVE_LOW>; + }; + + /* Enclosure fault LED at the back */ + led-rear-enc-fault0 { + gpios = <&gpio0 ASPEED_GPIO(H, 3) GPIO_ACTIVE_LOW>; + }; + + /* PCIE slot power LED */ + led-pcieslot-power { + gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_LOW>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + poll-interval = <1000>; + + event-fan0-presence { + gpios = <&pca0 6 GPIO_ACTIVE_LOW>; + label = "fan0-presence"; + linux,code = <6>; + }; + + event-fan1-presence { + gpios = <&pca0 7 GPIO_ACTIVE_LOW>; + label = "fan1-presence"; + linux,code = <7>; + }; + + event-fan2-presence { + gpios = <&pca0 8 GPIO_ACTIVE_LOW>; + label = "fan2-presence"; + linux,code = <8>; + }; + + event-fan3-presence { + gpios = <&pca0 9 GPIO_ACTIVE_LOW>; + label = "fan3-presence"; + linux,code = <9>; + }; + + event-fan4-presence { + gpios = <&pca0 10 GPIO_ACTIVE_LOW>; + label = "fan4-presence"; + linux,code = <10>; + }; + + event-fan5-presence { + gpios = <&pca0 11 GPIO_ACTIVE_LOW>; + label = "fan5-presence"; + linux,code = <11>; + }; + }; + + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc1 7>; + }; +}; + +&adc1 { + status = "okay"; + aspeed,int-vref-microvolt = <2500000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default + &pinctrl_adc10_default &pinctrl_adc11_default + &pinctrl_adc12_default &pinctrl_adc13_default + &pinctrl_adc14_default &pinctrl_adc15_default>; +}; + +&ehci1 { + status = "okay"; +}; + +&uhci { + status = "okay"; +}; + +&gpio0 { + gpio-line-names = + /*A0-A7*/ "","","","","","","","", + /*B0-B7*/ "bmc-management-ready","","","","","","checkstop","", + /*C0-C7*/ "","","","","","","","", + /*D0-D7*/ "","","","","","","","", + /*E0-E7*/ "","","","","","","","", + /*F0-F7*/ "","","rtc-battery-voltage-read-enable","reset-cause-pinhole","","", + "factory-reset-toggle","", + /*G0-G7*/ "","","","","","","","", + /*H0-H7*/ "","bmc-ingraham0","rear-enc-id0","rear-enc-fault0","","","","", + /*I0-I7*/ "","","","","","","bmc-secure-boot","", + /*J0-J7*/ "","","","","","","","", + /*K0-K7*/ "","","","","","","","", + /*L0-L7*/ "","","","","","","","", + /*M0-M7*/ "","","","","","","","", + /*N0-N7*/ "","","","","","","","", + /*O0-O7*/ "","","","usb-power","","","","", + /*P0-P7*/ "","","","","pcieslot-power","","","", + /*Q0-Q7*/ "cfam-reset","","regulator-standby-faulted","","","","","", + /*R0-R7*/ "bmc-tpm-reset","power-chassis-control","power-chassis-good","","","","", + "", + /*S0-S7*/ "presence-ps0","presence-ps1","presence-ps2","presence-ps3", + "power-ffs-sync-history","","","", + /*T0-T7*/ "","","","","","","","", + /*U0-U7*/ "","","","","","","","", + /*V0-V7*/ "","","","","","","","", + /*W0-W7*/ "","","","","","","","", + /*X0-X7*/ "","","","","","","","", + /*Y0-Y7*/ "","","","","","","","", + /*Z0-Z7*/ "","","","","","","",""; + + i2c3-mux-oe-n-hog { + gpio-hog; + gpios = <ASPEED_GPIO(G, 6) GPIO_ACTIVE_LOW>; + line-name = "I2C3_MUX_OE_N"; + output-high; + }; + + usb-power-hog { + gpio-hog; + gpios = <ASPEED_GPIO(O, 3) GPIO_ACTIVE_LOW>; + output-high; + }; +}; + +&emmc_controller { + status = "okay"; +}; + +&pinctrl_emmc_default { + bias-disable; +}; + +&emmc { + status = "okay"; + clk-phase-mmc-hs200 = <180>, <180>; +}; + +&ibt { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + gpio@20 { + compatible = "ti,tca9554"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = "", + "RUSSEL_FW_I2C_ENABLE_N", + "RUSSEL_OPPANEL_PRESENCE_N", + "BLYTH_OPPANEL_PRESENCE_N", + "CPU_TPM_CARD_PRESENT_N", + "DASD_BP2_PRESENT_N", + "DASD_BP1_PRESENT_N", + "DASD_BP0_PRESENT_N"; + }; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + + power-supply@68 { + compatible = "ibm,cffps"; + reg = <0x68>; + }; + + power-supply@69 { + compatible = "ibm,cffps"; + reg = <0x69>; + }; + + led-controller@61 { + compatible = "nxp,pca9552"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "SLOT0_PRSNT_EN_RSVD", "SLOT1_PRSNT_EN_RSVD", + "SLOT2_PRSNT_EN_RSVD", "SLOT3_PRSNT_EN_RSVD", + "SLOT4_PRSNT_EN_RSVD", "SLOT0_EXPANDER_PRSNT_N", + "SLOT1_EXPANDER_PRSNT_N", "SLOT2_EXPANDER_PRSNT_N", + "SLOT3_EXPANDER_PRSNT_N", "SLOT4_EXPANDER_PRSNT_N", + "", "", "", "", "", ""; + }; +}; + +&i2c4 { + status = "okay"; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + temperature-sensor@49 { + compatible = "ti,tmp275"; + reg = <0x49>; + }; + + temperature-sensor@4a { + compatible = "ti,tmp275"; + reg = <0x4a>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c4mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard0-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard0-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c4mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + }; + + i2c4mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + }; + }; +}; + +&i2c5 { + status = "okay"; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + temperature-sensor@49 { + compatible = "ti,tmp275"; + reg = <0x49>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c5mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard3-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard3-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c5mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@61 { + compatible = "nxp,pca9551"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard4-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard4-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + }; +}; + +&i2c6 { + status = "okay"; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + temperature-sensor@4a { + compatible = "ti,tmp275"; + reg = <0x4a>; + }; + + temperature-sensor@4b { + compatible = "ti,tmp275"; + reg = <0x4b>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c6mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c6mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + }; + + i2c6mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + }; + + i2c6mux0chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + }; + }; +}; + +&i2c7 { + multi-master; + status = "okay"; + + led-controller@30 { + compatible = "ibm,pca9552"; + reg = <0x30>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "pcieslot0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "pcieslot1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "pcieslot2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "pcieslot3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "pcieslot4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "cpu1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "cpu-vrm1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "lcd-russel"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@31 { + compatible = "ibm,pca9552"; + reg = <0x31>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm12"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm13"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm14"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm15"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@32 { + compatible = "ibm,pca9552"; + reg = <0x32>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm16"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm17"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm18"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm19"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm20"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm21"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm22"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm23"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm24"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm25"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm26"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm27"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm28"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm29"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm30"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm31"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@33 { + compatible = "ibm,pca9552"; + reg = <0x33>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "planar"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cpu0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "dasd-pyramid0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "dasd-pyramid1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "dasd-pyramid2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "cpu0-vrm0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "rtc-battery"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "base-blyth"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "pcieslot6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "pcieslot7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "pcieslot8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "pcieslot9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "pcieslot10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "pcieslot11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "tpm-wilson"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + humidity-sensor@40 { + compatible = "silabs,si7020"; + reg = <0x40>; + }; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + pwm@52 { + compatible = "maxim,max31785a"; + reg = <0x52>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "front-sys-id0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "front-check-log0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "front-enc-fault1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "front-sys-pwron0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + pca0: led-controller@61 { + compatible = "nxp,pca9552"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "fan0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "fan1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "fan2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "fan3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "fan4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "fan5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + lcd-controller@62 { + compatible = "ibm,op-panel"; + reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>; + }; + + pressure-sensor@76 { + compatible = "infineon,dps310"; + reg = <0x76>; + #io-channel-cells = <0>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; +}; + +&i2c8 { + status = "okay"; + + pmic@11 { + compatible = "ti,ucd90320"; + reg = <0x11>; + }; + + rtc@32 { + compatible = "epson,rx8900"; + reg = <0x32>; + }; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + temperature-sensor@4a { + compatible = "ti,tmp275"; + reg = <0x4a>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "power-config-full-load", ""; + }; + + led-controller@61 { + compatible = "nxp,pca9552"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "SLOT6_PRSNT_EN_RSVD", "SLOT7_PRSNT_EN_RSVD", + "SLOT8_PRSNT_EN_RSVD", "SLOT9_PRSNT_EN_RSVD", + "SLOT10_PRSNT_EN_RSVD", "SLOT11_PRSNT_EN_RSVD", + "SLOT6_EXPANDER_PRSNT_N", "SLOT7_EXPANDER_PRSNT_N", + "SLOT8_EXPANDER_PRSNT_N", "SLOT9_EXPANDER_PRSNT_N", + "SLOT10_EXPANDER_PRSNT_N", "SLOT11_EXPANDER_PRSNT_N", + "", "", "", ""; + }; + +}; + +&i2c9 { + status = "okay"; + + temperature-sensor@4c { + compatible = "ti,tmp423"; + reg = <0x4c>; + }; + + temperature-sensor@4d { + compatible = "ti,tmp423"; + reg = <0x4d>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; +}; + +&i2c10 { + status = "okay"; + + temperature-sensor@4c { + compatible = "ti,tmp423"; + reg = <0x4c>; + }; + + temperature-sensor@4d { + compatible = "ti,tmp423"; + reg = <0x4d>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; +}; + +&i2c11 { + status = "okay"; + + temperature-sensor@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + temperature-sensor@49 { + compatible = "ti,tmp275"; + reg = <0x49>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c11mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard10-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard10-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c11mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + }; + }; +}; + +&i2c12 { + status = "okay"; + + tpm@2e { + compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + memory-region = <&event_log>; + }; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; +}; + +&i2c13 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "nvme0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "nvme1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "nvme2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "nvme3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "nvme4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "nvme5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "nvme6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "nvme7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; +}; + +&i2c14 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "nvme8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "nvme9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "nvme10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "nvme11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "nvme12"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "nvme13"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "nvme14"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "nvme15"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; +}; + +&i2c15 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "nvme16"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "nvme17"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "nvme18"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "nvme19"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "nvme20"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "nvme21"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "nvme22"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "nvme23"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; +}; + +&uart2 { + status = "okay"; +}; + +&vuart1 { + status = "okay"; +}; + +&vuart2 { + status = "okay"; +}; + +&lpc_ctrl { + status = "okay"; + memory-region = <&flash_memory>; +}; + +&mac2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii3_default>; + clocks = <&syscon ASPEED_CLK_GATE_MAC3CLK>, + <&syscon ASPEED_CLK_MAC3RCLK>; + clock-names = "MACCLK", "RCLK"; + use-ncsi; +}; + +&mac3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii4_default>; + clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>, + <&syscon ASPEED_CLK_MAC4RCLK>; + clock-names = "MACCLK", "RCLK"; + use-ncsi; +}; + +&wdt1 { + aspeed,reset-type = "none"; + aspeed,external-signal; + aspeed,ext-push-pull; + aspeed,ext-active-high; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdtrst1_default>; +}; + +&wdt2 { + status = "okay"; +}; + +&kcs2 { + status = "okay"; + aspeed,lpc-io-reg = <0xca8 0xcac>; +}; + +&kcs3 { + status = "okay"; + aspeed,lpc-io-reg = <0xca2>; + aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>; +}; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts index 6fdda42575df..7364adc6b80d 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-bonnell.dts @@ -570,11 +570,6 @@ status = "okay"; }; -&xdma { - status = "okay"; - memory-region = <&vga_memory>; -}; - &kcs2 { status = "okay"; aspeed,lpc-io-reg = <0xca8 0xcac>; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts index 214b2e6a4c6d..513077a1f4be 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-everest.dts @@ -2486,11 +2486,6 @@ status = "okay"; }; -&xdma { - status = "okay"; - memory-region = <&vga_memory>; -}; - &kcs2 { status = "okay"; aspeed,lpc-io-reg = <0xca8 0xcac>; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-fuji.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-fuji.dts new file mode 100644 index 000000000000..c24e464e5faa --- /dev/null +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-fuji.dts @@ -0,0 +1,3876 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright 2024 IBM Corp. +/dts-v1/; + +#include <dt-bindings/gpio/aspeed-gpio.h> +#include <dt-bindings/i2c/i2c.h> +#include <dt-bindings/leds/leds-pca955x.h> +#include "aspeed-g6.dtsi" +#include "ibm-power11-quad.dtsi" + +/ { + model = "Fuji"; + compatible = "ibm,fuji-bmc", "aspeed,ast2600"; + + aliases { + i2c500 = &cfam4_i2c0; + i2c501 = &cfam4_i2c1; + i2c510 = &cfam4_i2c10; + i2c511 = &cfam4_i2c11; + i2c512 = &cfam4_i2c12; + i2c513 = &cfam4_i2c13; + i2c514 = &cfam4_i2c14; + i2c515 = &cfam4_i2c15; + i2c602 = &cfam5_i2c2; + i2c603 = &cfam5_i2c3; + i2c610 = &cfam5_i2c10; + i2c611 = &cfam5_i2c11; + i2c614 = &cfam5_i2c14; + i2c615 = &cfam5_i2c15; + i2c616 = &cfam5_i2c16; + i2c617 = &cfam5_i2c17; + i2c700 = &cfam6_i2c0; + i2c701 = &cfam6_i2c1; + i2c710 = &cfam6_i2c10; + i2c711 = &cfam6_i2c11; + i2c712 = &cfam6_i2c12; + i2c713 = &cfam6_i2c13; + i2c714 = &cfam6_i2c14; + i2c715 = &cfam6_i2c15; + i2c802 = &cfam7_i2c2; + i2c803 = &cfam7_i2c3; + i2c810 = &cfam7_i2c10; + i2c811 = &cfam7_i2c11; + i2c814 = &cfam7_i2c14; + i2c815 = &cfam7_i2c15; + i2c816 = &cfam7_i2c16; + i2c817 = &cfam7_i2c17; + + i2c16 = &i2c4mux0chn0; + i2c17 = &i2c4mux0chn1; + i2c18 = &i2c4mux0chn2; + i2c19 = &i2c5mux0chn0; + i2c20 = &i2c5mux0chn1; + i2c21 = &i2c5mux0chn2; + i2c22 = &i2c5mux0chn3; + i2c23 = &i2c6mux0chn0; + i2c24 = &i2c6mux0chn1; + i2c25 = &i2c6mux0chn2; + i2c26 = &i2c6mux0chn3; + i2c27 = &i2c14mux0chn0; + i2c28 = &i2c14mux0chn1; + i2c29 = &i2c14mux0chn2; + i2c30 = &i2c14mux0chn3; + i2c31 = &i2c14mux1chn0; + i2c32 = &i2c14mux1chn1; + i2c33 = &i2c14mux1chn2; + i2c34 = &i2c14mux1chn3; + i2c35 = &i2c15mux0chn0; + i2c36 = &i2c15mux0chn1; + i2c37 = &i2c15mux0chn2; + i2c38 = &i2c15mux0chn3; + i2c39 = &i2c15mux1chn0; + i2c40 = &i2c15mux1chn1; + i2c41 = &i2c15mux1chn2; + i2c42 = &i2c15mux1chn3; + i2c43 = &i2c15mux2chn0; + i2c44 = &i2c15mux2chn1; + i2c45 = &i2c15mux2chn2; + i2c46 = &i2c15mux2chn3; + i2c47 = &i2c8mux0chn0; + i2c48 = &i2c8mux0chn1; + + serial4 = &uart5; + + sbefifo500 = &sbefifo500; + sbefifo501 = &sbefifo501; + sbefifo510 = &sbefifo510; + sbefifo511 = &sbefifo511; + sbefifo512 = &sbefifo512; + sbefifo513 = &sbefifo513; + sbefifo514 = &sbefifo514; + sbefifo515 = &sbefifo515; + sbefifo602 = &sbefifo602; + sbefifo603 = &sbefifo603; + sbefifo610 = &sbefifo610; + sbefifo611 = &sbefifo611; + sbefifo614 = &sbefifo614; + sbefifo615 = &sbefifo615; + sbefifo616 = &sbefifo616; + sbefifo617 = &sbefifo617; + sbefifo700 = &sbefifo700; + sbefifo701 = &sbefifo701; + sbefifo710 = &sbefifo710; + sbefifo711 = &sbefifo711; + sbefifo712 = &sbefifo712; + sbefifo713 = &sbefifo713; + sbefifo714 = &sbefifo714; + sbefifo715 = &sbefifo715; + sbefifo802 = &sbefifo802; + sbefifo803 = &sbefifo803; + sbefifo810 = &sbefifo810; + sbefifo811 = &sbefifo811; + sbefifo814 = &sbefifo814; + sbefifo815 = &sbefifo815; + sbefifo816 = &sbefifo816; + sbefifo817 = &sbefifo817; + + scom500 = &scom500; + scom501 = &scom501; + scom510 = &scom510; + scom511 = &scom511; + scom512 = &scom512; + scom513 = &scom513; + scom514 = &scom514; + scom515 = &scom515; + scom602 = &scom602; + scom603 = &scom603; + scom610 = &scom610; + scom611 = &scom611; + scom614 = &scom614; + scom615 = &scom615; + scom616 = &scom616; + scom617 = &scom617; + scom700 = &scom700; + scom701 = &scom701; + scom710 = &scom710; + scom711 = &scom711; + scom712 = &scom712; + scom713 = &scom713; + scom714 = &scom714; + scom715 = &scom715; + scom802 = &scom802; + scom803 = &scom803; + scom810 = &scom810; + scom811 = &scom811; + scom814 = &scom814; + scom815 = &scom815; + scom816 = &scom816; + scom817 = &scom817; + + spi50 = &cfam4_spi0; + spi51 = &cfam4_spi1; + spi52 = &cfam4_spi2; + spi53 = &cfam4_spi3; + spi60 = &cfam5_spi0; + spi61 = &cfam5_spi1; + spi62 = &cfam5_spi2; + spi63 = &cfam5_spi3; + spi70 = &cfam6_spi0; + spi71 = &cfam6_spi1; + spi72 = &cfam6_spi2; + spi73 = &cfam6_spi3; + spi80 = &cfam7_spi0; + spi81 = &cfam7_spi1; + spi82 = &cfam7_spi2; + spi83 = &cfam7_spi3; + }; + + chosen { + stdout-path = &uart5; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: region@b3d00000 { + reg = <0xb3d00000 0x100000>; + no-map; + }; + + ramoops@b3e00000 { + compatible = "ramoops"; + reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */ + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x8000>; + pmsg-size = <0x8000>; + max-reason = <3>; /* KMSG_DUMP_EMERG */ + }; + + /* LPC FW cycle bridge region requires natural alignment */ + flash_memory: region@b4000000 { + reg = <0xb4000000 0x04000000>; /* 64M */ + no-map; + }; + + /* VGA region is dictated by hardware strapping */ + vga_memory: region@bf000000 { + compatible = "shared-dma-pool"; + reg = <0xbf000000 0x01000000>; /* 16M */ + no-map; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + poll-interval = <1000>; + + event-fan0-presence { + gpios = <&pca0 15 GPIO_ACTIVE_LOW>; + label = "fan0-presence"; + linux,code = <15>; + }; + + event-fan1-presence { + gpios = <&pca0 14 GPIO_ACTIVE_LOW>; + label = "fan1-presence"; + linux,code = <14>; + }; + + event-fan2-presence { + gpios = <&pca0 13 GPIO_ACTIVE_LOW>; + label = "fan2-presence"; + linux,code = <13>; + }; + + event-fan3-presence { + gpios = <&pca0 12 GPIO_ACTIVE_LOW>; + label = "fan3-presence"; + linux,code = <12>; + }; + }; + + leds { + compatible = "gpio-leds"; + + /* RTC battery fault LED at the back */ + led-rtc-battery { + gpios = <&gpio0 ASPEED_GPIO(H, 0) GPIO_ACTIVE_LOW>; + }; + + /* BMC Card fault LED at the back */ + led-bmc { + gpios = <&gpio0 ASPEED_GPIO(H, 1) GPIO_ACTIVE_LOW>; + }; + + /* Enclosure Identify LED at the back */ + led-rear-enc-id0 { + gpios = <&gpio0 ASPEED_GPIO(H, 2) GPIO_ACTIVE_LOW>; + }; + + /* Enclosure fault LED at the back */ + led-rear-enc-fault0 { + gpios = <&gpio0 ASPEED_GPIO(H, 3) GPIO_ACTIVE_LOW>; + }; + + /* PCIE slot power LED */ + led-pcieslot-power { + gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_LOW>; + }; + }; + + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc1 7>; + }; +}; + +&adc1 { + status = "okay"; + aspeed,int-vref-microvolt = <2500000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default + &pinctrl_adc10_default &pinctrl_adc11_default + &pinctrl_adc12_default &pinctrl_adc13_default + &pinctrl_adc14_default &pinctrl_adc15_default>; +}; + +&gpio0 { + gpio-line-names = + /*A0-A7*/ "","","","","","","","", + /*B0-B7*/ "bmc-management-ready","","","","","","checkstop","", + /*C0-C7*/ "","","","","","","","", + /*D0-D7*/ "","","","","","","","", + /*E0-E7*/ "","","","","","","","", + /*F0-F7*/ "","","rtc-battery-voltage-read-enable","reset-cause-pinhole","","", + "factory-reset-toggle","", + /*G0-G7*/ "","","","","","","","", + /*H0-H7*/ "led-rtc-battery","led-bmc","led-rear-enc-id0","led-rear-enc-fault0","","", + "","", + /*I0-I7*/ "","","","","","","bmc-secure-boot","", + /*J0-J7*/ "","","","","","","","", + /*K0-K7*/ "","","","","","","","", + /*L0-L7*/ "","","","","","","","", + /*M0-M7*/ "","","","","","","","", + /*N0-N7*/ "","","","","","","","", + /*O0-O7*/ "","","","usb-power","","","","", + /*P0-P7*/ "","","","","led-pcieslot-power","","","", + /*Q0-Q7*/ "","","regulator-standby-faulted","","","","","", + /*R0-R7*/ "bmc-tpm-reset","power-chassis-control","power-chassis-good","","", + "I2C_FLASH_MICRO_N","","", + /*S0-S7*/ "","","","","power-ffs-sync-history","","","", + /*T0-T7*/ "","","","","","","","", + /*U0-U7*/ "","","","","","","","", + /*V0-V7*/ "","BMC_3RESTART_ATTEMPT_P","","","","","","", + /*W0-W7*/ "","","","","","","","", + /*X0-X7*/ "","","","","","","","", + /*Y0-Y7*/ "","","","","","","","", + /*Z0-Z7*/ "","","","","","","",""; + + usb-power-hog { + gpio-hog; + gpios = <ASPEED_GPIO(O, 3) GPIO_ACTIVE_LOW>; + output-high; + }; +}; + +&i2c0 { + status = "okay"; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@62 { + compatible = "nxp,pca9552"; + reg = <0x62>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "presence-ps0", + "presence-ps1", + "presence-ps2", + "presence-ps3", + "presence-pdb", + "presence-tpm", + "", "", + "presence-cp0", + "presence-cp1", + "presence-cp2", + "presence-cp3", + "presence-dasd", + "presence-lcd-op", + "presence-base-op", + ""; + }; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + + eeprom@54 { + compatible = "atmel,24c128"; + reg = <0x54>; + }; + + power-supply@68 { + compatible = "ibm,cffps"; + reg = <0x68>; + }; + + power-supply@69 { + compatible = "ibm,cffps"; + reg = <0x69>; + }; + + power-supply@6b { + compatible = "ibm,cffps"; + reg = <0x6b>; + }; + + power-supply@6d { + compatible = "ibm,cffps"; + reg = <0x6d>; + }; +}; + +&i2c4 { + status = "okay"; + + led-controller@65 { + compatible = "nxp,pca9552"; + reg = <0x65>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "presence-cable-card1", + "presence-cable-card2", + "presence-cable-card3", + "presence-cable-card4", + "presence-cable-card5", + "expander-cable-card1", + "expander-cable-card2", + "expander-cable-card3", + "expander-cable-card4", + "expander-cable-card5"; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c4mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + + led-controller@62 { + compatible = "nxp,pca9551"; + reg = <0x62>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c01-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c01-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c4mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c02-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c02-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c4mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@61 { + compatible = "nxp,pca9551"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c03-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c03-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + }; +}; + +&i2c5 { + status = "okay"; + + led-controller@66 { + compatible = "nxp,pca9552"; + reg = <0x66>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "presence-cable-card6", + "presence-cable-card7", + "presence-cable-card8", + "presence-cable-card9", + "presence-cable-card10", + "presence-cable-card11", + "expander-cable-card6", + "expander-cable-card7", + "expander-cable-card8", + "expander-cable-card9", + "expander-cable-card10", + "expander-cable-card11"; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c5mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c04-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c04-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c5mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@61 { + compatible = "nxp,pca9551"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c05-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c05-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c5mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + + led-controller@62 { + compatible = "nxp,pca9551"; + reg = <0x62>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c06-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c06-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c5mux0chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + + led-controller@63 { + compatible = "nxp,pca9551"; + reg = <0x63>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c07-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c07-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + }; +}; + +&i2c6 { + status = "okay"; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c6mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c08-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c08-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c6mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@52 { + compatible = "atmel,24c64"; + reg = <0x52>; + }; + + led-controller@62 { + compatible = "nxp,pca9551"; + reg = <0x62>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c09-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c09-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c6mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + + led-controller@63 { + compatible = "nxp,pca9551"; + reg = <0x63>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c10-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c10-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c6mux0chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + led-controller@61 { + compatible = "nxp,pca9551"; + reg = <0x61>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "cablecard-c11-cxp-top"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "cablecard-c11-cxp-bot"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + }; + + led-controller@65 { + compatible = "nxp,pca9552"; + reg = <0x65>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "pcieslot-c01"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "pcieslot-c02"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "pcieslot-c03"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "pcieslot-c04"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "pcieslot-c05"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "pcieslot-c06"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "pcieslot-c07"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "pcieslot-c08"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "pcieslot-c09"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "pcieslot-c10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "pcieslot-c11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; +}; + +&i2c7 { + status = "okay"; + + led-controller@31 { + compatible = "ibm,pca9552"; + reg = <0x31>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm12"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm13"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm14"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm15"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@32 { + compatible = "ibm,pca9552"; + reg = <0x32>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm16"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm17"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm18"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm19"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm20"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm21"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm22"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm23"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm24"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm25"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm26"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm27"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm28"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm29"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm30"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm31"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@33 { + compatible = "ibm,pca9552"; + reg = <0x33>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm32"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm33"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm34"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm35"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm36"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm37"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm38"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm39"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm40"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm41"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm42"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm43"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm44"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm45"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm46"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm47"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@30 { + compatible = "ibm,pca9552"; + reg = <0x30>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "ddimm48"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "ddimm49"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "ddimm50"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "ddimm51"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "ddimm52"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "ddimm53"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "ddimm54"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "ddimm55"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "ddimm56"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "ddimm57"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "ddimm58"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "ddimm59"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "ddimm60"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "ddimm61"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "ddimm62"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "ddimm63"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@34 { + compatible = "ibm,pca9552"; + reg = <0x34>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "planar"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "tpm"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "cpu3-c61"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "cpu0-c14"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "opencapi-connector3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "opencapi-connector4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "opencapi-connector5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "vrm4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "vrm5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "vrm6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "vrm7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "vrm12"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "vrm13"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "vrm14"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "vrm15"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + led-controller@35 { + compatible = "ibm,pca9552"; + reg = <0x35>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "dasd-backplane"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "power-distribution"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "cpu1-c19"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "cpu2-c56"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "opencapi-connector0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "opencapi-connector1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "opencapi-connector2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "vrm0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "vrm1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "vrm2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "vrm3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "vrm8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "vrm9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@14 { + reg = <14>; + default-state = "keep"; + label = "vrm10"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@15 { + reg = <15>; + default-state = "keep"; + label = "vrm11"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; +}; + +&i2c8 { + status = "okay"; + + pmic@11 { + compatible = "ti,ucd90320"; + reg = <0x11>; + }; + + rtc@32 { + compatible = "epson,rx8900"; + reg = <0x32>; + }; + + eeprom@51 { + compatible = "atmel,24c64"; + reg = <0x51>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + reset-gpio = <&gpio0 ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>; + + i2c8mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c8mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&i2c9 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; + + eeprom@51 { + compatible = "atmel,24c128"; + reg = <0x51>; + }; + + eeprom@53 { + compatible = "atmel,24c128"; + reg = <0x53>; + }; + + eeprom@52 { + compatible = "atmel,24c128"; + reg = <0x52>; + }; +}; + +&i2c10 { + status = "okay"; + + eeprom@51 { + compatible = "atmel,24c128"; + reg = <0x51>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; + + eeprom@53 { + compatible = "atmel,24c128"; + reg = <0x53>; + }; + + eeprom@52 { + compatible = "atmel,24c128"; + reg = <0x52>; + }; +}; + +&i2c11 { + status = "okay"; + + eeprom@51 { + compatible = "atmel,24c128"; + reg = <0x51>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; + + eeprom@53 { + compatible = "atmel,24c128"; + reg = <0x53>; + }; + + eeprom@52 { + compatible = "atmel,24c128"; + reg = <0x52>; + }; +}; + +&i2c12 { + status = "okay"; + + tpm@2e { + compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + memory-region = <&event_log>; + }; +}; + +&i2c13 { + status = "okay"; + + eeprom@51 { + compatible = "atmel,24c128"; + reg = <0x51>; + }; + + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + }; + + eeprom@53 { + compatible = "atmel,24c128"; + reg = <0x53>; + }; + + eeprom@52 { + compatible = "atmel,24c128"; + reg = <0x52>; + }; +}; + +&i2c14 { + multi-master; + status = "okay"; + + lcd-controller@62 { + compatible = "ibm,op-panel"; + reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>; + }; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + idle-state = <1>; + + i2c14mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c64"; + reg = <0x50>; + }; + }; + + i2c14mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@51 { + compatible = "atmel,24c32"; + reg = <0x51>; + }; + }; + + i2c14mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + + led-controller@60 { + compatible = "nxp,pca9551"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "front-sys-id0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "front-check-log0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "front-enc-fault1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "front-sys-pwron0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + }; + + i2c14mux0chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + pwm@52 { + compatible = "maxim,max31785a"; + reg = <0x52>; + #address-cells = <1>; + #size-cells = <0>; + }; + + led-controller@60 { + compatible = "nxp,pca9552"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + + led@0 { + reg = <0>; + default-state = "keep"; + label = "nvme0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@1 { + reg = <1>; + default-state = "keep"; + label = "nvme1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@2 { + reg = <2>; + default-state = "keep"; + label = "nvme2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@3 { + reg = <3>; + default-state = "keep"; + label = "nvme3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@4 { + reg = <4>; + default-state = "keep"; + label = "nvme4"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@5 { + reg = <5>; + default-state = "keep"; + label = "nvme5"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@6 { + reg = <6>; + default-state = "keep"; + label = "nvme6"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@7 { + reg = <7>; + default-state = "keep"; + label = "nvme7"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@8 { + reg = <8>; + default-state = "keep"; + label = "nvme8"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@9 { + reg = <9>; + default-state = "keep"; + label = "nvme9"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@10 { + reg = <10>; + default-state = "keep"; + label = "fan0"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@11 { + reg = <11>; + default-state = "keep"; + label = "fan1"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@12 { + reg = <12>; + default-state = "keep"; + label = "fan2"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + + led@13 { + reg = <13>; + default-state = "keep"; + label = "fan3"; + retain-state-shutdown; + type = <PCA955X_TYPE_LED>; + }; + }; + + pca0: led-controller@61 { + compatible = "nxp,pca9552"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x61>; + gpio-controller; + #gpio-cells = <2>; + + gpio-line-names = + "","","","", + "","","","", + "","","","", + "presence-fan3", + "presence-fan2", + "presence-fan1", + "presence-fan0"; + }; + }; + }; + + i2c-mux@71 { + compatible = "nxp,pca9546"; + reg = <0x71>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c14mux1chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + }; + + i2c14mux1chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + }; + + i2c14mux1chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + }; + + i2c14mux1chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + }; + }; +}; + +&i2c15 { + status = "okay"; + + i2c-mux@70 { + compatible = "nxp,pca9546"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c15mux0chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux0chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux0chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux0chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + }; + + i2c-mux@71 { + compatible = "nxp,pca9546"; + reg = <0x71>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c15mux1chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux1chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux1chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux1chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + }; + + i2c-mux@72 { + compatible = "nxp,pca9546"; + reg = <0x72>; + #address-cells = <1>; + #size-cells = <0>; + i2c-mux-idle-disconnect; + + i2c15mux2chn0: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux2chn1: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@53 { + compatible = "atmel,24c64"; + reg = <0x53>; + }; + }; + + i2c15mux2chn2: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c15mux2chn3: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&uhci { + status = "okay"; +}; + +&emmc_controller { + status = "okay"; +}; + +&pinctrl_emmc_default { + bias-disable; +}; + +&emmc { + status = "okay"; + clk-phase-mmc-hs200 = <210>, <228>; +}; + +&ibt { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&vuart1 { + status = "okay"; +}; + +&vuart2 { + status = "okay"; +}; + +&lpc_ctrl { + status = "okay"; + memory-region = <&flash_memory>; +}; + +&mac2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii3_default>; + clocks = <&syscon ASPEED_CLK_GATE_MAC3CLK>, + <&syscon ASPEED_CLK_MAC3RCLK>; + clock-names = "MACCLK", "RCLK"; + use-ncsi; +}; + +&mac3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii4_default>; + clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>, + <&syscon ASPEED_CLK_MAC4RCLK>; + clock-names = "MACCLK", "RCLK"; + use-ncsi; +}; + +&wdt1 { + aspeed,reset-type = "none"; + aspeed,external-signal; + aspeed,ext-push-pull; + aspeed,ext-active-high; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdtrst1_default>; +}; + +&wdt2 { + status = "okay"; +}; + +&kcs2 { + status = "okay"; + aspeed,lpc-io-reg = <0xca8 0xcac>; +}; + +&kcs3 { + status = "okay"; + aspeed,lpc-io-reg = <0xca2>; + aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>; +}; + +&fsi_hub0 { + cfam@4,0 { /* DCM2_C0 */ + reg = <4 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <4>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam4_i2c0: i2c-bus@0 { + reg = <0>; /* OM01 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom500: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo500: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c1: i2c-bus@1 { + reg = <1>; /* OM23 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom501: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo501: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom510: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo510: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom511: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo511: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c12: i2c-bus@c { + reg = <12>; /* OP4A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom512: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo512: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c13: i2c-bus@d { + reg = <13>; /* OP4B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom513: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo513: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom514: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo514: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam4_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom515: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo515: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam4_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam4_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam4_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam4_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; + + cfam@5,0 { /* DCM2_C1 */ + reg = <5 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <5>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam5_i2c2: i2c-bus@2 { + reg = <2>; /* OM45 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom602: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo602: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c3: i2c-bus@3 { + reg = <3>; /* OM67 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom603: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo603: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom610: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo610: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom611: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo611: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom614: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo614: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom615: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo615: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c16: i2c-bus@10 { + reg = <16>; /* OP6A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom616: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo616: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam5_i2c17: i2c-bus@11 { + reg = <17>; /* OP6B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom617: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo617: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam5_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam5_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam5_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam5_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; + + cfam@6,0 { /* DCM3_C0 */ + reg = <6 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <6>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam6_i2c0: i2c-bus@0 { + reg = <0>; /* OM01 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom700: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo700: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c1: i2c-bus@1 { + reg = <1>; /* OM23 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom701: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo701: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom710: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo710: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom711: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo711: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c12: i2c-bus@c { + reg = <12>; /* OP4A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom712: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo712: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c13: i2c-bus@d { + reg = <13>; /* OP4B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom713: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo713: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom714: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo714: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam6_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom715: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo715: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam6_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam6_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam6_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam6_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; + + cfam@7,0 { /* DCM3_C1 */ + reg = <7 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <7>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam7_i2c2: i2c-bus@2 { + reg = <2>; /* OM45 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom802: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo802: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c3: i2c-bus@3 { + reg = <3>; /* OM67 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom803: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo803: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom810: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo810: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom811: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo811: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom814: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo814: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom815: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo815: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c16: i2c-bus@10 { + reg = <16>; /* OP6A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom816: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo816: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam7_i2c17: i2c-bus@11 { + reg = <17>; /* OP6B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom817: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo817: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam7_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam7_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam7_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam7_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; +}; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts index 5cb0094e21e0..0776b72c2199 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-rainier.dts @@ -1722,11 +1722,6 @@ status = "okay"; }; -&xdma { - status = "okay"; - memory-region = <&vga_memory>; -}; - &kcs2 { status = "okay"; aspeed,lpc-io-reg = <0xca8 0xcac>; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts index dcbc16308ab5..f3efecc7eb8d 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts @@ -1138,7 +1138,7 @@ reg = <6>; temperature-sensor@4c { - compatible = "ti,tmp423"; + compatible = "ti,tmp432"; reg = <0x4c>; }; }; @@ -1599,7 +1599,7 @@ reg = <6>; temperature-sensor@4c { - compatible = "ti,tmp423"; + compatible = "ti,tmp432"; reg = <0x4c>; }; }; @@ -1615,7 +1615,7 @@ }; temperature-sensor@4c { - compatible = "ti,tmp423"; + compatible = "ti,tmp432"; reg = <0x4c>; }; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts index 0dea014e4f30..78a5656ef75d 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-fp5280g2.dts @@ -814,10 +814,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &wdt1 { aspeed,reset-type = "none"; aspeed,external-signal; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts index 5a98a19f445e..7a78c34cff40 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-inspur-on5263m5.dts @@ -123,10 +123,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &pwm_tacho { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts index d5b7d28cda88..da55e7b29fac 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-intel-s2600wf.dts @@ -118,10 +118,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &pwm_tacho { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts index c0847636f20b..370738572a55 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-lanyang.dts @@ -263,10 +263,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &gpio { pin_gpio_b0 { gpio-hog; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts index ac0d666ca10e..b1d0ff85d397 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-nicole.dts @@ -284,10 +284,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &ibt { status = "okay"; }; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts index 893e621ecab1..24df24ad9c80 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-romulus.dts @@ -289,10 +289,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &pwm_tacho { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts index bbf864f84d37..a0e8c97e944a 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-swift.dts @@ -938,10 +938,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &wdt1 { aspeed,reset-type = "none"; aspeed,external-signal; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts index 213023bc5aec..b31eb8e58c6b 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-tacoma.dts @@ -870,11 +870,6 @@ <&pinctrl_lsirq_default>; }; -&xdma { - status = "okay"; - memory-region = <&vga_memory>; -}; - &kcs2 { status = "okay"; aspeed,lpc-io-reg = <0xca8 0xcac>; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts index a20a532fc280..8b1e82c8cdfe 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-witherspoon.dts @@ -661,10 +661,6 @@ memory-region = <&gfx_memory>; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &wdt1 { aspeed,reset-type = "none"; aspeed,external-signal; @@ -696,9 +692,4 @@ memory-region = <&video_engine_memory>; }; -&xdma { - status = "okay"; - memory-region = <&vga_memory>; -}; - #include "ibm-power9-dual.dtsi" diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts index 3d2d8db73ca6..9904f0a58cfa 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-opp-zaius.dts @@ -466,8 +466,6 @@ }; &pinctrl { - aspeed,external-nodes = <&gfx &lhc>; - pinctrl_gpioh_unbiased: gpioi_unbiased { pins = "A8", "C7", "B7", "A7", "D7", "B6", "A6", "E7"; bias-disable; diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts index 50f3c6a5c0c8..b961dff388d1 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-supermicro-x11spi.dts @@ -123,10 +123,6 @@ status = "okay"; }; -&pinctrl { - aspeed,external-nodes = <&gfx &lhc>; -}; - &pwm_tacho { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi index c669ec202085..78c967812492 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi @@ -122,8 +122,8 @@ reg = <0x1e6c0080 0x80>; }; - cvic: copro-interrupt-controller@1e6c2000 { - compatible = "aspeed,ast2400-cvic", "aspeed-cvic"; + cvic: interrupt-controller@1e6c2000 { + compatible = "aspeed,ast2400-cvic", "aspeed,cvic"; valid-sources = <0x7fffffff>; reg = <0x1e6c2000 0x80>; }; @@ -230,6 +230,9 @@ sram: sram@1e720000 { compatible = "mmio-sram"; reg = <0x1e720000 0x8000>; // 32K + ranges; + #address-cells = <1>; + #size-cells = <1>; }; video: video@1e700000 { diff --git a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi index 6e05cbcce49c..57a699a7c149 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi @@ -139,8 +139,8 @@ reg = <0x1e6c0080 0x80>; }; - cvic: copro-interrupt-controller@1e6c2000 { - compatible = "aspeed,ast2500-cvic", "aspeed-cvic"; + cvic: interrupt-controller@1e6c2000 { + compatible = "aspeed,ast2500-cvic", "aspeed,cvic"; valid-sources = <0xffffffff>; copro-sw-interrupts = <1>; reg = <0x1e6c2000 0x80>; @@ -281,17 +281,6 @@ interrupts = <0x19>; }; - xdma: xdma@1e6e7000 { - compatible = "aspeed,ast2500-xdma"; - reg = <0x1e6e7000 0x100>; - clocks = <&syscon ASPEED_CLK_GATE_BCLK>; - resets = <&syscon ASPEED_RESET_XDMA>; - interrupts-extended = <&vic 6>, <&scu_ic ASPEED_AST2500_SCU_IC_PCIE_RESET_LO_TO_HI>; - aspeed,pcie-device = "bmc"; - aspeed,scu = <&syscon>; - status = "disabled"; - }; - adc: adc@1e6e9000 { compatible = "aspeed,ast2500-adc"; reg = <0x1e6e9000 0xb0>; @@ -314,6 +303,9 @@ sram: sram@1e720000 { compatible = "mmio-sram"; reg = <0x1e720000 0x9000>; // 36K + ranges; + #address-cells = <1>; + #size-cells = <1>; }; sdmmc: sd-controller@1e740000 { diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi index 0c00882f111a..8ed715bd53aa 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi @@ -231,41 +231,33 @@ resets = <&syscon ASPEED_RESET_MII>; }; - mac0: ftgmac@1e660000 { + mac0: ethernet@1e660000 { compatible = "aspeed,ast2600-mac", "faraday,ftgmac100"; reg = <0x1e660000 0x180>; - #address-cells = <1>; - #size-cells = <0>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>; status = "disabled"; }; - mac1: ftgmac@1e680000 { + mac1: ethernet@1e680000 { compatible = "aspeed,ast2600-mac", "faraday,ftgmac100"; reg = <0x1e680000 0x180>; - #address-cells = <1>; - #size-cells = <0>; interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; clocks = <&syscon ASPEED_CLK_GATE_MAC2CLK>; status = "disabled"; }; - mac2: ftgmac@1e670000 { + mac2: ethernet@1e670000 { compatible = "aspeed,ast2600-mac", "faraday,ftgmac100"; reg = <0x1e670000 0x180>; - #address-cells = <1>; - #size-cells = <0>; interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; clocks = <&syscon ASPEED_CLK_GATE_MAC3CLK>; status = "disabled"; }; - mac3: ftgmac@1e690000 { + mac3: ethernet@1e690000 { compatible = "aspeed,ast2600-mac", "faraday,ftgmac100"; reg = <0x1e690000 0x180>; - #address-cells = <1>; - #size-cells = <0>; interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>; status = "disabled"; @@ -398,19 +390,6 @@ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; }; - xdma: xdma@1e6e7000 { - compatible = "aspeed,ast2600-xdma"; - reg = <0x1e6e7000 0x100>; - clocks = <&syscon ASPEED_CLK_GATE_BCLK>; - resets = <&syscon ASPEED_RESET_DEV_XDMA>, <&syscon ASPEED_RESET_RC_XDMA>; - reset-names = "device", "root-complex"; - interrupts-extended = <&gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, - <&scu_ic0 ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>; - aspeed,pcie-device = "bmc"; - aspeed,scu = <&syscon>; - status = "disabled"; - }; - adc0: adc@1e6e9000 { compatible = "aspeed,ast2600-adc0"; reg = <0x1e6e9000 0x100>; diff --git a/arch/arm/boot/dts/aspeed/ibm-power11-quad.dtsi b/arch/arm/boot/dts/aspeed/ibm-power11-quad.dtsi new file mode 100644 index 000000000000..68c941a194b6 --- /dev/null +++ b/arch/arm/boot/dts/aspeed/ibm-power11-quad.dtsi @@ -0,0 +1,1539 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright 2024 IBM Corp. + +/ { + aliases { + i2c100 = &cfam0_i2c0; + i2c101 = &cfam0_i2c1; + i2c110 = &cfam0_i2c10; + i2c111 = &cfam0_i2c11; + i2c112 = &cfam0_i2c12; + i2c113 = &cfam0_i2c13; + i2c114 = &cfam0_i2c14; + i2c115 = &cfam0_i2c15; + i2c202 = &cfam1_i2c2; + i2c203 = &cfam1_i2c3; + i2c210 = &cfam1_i2c10; + i2c211 = &cfam1_i2c11; + i2c214 = &cfam1_i2c14; + i2c215 = &cfam1_i2c15; + i2c216 = &cfam1_i2c16; + i2c217 = &cfam1_i2c17; + i2c300 = &cfam2_i2c0; + i2c301 = &cfam2_i2c1; + i2c310 = &cfam2_i2c10; + i2c311 = &cfam2_i2c11; + i2c312 = &cfam2_i2c12; + i2c313 = &cfam2_i2c13; + i2c314 = &cfam2_i2c14; + i2c315 = &cfam2_i2c15; + i2c402 = &cfam3_i2c2; + i2c403 = &cfam3_i2c3; + i2c410 = &cfam3_i2c10; + i2c411 = &cfam3_i2c11; + i2c414 = &cfam3_i2c14; + i2c415 = &cfam3_i2c15; + i2c416 = &cfam3_i2c16; + i2c417 = &cfam3_i2c17; + + sbefifo100 = &sbefifo100; + sbefifo101 = &sbefifo101; + sbefifo110 = &sbefifo110; + sbefifo111 = &sbefifo111; + sbefifo112 = &sbefifo112; + sbefifo113 = &sbefifo113; + sbefifo114 = &sbefifo114; + sbefifo115 = &sbefifo115; + sbefifo202 = &sbefifo202; + sbefifo203 = &sbefifo203; + sbefifo210 = &sbefifo210; + sbefifo211 = &sbefifo211; + sbefifo214 = &sbefifo214; + sbefifo215 = &sbefifo215; + sbefifo216 = &sbefifo216; + sbefifo217 = &sbefifo217; + sbefifo300 = &sbefifo300; + sbefifo301 = &sbefifo301; + sbefifo310 = &sbefifo310; + sbefifo311 = &sbefifo311; + sbefifo312 = &sbefifo312; + sbefifo313 = &sbefifo313; + sbefifo314 = &sbefifo314; + sbefifo315 = &sbefifo315; + sbefifo402 = &sbefifo402; + sbefifo403 = &sbefifo403; + sbefifo410 = &sbefifo410; + sbefifo411 = &sbefifo411; + sbefifo414 = &sbefifo414; + sbefifo415 = &sbefifo415; + sbefifo416 = &sbefifo416; + sbefifo417 = &sbefifo417; + + scom100 = &scom100; + scom101 = &scom101; + scom110 = &scom110; + scom111 = &scom111; + scom112 = &scom112; + scom113 = &scom113; + scom114 = &scom114; + scom115 = &scom115; + scom202 = &scom202; + scom203 = &scom203; + scom210 = &scom210; + scom211 = &scom211; + scom214 = &scom214; + scom215 = &scom215; + scom216 = &scom216; + scom217 = &scom217; + scom300 = &scom300; + scom301 = &scom301; + scom310 = &scom310; + scom311 = &scom311; + scom312 = &scom312; + scom313 = &scom313; + scom314 = &scom314; + scom315 = &scom315; + scom402 = &scom402; + scom403 = &scom403; + scom410 = &scom410; + scom411 = &scom411; + scom414 = &scom414; + scom415 = &scom415; + scom416 = &scom416; + scom417 = &scom417; + + spi10 = &cfam0_spi0; + spi11 = &cfam0_spi1; + spi12 = &cfam0_spi2; + spi13 = &cfam0_spi3; + spi20 = &cfam1_spi0; + spi21 = &cfam1_spi1; + spi22 = &cfam1_spi2; + spi23 = &cfam1_spi3; + spi30 = &cfam2_spi0; + spi31 = &cfam2_spi1; + spi32 = &cfam2_spi2; + spi33 = &cfam2_spi3; + spi40 = &cfam3_spi0; + spi41 = &cfam3_spi1; + spi42 = &cfam3_spi2; + spi43 = &cfam3_spi3; + }; +}; + +&fsim0 { + #address-cells = <2>; + #size-cells = <0>; + status = "okay"; + bus-frequency = <100000000>; + cfam-reset-gpios = <&gpio0 ASPEED_GPIO(Q, 0) GPIO_ACTIVE_HIGH>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam0_i2c0: i2c-bus@0 { + reg = <0>; /* OMI01 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom100: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo100: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c1: i2c-bus@1 { + reg = <1>; /* OMI23 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom101: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo101: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom110: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo110: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom111: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo111: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c12: i2c-bus@c { + reg = <12>; /* OP4A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom112: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo112: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c13: i2c-bus@d { + reg = <13>; /* OP4B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom113: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo113: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom114: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo114: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam0_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom115: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo115: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam0_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam0_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam0_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam0_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi_hub0: fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + }; + }; +}; + +&fsi_hub0 { + cfam@1,0 { + reg = <1 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <1>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam1_i2c2: i2c-bus@2 { + reg = <2>; /* OMI45 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom202: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo202: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c3: i2c-bus@3 { + reg = <3>; /* OMI67 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom203: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo203: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom210: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo210: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom211: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo211: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom214: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo214: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom215: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo215: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c16: i2c-bus@10 { + reg = <16>; /* OP6A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom216: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo216: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam1_i2c17: i2c-bus@11 { + reg = <17>; /* OP6B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom217: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo217: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam1_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam1_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam1_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam1_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; + + cfam@2,0 { + reg = <2 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <2>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam2_i2c0: i2c-bus@0 { + reg = <0>; /* OM01 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom300: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo300: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c1: i2c-bus@1 { + reg = <1>; /* OM23 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom301: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo301: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom310: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo310: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom311: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo311: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c12: i2c-bus@c { + reg = <12>; /* OP4A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom312: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo312: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c13: i2c-bus@d { + reg = <13>; /* OP4B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom313: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo313: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom314: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo314: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam2_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom315: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo315: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam2_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam2_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam2_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam2_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; + + cfam@3,0 { + reg = <3 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <3>; + + scom@1000 { + compatible = "ibm,p9-scom"; + reg = <0x1000 0x400>; + }; + + i2c@1800 { + compatible = "ibm,i2c-fsi"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam3_i2c2: i2c-bus@2 { + reg = <2>; /* OM45 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom402: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo402: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c3: i2c-bus@3 { + reg = <3>; /* OM67 */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom403: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo403: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c10: i2c-bus@a { + reg = <10>; /* OP3A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom410: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo410: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c11: i2c-bus@b { + reg = <11>; /* OP3B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom411: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo411: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c14: i2c-bus@e { + reg = <14>; /* OP5A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom414: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo414: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c15: i2c-bus@f { + reg = <15>; /* OP5B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom415: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo415: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c16: i2c-bus@10 { + reg = <16>; /* OP6A */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom416: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo416: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + + cfam3_i2c17: i2c-bus@11 { + reg = <17>; /* OP6B */ + #address-cells = <1>; + #size-cells = <0>; + + fsi@20 { + compatible = "ibm,i2cr-fsi-master"; + reg = <0x20>; + #address-cells = <2>; + #size-cells = <0>; + + cfam@0,0 { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + chip-id = <0>; + + scom417: scom@1000 { + compatible = "ibm,i2cr-scom"; + reg = <0x1000 0x400>; + }; + + sbefifo417: sbefifo@2400 { + compatible = "ibm,odyssey-sbefifo"; + reg = <0x2400 0x400>; + }; + }; + }; + }; + }; + + fsi2spi@1c00 { + compatible = "ibm,fsi2spi"; + reg = <0x1c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + cfam3_spi0: spi@0 { + compatible = "ibm,spi-fsi"; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam3_spi1: spi@20 { + compatible = "ibm,spi-fsi"; + reg = <0x20>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam3_spi2: spi@40 { + compatible = "ibm,spi-fsi"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + + cfam3_spi3: spi@60 { + compatible = "ibm,spi-fsi"; + reg = <0x60>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom@0 { + compatible = "atmel,at25"; + reg = <0>; + address-width = <24>; + pagesize = <256>; + size = <0x80000>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sbefifo@2400 { + compatible = "ibm,p9-sbefifo"; + reg = <0x2400 0x400>; + + occ { + compatible = "ibm,p10-occ"; + + hwmon { + compatible = "ibm,p10-occ-hwmon"; + ibm,no-poll-on-init; + }; + }; + }; + + fsi@3400 { + compatible = "ibm,p9-fsi-controller"; + reg = <0x3400 0x400>; + #address-cells = <2>; + #size-cells = <0>; + no-scan-on-init; + }; + }; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts b/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts index 8789fae178bf..4f8ddc1b3ab7 100644 --- a/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts +++ b/arch/arm/boot/dts/broadcom/bcm21664-garnet.dts @@ -11,6 +11,10 @@ model = "BCM21664 Garnet board"; compatible = "brcm,bcm21664-garnet", "brcm,bcm21664"; + chosen { + bootargs = "console=ttyS0,115200n8"; + }; + memory@80000000 { device_type = "memory"; reg = <0x80000000 0x40000000>; /* 1 GB */ diff --git a/arch/arm/boot/dts/broadcom/bcm21664.dtsi b/arch/arm/boot/dts/broadcom/bcm21664.dtsi index fa73600e883e..f0d0300079b6 100644 --- a/arch/arm/boot/dts/broadcom/bcm21664.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm21664.dtsi @@ -1,21 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (C) 2014 Broadcom Corporation -#include <dt-bindings/clock/bcm21664.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> -#include <dt-bindings/interrupt-controller/irq.h> +#include "bcm2166x-common.dtsi" / { - #address-cells = <1>; - #size-cells = <1>; - model = "BCM21664 SoC"; - compatible = "brcm,bcm21664"; interrupt-parent = <&gic>; - chosen { - bootargs = "console=ttyS0,115200n8"; - }; - cpus { #address-cells = <1>; #size-cells = <0>; @@ -34,312 +24,46 @@ reg = <1>; }; }; +}; - gic: interrupt-controller@3ff00100 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0x3ff01000 0x1000>, - <0x3ff00100 0x100>; - }; - - smc@3404e000 { - compatible = "brcm,bcm21664-smc", "brcm,kona-smc"; - reg = <0x3404e000 0x400>; /* 1 KiB in SRAM */ - }; - - uartb: serial@3e000000 { - compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - reg = <0x3e000000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>; - interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uartb2: serial@3e001000 { - compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - reg = <0x3e001000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>; - interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uartb3: serial@3e002000 { - compatible = "brcm,bcm21664-dw-apb-uart", "snps,dw-apb-uart"; - reg = <0x3e002000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>; - interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - L2: cache-controller@3ff20000 { - compatible = "arm,pl310-cache"; - reg = <0x3ff20000 0x1000>; - cache-unified; - cache-level = <2>; - }; - - brcm,resetmgr@35001f00 { - compatible = "brcm,bcm21664-resetmgr"; - reg = <0x35001f00 0x24>; - }; - - timer@35006000 { - compatible = "brcm,kona-timer"; - reg = <0x35006000 0x1c>; - interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&aon_ccu BCM21664_AON_CCU_HUB_TIMER>; - }; - - gpio: gpio@35003000 { - compatible = "brcm,bcm21664-gpio", "brcm,kona-gpio"; - reg = <0x35003000 0x524>; - interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; - #gpio-cells = <2>; - #interrupt-cells = <2>; - gpio-controller; - interrupt-controller; - }; - - sdio1: mmc@3f180000 { - compatible = "brcm,kona-sdhci"; - reg = <0x3f180000 0x801c>; - interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO1>; - status = "disabled"; - }; - - sdio2: mmc@3f190000 { - compatible = "brcm,kona-sdhci"; - reg = <0x3f190000 0x801c>; - interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO2>; - status = "disabled"; - }; - - sdio3: mmc@3f1a0000 { - compatible = "brcm,kona-sdhci"; - reg = <0x3f1a0000 0x801c>; - interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO3>; - status = "disabled"; - }; - - sdio4: mmc@3f1b0000 { - compatible = "brcm,kona-sdhci"; - reg = <0x3f1b0000 0x801c>; - interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO4>; - status = "disabled"; - }; - - bsc1: i2c@3e016000 { - compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; - reg = <0x3e016000 0x70>; - interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC1>; - status = "disabled"; - }; - - bsc2: i2c@3e017000 { - compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; - reg = <0x3e017000 0x70>; - interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC2>; - status = "disabled"; - }; - - bsc3: i2c@3e018000 { - compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; - reg = <0x3e018000 0x70>; - interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC3>; - status = "disabled"; - }; - - bsc4: i2c@3e01c000 { - compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; - reg = <0x3e01c000 0x70>; - interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC4>; - status = "disabled"; - }; - - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* - * Fixed clocks are defined before CCUs whose - * clocks may depend on them. - */ - - ref_32k_clk: ref_32k { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - }; - - bbl_32k_clk: bbl_32k { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - }; - - ref_13m_clk: ref_13m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <13000000>; - }; - - var_13m_clk: var_13m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <13000000>; - }; - - dft_19_5m_clk: dft_19_5m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <19500000>; - }; - - ref_crystal_clk: ref_crystal { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <26000000>; - }; - - ref_52m_clk: ref_52m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - var_52m_clk: var_52m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - usb_otg_ahb_clk: usb_otg_ahb { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - ref_96m_clk: ref_96m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <96000000>; - }; - - var_96m_clk: var_96m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <96000000>; - }; - - ref_104m_clk: ref_104m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <104000000>; - }; - - var_104m_clk: var_104m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <104000000>; - }; - - ref_156m_clk: ref_156m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <156000000>; +&apps { + gic: interrupt-controller@1c01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x01c01000 0x1000>, + <0x01c00100 0x100>; }; - var_156m_clk: var_156m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <156000000>; + L2: cache-controller@1c20000 { + compatible = "arm,pl310-cache"; + reg = <0x01c20000 0x1000>; + cache-unified; + cache-level = <2>; }; +}; - root_ccu: root_ccu@35001000 { - compatible = "brcm,bcm21664-root-ccu"; - reg = <0x35001000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "frac_1m"; - }; +&bsc1 { + compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; +}; - aon_ccu: aon_ccu@35002000 { - compatible = "brcm,bcm21664-aon-ccu"; - reg = <0x35002000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "hub_timer"; - }; +&bsc2 { + compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; +}; - master_ccu: master_ccu@3f001000 { - compatible = "brcm,bcm21664-master-ccu"; - reg = <0x3f001000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "sdio1", - "sdio2", - "sdio3", - "sdio4", - "sdio1_sleep", - "sdio2_sleep", - "sdio3_sleep", - "sdio4_sleep"; - }; +&bsc3 { + compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; +}; - slave_ccu: slave_ccu@3e011000 { - compatible = "brcm,bcm21664-slave-ccu"; - reg = <0x3e011000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "uartb", - "uartb2", - "uartb3", - "bsc1", - "bsc2", - "bsc3", - "bsc4"; - }; - }; +&bsc4 { + compatible = "brcm,bcm21664-i2c", "brcm,kona-i2c"; +}; - usbotg: usb@3f120000 { - compatible = "snps,dwc2"; - reg = <0x3f120000 0x10000>; - interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&usb_otg_ahb_clk>; - clock-names = "otg"; - phys = <&usbphy>; - phy-names = "usb2-phy"; - status = "disabled"; - }; +&gpio { + compatible = "brcm,bcm21664-gpio", "brcm,kona-gpio"; +}; - usbphy: usb-phy@3f130000 { - compatible = "brcm,kona-usb2-phy"; - reg = <0x3f130000 0x28>; - #phy-cells = <0>; - status = "disabled"; - }; +&smc { + compatible = "brcm,bcm21664-smc", "brcm,kona-smc"; }; diff --git a/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi new file mode 100644 index 000000000000..87180b7fd695 --- /dev/null +++ b/arch/arm/boot/dts/broadcom/bcm2166x-common.dtsi @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Common device tree for components shared between the BCM21664 and BCM23550 + * SoCs. + * + * Copyright (C) 2016 Broadcom + */ + +/dts-v1/; + +#include <dt-bindings/clock/bcm21664.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + #address-cells = <1>; + #size-cells = <1>; + + /* Hub bus */ + hub: hub-bus@34000000 { + compatible = "simple-bus"; + ranges = <0 0x34000000 0x102f83ac>; + #address-cells = <1>; + #size-cells = <1>; + + smc: smc@4e000 { + /* Compatible filled by SoC DTSI */ + reg = <0x0004e000 0x400>; /* 1 KiB in SRAM */ + }; + + resetmgr: reset-controller@1001f00 { + compatible = "brcm,bcm21664-resetmgr"; + reg = <0x01001f00 0x24>; + }; + + gpio: gpio@1003000 { + /* Compatible filled by SoC DTSI */ + reg = <0x01003000 0x524>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + }; + + timer@1006000 { + compatible = "brcm,kona-timer"; + reg = <0x01006000 0x1c>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&aon_ccu BCM21664_AON_CCU_HUB_TIMER>; + }; + }; + + /* Slaves bus */ + slaves: slaves-bus@3e000000 { + compatible = "simple-bus"; + ranges = <0 0x3e000000 0x0001c070>; + #address-cells = <1>; + #size-cells = <1>; + + uartb: serial@0 { + compatible = "snps,dw-apb-uart"; + reg = <0x00000000 0x118>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uartb2: serial@1000 { + compatible = "snps,dw-apb-uart"; + reg = <0x00001000 0x118>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>; + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uartb3: serial@2000 { + compatible = "snps,dw-apb-uart"; + reg = <0x00002000 0x118>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>; + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + bsc1: i2c@16000 { + /* Compatible filled by SoC DTSI */ + reg = <0x00016000 0x70>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC1>; + status = "disabled"; + }; + + bsc2: i2c@17000 { + /* Compatible filled by SoC DTSI */ + reg = <0x00017000 0x70>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC2>; + status = "disabled"; + }; + + bsc3: i2c@18000 { + /* Compatible filled by SoC DTSI */ + reg = <0x00018000 0x70>; + interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC3>; + status = "disabled"; + }; + + bsc4: i2c@1c000 { + /* Compatible filled by SoC DTSI */ + reg = <0x0001c000 0x70>; + interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC4>; + status = "disabled"; + }; + }; + + /* Apps bus */ + apps: apps-bus@3e300000 { + compatible = "simple-bus"; + ranges = <0 0x3e300000 0x01c02000>; + #address-cells = <1>; + #size-cells = <1>; + + usbotg: usb@e20000 { + compatible = "snps,dwc2"; + reg = <0x00e20000 0x10000>; + interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&usb_otg_ahb_clk>; + clock-names = "otg"; + phys = <&usbphy>; + phy-names = "usb2-phy"; + status = "disabled"; + }; + + usbphy: usb-phy@e30000 { + compatible = "brcm,kona-usb2-phy"; + reg = <0x00e30000 0x28>; + #phy-cells = <0>; + status = "disabled"; + }; + + sdio1: mmc@e80000 { + compatible = "brcm,kona-sdhci"; + reg = <0x00e80000 0x801c>; + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO1>; + status = "disabled"; + }; + + sdio2: mmc@e90000 { + compatible = "brcm,kona-sdhci"; + reg = <0x00e90000 0x801c>; + interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO2>; + status = "disabled"; + }; + + sdio3: mmc@ea0000 { + compatible = "brcm,kona-sdhci"; + reg = <0x00ea0000 0x801c>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO3>; + status = "disabled"; + }; + + sdio4: mmc@eb0000 { + compatible = "brcm,kona-sdhci"; + reg = <0x00eb0000 0x801c>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO4>; + status = "disabled"; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* + * Fixed clocks are defined before CCUs whose + * clocks may depend on them. + */ + + ref_32k_clk: ref_32k { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + bbl_32k_clk: bbl_32k { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + ref_13m_clk: ref_13m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <13000000>; + }; + + var_13m_clk: var_13m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <13000000>; + }; + + dft_19_5m_clk: dft_19_5m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <19500000>; + }; + + ref_crystal_clk: ref_crystal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + }; + + ref_52m_clk: ref_52m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <52000000>; + }; + + var_52m_clk: var_52m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <52000000>; + }; + + usb_otg_ahb_clk: usb_otg_ahb { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <52000000>; + }; + + ref_96m_clk: ref_96m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <96000000>; + }; + + var_96m_clk: var_96m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <96000000>; + }; + + ref_104m_clk: ref_104m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <104000000>; + }; + + var_104m_clk: var_104m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <104000000>; + }; + + ref_156m_clk: ref_156m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <156000000>; + }; + + var_156m_clk: var_156m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <156000000>; + }; + + root_ccu: root_ccu@35001000 { + compatible = "brcm,bcm21664-root-ccu"; + reg = <0x35001000 0x0f00>; + #clock-cells = <1>; + clock-output-names = "frac_1m"; + }; + + aon_ccu: aon_ccu@35002000 { + compatible = "brcm,bcm21664-aon-ccu"; + reg = <0x35002000 0x0f00>; + #clock-cells = <1>; + clock-output-names = "hub_timer"; + }; + + slave_ccu: slave_ccu@3e011000 { + compatible = "brcm,bcm21664-slave-ccu"; + reg = <0x3e011000 0x0f00>; + #clock-cells = <1>; + clock-output-names = "uartb", + "uartb2", + "uartb3", + "bsc1", + "bsc2", + "bsc3", + "bsc4"; + }; + + master_ccu: master_ccu@3f001000 { + compatible = "brcm,bcm21664-master-ccu"; + reg = <0x3f001000 0x0f00>; + #clock-cells = <1>; + clock-output-names = "sdio1", + "sdio2", + "sdio3", + "sdio4", + "sdio1_sleep", + "sdio2_sleep", + "sdio3_sleep", + "sdio4_sleep"; + }; + }; +}; diff --git a/arch/arm/boot/dts/broadcom/bcm23550.dtsi b/arch/arm/boot/dts/broadcom/bcm23550.dtsi index 50ebe93d6bd0..c1c69381286b 100644 --- a/arch/arm/boot/dts/broadcom/bcm23550.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm23550.dtsi @@ -1,45 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause /* - * BSD LICENSE + * Device tree for the BCM23550 SoC. * - * Copyright(c) 2016 Broadcom. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Broadcom Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016 Broadcom */ -/* BCM23550 and BCM21664 have almost identical clocks */ -#include <dt-bindings/clock/bcm21664.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> -#include <dt-bindings/interrupt-controller/irq.h> +#include "bcm2166x-common.dtsi" / { - #address-cells = <1>; - #size-cells = <1>; - model = "BCM23550 SoC"; - compatible = "brcm,bcm23550"; interrupt-parent = <&gic>; cpus { @@ -80,180 +48,9 @@ clock-frequency = <1000000000>; }; }; +}; - /* Hub bus */ - hub@34000000 { - compatible = "simple-bus"; - ranges = <0 0x34000000 0x102f83ac>; - #address-cells = <1>; - #size-cells = <1>; - - smc@4e000 { - compatible = "brcm,bcm23550-smc", "brcm,kona-smc"; - reg = <0x0004e000 0x400>; /* 1 KiB in SRAM */ - }; - - resetmgr: reset-controller@1001f00 { - compatible = "brcm,bcm21664-resetmgr"; - reg = <0x01001f00 0x24>; - }; - - gpio: gpio@1003000 { - compatible = "brcm,bcm23550-gpio", "brcm,kona-gpio"; - reg = <0x01003000 0x524>; - interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; - #gpio-cells = <2>; - #interrupt-cells = <2>; - gpio-controller; - interrupt-controller; - }; - - timer@1006000 { - compatible = "brcm,kona-timer"; - reg = <0x01006000 0x1c>; - interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&aon_ccu BCM21664_AON_CCU_HUB_TIMER>; - }; - }; - - /* Slaves bus */ - slaves@3e000000 { - compatible = "simple-bus"; - ranges = <0 0x3e000000 0x0001c070>; - #address-cells = <1>; - #size-cells = <1>; - - uartb: serial@0 { - compatible = "snps,dw-apb-uart"; - reg = <0x00000000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>; - interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uartb2: serial@1000 { - compatible = "snps,dw-apb-uart"; - reg = <0x00001000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>; - interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - uartb3: serial@2000 { - compatible = "snps,dw-apb-uart"; - reg = <0x00002000 0x118>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>; - interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; - - bsc1: i2c@16000 { - compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; - reg = <0x00016000 0x70>; - interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC1>; - status = "disabled"; - }; - - bsc2: i2c@17000 { - compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; - reg = <0x00017000 0x70>; - interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC2>; - status = "disabled"; - }; - - bsc3: i2c@18000 { - compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; - reg = <0x00018000 0x70>; - interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC3>; - status = "disabled"; - }; - - bsc4: i2c@1c000 { - compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; - reg = <0x0001c000 0x70>; - interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC4>; - status = "disabled"; - }; - }; - - /* Apps bus */ - apps@3e300000 { - compatible = "simple-bus"; - ranges = <0 0x3e300000 0x01b77000>; - #address-cells = <1>; - #size-cells = <1>; - - usbotg: usb@e20000 { - compatible = "snps,dwc2"; - reg = <0x00e20000 0x10000>; - interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&usb_otg_ahb_clk>; - clock-names = "otg"; - phys = <&usbphy>; - phy-names = "usb2-phy"; - status = "disabled"; - }; - - usbphy: usb-phy@e30000 { - compatible = "brcm,kona-usb2-phy"; - reg = <0x00e30000 0x28>; - #phy-cells = <0>; - status = "disabled"; - }; - - sdio1: mmc@e80000 { - compatible = "brcm,kona-sdhci"; - reg = <0x00e80000 0x801c>; - interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO1>; - status = "disabled"; - }; - - sdio2: mmc@e90000 { - compatible = "brcm,kona-sdhci"; - reg = <0x00e90000 0x801c>; - interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO2>; - status = "disabled"; - }; - - sdio3: mmc@ea0000 { - compatible = "brcm,kona-sdhci"; - reg = <0x00ea0000 0x801c>; - interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO3>; - status = "disabled"; - }; - - sdio4: mmc@eb0000 { - compatible = "brcm,kona-sdhci"; - reg = <0x00eb0000 0x801c>; - interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO4>; - status = "disabled"; - }; - +&apps { cdc: cdc@1b0e000 { compatible = "brcm,bcm23550-cdc"; reg = <0x01b0e000 0x78>; @@ -267,147 +64,28 @@ reg = <0x01b21000 0x1000>, <0x01b22000 0x1000>; }; - }; - - clocks { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* - * Fixed clocks are defined before CCUs whose - * clocks may depend on them. - */ - - ref_32k_clk: ref_32k { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - }; - - bbl_32k_clk: bbl_32k { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <32768>; - }; - - ref_13m_clk: ref_13m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <13000000>; - }; - - var_13m_clk: var_13m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <13000000>; - }; - - dft_19_5m_clk: dft_19_5m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <19500000>; - }; - - ref_crystal_clk: ref_crystal { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <26000000>; - }; - - ref_52m_clk: ref_52m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - var_52m_clk: var_52m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - usb_otg_ahb_clk: usb_otg_ahb { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <52000000>; - }; - - ref_96m_clk: ref_96m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <96000000>; - }; - - var_96m_clk: var_96m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <96000000>; - }; - - ref_104m_clk: ref_104m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <104000000>; - }; - - var_104m_clk: var_104m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <104000000>; - }; +}; - ref_156m_clk: ref_156m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <156000000>; - }; +&bsc1 { + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; +}; - var_156m_clk: var_156m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <156000000>; - }; +&bsc2 { + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; +}; - root_ccu: root_ccu@35001000 { - compatible = "brcm,bcm21664-root-ccu"; - reg = <0x35001000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "frac_1m"; - }; +&bsc3 { + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; +}; - aon_ccu: aon_ccu@35002000 { - compatible = "brcm,bcm21664-aon-ccu"; - reg = <0x35002000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "hub_timer"; - }; +&bsc4 { + compatible = "brcm,bcm23550-i2c", "brcm,kona-i2c"; +}; - slave_ccu: slave_ccu@3e011000 { - compatible = "brcm,bcm21664-slave-ccu"; - reg = <0x3e011000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "uartb", - "uartb2", - "uartb3", - "bsc1", - "bsc2", - "bsc3", - "bsc4"; - }; +&gpio { + compatible = "brcm,bcm23550-gpio", "brcm,kona-gpio"; +}; - master_ccu: master_ccu@3f001000 { - compatible = "brcm,bcm21664-master-ccu"; - reg = <0x3f001000 0x0f00>; - #clock-cells = <1>; - clock-output-names = "sdio1", - "sdio2", - "sdio3", - "sdio4", - "sdio1_sleep", - "sdio2_sleep", - "sdio3_sleep", - "sdio4_sleep"; - }; - }; +&smc { + compatible = "brcm,bcm23550-smc", "brcm,kona-smc"; }; diff --git a/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts index 72d26d130efa..85f54fa595aa 100644 --- a/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts +++ b/arch/arm/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts @@ -77,7 +77,7 @@ }; &hdmi { - hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>; + hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>; power-domains = <&power RPI_POWER_DOMAIN_HDMI>; status = "okay"; }; diff --git a/arch/arm/boot/dts/broadcom/bcm2837.dtsi b/arch/arm/boot/dts/broadcom/bcm2837.dtsi index 84c08b46519d..c281697142b1 100644 --- a/arch/arm/boot/dts/broadcom/bcm2837.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm2837.dtsi @@ -9,7 +9,7 @@ <0x40000000 0x40000000 0x00001000>; dma-ranges = <0xc0000000 0x00000000 0x3f000000>; - local_intc: local_intc@40000000 { + local_intc: interrupt-controller@40000000 { compatible = "brcm,bcm2836-l1-intc"; reg = <0x40000000 0x100>; interrupt-controller; diff --git a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts index 25eeacf6a248..45bd27906f29 100644 --- a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts +++ b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts @@ -215,11 +215,15 @@ reg = <0x50>; pagesize = <32>; read-only; - #address-cells = <1>; - #size-cells = <1>; - mac_address: mac-address@66 { - reg = <0x66 0x6>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_address: mac-address@66 { + reg = <0x66 0x6>; + }; }; }; }; diff --git a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi index b0854d881ac6..71a8b77b46f4 100644 --- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi @@ -55,11 +55,15 @@ reg = <0x50>; pagesize = <32>; read-only; - #address-cells = <1>; - #size-cells = <1>; - mac_address: mac-address@66 { - reg = <0x66 0x6>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_address: mac-address@66 { + reg = <0x66 0x6>; + }; }; }; }; diff --git a/arch/arm/boot/dts/cirrus/Makefile b/arch/arm/boot/dts/cirrus/Makefile index e944d3e2129d..e6015983e464 100644 --- a/arch/arm/boot/dts/cirrus/Makefile +++ b/arch/arm/boot/dts/cirrus/Makefile @@ -3,3 +3,7 @@ dtb-$(CONFIG_ARCH_CLPS711X) += \ ep7211-edb7211.dtb dtb-$(CONFIG_ARCH_CLPS711X) += \ ep7211-edb7211.dtb +dtb-$(CONFIG_ARCH_EP93XX) += \ + ep93xx-edb9302.dtb \ + ep93xx-bk3.dtb \ + ep93xx-ts7250.dtb diff --git a/arch/arm/boot/dts/cirrus/ep93xx-bk3.dts b/arch/arm/boot/dts/cirrus/ep93xx-bk3.dts new file mode 100644 index 000000000000..40bc9b2a6ba8 --- /dev/null +++ b/arch/arm/boot/dts/cirrus/ep93xx-bk3.dts @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for Liebherr controller BK3.1 based on Cirrus EP9302 SoC + */ +/dts-v1/; +#include "ep93xx.dtsi" + +/ { + model = "Liebherr controller BK3.1"; + compatible = "liebherr,bk3", "cirrus,ep9301"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + }; + + memory@0 { + device_type = "memory"; + /* should be set from ATAGS */ + reg = <0x00000000 0x02000000>, + <0x000530c0 0x01fdd000>; + }; + + leds { + compatible = "gpio-leds"; + led-0 { + label = "grled"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; + }; + + led-1 { + label = "rdled"; + gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_FAULT; + }; + }; +}; + +&ebi { + nand-controller@60000000 { + compatible = "technologic,ts7200-nand"; + reg = <0x60000000 0x8000000>; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "System"; + reg = <0x00000000 0x01e00000>; + read-only; + }; + + partition@1e00000 { + label = "Data"; + reg = <0x01e00000 0x05f20000>; + }; + + partition@7d20000 { + label = "RedBoot"; + reg = <0x07d20000 0x002e0000>; + read-only; + }; + }; + }; + }; +}; + +ð0 { + phy-handle = <&phy0>; +}; + +&i2s { + dmas = <&dma0 0 1>, <&dma0 0 2>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_on_ac97_pins>; + status = "okay"; +}; + +&gpio1 { + /* PWM */ + gpio-ranges = <&syscon 6 163 1>; +}; + +&gpio4 { + gpio-ranges = <&syscon 0 97 2>; + status = "okay"; +}; + +&gpio6 { + gpio-ranges = <&syscon 0 87 2>; + status = "okay"; +}; + +&gpio7 { + gpio-ranges = <&syscon 2 199 4>; + status = "okay"; +}; + +&mdio0 { + phy0: ethernet-phy@1 { + reg = <1>; + device_type = "ethernet-phy"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/cirrus/ep93xx-edb9302.dts b/arch/arm/boot/dts/cirrus/ep93xx-edb9302.dts new file mode 100644 index 000000000000..312b2be1c638 --- /dev/null +++ b/arch/arm/boot/dts/cirrus/ep93xx-edb9302.dts @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/* + * Device Tree file for Cirrus Logic EDB9302 board based on EP9302 SoC + */ +/dts-v1/; +#include "ep93xx.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "cirrus,edb9302", "cirrus,ep9301"; + model = "cirrus,edb9302"; + + chosen { + }; + + memory@0 { + device_type = "memory"; + /* should be set from ATAGS */ + reg = <0x0000000 0x800000>, + <0x1000000 0x800000>, + <0x4000000 0x800000>, + <0x5000000 0x800000>; + }; + + sound { + compatible = "audio-graph-card2"; + label = "EDB93XX"; + links = <&i2s_port>; + }; + + leds { + compatible = "gpio-leds"; + led-0 { + label = "grled"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; + }; + + led-1 { + label = "rdled"; + gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_FAULT; + }; + }; +}; + +&adc { + status = "okay"; +}; + +&ebi { + flash@60000000 { + compatible = "cfi-flash"; + reg = <0x60000000 0x1000000>; + bank-width = <2>; + }; +}; + +ð0 { + phy-handle = <&phy0>; +}; + +&gpio0 { + gpio-ranges = <&syscon 0 153 1>, + <&syscon 1 152 1>, + <&syscon 2 151 1>, + <&syscon 3 148 1>, + <&syscon 4 147 1>, + <&syscon 5 146 1>, + <&syscon 6 145 1>, + <&syscon 7 144 1>; +}; + +&gpio1 { + gpio-ranges = <&syscon 0 143 1>, + <&syscon 1 142 1>, + <&syscon 2 141 1>, + <&syscon 3 140 1>, + <&syscon 4 165 1>, + <&syscon 5 164 1>, + <&syscon 6 163 1>, + <&syscon 7 160 1>; +}; + +&gpio2 { + gpio-ranges = <&syscon 0 115 1>; +}; + +/* edb9302 doesn't have GPIO Port D present */ +&gpio3 { + status = "disabled"; +}; + +&gpio4 { + gpio-ranges = <&syscon 0 97 2>; +}; + +&gpio5 { + gpio-ranges = <&syscon 1 170 1>, + <&syscon 2 169 1>, + <&syscon 3 168 1>; +}; + +&gpio6 { + gpio-ranges = <&syscon 0 87 2>; +}; + +&gpio7 { + gpio-ranges = <&syscon 2 199 4>; +}; + +&i2s { + pinctrl-names = "default"; + pinctrl-0 = <&i2s_on_ac97_pins>; + status = "okay"; + i2s_port: port { + i2s_ep: endpoint { + system-clock-direction-out; + frame-master; + bitclock-master; + mclk-fs = <256>; + dai-format = "i2s"; + convert-channels = <2>; + convert-sample-format = "s32_le"; + remote-endpoint = <&codec_ep>; + }; + }; +}; + +&mdio0 { + phy0: ethernet-phy@1 { + reg = <1>; + device_type = "ethernet-phy"; + }; +}; + +&spi0 { + cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW + &gpio0 7 GPIO_ACTIVE_LOW>; + dmas = <&dma1 10 2>, <&dma1 10 1>; + dma-names = "rx", "tx"; + status = "okay"; + + cs4271: codec@0 { + compatible = "cirrus,cs4271"; + reg = <0>; + #sound-dai-cells = <0>; + spi-max-frequency = <6000000>; + spi-cpol; + spi-cpha; + reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + port { + codec_ep: endpoint { + remote-endpoint = <&i2s_ep>; + }; + }; + }; + + at25f1024: eeprom@1 { + compatible = "atmel,at25"; + reg = <1>; + address-width = <8>; + size = <0x20000>; + pagesize = <256>; + spi-max-frequency = <20000000>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/cirrus/ep93xx-ts7250.dts b/arch/arm/boot/dts/cirrus/ep93xx-ts7250.dts new file mode 100644 index 000000000000..9e03f93d9fc8 --- /dev/null +++ b/arch/arm/boot/dts/cirrus/ep93xx-ts7250.dts @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for Technologic Systems ts7250 board based on Cirrus EP9302 SoC + */ +/dts-v1/; +#include "ep93xx.dtsi" + +/ { + compatible = "technologic,ts7250", "cirrus,ep9301"; + model = "TS-7250 SBC"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + }; + + memory@0 { + device_type = "memory"; + /* should be set from ATAGS */ + reg = <0x00000000 0x02000000>, + <0x000530c0 0x01fdd000>; + }; + + leds { + compatible = "gpio-leds"; + led-0 { + label = "grled"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; + }; + + led-1 { + label = "rdled"; + gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_FAULT; + }; + }; +}; + +&ebi { + nand-controller@60000000 { + compatible = "technologic,ts7200-nand"; + reg = <0x60000000 0x8000000>; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "TS-BOOTROM"; + reg = <0x00000000 0x00020000>; + read-only; + }; + + partition@20000 { + label = "Linux"; + reg = <0x00020000 0x07d00000>; + }; + + partition@7d20000 { + label = "RedBoot"; + reg = <0x07d20000 0x002e0000>; + read-only; + }; + }; + }; + }; + + rtc@10800000 { + compatible = "st,m48t86"; + reg = <0x10800000 0x1>, + <0x11700000 0x1>; + }; + + watchdog@23800000 { + compatible = "technologic,ts7200-wdt"; + reg = <0x23800000 0x01>, + <0x23c00000 0x01>; + timeout-sec = <30>; + }; +}; + +ð0 { + phy-handle = <&phy0>; +}; + +&gpio1 { + /* PWM */ + gpio-ranges = <&syscon 6 163 1>; +}; + +/* ts7250 doesn't have GPIO Port D present */ +&gpio3 { + status = "disabled"; +}; + +&gpio4 { + gpio-ranges = <&syscon 0 97 2>; +}; + +&gpio6 { + gpio-ranges = <&syscon 0 87 2>; +}; + +&gpio7 { + gpio-ranges = <&syscon 2 199 4>; +}; + +&spi0 { + cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; + dmas = <&dma1 10 2>, <&dma1 10 1>; + dma-names = "rx", "tx"; + status = "okay"; + + tmp122: temperature-sensor@0 { + compatible = "ti,tmp122"; + reg = <0>; + spi-max-frequency = <2000000>; + }; +}; + +&mdio0 { + phy0: ethernet-phy@1 { + reg = <1>; + device_type = "ethernet-phy"; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/cirrus/ep93xx.dtsi b/arch/arm/boot/dts/cirrus/ep93xx.dtsi new file mode 100644 index 000000000000..0dd1eee346ca --- /dev/null +++ b/arch/arm/boot/dts/cirrus/ep93xx.dtsi @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree file for Cirrus Logic systems EP93XX SoC + */ +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/clock/cirrus,ep9301-syscon.h> +/ { + soc: soc { + compatible = "simple-bus"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + + syscon: syscon@80930000 { + compatible = "cirrus,ep9301-syscon", "syscon"; + reg = <0x80930000 0x1000>; + + #clock-cells = <1>; + clocks = <&xtali>; + + spi_default_pins: pins-spi { + function = "spi"; + groups = "ssp"; + }; + + ac97_default_pins: pins-ac97 { + function = "ac97"; + groups = "ac97"; + }; + + i2s_on_ssp_pins: pins-i2sonssp { + function = "i2s"; + groups = "i2s_on_ssp"; + }; + + i2s_on_ac97_pins: pins-i2sonac97 { + function = "i2s"; + groups = "i2s_on_ac97"; + }; + + gpio1_default_pins: pins-gpio1 { + function = "gpio"; + groups = "gpio1agrp"; + }; + + pwm1_default_pins: pins-pwm1 { + function = "pwm"; + groups = "pwm1"; + }; + + gpio2_default_pins: pins-gpio2 { + function = "gpio"; + groups = "gpio2agrp"; + }; + + gpio3_default_pins: pins-gpio3 { + function = "gpio"; + groups = "gpio3agrp"; + }; + + keypad_default_pins: pins-keypad { + function = "keypad"; + groups = "keypadgrp"; + }; + + gpio4_default_pins: pins-gpio4 { + function = "gpio"; + groups = "gpio4agrp"; + }; + + gpio6_default_pins: pins-gpio6 { + function = "gpio"; + groups = "gpio6agrp"; + }; + + gpio7_default_pins: pins-gpio7 { + function = "gpio"; + groups = "gpio7agrp"; + }; + + ide_default_pins: pins-ide { + function = "pata"; + groups = "idegrp"; + }; + + lcd_on_dram0_pins: pins-rasteronsdram0 { + function = "lcd"; + groups = "rasteronsdram0grp"; + }; + + lcd_on_dram3_pins: pins-rasteronsdram3 { + function = "lcd"; + groups = "rasteronsdram3grp"; + }; + }; + + adc: adc@80900000 { + compatible = "cirrus,ep9301-adc"; + reg = <0x80900000 0x28>; + clocks = <&syscon EP93XX_CLK_ADC>; + interrupt-parent = <&vic0>; + interrupts = <30>; + status = "disabled"; + }; + + /* + * The EP93XX expansion bus is a set of up to 7 each up to 16MB + * windows in the 256MB space from 0x50000000 to 0x5fffffff. + * But since we don't require to setup it in any way, we can + * represent it as a simple-bus. + */ + ebi: bus@80080000 { + compatible = "simple-bus"; + reg = <0x80080000 0x20>; + native-endian; + #address-cells = <1>; + #size-cells = <1>; + ranges; + }; + + dma0: dma-controller@80000000 { + compatible = "cirrus,ep9301-dma-m2p"; + reg = <0x80000000 0x0040>, + <0x80000040 0x0040>, + <0x80000080 0x0040>, + <0x800000c0 0x0040>, + <0x80000240 0x0040>, + <0x80000200 0x0040>, + <0x800002c0 0x0040>, + <0x80000280 0x0040>, + <0x80000340 0x0040>, + <0x80000300 0x0040>; + clocks = <&syscon EP93XX_CLK_M2P0>, + <&syscon EP93XX_CLK_M2P1>, + <&syscon EP93XX_CLK_M2P2>, + <&syscon EP93XX_CLK_M2P3>, + <&syscon EP93XX_CLK_M2P4>, + <&syscon EP93XX_CLK_M2P5>, + <&syscon EP93XX_CLK_M2P6>, + <&syscon EP93XX_CLK_M2P7>, + <&syscon EP93XX_CLK_M2P8>, + <&syscon EP93XX_CLK_M2P9>; + clock-names = "m2p0", "m2p1", + "m2p2", "m2p3", + "m2p4", "m2p5", + "m2p6", "m2p7", + "m2p8", "m2p9"; + interrupt-parent = <&vic0>; + interrupts = <7>, <8>, <9>, <10>, <11>, + <12>, <13>, <14>, <15>, <16>; + #dma-cells = <2>; + }; + + dma1: dma-controller@80000100 { + compatible = "cirrus,ep9301-dma-m2m"; + reg = <0x80000100 0x0040>, + <0x80000140 0x0040>; + clocks = <&syscon EP93XX_CLK_M2M0>, + <&syscon EP93XX_CLK_M2M1>; + clock-names = "m2m0", "m2m1"; + interrupt-parent = <&vic0>; + interrupts = <17>, <18>; + #dma-cells = <2>; + }; + + eth0: ethernet@80010000 { + compatible = "cirrus,ep9301-eth"; + reg = <0x80010000 0x10000>; + interrupt-parent = <&vic1>; + interrupts = <7>; + mdio0: mdio { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + gpio0: gpio@80840000 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840000 0x04>, + <0x80840010 0x04>, + <0x80840090 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio1: gpio@80840004 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840004 0x04>, + <0x80840014 0x04>, + <0x808400ac 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&vic1>; + interrupts = <27>; + }; + + gpio2: gpio@80840008 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840008 0x04>, + <0x80840018 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio2_default_pins>; + }; + + gpio3: gpio@8084000c { + compatible = "cirrus,ep9301-gpio"; + reg = <0x8084000c 0x04>, + <0x8084001c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio3_default_pins>; + }; + + gpio4: gpio@80840020 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840020 0x04>, + <0x80840024 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio4_default_pins>; + }; + + gpio5: gpio@80840030 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840030 0x04>, + <0x80840034 0x04>, + <0x8084004c 0x1c>; + reg-names = "data", "dir", "intr"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts-extended = <&vic0 19>, <&vic0 20>, + <&vic0 21>, <&vic0 22>, + <&vic1 15>, <&vic1 16>, + <&vic1 17>, <&vic1 18>; + }; + + gpio6: gpio@80840038 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840038 0x04>, + <0x8084003c 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio6_default_pins>; + }; + + gpio7: gpio@80840040 { + compatible = "cirrus,ep9301-gpio"; + reg = <0x80840040 0x04>, + <0x80840044 0x04>; + reg-names = "data", "dir"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio7_default_pins>; + }; + + i2s: i2s@80820000 { + compatible = "cirrus,ep9301-i2s"; + reg = <0x80820000 0x100>; + #sound-dai-cells = <0>; + interrupt-parent = <&vic1>; + interrupts = <28>; + clocks = <&syscon EP93XX_CLK_I2S_MCLK>, + <&syscon EP93XX_CLK_I2S_SCLK>, + <&syscon EP93XX_CLK_I2S_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + dmas = <&dma0 0 1>, <&dma0 0 2>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + ide: ide@800a0000 { + compatible = "cirrus,ep9312-pata"; + reg = <0x800a0000 0x38>; + interrupt-parent = <&vic1>; + interrupts = <8>; + pinctrl-names = "default"; + pinctrl-0 = <&ide_default_pins>; + status = "disabled"; + }; + + vic0: interrupt-controller@800b0000 { + compatible = "arm,pl192-vic"; + reg = <0x800b0000 0x1000>; + interrupt-controller; + #interrupt-cells = <1>; + valid-mask = <0x7ffffffc>; + valid-wakeup-mask = <0x0>; + }; + + vic1: interrupt-controller@800c0000 { + compatible = "arm,pl192-vic"; + reg = <0x800c0000 0x1000>; + interrupt-controller; + #interrupt-cells = <1>; + valid-mask = <0x1fffffff>; + valid-wakeup-mask = <0x0>; + }; + + keypad: keypad@800f0000 { + compatible = "cirrus,ep9307-keypad"; + reg = <0x800f0000 0x0c>; + interrupt-parent = <&vic0>; + interrupts = <29>; + clocks = <&syscon EP93XX_CLK_KEYPAD>; + pinctrl-names = "default"; + pinctrl-0 = <&keypad_default_pins>; + linux,keymap = <KEY_UP>, + <KEY_DOWN>, + <KEY_VOLUMEDOWN>, + <KEY_HOME>, + <KEY_RIGHT>, + <KEY_LEFT>, + <KEY_ENTER>, + <KEY_VOLUMEUP>, + <KEY_F6>, + <KEY_F8>, + <KEY_F9>, + <KEY_F10>, + <KEY_F1>, + <KEY_F2>, + <KEY_F3>, + <KEY_POWER>; + }; + + pwm0: pwm@80910000 { + compatible = "cirrus,ep9301-pwm"; + reg = <0x80910000 0x10>; + clocks = <&syscon EP93XX_CLK_PWM>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm1: pwm@80910020 { + compatible = "cirrus,ep9301-pwm"; + reg = <0x80910020 0x10>; + clocks = <&syscon EP93XX_CLK_PWM>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1_default_pins>; + status = "disabled"; + }; + + rtc0: rtc@80920000 { + compatible = "cirrus,ep9301-rtc"; + reg = <0x80920000 0x100>; + }; + + spi0: spi@808a0000 { + compatible = "cirrus,ep9301-spi"; + reg = <0x808a0000 0x18>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&vic1>; + interrupts = <21>; + clocks = <&syscon EP93XX_CLK_SPI>; + pinctrl-names = "default"; + pinctrl-0 = <&spi_default_pins>; + status = "disabled"; + }; + + timer: timer@80810000 { + compatible = "cirrus,ep9301-timer"; + reg = <0x80810000 0x100>; + interrupt-parent = <&vic1>; + interrupts = <19>; + }; + + uart0: serial@808c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x808c0000 0x1000>; + arm,primecell-periphid = <0x00041010>; + clocks = <&syscon EP93XX_CLK_UART1>, <&syscon EP93XX_CLK_UART>; + clock-names = "uartclk", "apb_pclk"; + interrupt-parent = <&vic1>; + interrupts = <20>; + status = "disabled"; + }; + + uart1: uart@808d0000 { + compatible = "arm,primecell"; + reg = <0x808d0000 0x1000>; + arm,primecell-periphid = <0x00041010>; + clocks = <&syscon EP93XX_CLK_UART2>, <&syscon EP93XX_CLK_UART>; + clock-names = "apb:uart2", "apb_pclk"; + interrupt-parent = <&vic1>; + interrupts = <22>; + status = "disabled"; + }; + + uart2: uart@808b0000 { + compatible = "arm,primecell"; + reg = <0x808b0000 0x1000>; + arm,primecell-periphid = <0x00041010>; + clocks = <&syscon EP93XX_CLK_UART3>, <&syscon EP93XX_CLK_UART>; + clock-names = "apb:uart3", "apb_pclk"; + interrupt-parent = <&vic1>; + interrupts = <23>; + status = "disabled"; + }; + + usb0: usb@80020000 { + compatible = "generic-ohci"; + reg = <0x80020000 0x10000>; + interrupt-parent = <&vic1>; + interrupts = <24>; + clocks = <&syscon EP93XX_CLK_USB>; + status = "disabled"; + }; + + watchdog0: watchdog@80940000 { + compatible = "cirrus,ep9301-wdt"; + reg = <0x80940000 0x08>; + }; + }; + + xtali: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <14745600>; + clock-output-names = "xtali"; + }; +}; diff --git a/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts index 65f390bf8975..84f39dec3c42 100644 --- a/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_vining_fpga.dts @@ -130,8 +130,8 @@ #gpio-cells = <2>; }; - temp: lm75@48 { - compatible = "lm75"; + temp: temperature-sensor@48 { + compatible = "national,lm75"; reg = <0x48>; }; diff --git a/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi b/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi index f3a3cb6ac311..8208c6a9627a 100644 --- a/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi +++ b/arch/arm/boot/dts/marvell/armada-385-clearfog-gtr.dtsi @@ -423,14 +423,14 @@ status = "okay"; /* U26 temperature sensor placed near SoC */ - temp1: nct75@4c { - compatible = "lm75"; + temp1: temperature-sensor@4c { + compatible = "ti,tmp75c"; reg = <0x4c>; }; /* U27 temperature sensor placed near RTC battery */ - temp2: nct75@4d { - compatible = "lm75"; + temp2: temperature-sensor@4d { + compatible = "ti,tmp75c"; reg = <0x4d>; }; diff --git a/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts index c6fbdd29019f..b9ffd9e5faac 100644 --- a/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts +++ b/arch/arm/boot/dts/microchip/at91-sam9x60_curiosity.dts @@ -198,8 +198,6 @@ dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx0_default>; - #address-cells = <1>; - #size-cells = <0>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; diff --git a/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts b/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts index f3cbb675cea4..3b38707d736e 100644 --- a/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts +++ b/arch/arm/boot/dts/microchip/at91-sam9x60ek.dts @@ -207,8 +207,6 @@ status = "okay"; i2c0: i2c@600 { - #address-cells = <1>; - #size-cells = <0>; dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx0_default>; @@ -254,8 +252,6 @@ status = "okay"; i2c6: i2c@600 { - #address-cells = <1>; - #size-cells = <0>; dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx6_default>; diff --git a/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi index 4617805c7748..c173f49cb910 100644 --- a/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi +++ b/arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi @@ -31,6 +31,14 @@ }; }; + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "VDD_MAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-wilc1000"; reset-gpios = <&pioA PIN_PA27 GPIO_ACTIVE_HIGH>; @@ -70,6 +78,11 @@ mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; + lvin-supply = <®_5v>; + pvin1-supply = <®_5v>; + pvin2-supply = <®_5v>; + pvin3-supply = <®_5v>; + pvin4-supply = <®_5v>; status = "okay"; lpm-gpios = <&pioBU 0 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts index 6b02b7bcfd49..951a0c97d3c6 100644 --- a/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts +++ b/arch/arm/boot/dts/microchip/at91-sama5d29_curiosity.dts @@ -84,6 +84,14 @@ device_type = "memory"; reg = <0x20000000 0x20000000>; }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V_MAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; }; &adc { @@ -144,6 +152,11 @@ mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; + lvin-supply = <®_5v>; + pvin1-supply = <®_5v>; + pvin2-supply = <®_5v>; + pvin3-supply = <®_5v>; + pvin4-supply = <®_5v>; status = "okay"; lpm-gpios = <&pioBU 0 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts b/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts index 999adeca6f33..5e2bb517a480 100644 --- a/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts +++ b/arch/arm/boot/dts/microchip/at91-sama5d2_icp.dts @@ -78,6 +78,14 @@ linux,default-trigger = "heartbeat"; }; }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "VDD_MAIN_5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; }; &adc { @@ -190,6 +198,11 @@ mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; + lvin-supply = <®_5v>; + pvin1-supply = <®_5v>; + pvin2-supply = <®_5v>; + pvin3-supply = <®_5v>; + pvin4-supply = <®_5v>; status = "okay"; lpm-gpios = <&pioBU 7 GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts index 009d2c832421..645e49fdb7fe 100644 --- a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts +++ b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts @@ -72,6 +72,14 @@ device_type = "memory"; reg = <0x60000000 0x10000000>; /* 256 MiB DDR3L-1066 16-bit */ }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V_MAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; }; &adc { @@ -189,6 +197,11 @@ pmic@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; + lvin-supply = <®_5v>; + pvin1-supply = <®_5v>; + pvin2-supply = <®_5v>; + pvin3-supply = <®_5v>; + pvin4-supply = <®_5v>; regulators { vdd_3v3: VDD_IO { diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts index 20b2497657ae..ed75d491a246 100644 --- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts +++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts @@ -88,6 +88,14 @@ reg = <0x60000000 0x20000000>; }; + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V_MAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + sound: sound { compatible = "simple-audio-card"; simple-audio-card,name = "sama7g5ek audio"; @@ -239,6 +247,11 @@ mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; + lvin-supply = <®_5v>; + pvin1-supply = <®_5v>; + pvin2-supply = <®_5v>; + pvin3-supply = <®_5v>; + pvin4-supply = <®_5v>; status = "okay"; regulators { @@ -403,6 +416,42 @@ i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "okay"; + + eeprom0: eeprom@52 { + compatible = "microchip,24aa025e48"; + reg = <0x52>; + size = <256>; + pagesize = <16>; + vcc-supply = <&vdd_3v3>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom0_eui48: eui48@fa { + reg = <0xfa 0x6>; + }; + }; + }; + + eeprom1: eeprom@53 { + compatible = "microchip,24aa025e48"; + reg = <0x53>; + size = <256>; + pagesize = <16>; + vcc-supply = <&vdd_3v3>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom1_eui48: eui48@fa { + reg = <0xfa 0x6>; + }; + }; + }; }; }; @@ -440,6 +489,8 @@ &pinctrl_gmac0_txck_default &pinctrl_gmac0_phy_irq>; phy-mode = "rgmii-id"; + nvmem-cells = <&eeprom0_eui48>; + nvmem-cell-names = "mac-address"; status = "okay"; ethernet-phy@7 { @@ -457,6 +508,8 @@ &pinctrl_gmac1_mdio_default &pinctrl_gmac1_phy_irq>; phy-mode = "rmii"; + nvmem-cells = <&eeprom1_eui48>; + nvmem-cell-names = "mac-address"; status = "okay"; /* Conflict with pdmc0. */ ethernet-phy@0 { diff --git a/arch/arm/boot/dts/microchip/at91rm9200.dtsi b/arch/arm/boot/dts/microchip/at91rm9200.dtsi index 16c675e3a890..02a838541dc3 100644 --- a/arch/arm/boot/dts/microchip/at91rm9200.dtsi +++ b/arch/arm/boot/dts/microchip/at91rm9200.dtsi @@ -225,7 +225,7 @@ pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x800>; atmel,mux-mask = < diff --git a/arch/arm/boot/dts/microchip/at91sam9260.dtsi b/arch/arm/boot/dts/microchip/at91sam9260.dtsi index e56d5546554c..0038183e9a53 100644 --- a/arch/arm/boot/dts/microchip/at91sam9260.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9260.dtsi @@ -170,7 +170,7 @@ pinctrl: pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x600>; atmel,mux-mask = < diff --git a/arch/arm/boot/dts/microchip/at91sam9261.dtsi b/arch/arm/boot/dts/microchip/at91sam9261.dtsi index 307b60658014..b57a7fd67197 100644 --- a/arch/arm/boot/dts/microchip/at91sam9261.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9261.dtsi @@ -317,7 +317,7 @@ pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x600>; atmel,mux-mask = diff --git a/arch/arm/boot/dts/microchip/at91sam9263.dtsi b/arch/arm/boot/dts/microchip/at91sam9263.dtsi index 75d8ff2d12c8..b95d4016ae9f 100644 --- a/arch/arm/boot/dts/microchip/at91sam9263.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9263.dtsi @@ -167,7 +167,7 @@ pinctrl@fffff200 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff200 0xfffff200 0xa00>; atmel,mux-mask = < diff --git a/arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts index 172af6ff4b18..3e5eab57d1a5 100644 --- a/arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts +++ b/arch/arm/boot/dts/microchip/at91sam9g20ek_2mmc.dts @@ -40,13 +40,13 @@ leds { compatible = "gpio-leds"; - ds1 { + led-ds1 { label = "ds1"; gpios = <&pioB 9 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; - ds5 { + led-ds5 { label = "ds5"; gpios = <&pioB 8 GPIO_ACTIVE_LOW>; }; diff --git a/arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts b/arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts index af70eb8a3a02..e0c1e8df81b1 100644 --- a/arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts +++ b/arch/arm/boot/dts/microchip/at91sam9g25-gardena-smart-gateway.dts @@ -37,71 +37,71 @@ leds { compatible = "gpio-leds"; - power_blue { + led-power-blue { label = "smartgw:power:blue"; gpios = <&pioC 21 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - power_green { + led-power-green { label = "smartgw:power:green"; gpios = <&pioC 20 GPIO_ACTIVE_HIGH>; default-state = "on"; }; - power_red { + led-power-red { label = "smartgw:power:red"; gpios = <&pioC 19 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - radio_blue { + led-radio-blue { label = "smartgw:radio:blue"; gpios = <&pioC 18 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - radio_green { + led-radio-green { label = "smartgw:radio:green"; gpios = <&pioC 17 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - radio_red { + led-radio-red { label = "smartgw:radio:red"; gpios = <&pioC 16 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - internet_blue { + led-internet-blue { label = "smartgw:internet:blue"; gpios = <&pioC 15 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - internet_green { + led-internet-green { label = "smartgw:internet:green"; gpios = <&pioC 14 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - internet_red { + led-internet-red { label = "smartgw:internet:red"; gpios = <&pioC 13 GPIO_ACTIVE_HIGH>; default-state = "off"; }; - heartbeat { + led-heartbeat { label = "smartgw:heartbeat"; gpios = <&pioB 8 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; - pb18 { + led-pb18 { status = "disabled"; }; - pd21 { + led-pd21 { status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/microchip/at91sam9g45.dtsi b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi index 325c63a53118..c54eb21d5cba 100644 --- a/arch/arm/boot/dts/microchip/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9g45.dtsi @@ -190,7 +190,7 @@ pinctrl@fffff200 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff200 0xfffff200 0xa00>; atmel,mux-mask = < diff --git a/arch/arm/boot/dts/microchip/at91sam9n12.dtsi b/arch/arm/boot/dts/microchip/at91sam9n12.dtsi index 8dc04e9031a6..844bd50943fc 100644 --- a/arch/arm/boot/dts/microchip/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9n12.dtsi @@ -226,7 +226,7 @@ pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91sam9x5-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x800>; atmel,mux-mask = < diff --git a/arch/arm/boot/dts/microchip/at91sam9n12ek.dts b/arch/arm/boot/dts/microchip/at91sam9n12ek.dts index 4c644d4c6be7..643c3b2ab97e 100644 --- a/arch/arm/boot/dts/microchip/at91sam9n12ek.dts +++ b/arch/arm/boot/dts/microchip/at91sam9n12ek.dts @@ -207,19 +207,19 @@ leds { compatible = "gpio-leds"; - d8 { + led-d8 { label = "d8"; gpios = <&pioB 4 GPIO_ACTIVE_LOW>; linux,default-trigger = "mmc0"; }; - d9 { + led-d9 { label = "d9"; gpios = <&pioB 5 GPIO_ACTIVE_LOW>; linux,default-trigger = "nand-disk"; }; - d10 { + led-d10 { label = "d10"; gpios = <&pioB 6 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; diff --git a/arch/arm/boot/dts/microchip/at91sam9rl.dtsi b/arch/arm/boot/dts/microchip/at91sam9rl.dtsi index 7436b5c862b1..1fec9fcc7cd1 100644 --- a/arch/arm/boot/dts/microchip/at91sam9rl.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9rl.dtsi @@ -339,7 +339,7 @@ pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91rm9200-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x800>; atmel,mux-mask = diff --git a/arch/arm/boot/dts/microchip/at91sam9x5.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5.dtsi index a7456c2191fa..27c1f2861cc3 100644 --- a/arch/arm/boot/dts/microchip/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9x5.dtsi @@ -202,7 +202,7 @@ pinctrl: pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "atmel,at91sam9x5-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x800>; /* shared pinctrl settings */ diff --git a/arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi b/arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi index cdd37f67280b..fb3c19bdfcb6 100644 --- a/arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi +++ b/arch/arm/boot/dts/microchip/at91sam9x5cm.dtsi @@ -120,13 +120,13 @@ leds { compatible = "gpio-leds"; - pb18 { + led-pb18 { label = "pb18"; gpios = <&pioB 18 GPIO_ACTIVE_LOW>; linux,default-trigger = "heartbeat"; }; - pd21 { + led-pd21 { label = "pd21"; gpios = <&pioD 21 GPIO_ACTIVE_HIGH>; }; diff --git a/arch/arm/boot/dts/microchip/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi index 291540e5d81e..04a6d716ecaf 100644 --- a/arch/arm/boot/dts/microchip/sam9x60.dtsi +++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi @@ -215,6 +215,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 13>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -284,6 +286,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 14>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -394,6 +398,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 32>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -443,6 +449,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 33>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -600,6 +608,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 9>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -649,6 +659,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 10>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -698,6 +710,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -766,6 +780,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 5>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -834,6 +850,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 6>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -902,6 +920,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -970,6 +990,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 8>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -1074,6 +1096,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 15>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -1123,6 +1147,8 @@ compatible = "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 16>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | @@ -1223,7 +1249,7 @@ pinctrl: pinctrl@fffff400 { #address-cells = <1>; #size-cells = <1>; - compatible = "microchip,sam9x60-pinctrl", "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus"; + compatible = "microchip,sam9x60-pinctrl", "simple-mfd"; ranges = <0xfffff400 0xfffff400 0x800>; /* mux-mask corresponding to sam9x60 SoC in TFBGA228L package */ @@ -1236,7 +1262,7 @@ >; pioA: gpio@fffff400 { - compatible = "microchip,sam9x60-gpio", "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + compatible = "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffff400 0x200>; interrupts = <2 IRQ_TYPE_LEVEL_HIGH 1>; #gpio-cells = <2>; @@ -1247,7 +1273,7 @@ }; pioB: gpio@fffff600 { - compatible = "microchip,sam9x60-gpio", "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + compatible = "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffff600 0x200>; interrupts = <3 IRQ_TYPE_LEVEL_HIGH 1>; #gpio-cells = <2>; @@ -1259,7 +1285,7 @@ }; pioC: gpio@fffff800 { - compatible = "microchip,sam9x60-gpio", "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + compatible = "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffff800 0x200>; interrupts = <4 IRQ_TYPE_LEVEL_HIGH 1>; #gpio-cells = <2>; @@ -1270,7 +1296,7 @@ }; pioD: gpio@fffffa00 { - compatible = "microchip,sam9x60-gpio", "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; + compatible = "microchip,sam9x60-gpio", "atmel,at91rm9200-gpio"; reg = <0xfffffa00 0x200>; interrupts = <44 IRQ_TYPE_LEVEL_HIGH 1>; #gpio-cells = <2>; @@ -1312,7 +1338,7 @@ compatible = "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; reg = <0xfffffe20 0x20>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; - clocks = <&clk32k 0>; + clocks = <&clk32k 1>; }; pit: timer@fffffe40 { @@ -1338,7 +1364,7 @@ compatible = "microchip,sam9x60-rtc", "atmel,at91sam9x5-rtc"; reg = <0xfffffea8 0x100>; interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; - clocks = <&clk32k 0>; + clocks = <&clk32k 1>; }; watchdog: watchdog@ffffff80 { diff --git a/arch/arm/boot/dts/microchip/sama5d3.dtsi b/arch/arm/boot/dts/microchip/sama5d3.dtsi index d4fc0c1dfc10..39865133aa56 100644 --- a/arch/arm/boot/dts/microchip/sama5d3.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d3.dtsi @@ -493,7 +493,7 @@ pinctrl: pinctrl@fffff200 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,sama5d3-pinctrl", "atmel,at91sam9x5-pinctrl", "simple-bus"; + compatible = "atmel,sama5d3-pinctrl", "simple-mfd"; ranges = <0xfffff200 0xfffff200 0xa00>; atmel,mux-mask = < /* A B C */ diff --git a/arch/arm/boot/dts/microchip/sama5d4.dtsi b/arch/arm/boot/dts/microchip/sama5d4.dtsi index 58ceed997889..b253ba33fc38 100644 --- a/arch/arm/boot/dts/microchip/sama5d4.dtsi +++ b/arch/arm/boot/dts/microchip/sama5d4.dtsi @@ -791,7 +791,7 @@ pinctrl: pinctrl@fc06a000 { #address-cells = <1>; #size-cells = <1>; - compatible = "atmel,sama5d3-pinctrl", "atmel,at91sam9x5-pinctrl", "simple-bus"; + compatible = "atmel,sama5d3-pinctrl", "simple-mfd"; ranges = <0xfc068000 0xfc068000 0x100 0xfc06a000 0xfc06a000 0x4000>; /* WARNING: revisit as pin spec has changed */ diff --git a/arch/arm/boot/dts/microchip/sama7g5.dtsi b/arch/arm/boot/dts/microchip/sama7g5.dtsi index 75778be126a3..17bcdcf0cf4a 100644 --- a/arch/arm/boot/dts/microchip/sama7g5.dtsi +++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi @@ -272,7 +272,7 @@ compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; reg = <0xe001d020 0x30>; interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk32k 0>; + clocks = <&clk32k 1>; }; clk32k: clock-controller@e001d050 { diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts index 1f07ba382910..886a87dfcd0d 100644 --- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts +++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm730-kudo.dts @@ -531,8 +531,8 @@ reg = <4>; // INLET1_T - lm75@5c { - compatible = "ti,lm75"; + temperature-sensor@5c { + compatible = "national,lm75"; reg = <0x5c>; }; }; @@ -543,8 +543,8 @@ reg = <5>; // OUTLET1_T - lm75@5c { - compatible = "ti,lm75"; + temperature-sensor@5c { + compatible = "national,lm75"; reg = <0x5c>; }; }; @@ -555,8 +555,8 @@ reg = <6>; // OUTLET2_T - lm75@5c { - compatible = "ti,lm75"; + temperature-sensor@5c { + compatible = "national,lm75"; reg = <0x5c>; }; }; @@ -567,8 +567,8 @@ reg = <7>; // OUTLET3_T - lm75@5c { - compatible = "ti,lm75"; + temperature-sensor@5c { + compatible = "national,lm75"; reg = <0x5c>; }; }; @@ -697,8 +697,8 @@ reg = <3>; // M2_ZONE_T - lm75@28 { - compatible = "ti,lm75"; + temperature-sensor@28 { + compatible = "national,lm75"; reg = <0x28>; }; }; @@ -709,8 +709,8 @@ reg = <4>; // BATT_ZONE_T - lm75@29 { - compatible = "ti,lm75"; + temperature-sensor@29 { + compatible = "national,lm75"; reg = <0x29>; }; }; @@ -721,8 +721,8 @@ reg = <5>; // NBM1_ZONE_T - lm75@28 { - compatible = "ti,lm75"; + temperature-sensor@28 { + compatible = "national,lm75"; reg = <0x28>; }; }; @@ -732,8 +732,8 @@ reg = <6>; // NBM2_ZONE_T - lm75@29 { - compatible = "ti,lm75"; + temperature-sensor@29 { + compatible = "national,lm75"; reg = <0x29>; }; }; diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts index f53d45fa1de8..bcdcb30c7bf6 100644 --- a/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts +++ b/arch/arm/boot/dts/nuvoton/nuvoton-npcm750-evb.dts @@ -198,7 +198,7 @@ clock-frequency = <100000>; status = "okay"; lm75@48 { - compatible = "lm75"; + compatible = "national,lm75"; reg = <0x48>; status = "okay"; }; @@ -208,8 +208,8 @@ &i2c1 { clock-frequency = <100000>; status = "okay"; - lm75@48 { - compatible = "lm75"; + temperature-sensor@48 { + compatible = "national,lm75"; reg = <0x48>; status = "okay"; }; diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts b/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts index b78c116cbc18..edb907f740bf 100644 --- a/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts +++ b/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts @@ -34,7 +34,7 @@ pinctrl-names = "default"; pinctrl-0 = <&key_pins>; - uid { + button-uid { label = "UID button"; linux,code = <KEY_HOME>; gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; @@ -46,12 +46,12 @@ pinctrl-names = "default"; pinctrl-0 = <&led_pins>; - uid { + led-uid { label = "UID"; gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; }; - heartbeat { + led-heartbeat { label = "heartbeat"; gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; }; diff --git a/arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts b/arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts index 763ab812eb87..f02e2cf65fe8 100644 --- a/arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts +++ b/arch/arm/boot/dts/nvidia/tegra114-asus-tf701t.dts @@ -57,10 +57,24 @@ }; host1x@50000000 { + hdmi@54280000 { + status = "okay"; + + hdmi-supply = <&hdmi_5v0_sys>; + pll-supply = <&avdd_hdmi_pll>; + vdd-supply = <&avdd_hdmi>; + + port { + hdmi_out: endpoint { + remote-endpoint = <&connector_in>; + }; + }; + }; + dsi@54300000 { status = "okay"; - avdd-dsi-csi-supply = <&tps65913_ldo2>; + avdd-dsi-csi-supply = <&avdd_dsi_csi>; nvidia,ganged-mode = <&dsib>; @@ -70,7 +84,7 @@ link2 = <&panel_secondary>; - power-supply = <&vdd_lcd>; + power-supply = <&dvdd_1v8_lcd>; backlight = <&backlight>; }; }; @@ -78,7 +92,7 @@ dsi@54400000 { status = "okay"; - avdd-dsi-csi-supply = <&tps65913_ldo2>; + avdd-dsi-csi-supply = <&avdd_dsi_csi>; panel_secondary: panel@0 { compatible = "sharp,lq101r1sx01"; @@ -87,66 +101,377 @@ }; }; + vde@6001a000 { + assigned-clocks = <&tegra_car TEGRA114_CLK_VDE>; + assigned-clock-parents = <&tegra_car TEGRA114_CLK_PLL_P>; + assigned-clock-rates = <408000000>; + }; + pinmux@70000868 { - asus_pad_ec_default: pinmux-asus-pad-ec-default { - ec-interrupt { - nvidia,pins = "kb_col5_pq5"; - nvidia,function = "kbc"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + /* WLAN SDIO pinmux */ + sdmmc1-clk { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc1-cmd { + nvidia,pins = "sdmmc1_cmd_pz1", + "sdmmc1_dat0_py7", + "sdmmc1_dat1_py6", + "sdmmc1_dat2_py5", + "sdmmc1_dat3_py4"; + nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - ec-request { - nvidia,pins = "kb_col2_pq2"; - nvidia,function = "kbc"; + wlan-power { + nvidia,pins = "clk2_req_pcc5"; + nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - backlight_default: pinmux-backlight-default { - backlight-enable { - nvidia,pins = "gmi_ad10_ph2"; + wlan-reset { + nvidia,pins = "gpio_x7_aud_px7"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + wlan-host-wake { + nvidia,pins = "pu5"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + wlan-3v3-com { + nvidia,pins = "pu1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* UART-A pinmux */ + uarta-cts { + nvidia,pins = "kb_row10_ps2"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uarta-rts { + nvidia,pins = "kb_row9_ps1"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* GNSS UART-B pinmux */ + uartb-cts { + nvidia,pins = "uart2_cts_n_pj5"; + nvidia,function = "uartb"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uartb-rts { + nvidia,pins = "uart2_rts_n_pj6"; + nvidia,function = "uartb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + uartb-rxd { + nvidia,pins = "uart2_rxd_pc3"; + nvidia,function = "irda"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uartb-txd { + nvidia,pins = "uart2_txd_pc2"; + nvidia,function = "irda"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Bluetooth UART-C pinmux */ + uartc-cts-rxd { + nvidia,pins = "uart3_cts_n_pa1", + "uart3_rxd_pw7"; + nvidia,function = "uartc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uartc-rts-txd { + nvidia,pins = "uart3_rts_n_pc0", + "uart3_txd_pw6"; + nvidia,function = "uartc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + bt-shutdown { + nvidia,pins = "kb_col6_pq6", + "kb_col7_pq7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + bt-dev-wake { + nvidia,pins = "clk3_req_pee1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + bt-host-wake { + nvidia,pins = "pu6"; + nvidia,function = "pwm3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + bt-pcm-dap4-out { + nvidia,pins = "dap4_fs_pp4", + "dap4_dout_pp6", + "dap4_sclk_pp7"; + nvidia,function = "i2s3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + bt-pcm-dap4-in { + nvidia,pins = "dap4_din_pp5"; + nvidia,function = "i2s3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* UART-D pinmux */ + uartd-cts { + nvidia,pins = "gmi_a17_pb0"; + nvidia,function = "uartd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + uartd-rts { + nvidia,pins = "gmi_a16_pj7", + "gmi_a19_pk7"; + nvidia,function = "uartd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* MicroSD pinmux */ + sdmmc3-clk { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc3-data { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "kb_col4_pq4", + "sdmmc3_cd_n_pv2", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + microsd-pwr { + nvidia,pins = "gmi_clk_pk1"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - codec_default: pinmux-codec-default { - interrupt { - nvidia,pins = "gpio_w2_aud_pw2", - "gpio_w3_aud_pw3"; - nvidia,function = "spi6"; + /* EMMC pinmux */ + sdmmc4-clk-cmd { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sdmmc4-data { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - ldo1-en { - nvidia,pins = "sdmmc1_wp_n_pv3"; - nvidia,function = "sdmmc1"; + /* I2C pinmux */ + gen1-i2c { + nvidia,pins = "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5"; + nvidia,function = "i2c1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + gen2-i2c { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + cam-i2c { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + ddc-i2c { + nvidia,pins = "ddc_scl_pv4", + "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + pwr-i2c { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <TEGRA_PIN_ENABLE>; + nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + /* SPI pinmux */ + spi1-out { + nvidia,pins = "ulpi_clk_py0", + "ulpi_nxt_py2", + "ulpi_stp_py3"; + nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - gpio_hall_sensor_default: pinmux-gpio-hall-sensor-default { - ulpi_data4_po5 { + spi1-in { + nvidia,pins = "ulpi_dir_py1"; + nvidia,function = "spi1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + spi2 { + nvidia,pins = "ulpi_data4_po5", + "ulpi_data7_po0"; + nvidia,function = "spi2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + spi4-out { + nvidia,pins = "gmi_ad6_pg6", + "gmi_wr_n_pi0"; + nvidia,function = "spi4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spi4-in { + nvidia,pins = "gmi_ad5_pg5", + "gmi_ad7_pg7"; + nvidia,function = "spi4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* GPIO keys pinmux */ + hall-switch { nvidia,pins = "ulpi_data4_po5"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - }; - gpio_keys_default: pinmux-gpio-keys-default { - power { + lineout-switch { + nvidia,pins = "gpio_x5_aud_px5"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + power-key { nvidia,pins = "kb_col0_pq0"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -154,111 +479,722 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - volume { + volume-keys { nvidia,pins = "kb_row1_pr1", - "kb_row2_pr2"; + "kb_row2_pr2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - }; - hp_det_default: pinmux-hp-det-default { - gmi_iordy_pi5 { - nvidia,pins = "kb_row7_pr7"; - nvidia,function = "rsvd2"; + /* Sensors pinmux */ + nct-irq { + nvidia,pins = "ulpi_data3_po4"; + nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - }; - imu_default: pinmux-imu-default { - kb_row3_pr3 { + mpu-irq { nvidia,pins = "kb_row3_pr3"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - }; - pwm_default: pinmux-pwm-default { - gmi_ad9_ph1 { + /* HDMI pinmux */ + hdmi-hpd { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + hdmi-en { + nvidia,pins = "dap3_dout_pp2"; + nvidia,function = "i2s2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + hdmi-cec { + nvidia,pins = "hdmi_cec_pee3"; + nvidia,function = "cec"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* LED pinmux */ + backlight-pwm { nvidia,pins = "gmi_ad9_ph1"; nvidia,function = "pwm1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - /* XXX make this something more sensible */ - pwm_sleep: pinmux-pwm-sleep { - gmi_ad9_ph1 { - nvidia,pins = "gmi_ad9_ph1"; + backlight-en { + nvidia,pins = "gmi_ad10_ph2"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Touchscreen pinmux */ + touch-irq { + nvidia,pins = "gmi_cs4_n_pk2"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + touch-rst { + nvidia,pins = "gmi_cs3_n_pk4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + touch-pwr { + nvidia,pins = "gmi_ad8_ph0"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + touch-vio { + nvidia,pins = "gmi_ad12_ph4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* AUDIO pinmux */ + audio-ldo1 { + nvidia,pins = "sdmmc1_wp_n_pv3"; + nvidia,function = "sdmmc1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + hp-detect { + nvidia,pins = "kb_row7_pr7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap-i2s0-in { + nvidia,pins = "dap1_din_pn1"; + nvidia,function = "i2s0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap-i2s0-out { + nvidia,pins = "dap1_dout_pn2", + "dap1_fs_pn0", + "dap1_sclk_pn3"; + nvidia,function = "i2s0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + dap-i2s1-in { + nvidia,pins = "dap2_din_pa4"; + nvidia,function = "i2s1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap-i2s1-out { + nvidia,pins = "dap2_dout_pa5", + "dap2_fs_pa2", + "dap2_sclk_pa3"; + nvidia,function = "i2s1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + dap-i2s2-in { + nvidia,pins = "dap3_fs_pp0", + "dap3_sclk_pp3"; + nvidia,function = "i2s2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dap-i2s2-out { + nvidia,pins = "dap3_din_pp1"; + nvidia,function = "i2s2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spdif-in { + nvidia,pins = "spdif_in_pk6"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + spdif-out { + nvidia,pins = "spdif_out_pk5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* AsusEC pinmux */ + ec-irq { + nvidia,pins = "kb_col5_pq5"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + ec-req { + nvidia,pins = "kb_col2_pq2"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + hotplug-i2c { + nvidia,pins = "ulpi_data7_po0"; + nvidia,function = "spi2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + ps2-irq { + nvidia,pins = "gpio_w2_aud_pw2"; + nvidia,function = "spi6"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kbd-irq { + nvidia,pins = "gmi_cs0_n_pj0"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + dvfs-pin { + nvidia,pins = "dvfs_pwm_px0", + "dvfs_clk_px2"; + nvidia,function = "cldvfs"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Core pinmux */ + clk-32k-out { + nvidia,pins = "clk_32k_out_pa0"; + nvidia,function = "soc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + sys-clk-req { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "sysclk"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + core-pwr-req { + nvidia,pins = "core_pwr_req"; + nvidia,function = "pwron"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + cpu-pwr-req { + nvidia,pins = "cpu_pwr_req"; + nvidia,function = "cpu"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pwr-int-n { + nvidia,pins = "pwr_int_n"; + nvidia,function = "pmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + clk-32k-in { + nvidia,pins = "clk_32k_in"; + nvidia,function = "clk"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + owr { + nvidia,pins = "owr"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + reset-out-n { + nvidia,pins = "reset_out_n"; + nvidia,function = "reset_out_n"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* ULPI pinmux */ + ulpi-data0-6 { + nvidia,pins = "ulpi_data0_po1", + "ulpi_data6_po7"; + nvidia,function = "ulpi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + ulpi-data1-5 { + nvidia,pins = "ulpi_data1_po2", + "ulpi_data5_po6"; + nvidia,function = "ulpi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + ulpi-data2-3 { + nvidia,pins = "ulpi_data2_po3", + "ulpi_data3_po4"; + nvidia,function = "ulpi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* PORT V */ + pv0-gpio { + nvidia,pins = "pv0"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pv1-gpio { + nvidia,pins = "pv1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* PORT U */ + pu0-gpio { + nvidia,pins = "pu0"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pu2-gpio { + nvidia,pins = "pu2"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* PWM pinmux */ + pwm0 { + nvidia,pins = "pu3"; + nvidia,function = "pwm0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pwm1 { + nvidia,pins = "pu4"; nvidia,function = "pwm1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - sdmmc3_default: pinmux-sdmmc3-default { - drive_sdio3 { - nvidia,pins = "drive_sdio3"; - nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; - nvidia,schmitt = <TEGRA_PIN_DISABLE>; - nvidia,pull-down-strength = <22>; - nvidia,pull-up-strength = <36>; - nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; - nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + /* EXTPERIPH pinmux */ + clk1-out { + nvidia,pins = "clk1_out_pw4"; + nvidia,function = "extperiph1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - sdmmc3_clk_pa6 { - nvidia,pins = "sdmmc3_clk_pa6"; - nvidia,function = "sdmmc3"; + clk2-out { + nvidia,pins = "clk2_out_pw5"; + nvidia,function = "extperiph2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk3-out { + nvidia,pins = "clk3_out_pee0"; + nvidia,function = "extperiph3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + clk1-req { + nvidia,pins = "clk1_req_pee2"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* GMI pinmux */ + gmi-wp-n { + nvidia,pins = "gmi_wp_n_pc7"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_cmd_pa7 { - nvidia,pins = "sdmmc3_cmd_pa7", - "sdmmc3_dat0_pb7", - "sdmmc3_dat1_pb6", - "sdmmc3_dat2_pb5", - "sdmmc3_dat3_pb4", - "kb_col4_pq4", - "sdmmc3_clk_lb_out_pee4", - "sdmmc3_clk_lb_in_pee5", - "sdmmc3_cd_n_pv2"; - nvidia,function = "sdmmc3"; + gmi-adv { + nvidia,pins = "gmi_adv_n_pk0"; + nvidia,function = "rsvd1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - }; - sdmmc3_vdd_default: pinmux-sdmmc3-vdd-default { - gmi_clk_pk1 { - nvidia,pins = "gmi_clk_pk1"; + gmi-ad0-ad1 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad1_pg1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi-ad2-ad3 { + nvidia,pins = "gmi_ad2_pg2", + "gmi_ad3_pg3"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-iordy { + nvidia,pins = "gmi_iordy_pi5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-a18 { + nvidia,pins = "gmi_a18_pb1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-wait { + nvidia,pins = "gmi_wait_pi7"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi-cs6-n { + nvidia,pins = "gmi_cs6_n_pi3"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gmi-cs7-n { + nvidia,pins = "gmi_cs7_n_pi6"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-dqs-p { + nvidia,pins = "gmi_dqs_p_pj3"; + nvidia,function = "nand"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-cs2-ad { + nvidia,pins = "gmi_cs2_n_pk3", + "gmi_ad14_ph6", + "gmi_ad15_ph7"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-cs4-clk { + nvidia,pins = "gmi_cs4_n_pk2", + "gmi_clk_lb"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-ad11 { + nvidia,pins = "gmi_ad11_ph3"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - }; - vdd_lcd_default: pinmux-vdd-lcd-default { - sdmmc4_clk_pcc4 { - nvidia,pins = "sdmmc4_clk_pcc4"; - nvidia,function = "sdmmc4"; + gmi-cs1-oe { + nvidia,pins = "gmi_cs1_n_pj2", + "gmi_oe_n_pi1"; + nvidia,function = "soc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-ad4 { + nvidia,pins = "gmi_ad4_pg4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-ad13 { + nvidia,pins = "gmi_ad13_ph5"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gmi-rst-n { + nvidia,pins = "gmi_rst_n_pi4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* PORT CC */ + pcc-gpio { + nvidia,pins = "pcc1", "pcc2"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* PORT BB */ + pbb3-gpio { + nvidia,pins = "pbb3"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + pbb4-5-6-gpio { + nvidia,pins = "pbb4", "pbb5", "pbb6"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + pbb7-gpio { + nvidia,pins = "pbb7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* KBC pinmux */ + kb-r0-c1 { + nvidia,pins = "kb_row0_pr0", + "kb_col1_pq1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb-row4 { + nvidia,pins = "kb_row4_pr4"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb-row5 { + nvidia,pins = "kb_row5_pr5"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb-row6 { + nvidia,pins = "kb_row6_pr6"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + kb-r8-c3 { + nvidia,pins = "kb_row8_ps0", + "kb_col3_pq3"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* VI pinmux */ + cam-mclk { + nvidia,pins = "cam_mclk_pcc0", + "pbb0"; + nvidia,function = "vi_alt3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; + + /* AUD pinmux */ + gpio-x4-aud { + nvidia,pins = "gpio_x4_aud_px4"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + gpio-x1-aud { + nvidia,pins = "gpio_x1_aud_px1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gpio-x3-aud { + nvidia,pins = "gpio_x3_aud_px3"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + gpio-x6-aud { + nvidia,pins = "gpio_x6_aud_px6"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + usb-vbus { + nvidia,pins = "usb_vbus_en0_pn4", + "usb_vbus_en1_pn5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* GPIO power/drive control */ + drive-sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,pull-down-strength = <36>; + nvidia,pull-up-strength = <20>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOW>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOW>; + }; + + drive-sdio3 { + nvidia,pins = "drive_sdio3"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,pull-down-strength = <22>; + nvidia,pull-up-strength = <36>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive-gma { + nvidia,pins = "drive_gma"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,pull-down-strength = <2>; + nvidia,pull-up-strength = <2>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; }; }; @@ -267,7 +1203,33 @@ }; serial@70006200 { - /* Bluetooth */ + compatible = "nvidia,tegra114-hsuart", "nvidia,tegra30-hsuart"; + reset-names = "serial"; + /delete-property/ reg-shift; + status = "okay"; + + nvidia,adjust-baud-rates = <0 9600 100>, + <9600 115200 200>, + <1000000 4000000 136>; + + bluetooth { + compatible = "brcm,bcm4334-bt"; + max-speed = <4000000>; + + clocks = <&tegra_pmc TEGRA_PMC_CLK_BLINK>; + clock-names = "txco"; + + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(U, 6) IRQ_TYPE_EDGE_RISING>; + interrupt-names = "host-wakeup"; + + device-wakeup-gpios = <&gpio TEGRA_GPIO(EE, 1) GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&gpio TEGRA_GPIO(Q, 7) GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio TEGRA_GPIO(Q, 6) GPIO_ACTIVE_LOW>; + + vbat-supply = <&vdd_3v3_com>; + vddio-supply = <&vdd_1v8_vio>; + }; }; serial@70006300 { @@ -278,10 +1240,6 @@ pwm@7000a000 { status = "okay"; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&pwm_default>; - pinctrl-1 = <&pwm_sleep>; }; i2c@7000c000 { @@ -292,27 +1250,35 @@ compatible = "asahi-kasei,ak09911"; reg = <0xc>; - vdd-supply = <&vdd_3v3_sys>; + /* no DRDY (polling) */ + + vdd-supply = <&vdd_2v85_sen>; + vid-supply = <&vdd_1v8_vio>; + + mount-matrix = "0", "1", "0", + "1", "0", "0", + "0", "0","-1"; }; rt5639: audio-codec@1c { compatible = "realtek,rt5639"; reg = <0x1c>; - interrupt-parent = <&gpio>; - interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_EDGE_FALLING>; - - realtek,ldo1-en-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; + realtek,ldo1-en-gpios = + <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&codec_default>; + clocks = <&tegra_pmc TEGRA_PMC_CLK_OUT_1>; + clock-names = "mclk"; }; temp_sensor: temperature-sensor@4c { compatible = "onnn,nct1008"; reg = <0x4c>; - vcc-supply = <&vdd_3v3_sys>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_EDGE_FALLING>; + + vcc-supply = <&vdd_1v8_vio>; #thermal-sensor-cells = <1>; }; @@ -323,12 +1289,12 @@ interrupt-parent = <&gpio>; interrupts = <TEGRA_GPIO(R, 3) IRQ_TYPE_LEVEL_HIGH>; + vdd-supply = <&vdd_2v85_sen>; + vddio-supply = <&vdd_1v8_vio>; + mount-matrix = "0", "-1", "0", "1", "0", "0", "0", "0", "1"; - - pinctrl-names = "default"; - pinctrl-0 = <&imu_default>; }; }; @@ -339,6 +1305,8 @@ power-sensor@44 { compatible = "ti,ina230"; reg = <0x44>; + + shunt-resistor = <5000>; }; }; @@ -350,12 +1318,13 @@ compatible = "dynaimage,al3320a"; reg = <0x1c>; - vdd-supply = <&vdd_3v3_sys>; + vdd-supply = <&vdd_1v8_vio>; }; }; - i2c@7000c700 { - /* HDMI DDC */ + hdmi_ddc: i2c@7000c700 { + status = "okay"; + clock-frequency = <10000>; }; i2c@7000d000 { @@ -372,12 +1341,36 @@ ti,system-power-controller; + palmas_gpadc: adc { + compatible = "ti,palmas-gpadc"; + interrupts = <18 IRQ_TYPE_NONE>, + <16 IRQ_TYPE_NONE>, + <17 IRQ_TYPE_NONE>; + + ti,channel0-current-microamp = <5>; + ti,channel3-current-microamp = <400>; + ti,enable-extended-delay; + + #io-channel-cells = <1>; + }; + + palmas_extcon: extcon { + compatible = "ti,palmas-usb-vid"; + ti,enable-vbus-detection; + ti,enable-id-detection; + }; + palmas_gpio: gpio { compatible = "ti,palmas-gpio"; gpio-controller; #gpio-cells = <2>; }; + palmas_clk32kg@0 { + compatible = "ti,palmas-clk32kg"; + #clock-cells = <0>; + }; + pinmux { compatible = "ti,tps65913-pinctrl"; ti,palmas-enable-dvfs1; @@ -441,17 +1434,18 @@ pmic { compatible = "ti,tps65913-pmic", "ti,palmas-pmic"; - ldo1-in-supply = <&tps65913_smps7>; - ldo2-in-supply = <&tps65913_smps7>; - ldo4-in-supply = <&tps65913_smps8>; - ldo5-in-supply = <&tps65913_smps9>; - ldo6-in-supply = <&tps65913_smps9>; - ldo7-in-supply = <&tps65913_smps9>; - ldo9-in-supply = <&tps65913_smps9>; + ldo1-in-supply = <&vddio_ddr>; + ldo2-in-supply = <&vddio_ddr>; + ldo4-in-supply = <&vdd_1v8_vio>; + ldo5-in-supply = <&vcore_emmc>; + ldo6-in-supply = <&vcore_emmc>; + ldo7-in-supply = <&vcore_emmc>; + ldo9-in-supply = <&vcore_emmc>; + ldoln-in-supply = <&vdd_smps10_out2>; regulators { - tps65913_smps123: smps123 { - regulator-name = "vdd-cpu"; + vdd_cpu: smps123 { + regulator-name = "vdd_cpu"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1350000>; regulator-always-on; @@ -460,8 +1454,8 @@ ti,mode-sleep = <3>; }; - tps65913_smps45: smps45 { - regulator-name = "vdd-core"; + vdd_core: smps45 { + regulator-name = "vdd_core"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1400000>; regulator-always-on; @@ -469,101 +1463,95 @@ ti,roof-floor = <3>; }; - smps6 { - regulator-name = "va-lcd-hv"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - regulator-boot-on; - }; + /* smps6 disabled */ - tps65913_smps7: smps7 { - regulator-name = "vdd-ddr"; + vddio_ddr: smps7 { + regulator-name = "vddio_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-boot-on; }; - tps65913_smps8: smps8 { - regulator-name = "vdd-1v8"; + vdd_1v8_vio: smps8 { + regulator-name = "vdd_1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; }; - tps65913_smps9: smps9 { - regulator-name = "vdd-sd"; + vcore_emmc: smps9 { + regulator-name = "vdd_emmc"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; - regulator-always-on; + regulator-boot-on; }; - tps65913_smps10_out1: smps10_out1 { - regulator-name = "vd-smps10-out1"; + smps10_out1 { + regulator-name = "vd_smps10_out1"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; regulator-boot-on; }; - tps65913_smps10_out2: smps10_out2 { - regulator-name = "vd-smps10-out2"; + vdd_smps10_out2: smps10_out2 { + regulator-name = "vd_smps10_out2"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; regulator-boot-on; }; - tps65913_ldo1: ldo1 { - regulator-name = "vdd-hdmi-pll"; + avdd_hdmi_pll: ldo1 { + regulator-name = "avdd_hdmi_pll"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; regulator-always-on; + regulator-boot-on; ti,roof-floor = <3>; }; - tps65913_ldo2: ldo2 { - regulator-name = "vdd-2v8-dsi-csi"; + avdd_dsi_csi: ldo2 { + regulator-name = "avdd_dsi_csi"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-boot-on; }; ldo3 { - regulator-name = "vpp-fuse"; + regulator-name = "vpp_fuse"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; - ldo4 { - regulator-name = "vdd-1v2-cam"; + vdd_1v2_cam: ldo4 { + regulator-name = "vdd_1v2_cam"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; - ldo5 { - regulator-name = "vdd-cam"; + avdd_2v8_cam: ldo5 { + regulator-name = "avdd_cam2"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; - ldo6 { - regulator-name = "vdd-dev"; + vdd_2v85_sen: ldo6 { + regulator-name = "vdd_dev"; regulator-min-microvolt = <2850000>; regulator-max-microvolt = <2850000>; - regulator-boot-on; }; - ldo7 { - regulator-name = "vdd-2v8-cam"; + avdd_2v8_af: ldo7 { + regulator-name = "avdd_2v8_cam"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; - tps65913_ldo8: ldo8 { - regulator-name = "vdd-rtc"; + ldo8 { + regulator-name = "vdd_rtc"; regulator-min-microvolt = <950000>; regulator-max-microvolt = <950000>; regulator-always-on; @@ -571,23 +1559,24 @@ ti,enable-ldo8-tracking; }; - tps65913_ldo9: ldo9 { - regulator-name = "vdd-sdmmc"; - regulator-min-microvolt = <1800000>; + vddio_usd: ldo9 { + regulator-name = "vddio_usd"; + /* min voltage of 1.8v is not stable */ + regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; }; - tps65913_ldoln: ldoln { - regulator-name = "vdd-hdmi"; + avdd_hdmi: ldoln { + regulator-name = "avdd_hdmi"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-boot-on; }; - ldousb { - regulator-name = "vdd-usb"; + avdd_usb: ldousb { + regulator-name = "avdd_usb"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-always-on; regulator-boot-on; }; }; @@ -596,19 +1585,89 @@ rtc { compatible = "ti,palmas-rtc"; interrupt-parent = <&palmas>; - interrupts = <8 0>; + interrupts = <8 IRQ_TYPE_NONE>; }; }; }; + pmc@7000e400 { + status = "okay"; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <300>; + nvidia,cpu-pwr-off-time = <300>; + nvidia,core-pwr-good-time = <641 3845>; + nvidia,core-pwr-off-time = <2000>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + + /* Clear DEV_ON bit in DEV_CTRL register of TPS65913 PMIC */ + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x58>; + nvidia,reg-addr = <0xA0>; + nvidia,reg-data = <0x00>; + }; + }; + ahub@70080000 { - i2s@70080300 { + /* HIFI CODEC (i2s1) */ + i2s@70080400 { status = "okay"; }; + + /* BT SCO (i2s3) */ + i2s@70080600 { + status = "okay"; + }; + }; + + brcm_wifi_pwrseq: pwrseq-wifi { + compatible = "mmc-pwrseq-simple"; + + clocks = <&tegra_pmc TEGRA_PMC_CLK_BLINK>; + clock-names = "ext_clock"; + + reset-gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>; + post-power-on-delay-ms = <300>; + power-off-delay-us = <300>; }; + /* WiFi */ mmc@78000000 { - /* WiFi */ + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + assigned-clocks = <&tegra_car TEGRA114_CLK_SDMMC1>; + assigned-clock-parents = <&tegra_car TEGRA114_CLK_PLL_P>; + assigned-clock-rates = <82000000>; + + max-frequency = <82000000>; + keep-power-in-suspend; + bus-width = <4>; + non-removable; + + sd-uhs-ddr50; + mmc-ddr-1_8v; + + power-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_HIGH>; + + nvidia,default-tap = <0x2>; + nvidia,default-trim = <0x2>; + + mmc-pwrseq = <&brcm_wifi_pwrseq>; + vmmc-supply = <&vdd_3v3_com>; + vqmmc-supply = <&vdd_1v8_vio>; + + wifi@1 { + compatible = "brcm,bcm4329-fmac"; + reg = <1>; + + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(U, 5) IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wake"; + }; }; /* MicroSD card */ @@ -621,33 +1680,38 @@ nvidia,default-tap = <0x3>; nvidia,default-trim = <0x3>; - vmmc-supply = <&vdd_usd>; - vqmmc-supply = <&tps65913_ldo9>; - - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc3_default>; + vmmc-supply = <&vdd_2v9_usd>; + vqmmc-supply = <&vddio_usd>; }; + /* eMMC */ mmc@78000600 { - /* eMMC */ + status = "okay"; + bus-width = <8>; + + non-removable; + mmc-ddr-1_8v; + + vmmc-supply = <&vcore_emmc>; + vqmmc-supply = <&vdd_1v8_vio>; }; + /* Peripheral USB via ASUS connector */ usb@7d000000 { compatible = "nvidia,tegra114-udc"; status = "okay"; dr_mode = "peripheral"; - - /* Peripheral USB via ASUS connector */ }; usb-phy@7d000000 { status = "okay"; + dr_mode = "peripheral"; + vbus-supply = <&avdd_usb>; }; + /* Host USB via dock */ usb@7d008000 { status = "okay"; - - /* Host USB via dock */ }; usb-phy@7d008000 { @@ -658,16 +1722,12 @@ backlight: backlight { compatible = "pwm-backlight"; - enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>; - power-supply = <&vdd_5v0_sys>; + power-supply = <&vdd_3v7_bl>; pwms = <&pwm 1 1000000>; brightness-levels = <1 255>; num-interpolated-steps = <254>; default-brightness-level = <224>; - - pinctrl-names = "default"; - pinctrl-0 = <&backlight_default>; }; /* PMIC has a built-in 32KHz oscillator which is used by PMC */ @@ -678,13 +1738,22 @@ clock-output-names = "pmic-oscillator"; }; - gpio-hall-sensor { - compatible = "gpio-keys"; + connector { + compatible = "hdmi-connector"; + type = "d"; - label = "GPIO Hall Effect Sensor"; + hpd-gpios = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + ddc-i2c-bus = <&hdmi_ddc>; - pinctrl-names = "default"; - pinctrl-0 = <&gpio_hall_sensor_default>; + port { + connector_in: endpoint { + remote-endpoint = <&hdmi_out>; + }; + }; + }; + + extcon-keys { + compatible = "gpio-keys"; switch-hall-sensor { label = "Hall Effect Sensor"; @@ -694,17 +1763,20 @@ linux,can-disable; wakeup-source; }; + + switch-lineout-detect { + label = "Audio dock line-out detect"; + gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>; + linux,input-type = <EV_SW>; + linux,code = <SW_LINEOUT_INSERT>; + debounce-interval = <10>; + }; }; gpio-keys { compatible = "gpio-keys"; - label = "GPIO Buttons"; - - pinctrl-names = "default"; - pinctrl-0 = <&gpio_keys_default>; - - button-power { + key-power { label = "Power"; gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = <KEY_POWER>; @@ -712,14 +1784,14 @@ wakeup-source; }; - button-volume-down { + key-volume-down { label = "Volume Down"; gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEDOWN>; debounce-interval = <10>; }; - button-volume-up { + key-volume-up { label = "Volume Up"; gpios = <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEUP>; @@ -739,13 +1811,16 @@ "Speakers", "SPORN", "Speakers", "SPOLP", "Speakers", "SPOLN", - "Mic Jack", "MICBIAS1", - "IN2P", "Mic Jack"; + "IN1P", "Mic Jack", + "IN1N", "Mic Jack", + "DMIC1", "Int Mic", + "DMIC2", "Int Mic"; - nvidia,i2s-controller = <&tegra_i2s0>; + nvidia,i2s-controller = <&tegra_i2s1>; nvidia,audio-codec = <&rt5639>; nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_LOW>; + nvidia,int-mic-en-gpios = <&gpio TEGRA_GPIO(K, 3) GPIO_ACTIVE_HIGH>; clocks = <&tegra_car TEGRA114_CLK_PLL_A>, <&tegra_car TEGRA114_CLK_PLL_A_OUT0>, @@ -757,14 +1832,11 @@ assigned-clock-parents = <&tegra_car TEGRA114_CLK_PLL_A_OUT0>, <&tegra_car TEGRA114_CLK_EXTERN1>; - - pinctrl-names = "default"; - pinctrl-0 = <&hp_det_default>; }; vdd_5v0_sys: regulator-5v0-sys { compatible = "regulator-fixed"; - regulator-name = "vdd_5v0"; + regulator-name = "vdd_5v0_sys"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; @@ -773,37 +1845,119 @@ vdd_3v3_sys: regulator-3v3-sys { compatible = "regulator-fixed"; - regulator-name = "vdd_3v3"; + regulator-name = "vdd_3v3_sys"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; }; - vdd_lcd: regulator-vdd-lcd { + dvdd_1v8_lcd: regulator-vdd-lcd { compatible = "regulator-fixed"; - regulator-name = "vdd_lcd_1v8"; + regulator-name = "dvdd_1v8_lcd"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - vin-supply = <&tps65913_smps8>; + regulator-boot-on; + gpio = <&palmas_gpio 4 GPIO_ACTIVE_HIGH>; enable-active-high; - gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>; + vin-supply = <&vdd_1v8_vio>; + }; + + vdd_3v7_bl: regulator-bl-en { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v7_bl"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_5v0_sys>; + }; - pinctrl-names = "default"; - pinctrl-0 = <&vdd_lcd_default>; + hdmi_5v0_sys: regulator-hdmi { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v0_hdmi"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_smps10_out2>; }; - vdd_usd: regulator-vdd-usd { + vdd_2v9_usd: regulator-vdd-usd { compatible = "regulator-fixed"; regulator-name = "vdd_sd_slot"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; - vin-supply = <&tps65913_smps9>; - enable-active-high; + regulator-boot-on; gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vcore_emmc>; + }; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc3_vdd_default>; + vdd_1v8_cam: regulator-cam-vio { + compatible = "regulator-fixed"; + regulator-name = "vdd_1v8_cam"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + gpio = <&palmas_gpio 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_1v8_vio>; + }; + + vdd_1v2_xusb: regulator-xusb-vio { + compatible = "regulator-fixed"; + regulator-name = "avddio_1v2_xusb"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + gpio = <&palmas_gpio 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vdd_3v3_xusb: regulator-xusb-vdd { + compatible = "regulator-fixed"; + regulator-name = "hvdd_3v3_xusb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + gpio = <&palmas_gpio 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vdd_3v3_com: regulator-com { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3_com"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(U, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_3v3_sys>; + }; + + vdd_3v3_touch: regulator-touch-pwr { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3_touch"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_3v3_sys>; + }; + + vdd_1v8_touch: regulator-touch-vio { + compatible = "regulator-fixed"; + regulator-name = "vdd_1v8_touch"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + gpio = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_3v3_sys>; }; }; diff --git a/arch/arm/boot/dts/nvidia/tegra20-trimslice.dts b/arch/arm/boot/dts/nvidia/tegra20-trimslice.dts index 7cae6ad57544..4caeeb9f1e1d 100644 --- a/arch/arm/boot/dts/nvidia/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/nvidia/tegra20-trimslice.dts @@ -2,6 +2,7 @@ /dts-v1/; #include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> #include "tegra20.dtsi" #include "tegra20-cpu-opp.dtsi" @@ -201,16 +202,17 @@ conf_ata { nvidia,pins = "ata", "atc", "atd", "ate", "crtp", "dap2", "dap3", "dap4", "dta", - "dtb", "dtc", "dtd", "dte", "gmb", - "gme", "i2cp", "pta", "slxc", "slxd", - "spdi", "spdo", "uda"; + "dtb", "dtc", "dtd", "gmb", "gme", + "i2cp", "pta", "slxc", "slxd", "spdi", + "spdo", "uda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; conf_atb { nvidia,pins = "atb", "cdev1", "cdev2", "dap1", - "gma", "gmc", "gmd", "gpu", "gpu7", - "gpv", "sdio1", "slxa", "slxk", "uac"; + "dte", "gma", "gmc", "gmd", "gpu", + "gpu7", "gpv", "sdio1", "slxa", "slxk", + "uac"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; @@ -408,6 +410,24 @@ }; }; + leds { + compatible = "gpio-leds"; + + led-ds2 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <2>; + gpios = <&gpio TEGRA_GPIO(D, 2) GPIO_ACTIVE_LOW>; + }; + + led-ds3 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <3>; + gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_LOW>; + }; + }; + poweroff { compatible = "gpio-poweroff"; gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>; diff --git a/arch/arm/boot/dts/nxp/imx/imx1.dtsi b/arch/arm/boot/dts/nxp/imx/imx1.dtsi index 389ecb1ebf8f..a1a89ccacf05 100644 --- a/arch/arm/boot/dts/nxp/imx/imx1.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx1.dtsi @@ -134,7 +134,7 @@ clock-names = "ipg", "per"; }; - dma: dma@209000 { + dma: dma-controller@209000 { compatible = "fsl,imx1-dma"; reg = <0x00209000 0x1000>; interrupts = <61 60>; diff --git a/arch/arm/boot/dts/nxp/imx/imx27.dtsi b/arch/arm/boot/dts/nxp/imx/imx27.dtsi index ec3ccc8f4095..989b7659b669 100644 --- a/arch/arm/boot/dts/nxp/imx/imx27.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx27.dtsi @@ -88,7 +88,7 @@ reg = <0x10000000 0x20000>; ranges; - dma: dma@10001000 { + dma: dma-controller@10001000 { compatible = "fsl,imx27-dma"; reg = <0x10001000 0x1000>; interrupts = <32>; diff --git a/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts b/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts index 2117de872703..0d336cbdb451 100644 --- a/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts +++ b/arch/arm/boot/dts/nxp/imx/imx53-mba53.dts @@ -175,8 +175,8 @@ gpio-controller; }; - sensor2: lm75@49 { - compatible = "lm75"; + sensor2: temperature-sensor@49 { + compatible = "national,lm75b"; reg = <0x49>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx53-qsb-hdmi.dtso b/arch/arm/boot/dts/nxp/imx/imx53-qsb-hdmi.dtso index 151e9cee3c87..2527bfe13145 100644 --- a/arch/arm/boot/dts/nxp/imx/imx53-qsb-hdmi.dtso +++ b/arch/arm/boot/dts/nxp/imx/imx53-qsb-hdmi.dtso @@ -34,9 +34,7 @@ &display0 { status = "okay"; -}; -&display0 { port@1 { display0_out: endpoint { remote-endpoint = <&sii9022_in>; @@ -83,7 +81,3 @@ &panel_dpi { status = "disabled"; }; - -&tve { - status = "disabled"; -}; diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi index b2d7271d1d24..c34ee84bd716 100644 --- a/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx53-tqma53.dtsi @@ -254,8 +254,8 @@ interrupts = <6 4>; /* PATA_DATA6, active high */ }; - sensor1: lm75@48 { - compatible = "lm75"; + sensor1: temperature-sensor@48 { + compatible = "national,lm75b"; reg = <0x48>; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi index 52a0f6ee426f..bcf4d9c870ec 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp43-common.dtsi @@ -274,24 +274,24 @@ led@0 { chan-name = "R"; - led-cur = /bits/ 8 <0x20>; - max-cur = /bits/ 8 <0x60>; + led-cur = /bits/ 8 <0x6e>; + max-cur = /bits/ 8 <0xc8>; reg = <0>; color = <LED_COLOR_ID_RED>; }; led@1 { chan-name = "G"; - led-cur = /bits/ 8 <0x20>; - max-cur = /bits/ 8 <0x60>; + led-cur = /bits/ 8 <0xbe>; + max-cur = /bits/ 8 <0xc8>; reg = <1>; color = <LED_COLOR_ID_GREEN>; }; led@2 { chan-name = "B"; - led-cur = /bits/ 8 <0x20>; - max-cur = /bits/ 8 <0x60>; + led-cur = /bits/ 8 <0xbe>; + max-cur = /bits/ 8 <0xc8>; reg = <2>; color = <LED_COLOR_ID_BLUE>; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts index 95b49fc83f7b..299106fbe51c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts @@ -127,12 +127,21 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; - spdif-in; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts index a7d5693c5ab7..8d2b608e0b90 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts @@ -111,12 +111,21 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-in; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts index 7c298d9aa21e..5353a0c24420 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts @@ -90,11 +90,16 @@ ssi-controller = <&ssi1>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "On-board SPDIF"; - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi index ea40623d12e5..edf55760a5c1 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi @@ -197,11 +197,20 @@ ssi-controller = <&ssi1>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound_spdif: sound-spdif { compatible = "fsl,imx-audio-spdif"; - spdif-controller = <&spdif>; - spdif-in; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; model = "imx-spdif"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi index 3a46ade3b6bd..9e97ef5e43f2 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi @@ -121,11 +121,16 @@ mux-ext-port = <3>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi index 758eaf9d93d2..f7fac86f0a6b 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-aristainetos2.dtsi @@ -506,7 +506,7 @@ >; }; - pinctrl_gpmi_nand: gpmi-nand { + pinctrl_gpmi_nand: gpminandgrp { fsl,pins = < MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi index d3a7a6eeb8e0..b01670cdd52c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi @@ -142,12 +142,21 @@ ssi-controller = <&ssi1>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + /* Optional S/PDIF in on SODIMM 88 and out on SODIMM 90, 137 or 168 */ sound_spdif: sound-spdif { compatible = "fsl,imx-audio-spdif"; - spdif-controller = <&spdif>; - spdif-in; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; model = "imx-spdif"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi index 761566ae3cf5..bd66430c1d78 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi @@ -100,12 +100,17 @@ vin-supply = <&v_5v0>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "Integrated SPDIF"; /* IMX6 doesn't implement this yet */ - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; gpio-keys { diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi index 082a2e3a391f..b57f4073f881 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw52xx.dtsi @@ -761,7 +761,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x170b9 @@ -774,7 +774,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi index 8ec442038ea0..090c0057d117 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw53xx.dtsi @@ -750,7 +750,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -763,7 +763,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi index 9df9f79affae..0ed6d25024a2 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw54xx.dtsi @@ -833,7 +833,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -846,7 +846,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi index 7f16c602cc07..c6e231de674a 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi @@ -704,7 +704,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -717,7 +717,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi index 7693f92195d5..d0f648938cae 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi @@ -896,7 +896,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -909,7 +909,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi index 9d0836df0fed..71911df881cc 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5903.dtsi @@ -680,7 +680,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x4001b0b0 /* EMMY_EN */ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x4001b0b0 /* EMMY_CFG1# */ @@ -710,7 +710,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9 MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9 @@ -723,7 +723,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9 MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9 @@ -752,7 +752,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -768,7 +768,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi index f4cb9e1d34a9..716c324a7458 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5904.dtsi @@ -817,7 +817,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -833,7 +833,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi index 424dc7fcd533..453dee4d9227 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5910.dtsi @@ -629,7 +629,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x170b9 @@ -642,7 +642,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi index 49ea25c71967..add700bc11cc 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw5912.dtsi @@ -569,7 +569,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -582,7 +582,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi index a955c77cd499..d1ad65ab6b72 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi @@ -140,12 +140,17 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "On-board SPDIF"; /* IMX6 doesn't implement this yet */ - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi index d339957cc097..dff184a119f3 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-icore-rqs.dtsi @@ -397,7 +397,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170B1 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100B1 @@ -408,7 +408,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170F9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100F9 @@ -434,7 +434,7 @@ >; }; - pinctrl_usdhc4_100mhz: usdhc4grp_100mhz { + pinctrl_usdhc4_100mhz: usdhc4-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD4_CMD__SD4_CMD 0x170B1 MX6QDL_PAD_SD4_CLK__SD4_CLK 0x100B1 @@ -449,7 +449,7 @@ >; }; - pinctrl_usdhc4_200mhz: usdhc4grp_200mhz { + pinctrl_usdhc4_200mhz: usdhc4-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD4_CMD__SD4_CMD 0x170F9 MX6QDL_PAD_SD4_CLK__SD4_CLK 0x100F9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi index 807f3c95e3ce..aca320ee8f47 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6a.dtsi @@ -13,7 +13,7 @@ &i2c1 { lm75: temperature-sensor@49 { - compatible = "national,lm75"; + compatible = "national,lm75a"; reg = <0x49>; vs-supply = <®_mba6_3p3v>; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi index 789733a45b95..c7bbd6195fef 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-mba6b.dtsi @@ -23,7 +23,7 @@ &i2c3 { lm75: temperature-sensor@49 { - compatible = "national,lm75"; + compatible = "national,lm75a"; reg = <0x49>; vs-supply = <®_mba6_3p3v>; }; @@ -50,12 +50,3 @@ reg = <0x68>; }; }; - -&iomuxc { - pinctrl_i2c1: i2c1grp { - fsl,pins = < - MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b899 - MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b899 - >; - }; -}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi index 0a3deaf92eea..35b6bec7a3fa 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi @@ -143,12 +143,17 @@ "AIN2R", "Line In Jack"; }; + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-sabreauto-spdif", "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-in; + audio-cpu = <&spdif>; + audio-codec = <&spdif_in>; }; backlight { @@ -690,7 +695,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -705,7 +710,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi index 344ea935c7da..6152a9ed4768 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6.dtsi @@ -59,20 +59,6 @@ >; }; - pinctrl_i2c3: i2c3grp { - fsl,pins = < - MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b899 - MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b899 - >; - }; - - pinctrl_i2c3_recovery: i2c3recoverygrp { - fsl,pins = < - MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x4001b899 - MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x4001b899 - >; - }; - pinctrl_pmic: pmicgrp { fsl,pins = < MX6QDL_PAD_NANDF_RB0__GPIO6_IO10 0x1b099 /* PMIC irq */ diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi index 68525f0205d3..828996382f24 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6a.dtsi @@ -27,8 +27,8 @@ reg = <0x08>; }; - sensor@48 { - compatible = "national,lm75"; + temperature-sensor@48 { + compatible = "national,lm75a"; reg = <0x48>; vs-supply = <®_3p3v>; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi index aeba0a273600..1d0966b8d99e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tqma6b.dtsi @@ -20,8 +20,8 @@ reg = <0x08>; }; - sensor@48 { - compatible = "national,lm75"; + temperature-sensor@48 { + compatible = "national,lm75a"; reg = <0x48>; vs-supply = <®_3p3v>; }; @@ -33,3 +33,19 @@ vcc-supply = <®_3p3v>; }; }; + +&iomuxc { + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b899 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b899 + >; + }; + + pinctrl_i2c3_recovery: i2c3recoverygrp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x4001b899 + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x4001b899 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi index e2fe337f7d9e..5a194f4c0cb9 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi @@ -373,7 +373,7 @@ >; }; - pinctrl_disp0_1: disp0grp-1 { + pinctrl_disp0_1: disp0-1-grp { fsl,pins = < MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 @@ -406,7 +406,7 @@ >; }; - pinctrl_disp0_2: disp0grp-2 { + pinctrl_disp0_2: disp0-2-grp { fsl,pins = < MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi index 200559d7158d..d8283eade43e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-dart.dtsi @@ -346,7 +346,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170B9 MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100B9 @@ -357,7 +357,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170F9 MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100F9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi index a1ea33c4eeb7..59833e8d11d8 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-var-som.dtsi @@ -436,7 +436,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhzgrp { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170B9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100B9 @@ -451,7 +451,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhzgrp { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170F9 MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100F9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi index 38abb6b50f6c..7130b9c3b3aa 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi @@ -26,11 +26,16 @@ mux-ext-port = <3>; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; reg_1p5v: regulator-1p5v { diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts index 31eee0419af7..7c899291ab0d 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sl-evk.dts @@ -457,7 +457,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9 MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9 @@ -472,7 +472,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9 MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9 @@ -498,7 +498,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9 MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9 @@ -509,7 +509,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9 MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9 @@ -531,7 +531,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9 MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9 @@ -542,7 +542,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9 MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts index 9d7c8884892a..2545c0fe47c8 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sl-warp.dts @@ -166,7 +166,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170b9 MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100b9 @@ -182,7 +182,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX6SL_PAD_SD2_CMD__SD2_CMD 0x4170f9 MX6SL_PAD_SD2_CLK__SD2_CLK 0x4100f9 @@ -209,7 +209,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170b9 MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100b9 @@ -220,7 +220,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX6SL_PAD_SD3_CMD__SD3_CMD 0x4170f9 MX6SL_PAD_SD3_CLK__SD3_CLK 0x4100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts b/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts index b0c27b9b0244..dfbfb8119bf3 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts @@ -97,11 +97,16 @@ "AIN2R", "Line In Jack"; }; + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-in; + audio-cpu = <&spdif>; + audio-codec = <&spdif_in>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi index 7d4170c27732..277a6e039045 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi @@ -183,12 +183,17 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx6sx-sdb-spdif", "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi index 725d0b5cb55f..bbf792ac4896 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi @@ -72,6 +72,11 @@ }; }; +&clks { + assigned-clocks = <&clks IMX6SX_CLK_ENET_REF>; + assigned-clock-rates = <50000000>; +}; + &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet1>; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi index 9cfb99ac9e9d..b74ee8948a78 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi @@ -608,7 +608,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -620,7 +620,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts index ad7f63ca521a..0d3b1ab82eab 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcexpress.dts @@ -112,7 +112,7 @@ >; }; - pinctrl_ecspi3_master: ecspi3grp1 { + pinctrl_ecspi3_master: ecspi3-1-grp { fsl,pins = < MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0 MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0 @@ -121,7 +121,7 @@ >; }; - pinctrl_ecspi3_slave: ecspi3grp2 { + pinctrl_ecspi3_slave: ecspi3-2-grp { fsl,pins = < MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b0 MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b0 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts index ed61ae8524fa..8aea8c99e2af 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsbcpro.dts @@ -248,7 +248,7 @@ >; }; - pinctrl_ecspi1_master: ecspi1grp1 { + pinctrl_ecspi1_master: ecspi1-1-grp { fsl,pins = < MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK 0x10b0 MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI 0x10b0 @@ -309,7 +309,7 @@ >; }; - pinctrl_lcdif_dat0_17: lcdifdatgrp0-17 { + pinctrl_lcdif_dat0_17: lcdifdat0-17-grp { fsl,pins = < MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79 MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79 @@ -332,14 +332,14 @@ >; }; - pinctrl_lcdif_clken: lcdifctrlgrp1 { + pinctrl_lcdif_clken: lcdifctrl-1-grp { fsl,pins = < MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x17050 MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79 >; }; - pinctrl_lcdif_hvsync: lcdifctrlgrp2 { + pinctrl_lcdif_hvsync: lcdifctrl-2-grp { fsl,pins = < MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79 MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79 @@ -370,7 +370,7 @@ >; }; - pinctrl_sai2_sleep: sai2grp-sleep { + pinctrl_sai2_sleep: sai2-sleep-grp { fsl,pins = < MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x3000 MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x3000 @@ -381,7 +381,7 @@ >; }; - pinctrl_uart2_4wires: uart2grp-4wires { + pinctrl_uart2_4wires: uart2-4wires-grp { fsl,pins = < MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 @@ -390,7 +390,7 @@ >; }; - pinctrl_uart3_2wires: uart3grp-2wires { + pinctrl_uart3_2wires: uart3-2wires-grp { fsl,pins = < MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi index 4a03ea6d24dc..9cc3eebb6b05 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-ccimx6ulsom.dtsi @@ -232,7 +232,7 @@ >; }; - pinctrl_usdhc1_sleep: usdhc1grp-sleep { + pinctrl_usdhc1_sleep: usdhc1-sleep-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__GPIO2_IO16 0x3000 MX6UL_PAD_SD1_CLK__GPIO2_IO17 0x3000 @@ -250,7 +250,7 @@ >; }; - pinctrl_wifibt_ctrl_sleep: wifibt-ctrl-grp-sleep { + pinctrl_wifibt_ctrl_sleep: wifibt-ctrl-sleep-grp { fsl,pins = < MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x3000 MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x3000 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts index cdbb8c435cd6..2a6bb5ff808a 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-geam.dts @@ -365,7 +365,7 @@ }; pinctrl_tsc: tscgrp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0 MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0 MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0 @@ -410,7 +410,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -421,7 +421,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi index ee86c36205f9..118df2a457c9 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-isiot.dtsi @@ -346,7 +346,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -357,7 +357,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi index d8f7877349c9..29d2f86d5e34 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi @@ -351,7 +351,7 @@ >; }; - pinctrl_usbotg1: usbotg1 { + pinctrl_usbotg1: usbotg1grp { fsl,pins = < MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0 >; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts index 1d863a16bcf0..5e62272acfba 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-liteboard.dts @@ -100,7 +100,7 @@ >; }; - pinctrl_usb_otg1_vbus: usb-otg1-vbus { + pinctrl_usb_otg1_vbus: usb-otg1-vbus-grp { fsl,pins = < MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08 0x79 >; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi index 04477fd4b9a9..4a45fb784ff7 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin-peb-wlbt-05.dtsi @@ -31,7 +31,7 @@ >; }; - pinctrl_uart2_bt: uart2grp-bt { + pinctrl_uart2_bt: uart2-bt-grp { fsl,pins = < MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x17059 MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x17059 @@ -40,7 +40,7 @@ >; }; - pinctrl_usdhc2_wl: usdhc2grp-wl { + pinctrl_usdhc2_wl: usdhc2-wl-grp { fsl,pins = < MX6UL_PAD_LCD_DATA18__USDHC2_CMD 0x10051 MX6UL_PAD_LCD_DATA19__USDHC2_CLK 0x10061 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi index 38ea4dcfa228..bef5eb38a90d 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-phytec-segin.dtsi @@ -219,7 +219,7 @@ >; }; - pinctrl_flexcan1: flexcan1 { + pinctrl_flexcan1: flexcan1grp { fsl,pins = < MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x0b0b0 MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x0b0b0 @@ -275,7 +275,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -286,7 +286,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi index 57e647fc3237..c9c0794f01a2 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tqma6ul-common.dtsi @@ -202,7 +202,7 @@ >; }; - pinctrl_pmic: pmic { + pinctrl_pmic: pmicgrp { fsl,pins = < /* PMIC irq */ MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x1b099 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts index ef76ece21010..20c810a81403 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-mainboard.dts @@ -198,7 +198,7 @@ >; }; - pinctrl_disp0_3: disp0grp-3 { + pinctrl_disp0_3: disp0-3-grp { fsl,pins = < MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi index 864173e30709..278120404d31 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi @@ -578,19 +578,13 @@ }; &iomuxc { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - - pinctrl_hog: hoggrp { - }; - pinctrl_led: ledgrp { fsl,pins = < MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x0b0b0 /* LED */ >; }; - pinctrl_disp0_1: disp0grp-1 { + pinctrl_disp0_1: disp0-1-grp { fsl,pins = < MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ @@ -623,7 +617,7 @@ >; }; - pinctrl_disp0_2: disp0grp-2 { + pinctrl_disp0_2: disp0-2-grp { fsl,pins = < MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x10 /* LSCLK */ MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x10 /* OE_ACD */ @@ -713,25 +707,25 @@ >; }; - pinctrl_etnphy0_int: etnphy-intgrp-0 { + pinctrl_etnphy0_int: etnphy-int-0-grp { fsl,pins = < MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05 0x0b0b0 /* ETN PHY INT */ >; }; - pinctrl_etnphy0_rst: etnphy-rstgrp-0 { + pinctrl_etnphy0_rst: etnphy-rst-0-grp { fsl,pins = < MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x0b0b0 /* ETN PHY RESET */ >; }; - pinctrl_etnphy1_int: etnphy-intgrp-1 { + pinctrl_etnphy1_int: etnphy-int-1-grp { fsl,pins = < MX6UL_PAD_CSI_DATA06__GPIO4_IO27 0x0b0b0 /* ETN PHY INT */ >; }; - pinctrl_etnphy1_rst: etnphy-rstgrp-1 { + pinctrl_etnphy1_rst: etnphy-rst-1-grp { fsl,pins = < MX6UL_PAD_CSI_DATA07__GPIO4_IO28 0x0b0b0 /* ETN PHY RESET */ >; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi index d03694feaf5c..83b9de17cee2 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-myir-mys-6ulx.dtsi @@ -169,7 +169,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -180,7 +180,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 @@ -206,7 +206,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9 MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9 @@ -221,7 +221,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9 MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi index 6bb12e0bbc7e..28fddbcdc55e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi-dev-board.dtsi @@ -323,7 +323,7 @@ >; }; - pinctrl_reg_vmmc: usdhc1regvmmc { + pinctrl_reg_vmmc: usdhc1regvmmc-grp { fsl,pins = < MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059 >; @@ -339,14 +339,14 @@ }; pinctrl_uart1: uart1grp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1 MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1 >; }; pinctrl_uart2: uart2grp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 MX6UL_PAD_UART2_CTS_B__UART2_DCE_CTS 0x1b0b1 @@ -355,7 +355,7 @@ }; pinctrl_uart3: uart3grp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 @@ -364,21 +364,21 @@ }; pinctrl_uart4: uart4grp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX 0x1b0b1 >; }; pinctrl_uart5: uart5grp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 >; }; pinctrl_usb_otg1_id: usbotg1idgrp { - fsl,pin = < + fsl,pins = < MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 >; }; @@ -394,7 +394,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170b9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100b9 @@ -405,7 +405,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x170f9 MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x100f9 @@ -416,7 +416,7 @@ >; }; - pinctrl_usdhc1_cd: usdhc1cd { + pinctrl_usdhc1_cd: usdhc1cd-grp { fsl,pins = < MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059 >; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi.dtsi index f5ad6b5c1ad0..278152875f8e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-seeed-npi.dtsi @@ -102,7 +102,7 @@ >; }; - pinctrl_reg_vqmmc: usdhc1regvqmmc { + pinctrl_reg_vqmmc: usdhc1regvqmmcgrp { fsl,pins = < MX6UL_PAD_GPIO1_IO05__GPIO1_IO05 0x17059 >; @@ -123,7 +123,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100b9 MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170b9 @@ -138,7 +138,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9 MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9 diff --git a/arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts b/arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts index c92e4e2f6ab9..6159ed70d966 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6ulz-bsh-smm-m2.dts @@ -94,7 +94,7 @@ }; &iomuxc { - pinctrl_gpmi_nand: gpmi-nand { + pinctrl_gpmi_nand: gpminandgrp { fsl,pins = < MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1 MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1 diff --git a/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi index 9fe51884af79..62e41edcaf1d 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-colibri.dtsi @@ -903,7 +903,7 @@ >; }; - pinctrl_lvds_transceiver: lvdstx { + pinctrl_lvds_transceiver: lvdstxgrp { fsl,pins = < MX7D_PAD_ENET1_RGMII_RD2__GPIO7_IO2 0x14 /* SODIMM 63 */ MX7D_PAD_ENET1_RGMII_RD3__GPIO7_IO3 0x74 /* SODIMM 55 */ diff --git a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi index 52869e68f833..e1c401f468e1 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi @@ -81,6 +81,12 @@ }; }; + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>, + <&adc2 0>, <&adc2 1>, <&adc2 2>, <&adc2 3>; + }; + reg_sd1_vmmc: regulator-sd1-vmmc { compatible = "regulator-fixed"; regulator-name = "VCC3V3_SD1"; @@ -310,7 +316,7 @@ &i2c1 { lm75: temperature-sensor@49 { - compatible = "national,lm75"; + compatible = "national,lm75a"; reg = <0x49>; vs-supply = <®_vcc_3v3>; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts index 9c6476bda4a0..7ee66be8bccb 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts @@ -419,7 +419,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog_1 &pinctrl_j2>; - pinctrl_hog_1: hoggrp-1 { + pinctrl_hog_1: hoggrp { fsl,pins = < MX7D_PAD_SD3_RESET_B__GPIO6_IO11 0x5d MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x7d @@ -665,7 +665,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog_2>; - pinctrl_hog_2: hoggrp-2 { + pinctrl_hog_2: hoggrp { fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x7d MX7D_PAD_LPSR_GPIO1_IO03__CCM_CLKO2 0x7d diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi index 8d5037ac03c7..a1574ccec89c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico.dtsi @@ -444,14 +444,14 @@ >; }; - pinctrl_can1: can1frp { + pinctrl_can1: can1frpgrp { fsl,pins = < MX7D_PAD_SAI1_RX_DATA__FLEXCAN1_RX 0x59 MX7D_PAD_SAI1_TX_BCLK__FLEXCAN1_TX 0x59 >; }; - pinctrl_can2: can2frp { + pinctrl_can2: can2frpgrp { fsl,pins = < MX7D_PAD_SAI1_TX_SYNC__FLEXCAN2_RX 0x59 MX7D_PAD_SAI1_TX_DATA__FLEXCAN2_TX 0x59 @@ -499,19 +499,19 @@ >; }; - pinctrl_pwm1: pwm1 { + pinctrl_pwm1: pwm1grp { fsl,pins = < MX7D_PAD_GPIO1_IO08__PWM1_OUT 0x7f >; }; - pinctrl_pwm2: pwm2 { + pinctrl_pwm2: pwm2grp { fsl,pins = < MX7D_PAD_GPIO1_IO09__PWM2_OUT 0x7f >; }; - pinctrl_pwm3: pwm3 { + pinctrl_pwm3: pwm3grp { fsl,pins = < MX7D_PAD_GPIO1_IO10__PWM3_OUT 0x7f >; @@ -563,7 +563,7 @@ >; }; - pinctrl_usbotg1_pwr: usbotg_pwr { + pinctrl_usbotg1_pwr: usbotgpwrgrp { fsl,pins = < MX7D_PAD_UART3_TX_DATA__GPIO4_IO5 0x14 >; @@ -581,7 +581,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp_100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX7D_PAD_SD1_CMD__SD1_CMD 0x5a MX7D_PAD_SD1_CLK__SD1_CLK 0x1a @@ -593,7 +593,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp_200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX7D_PAD_SD1_CMD__SD1_CMD 0x5b MX7D_PAD_SD1_CLK__SD1_CLK 0x1b @@ -631,7 +631,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5a MX7D_PAD_SD3_CLK__SD3_CLK 0x1a @@ -646,7 +646,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5b MX7D_PAD_SD3_CLK__SD3_CLK 0x1b diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts index 92cb45dacda6..eec526a96311 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-remarkable2.dts @@ -508,7 +508,7 @@ >; }; - pinctrl_usdhc2_100mhz: usdhc2grp_100mhz { + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { fsl,pins = < MX7D_PAD_SD2_CMD__SD2_CMD 0x5a MX7D_PAD_SD2_CLK__SD2_CLK 0x1a @@ -519,7 +519,7 @@ >; }; - pinctrl_usdhc2_200mhz: usdhc2grp_200mhz { + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { fsl,pins = < MX7D_PAD_SD2_CMD__SD2_CMD 0x5b MX7D_PAD_SD2_CLK__SD2_CLK 0x1b @@ -546,7 +546,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5a MX7D_PAD_SD3_CLK__SD3_CLK 0x1a @@ -562,7 +562,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5b MX7D_PAD_SD3_CLK__SD3_CLK 0x1b diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts index cabdaa6dc518..40156cd9195f 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-sdb-reva.dts @@ -21,23 +21,21 @@ }; &iomuxc { - imx7d-sdb { - pinctrl_tsc2046_pendown: tsc2046_pendown { - fsl,pins = < - MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x59 - >; - }; - - pinctrl_hog: hoggrp { - fsl,pins = < - MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */ - >; - }; - - pinctrl_usb_otg2_vbus_reg_reva: usbotg2vbusregrevagrp { - fsl,pins = < - MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14 - >; - }; + pinctrl_tsc2046_pendown: tsc2046-pendowngrp { + fsl,pins = < + MX7D_PAD_EPDC_DATA13__GPIO2_IO13 0x59 + >; + }; + + pinctrl_hog: hoggrp { + fsl,pins = < + MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */ + >; + }; + + pinctrl_usb_otg2_vbus_reg_reva: usbotg2vbusregrevagrp { + fsl,pins = < + MX7D_PAD_UART3_CTS_B__GPIO4_IO7 0x14 + >; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts b/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts index 0462e43ec09b..f712537fca16 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-sdb.dts @@ -537,342 +537,340 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; - imx7d-sdb { - pinctrl_brcm_reg: brcmreggrp { - fsl,pins = < - MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x14 - >; - }; + pinctrl_brcm_reg: brcmreggrp { + fsl,pins = < + MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21 0x14 + >; + }; - pinctrl_ecspi3: ecspi3grp { - fsl,pins = < - MX7D_PAD_SAI2_TX_SYNC__ECSPI3_MISO 0x2 - MX7D_PAD_SAI2_TX_BCLK__ECSPI3_MOSI 0x2 - MX7D_PAD_SAI2_RX_DATA__ECSPI3_SCLK 0x2 - MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x59 - >; - }; + pinctrl_ecspi3: ecspi3grp { + fsl,pins = < + MX7D_PAD_SAI2_TX_SYNC__ECSPI3_MISO 0x2 + MX7D_PAD_SAI2_TX_BCLK__ECSPI3_MOSI 0x2 + MX7D_PAD_SAI2_RX_DATA__ECSPI3_SCLK 0x2 + MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x59 + >; + }; - pinctrl_enet1: enet1grp { - fsl,pins = < - MX7D_PAD_GPIO1_IO10__ENET1_MDIO 0x3 - MX7D_PAD_GPIO1_IO11__ENET1_MDC 0x3 - MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1 - MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1 - MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1 - MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1 - MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1 - MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1 - MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1 - MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1 - MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1 - MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1 - MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1 - MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1 - >; - }; + pinctrl_enet1: enet1grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO10__ENET1_MDIO 0x3 + MX7D_PAD_GPIO1_IO11__ENET1_MDC 0x3 + MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1 + MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1 + MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1 + MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1 + MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1 + MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1 + MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1 + MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1 + MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1 + MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1 + MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1 + MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1 + >; + }; - pinctrl_enet2: enet2grp { - fsl,pins = < - MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC 0x1 - MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x1 - MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x1 - MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2 0x1 - MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3 0x1 - MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x1 - MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC 0x1 - MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x1 - MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x1 - MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2 0x1 - MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3 0x1 - MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x1 - >; - }; + pinctrl_enet2: enet2grp { + fsl,pins = < + MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC 0x1 + MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x1 + MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x1 + MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2 0x1 + MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3 0x1 + MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x1 + MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC 0x1 + MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x1 + MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x1 + MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2 0x1 + MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3 0x1 + MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x1 + >; + }; - pinctrl_enet2_reg: enet2reggrp { - fsl,pins = < - MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x14 - >; - }; + pinctrl_enet2_reg: enet2reggrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x14 + >; + }; - pinctrl_flexcan2: flexcan2grp { - fsl,pins = < - MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x59 - MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x59 - >; - }; + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX 0x59 + MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX 0x59 + >; + }; - pinctrl_flexcan2_reg: flexcan2reggrp { - fsl,pins = < - MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x59 /* CAN_STBY */ - >; - }; + pinctrl_flexcan2_reg: flexcan2reggrp { + fsl,pins = < + MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x59 /* CAN_STBY */ + >; + }; - pinctrl_gpio_keys: gpio_keysgrp { - fsl,pins = < - MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59 - MX7D_PAD_SD2_WP__GPIO5_IO10 0x59 - >; - }; + pinctrl_gpio_keys: gpio-keysgrp { + fsl,pins = < + MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59 + MX7D_PAD_SD2_WP__GPIO5_IO10 0x59 + >; + }; - pinctrl_hog: hoggrp { - fsl,pins = < - MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */ - MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x59 /* headphone detect */ - >; - }; + pinctrl_hog: hoggrp { + fsl,pins = < + MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x34 /* bt reg on */ + MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x59 /* headphone detect */ + >; + }; - pinctrl_i2c1: i2c1grp { - fsl,pins = < - MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f - MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f - >; - }; + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f + MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f + >; + }; - pinctrl_i2c2: i2c2grp { - fsl,pins = < - MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f - MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f - >; - }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f + MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f + >; + }; - pinctrl_i2c3: i2c3grp { - fsl,pins = < - MX7D_PAD_I2C3_SDA__I2C3_SDA 0x4000007f - MX7D_PAD_I2C3_SCL__I2C3_SCL 0x4000007f - >; - }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX7D_PAD_I2C3_SDA__I2C3_SDA 0x4000007f + MX7D_PAD_I2C3_SCL__I2C3_SCL 0x4000007f + >; + }; - pinctrl_i2c4: i2c4grp { - fsl,pins = < - MX7D_PAD_SAI1_RX_BCLK__I2C4_SDA 0x4000007f - MX7D_PAD_SAI1_RX_SYNC__I2C4_SCL 0x4000007f - >; - }; + pinctrl_i2c4: i2c4grp { + fsl,pins = < + MX7D_PAD_SAI1_RX_BCLK__I2C4_SDA 0x4000007f + MX7D_PAD_SAI1_RX_SYNC__I2C4_SCL 0x4000007f + >; + }; - pinctrl_lcdif: lcdifgrp { - fsl,pins = < - MX7D_PAD_LCD_DATA00__LCD_DATA0 0x79 - MX7D_PAD_LCD_DATA01__LCD_DATA1 0x79 - MX7D_PAD_LCD_DATA02__LCD_DATA2 0x79 - MX7D_PAD_LCD_DATA03__LCD_DATA3 0x79 - MX7D_PAD_LCD_DATA04__LCD_DATA4 0x79 - MX7D_PAD_LCD_DATA05__LCD_DATA5 0x79 - MX7D_PAD_LCD_DATA06__LCD_DATA6 0x79 - MX7D_PAD_LCD_DATA07__LCD_DATA7 0x79 - MX7D_PAD_LCD_DATA08__LCD_DATA8 0x79 - MX7D_PAD_LCD_DATA09__LCD_DATA9 0x79 - MX7D_PAD_LCD_DATA10__LCD_DATA10 0x79 - MX7D_PAD_LCD_DATA11__LCD_DATA11 0x79 - MX7D_PAD_LCD_DATA12__LCD_DATA12 0x79 - MX7D_PAD_LCD_DATA13__LCD_DATA13 0x79 - MX7D_PAD_LCD_DATA14__LCD_DATA14 0x79 - MX7D_PAD_LCD_DATA15__LCD_DATA15 0x79 - MX7D_PAD_LCD_DATA16__LCD_DATA16 0x79 - MX7D_PAD_LCD_DATA17__LCD_DATA17 0x79 - MX7D_PAD_LCD_DATA18__LCD_DATA18 0x79 - MX7D_PAD_LCD_DATA19__LCD_DATA19 0x79 - MX7D_PAD_LCD_DATA20__LCD_DATA20 0x79 - MX7D_PAD_LCD_DATA21__LCD_DATA21 0x79 - MX7D_PAD_LCD_DATA22__LCD_DATA22 0x79 - MX7D_PAD_LCD_DATA23__LCD_DATA23 0x79 - MX7D_PAD_LCD_CLK__LCD_CLK 0x79 - MX7D_PAD_LCD_ENABLE__LCD_ENABLE 0x79 - MX7D_PAD_LCD_VSYNC__LCD_VSYNC 0x79 - MX7D_PAD_LCD_HSYNC__LCD_HSYNC 0x79 - MX7D_PAD_LCD_RESET__LCD_RESET 0x79 - >; - }; + pinctrl_lcdif: lcdifgrp { + fsl,pins = < + MX7D_PAD_LCD_DATA00__LCD_DATA0 0x79 + MX7D_PAD_LCD_DATA01__LCD_DATA1 0x79 + MX7D_PAD_LCD_DATA02__LCD_DATA2 0x79 + MX7D_PAD_LCD_DATA03__LCD_DATA3 0x79 + MX7D_PAD_LCD_DATA04__LCD_DATA4 0x79 + MX7D_PAD_LCD_DATA05__LCD_DATA5 0x79 + MX7D_PAD_LCD_DATA06__LCD_DATA6 0x79 + MX7D_PAD_LCD_DATA07__LCD_DATA7 0x79 + MX7D_PAD_LCD_DATA08__LCD_DATA8 0x79 + MX7D_PAD_LCD_DATA09__LCD_DATA9 0x79 + MX7D_PAD_LCD_DATA10__LCD_DATA10 0x79 + MX7D_PAD_LCD_DATA11__LCD_DATA11 0x79 + MX7D_PAD_LCD_DATA12__LCD_DATA12 0x79 + MX7D_PAD_LCD_DATA13__LCD_DATA13 0x79 + MX7D_PAD_LCD_DATA14__LCD_DATA14 0x79 + MX7D_PAD_LCD_DATA15__LCD_DATA15 0x79 + MX7D_PAD_LCD_DATA16__LCD_DATA16 0x79 + MX7D_PAD_LCD_DATA17__LCD_DATA17 0x79 + MX7D_PAD_LCD_DATA18__LCD_DATA18 0x79 + MX7D_PAD_LCD_DATA19__LCD_DATA19 0x79 + MX7D_PAD_LCD_DATA20__LCD_DATA20 0x79 + MX7D_PAD_LCD_DATA21__LCD_DATA21 0x79 + MX7D_PAD_LCD_DATA22__LCD_DATA22 0x79 + MX7D_PAD_LCD_DATA23__LCD_DATA23 0x79 + MX7D_PAD_LCD_CLK__LCD_CLK 0x79 + MX7D_PAD_LCD_ENABLE__LCD_ENABLE 0x79 + MX7D_PAD_LCD_VSYNC__LCD_VSYNC 0x79 + MX7D_PAD_LCD_HSYNC__LCD_HSYNC 0x79 + MX7D_PAD_LCD_RESET__LCD_RESET 0x79 + >; + }; - pinctrl_sai1: sai1grp { - fsl,pins = < - MX7D_PAD_SAI1_MCLK__SAI1_MCLK 0x1f - MX7D_PAD_ENET1_RX_CLK__SAI1_TX_BCLK 0x1f - MX7D_PAD_ENET1_CRS__SAI1_TX_SYNC 0x1f - MX7D_PAD_ENET1_COL__SAI1_TX_DATA0 0x30 - MX7D_PAD_ENET1_TX_CLK__SAI1_RX_DATA0 0x1f - >; - }; + pinctrl_sai1: sai1grp { + fsl,pins = < + MX7D_PAD_SAI1_MCLK__SAI1_MCLK 0x1f + MX7D_PAD_ENET1_RX_CLK__SAI1_TX_BCLK 0x1f + MX7D_PAD_ENET1_CRS__SAI1_TX_SYNC 0x1f + MX7D_PAD_ENET1_COL__SAI1_TX_DATA0 0x30 + MX7D_PAD_ENET1_TX_CLK__SAI1_RX_DATA0 0x1f + >; + }; - pinctrl_sai2: sai2grp { - fsl,pins = < - MX7D_PAD_SAI2_TX_BCLK__SAI2_TX_BCLK 0x1f - MX7D_PAD_SAI2_TX_SYNC__SAI2_TX_SYNC 0x1f - MX7D_PAD_SAI2_TX_DATA__SAI2_TX_DATA0 0x30 - MX7D_PAD_SAI2_RX_DATA__SAI2_RX_DATA0 0x1f - >; - }; + pinctrl_sai2: sai2grp { + fsl,pins = < + MX7D_PAD_SAI2_TX_BCLK__SAI2_TX_BCLK 0x1f + MX7D_PAD_SAI2_TX_SYNC__SAI2_TX_SYNC 0x1f + MX7D_PAD_SAI2_TX_DATA__SAI2_TX_DATA0 0x30 + MX7D_PAD_SAI2_RX_DATA__SAI2_RX_DATA0 0x1f + >; + }; - pinctrl_sai3: sai3grp { - fsl,pins = < - MX7D_PAD_UART3_TX_DATA__SAI3_TX_BCLK 0x1f - MX7D_PAD_UART3_CTS_B__SAI3_TX_SYNC 0x1f - MX7D_PAD_UART3_RTS_B__SAI3_TX_DATA0 0x30 - >; - }; + pinctrl_sai3: sai3grp { + fsl,pins = < + MX7D_PAD_UART3_TX_DATA__SAI3_TX_BCLK 0x1f + MX7D_PAD_UART3_CTS_B__SAI3_TX_SYNC 0x1f + MX7D_PAD_UART3_RTS_B__SAI3_TX_DATA0 0x30 + >; + }; - pinctrl_spi4: spi4grp { - fsl,pins = < - MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59 - MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59 - MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59 - >; - }; + pinctrl_spi4: spi4grp { + fsl,pins = < + MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59 + MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59 + MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59 + >; + }; - pinctrl_tsc2046_pendown: tsc2046_pendown { - fsl,pins = < - MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x59 - >; - }; + pinctrl_tsc2046_pendown: tsc2046-pendowngrp { + fsl,pins = < + MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x59 + >; + }; - pinctrl_uart1: uart1grp { - fsl,pins = < - MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79 - MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79 - >; - }; + pinctrl_uart1: uart1grp { + fsl,pins = < + MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79 + MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79 + >; + }; - pinctrl_uart5: uart5grp { - fsl,pins = < - MX7D_PAD_SAI1_TX_BCLK__UART5_DCE_TX 0x79 - MX7D_PAD_SAI1_RX_DATA__UART5_DCE_RX 0x79 - MX7D_PAD_SAI1_TX_SYNC__UART5_DCE_CTS 0x79 - MX7D_PAD_SAI1_TX_DATA__UART5_DCE_RTS 0x79 - >; - }; + pinctrl_uart5: uart5grp { + fsl,pins = < + MX7D_PAD_SAI1_TX_BCLK__UART5_DCE_TX 0x79 + MX7D_PAD_SAI1_RX_DATA__UART5_DCE_RX 0x79 + MX7D_PAD_SAI1_TX_SYNC__UART5_DCE_CTS 0x79 + MX7D_PAD_SAI1_TX_DATA__UART5_DCE_RTS 0x79 + >; + }; - pinctrl_uart6: uart6grp { - fsl,pins = < - MX7D_PAD_ECSPI1_MOSI__UART6_DCE_TX 0x79 - MX7D_PAD_ECSPI1_SCLK__UART6_DCE_RX 0x79 - MX7D_PAD_ECSPI1_SS0__UART6_DCE_CTS 0x79 - MX7D_PAD_ECSPI1_MISO__UART6_DCE_RTS 0x79 - >; - }; + pinctrl_uart6: uart6grp { + fsl,pins = < + MX7D_PAD_ECSPI1_MOSI__UART6_DCE_TX 0x79 + MX7D_PAD_ECSPI1_SCLK__UART6_DCE_RX 0x79 + MX7D_PAD_ECSPI1_SS0__UART6_DCE_CTS 0x79 + MX7D_PAD_ECSPI1_MISO__UART6_DCE_RTS 0x79 + >; + }; - pinctrl_usdhc1_gpio: usdhc1_gpiogrp { - fsl,pins = < - MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */ - MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */ - MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */ - MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x59 /* VSELECT */ - >; - }; + pinctrl_usdhc1_gpio: usdhc1-gpiogrp { + fsl,pins = < + MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 /* CD */ + MX7D_PAD_SD1_WP__GPIO5_IO1 0x59 /* WP */ + MX7D_PAD_SD1_RESET_B__GPIO5_IO2 0x59 /* vmmc */ + MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x59 /* VSELECT */ + >; + }; - pinctrl_usdhc1: usdhc1grp { - fsl,pins = < - MX7D_PAD_SD1_CMD__SD1_CMD 0x59 - MX7D_PAD_SD1_CLK__SD1_CLK 0x19 - MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59 - MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 - MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 - MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 - >; - }; + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x59 + MX7D_PAD_SD1_CLK__SD1_CLK 0x19 + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59 + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 + >; + }; - pinctrl_usdhc1_100mhz: usdhc1grp_100mhz { - fsl,pins = < - MX7D_PAD_SD1_CMD__SD1_CMD 0x5a - MX7D_PAD_SD1_CLK__SD1_CLK 0x1a - MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5a - MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5a - MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5a - MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5a - >; - }; + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x5a + MX7D_PAD_SD1_CLK__SD1_CLK 0x1a + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5a + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5a + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5a + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5a + >; + }; - pinctrl_usdhc1_200mhz: usdhc1grp_200mhz { - fsl,pins = < - MX7D_PAD_SD1_CMD__SD1_CMD 0x5b - MX7D_PAD_SD1_CLK__SD1_CLK 0x1b - MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5b - MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5b - MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5b - MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5b - >; - }; + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x5b + MX7D_PAD_SD1_CLK__SD1_CLK 0x1b + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x5b + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x5b + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x5b + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x5b + >; + }; - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX7D_PAD_SD2_CMD__SD2_CMD 0x59 - MX7D_PAD_SD2_CLK__SD2_CLK 0x19 - MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59 - MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59 - MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59 - MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59 - >; - }; + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x59 + MX7D_PAD_SD2_CLK__SD2_CLK 0x19 + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59 + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59 + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59 + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59 + >; + }; - pinctrl_usdhc2_100mhz: usdhc2grp_100mhz { - fsl,pins = < - MX7D_PAD_SD2_CMD__SD2_CMD 0x5a - MX7D_PAD_SD2_CLK__SD2_CLK 0x1a - MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5a - MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5a - MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5a - MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5a - >; - }; + pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x5a + MX7D_PAD_SD2_CLK__SD2_CLK 0x1a + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5a + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5a + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5a + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5a + >; + }; - pinctrl_usdhc2_200mhz: usdhc2grp_200mhz { - fsl,pins = < - MX7D_PAD_SD2_CMD__SD2_CMD 0x5b - MX7D_PAD_SD2_CLK__SD2_CLK 0x1b - MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5b - MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5b - MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5b - MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5b - >; - }; + pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x5b + MX7D_PAD_SD2_CLK__SD2_CLK 0x1b + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5b + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5b + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5b + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5b + >; + }; - pinctrl_usdhc3: usdhc3grp { - fsl,pins = < - MX7D_PAD_SD3_CMD__SD3_CMD 0x59 - MX7D_PAD_SD3_CLK__SD3_CLK 0x19 - MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59 - MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59 - MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59 - MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59 - MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59 - MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59 - MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59 - MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59 - MX7D_PAD_SD3_STROBE__SD3_STROBE 0x19 - >; - }; + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX7D_PAD_SD3_CMD__SD3_CMD 0x59 + MX7D_PAD_SD3_CLK__SD3_CLK 0x19 + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59 + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59 + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59 + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59 + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59 + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59 + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59 + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59 + MX7D_PAD_SD3_STROBE__SD3_STROBE 0x19 + >; + }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { - fsl,pins = < - MX7D_PAD_SD3_CMD__SD3_CMD 0x5a - MX7D_PAD_SD3_CLK__SD3_CLK 0x1a - MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5a - MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5a - MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5a - MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5a - MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5a - MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5a - MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5a - MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5a - MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1a - >; - }; + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { + fsl,pins = < + MX7D_PAD_SD3_CMD__SD3_CMD 0x5a + MX7D_PAD_SD3_CLK__SD3_CLK 0x1a + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5a + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5a + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5a + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5a + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5a + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5a + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5a + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5a + MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1a + >; + }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { - fsl,pins = < - MX7D_PAD_SD3_CMD__SD3_CMD 0x5b - MX7D_PAD_SD3_CLK__SD3_CLK 0x1b - MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5b - MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5b - MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5b - MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5b - MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5b - MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5b - MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5b - MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5b - MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1b - >; - }; + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { + fsl,pins = < + MX7D_PAD_SD3_CMD__SD3_CMD 0x5b + MX7D_PAD_SD3_CLK__SD3_CLK 0x1b + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5b + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5b + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5b + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5b + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5b + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5b + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5b + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5b + MX7D_PAD_SD3_STROBE__SD3_STROBE 0x1b + >; }; }; @@ -901,7 +899,7 @@ >; }; - pinctrl_sai3_mclk: sai3grp_mclk { + pinctrl_sai3_mclk: sai3-mclk-grp { fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO03__SAI3_MCLK 0x1f >; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts index 521493342fe9..8f5566027c25 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-zii-rmu2.dts @@ -350,7 +350,7 @@ &iomuxc_lpsr { pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp { - fsl,phy = < + fsl,pins = < MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2 0x08 >; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts index 7bab113ca6da..af4acc311572 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts @@ -459,7 +459,7 @@ >; }; - pinctrl_usdhc3_100mhz: usdhc3grp_100mhz { + pinctrl_usdhc3_100mhz: usdhc3-100mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5a MX7D_PAD_SD3_CLK__SD3_CLK 0x1a @@ -475,7 +475,7 @@ >; }; - pinctrl_usdhc3_200mhz: usdhc3grp_200mhz { + pinctrl_usdhc3_200mhz: usdhc3-200mhz-grp { fsl,pins = < MX7D_PAD_SD3_CMD__SD3_CMD 0x5b MX7D_PAD_SD3_CLK__SD3_CLK 0x1b diff --git a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi index e78d0a7d8cd2..941d9860218e 100644 --- a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi @@ -505,7 +505,7 @@ >; }; - pinctrl_uart6dte: uart6dte { + pinctrl_uart6dte: uart6dtegrp { fsl,pins = < MX6UL_PAD_CSI_PIXCLK__UART6_DTE_TX 0x1b0b1 MX6UL_PAD_CSI_MCLK__UART6_DTE_RX 0x1b0b1 @@ -537,7 +537,7 @@ >; }; - pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x00017069 MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x000170b9 @@ -552,7 +552,7 @@ >; }; - pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp { fsl,pins = < MX6UL_PAD_SD1_CLK__USDHC1_CLK 0x00017069 MX6UL_PAD_SD1_CMD__USDHC1_CMD 0x000170f9 diff --git a/arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts b/arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts index 224f80a4a31d..4aefbc01dfc0 100644 --- a/arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts +++ b/arch/arm/boot/dts/nxp/lpc/lpc4357-ea4357-devkit.dts @@ -482,8 +482,8 @@ reg = <0x1d>; }; - lm75@48 { - compatible = "nxp,lm75"; + temperature-sensor@48 { + compatible = "national,lm75b"; reg = <0x48>; }; diff --git a/arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts b/arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts index 1f84654df50c..846afb8ccbf1 100644 --- a/arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts +++ b/arch/arm/boot/dts/nxp/lpc/lpc4357-myd-lpc4357.dts @@ -511,7 +511,7 @@ clock-frequency = <400000>; sensor@49 { - compatible = "lm75"; + compatible = "national,lm75"; reg = <0x49>; }; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts b/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts index 7365fe4581a3..33b36af1656f 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx23-evk.dts @@ -52,7 +52,7 @@ }; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { nand-controller@8000c000 { pinctrl-names = "default"; pinctrl-0 = <&gpmi_pins_a &gpmi_pins_fixup>; @@ -99,7 +99,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { lradc@80050000 { status = "okay"; fsl,lradc-touchscreen-wires = <4>; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts b/arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts index 229e727b222e..e372e9327a47 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx23-olinuxino.dts @@ -19,7 +19,7 @@ }; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; @@ -64,7 +64,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { lradc@80050000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts b/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts index b23e7ada9c80..cb661bf2d157 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts @@ -55,7 +55,7 @@ }; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; @@ -100,7 +100,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { pwm: pwm@80064000 { pinctrl-names = "default"; pinctrl-0 = <&pwm2_pins_a>; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts index 69124ba6a666..b2b6f8514999 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx23-stmp378x_devb.dts @@ -16,7 +16,7 @@ }; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; @@ -44,7 +44,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { auart0: serial@8006c000 { pinctrl-names = "default"; pinctrl-0 = <&auart0_pins_a>; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts b/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts index 28341d8315c2..0b088c8ab6b6 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx23-xfi3.dts @@ -54,7 +54,7 @@ }; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; @@ -101,7 +101,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { i2c: i2c@80058000 { pinctrl-names = "default"; pinctrl-0 = <&i2c_pins_a>; diff --git a/arch/arm/boot/dts/nxp/mxs/imx23.dtsi b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi index 0309592af1e1..5e21252fb7c9 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx23.dtsi +++ b/arch/arm/boot/dts/nxp/mxs/imx23.dtsi @@ -45,7 +45,7 @@ reg = <0x80000000 0x80000>; ranges; - apbh@80000000 { + apbh-bus@80000000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -476,7 +476,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts b/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts index f9bf40d96568..4c4ea91c286f 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-apx4devkit.dts @@ -11,19 +11,13 @@ reg = <0x40000000 0x04000000>; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_3p3v: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "3P3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; }; sound { diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts index c72fe2d392f1..fd177daa6385 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-cfa10037.dts @@ -14,7 +14,7 @@ compatible = "crystalfontz,cfa10037", "crystalfontz,cfa10036", "fsl,imx28"; apb@80000000 { - apbh@80000000 { + apbh-bus@80000000 { pinctrl@80018000 { usb_pins_cfa10037: usb-10037@0 { reg = <0>; @@ -38,7 +38,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { usbphy1: usbphy@8007e000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi index 69fcb0dde940..410dfe17f8ca 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi +++ b/arch/arm/boot/dts/nxp/mxs/imx28-lwe.dtsi @@ -55,23 +55,6 @@ status = "okay"; }; -&saif0 { - pinctrl-names = "default"; - pinctrl-0 = <&saif0_pins_a>; - #sound-dai-cells = <0>; - assigned-clocks = <&clks 53>; - assigned-clock-rates = <12000000>; - status = "okay"; -}; - -&saif1 { - pinctrl-names = "default"; - pinctrl-0 = <&saif1_pins_a>; - fsl,saif-master = <&saif0>; - #sound-dai-cells = <0>; - status = "okay"; -}; - &spi3_pins_a { fsl,pinmux-ids = < MX28_PAD_AUART2_RX__SSP3_D4 @@ -109,7 +92,7 @@ flash@0 { compatible = "jedec,spi-nor"; - spi-max-frequency = <40000000>; + spi-max-frequency = <20000000>; reg = <0>; partitions { @@ -133,14 +116,21 @@ reg = <0x90000 0x10000>; }; - partition@100000 { - label = "kernel"; - reg = <0x100000 0x400000>; + partition@a0000 { + label = "rescue"; + reg = <0xa0000 0xf40000>; + }; + + partition@fe0000 { + /* 1st sector for SPL boot img source data */ + label = "spl-boot-data1"; + reg = <0xfe0000 0x10000>; }; - partition@500000 { - label = "swupdate"; - reg = <0x500000 0x800000>; + partition@ff0000 { + /* 2nd sector for SPL boot img source data */ + label = "spl-boot-data2"; + reg = <0xff0000 0x10000>; }; }; }; diff --git a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts index d38183edf0fd..9290635352f1 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts +++ b/arch/arm/boot/dts/nxp/mxs/imx28-tx28.dts @@ -615,13 +615,13 @@ &saif0 { pinctrl-names = "default"; pinctrl-0 = <&saif0_pins_b>; - fsl,saif-master; status = "okay"; }; &saif1 { pinctrl-names = "default"; pinctrl-0 = <&saif1_pins_a>; + fsl,saif-master = <&saif0>; status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi index 4817fba2d938..bbea8b77386f 100644 --- a/arch/arm/boot/dts/nxp/mxs/imx28.dtsi +++ b/arch/arm/boot/dts/nxp/mxs/imx28.dtsi @@ -56,7 +56,7 @@ reg = <0x80000000 0x80000>; ranges; - apbh@80000000 { + apbh-bus@80000000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -1092,7 +1092,7 @@ }; }; - apbx@80040000 { + apbx-bus@80040000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/pma8084.dtsi b/arch/arm/boot/dts/qcom/pma8084.dtsi index 2985f4805b93..309f5256754b 100644 --- a/arch/arm/boot/dts/qcom/pma8084.dtsi +++ b/arch/arm/boot/dts/qcom/pma8084.dtsi @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include <dt-bindings/iio/qcom,spmi-vadc.h> +#include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/spmi/spmi.h> @@ -19,12 +20,17 @@ interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; }; - pwrkey@800 { - compatible = "qcom,pm8941-pwrkey"; + pon@800 { + compatible = "qcom,pm8941-pon"; reg = <0x800>; - interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; - debounce = <15625>; - bias-pull-up; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_POWER>; + }; }; pma8084_gpios: gpio@c000 { diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts index d460743fbb94..947183992850 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8064-asus-nexus7-flo.dts @@ -125,8 +125,6 @@ &gsbi1_i2c { status = "okay"; clock-frequency = <200000>; - pinctrl-0 = <&i2c1_pins>; - pinctrl-names = "default"; eeprom@52 { compatible = "atmel,24c128"; @@ -148,8 +146,6 @@ &gsbi3_i2c { clock-frequency = <200000>; - pinctrl-0 = <&i2c3_pins>; - pinctrl-names = "default"; status = "okay"; trackpad@10 { diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts index 671d58cc2741..178c55c1efeb 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8064-cm-qs600.dts @@ -188,24 +188,17 @@ }; &tlmm_pinmux { - card_detect: card_detect { - mux { - pins = "gpio26"; - function = "gpio"; - bias-disable; - }; + card_detect: card-detect-state { + pins = "gpio26"; + function = "gpio"; + bias-disable; }; - pcie_pins: pcie_pinmux { - mux { - pins = "gpio27"; - function = "gpio"; - }; - conf { - pins = "gpio27"; - drive-strength = <12>; - bias-disable; - }; + pcie_pins: pcie-state { + pins = "gpio27"; + function = "gpio"; + drive-strength = <12>; + bias-disable; }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts index ed86b24119c9..b3ff8010b149 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8064-ifc6410.dts @@ -321,24 +321,17 @@ }; &tlmm_pinmux { - card_detect: card_detect { - mux { - pins = "gpio26"; - function = "gpio"; - bias-disable; - }; + card_detect: card-detect-state { + pins = "gpio26"; + function = "gpio"; + bias-disable; }; - pcie_pins: pcie_pinmux { - mux { - pins = "gpio27"; - function = "gpio"; - }; - conf { - pins = "gpio27"; - drive-strength = <12>; - bias-disable; - }; + pcie_pins: pcie-state { + pins = "gpio27"; + function = "gpio"; + drive-strength = <12>; + bias-disable; }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi index 7c545c50847b..e53de709e9d1 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-apq8064-pins.dtsi @@ -1,318 +1,218 @@ // SPDX-License-Identifier: GPL-2.0 &tlmm_pinmux { - sdc4_gpios: sdc4-gpios { - pios { - pins = "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"; - function = "sdc4"; - }; - }; - - sdcc1_pins: sdcc1-pin-active { - clk { + sdcc1_default_state: sdcc1-default-state { + clk-pins { pins = "sdc1_clk"; - drive-strengh = <16>; + drive-strength = <16>; bias-disable; }; - cmd { + cmd-pins { pins = "sdc1_cmd"; - drive-strengh = <10>; + drive-strength = <10>; bias-pull-up; }; - data { + data-pins { pins = "sdc1_data"; - drive-strengh = <10>; + drive-strength = <10>; bias-pull-up; }; }; - sdcc3_pins: sdcc3-pin-active { - clk { + sdcc3_default_state: sdcc3-default-state { + clk-pins { pins = "sdc3_clk"; - drive-strengh = <8>; + drive-strength = <8>; bias-disable; }; - cmd { + cmd-pins { pins = "sdc3_cmd"; - drive-strengh = <8>; + drive-strength = <8>; bias-pull-up; }; - data { + data-pins { pins = "sdc3_data"; - drive-strengh = <8>; + drive-strength = <8>; bias-pull-up; }; }; - ps_hold: ps_hold { - mux { - pins = "gpio78"; - function = "ps_hold"; - }; + sdc4_default_state: sdc4-default-state { + pins = "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"; + function = "sdc4"; }; - i2c1_pins: i2c1 { - mux { - pins = "gpio20", "gpio21"; - function = "gsbi1"; - }; + gsbi1_uart_2pins: gsbi1-uart-2pins-state { + pins = "gpio18", "gpio19"; + function = "gsbi1"; + }; - pinconf { - pins = "gpio20", "gpio21"; - drive-strength = <16>; - bias-disable; - }; + gsbi1_uart_4pins: gsbi1-uart-4pins-state { + pins = "gpio18", "gpio19", "gpio20", "gpio21"; + function = "gsbi1"; }; - i2c1_pins_sleep: i2c1_pins_sleep { - mux { - pins = "gpio20", "gpio21"; - function = "gpio"; - }; - pinconf { - pins = "gpio20", "gpio21"; + gsbi4_uart_pin_a: gsbi4-uart-pin-active-state { + rx-pins { + pins = "gpio11"; + function = "gsbi4"; drive-strength = <2>; bias-disable; }; - }; - gsbi1_uart_2pins: gsbi1_uart_2pins { - mux { - pins = "gpio18", "gpio19"; - function = "gsbi1"; + tx-pins { + pins = "gpio10"; + function = "gsbi4"; + drive-strength = <4>; + bias-disable; }; }; - gsbi1_uart_4pins: gsbi1_uart_4pins { - mux { - pins = "gpio18", "gpio19", "gpio20", "gpio21"; - function = "gsbi1"; - }; + gsbi6_uart_2pins: gsbi6-uart-2pins-state { + pins = "gpio14", "gpio15"; + function = "gsbi6"; }; - i2c2_pins: i2c2 { - mux { - pins = "gpio24", "gpio25"; - function = "gsbi2"; - }; - - pinconf { - pins = "gpio24", "gpio25"; - drive-strength = <16>; - bias-disable; - }; + gsbi6_uart_4pins: gsbi6-uart-4pins-state { + pins = "gpio14", "gpio15", "gpio16", "gpio17"; + function = "gsbi6"; }; - i2c2_pins_sleep: i2c2_pins_sleep { - mux { - pins = "gpio24", "gpio25"; - function = "gpio"; - }; - - pinconf { - pins = "gpio24", "gpio25"; - drive-strength = <2>; - bias-disable; - }; + gsbi7_uart_2pins: gsbi7-uart-2pins-state { + pins = "gpio82", "gpio83"; + function = "gsbi7"; }; - i2c3_pins: i2c3 { - mux { - pins = "gpio8", "gpio9"; - function = "gsbi3"; - }; - - pinconf { - pins = "gpio8", "gpio9"; - drive-strength = <16>; - bias-disable; - }; + gsbi7_uart_4pins: gsbi7_uart_4pins-state { + pins = "gpio82", "gpio83", "gpio84", "gpio85"; + function = "gsbi7"; }; - i2c3_pins_sleep: i2c3_pins_sleep { - mux { - pins = "gpio8", "gpio9"; - function = "gpio"; - }; - pinconf { - pins = "gpio8", "gpio9"; - drive-strength = <2>; - bias-disable; - }; + i2c1_default_state: i2c1-default-state { + pins = "gpio20", "gpio21"; + function = "gsbi1"; + drive-strength = <16>; + bias-disable; }; - i2c4_pins: i2c4 { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - }; - - pinconf { - pins = "gpio12", "gpio13"; - drive-strength = <16>; - bias-disable; - }; + i2c1_sleep_state: i2c1-sleep-state { + pins = "gpio20", "gpio21"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - i2c4_pins_sleep: i2c4_pins_sleep { - mux { - pins = "gpio12", "gpio13"; - function = "gpio"; - }; - pinconf { - pins = "gpio12", "gpio13"; - drive-strength = <2>; - bias-disable; - }; + i2c2_default_state: i2c2-default-state { + pins = "gpio24", "gpio25"; + function = "gsbi2"; + drive-strength = <16>; + bias-disable; }; - spi5_default: spi5_default { - pinmux { - pins = "gpio51", "gpio52", "gpio54"; - function = "gsbi5"; - }; - - pinmux_cs { - function = "gpio"; - pins = "gpio53"; - }; - - pinconf { - pins = "gpio51", "gpio52", "gpio54"; - drive-strength = <16>; - bias-disable; - }; - - pinconf_cs { - pins = "gpio53"; - drive-strength = <16>; - bias-disable; - output-high; - }; + i2c2_sleep_state: i2c2-sleep-state { + pins = "gpio24", "gpio25"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - spi5_sleep: spi5_sleep { - pinmux { - function = "gpio"; - pins = "gpio51", "gpio52", "gpio53", "gpio54"; - }; - - pinconf { - pins = "gpio51", "gpio52", "gpio53", "gpio54"; - drive-strength = <2>; - bias-pull-down; - }; + i2c3_default_state: i2c3-default-state { + pins = "gpio8", "gpio9"; + function = "gsbi3"; + drive-strength = <16>; + bias-disable; }; - i2c6_pins: i2c6 { - mux { - pins = "gpio16", "gpio17"; - function = "gsbi6"; - }; - - pinconf { - pins = "gpio16", "gpio17"; - drive-strength = <16>; - bias-disable; - }; + i2c3_sleep_state: i2c3-sleep-state { + pins = "gpio8", "gpio9"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - i2c6_pins_sleep: i2c6_pins_sleep { - mux { - pins = "gpio16", "gpio17"; - function = "gpio"; - }; - pinconf { - pins = "gpio16", "gpio17"; - drive-strength = <2>; - bias-disable; - }; + i2c4_default_state: i2c4-default-state { + pins = "gpio12", "gpio13"; + function = "gsbi4"; + drive-strength = <16>; + bias-disable; }; - gsbi4_uart_pin_a: gsbi4-uart-pin-active-state { - rx-pins { - pins = "gpio11"; - function = "gsbi4"; - drive-strength = <2>; - bias-disable; - }; - - tx-pins { - pins = "gpio10"; - function = "gsbi4"; - drive-strength = <4>; - bias-disable; - }; + i2c4_sleep_state: i2c4-sleep-state { + pins = "gpio12", "gpio13"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - gsbi6_uart_2pins: gsbi6_uart_2pins { - mux { - pins = "gpio14", "gpio15"; - function = "gsbi6"; - }; + i2c6_default_state: i2c6-default-state { + pins = "gpio16", "gpio17"; + function = "gsbi6"; + drive-strength = <16>; + bias-disable; }; - gsbi6_uart_4pins: gsbi6_uart_4pins { - mux { - pins = "gpio14", "gpio15", "gpio16", "gpio17"; - function = "gsbi6"; - }; + i2c6_sleep_state: i2c6-sleep-state { + pins = "gpio16", "gpio17"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - gsbi7_uart_2pins: gsbi7_uart_2pins { - mux { - pins = "gpio82", "gpio83"; - function = "gsbi7"; - }; + i2c7_default_state: i2c7-default-state { + pins = "gpio84", "gpio85"; + function = "gsbi7"; + drive-strength = <16>; + bias-disable; }; - gsbi7_uart_4pins: gsbi7_uart_4pins { - mux { - pins = "gpio82", "gpio83", "gpio84", "gpio85"; - function = "gsbi7"; - }; + i2c7_sleep_state: i2c7-sleep-state { + pins = "gpio84", "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-disable; }; - i2c7_pins: i2c7 { - mux { - pins = "gpio84", "gpio85"; - function = "gsbi7"; + spi5_default_state: spi5-default-state { + spi5-pins { + pins = "gpio51", "gpio52", "gpio54"; + function = "gsbi5"; + drive-strength = <16>; + bias-disable; }; - pinconf { - pins = "gpio84", "gpio85"; + spi5-cs-pins { + pins = "gpio53"; + function = "gpio"; drive-strength = <16>; bias-disable; + output-high; }; }; - i2c7_pins_sleep: i2c7_pins_sleep { - mux { - pins = "gpio84", "gpio85"; + spi5_sleep_state: spi5-sleep-state { + spi5-pins { + pins = "gpio51", "gpio52", "gpio53", "gpio54"; function = "gpio"; - }; - pinconf { - pins = "gpio84", "gpio85"; drive-strength = <2>; - bias-disable; + bias-pull-down; }; }; - riva_fm_pin_a: riva-fm-active { + riva_fm_pin_a: riva-fm-active-state { pins = "gpio14", "gpio15"; function = "riva_fm"; }; - riva_bt_pin_a: riva-bt-active { + riva_bt_pin_a: riva-bt-active-state { pins = "gpio16", "gpio17"; function = "riva_bt"; }; - riva_wlan_pin_a: riva-wlan-active { + riva_wlan_pin_a: riva-wlan-active-state { pins = "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"; function = "riva_wlan"; @@ -320,22 +220,24 @@ bias-pull-down; }; - hdmi_pinctrl: hdmi-pinctrl { - mux { - pins = "gpio70", "gpio71", "gpio72"; - function = "hdmi"; - }; - - pinconf_ddc { + hdmi_pinctrl: hdmi-pinctrl-state { + ddc-pins { pins = "gpio70", "gpio71"; + function = "hdmi"; bias-pull-up; drive-strength = <2>; }; - pinconf_hpd { + hpd-pins { pins = "gpio72"; + function = "hdmi"; bias-pull-down; drive-strength = <16>; }; }; + + ps_hold_default_state: ps-hold-default-state { + pins = "gpio78"; + function = "ps_hold"; + }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts b/arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts index 2412aa3e3e8d..7752f07973f9 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts +++ b/arch/arm/boot/dts/qcom/qcom-apq8064-sony-xperia-lagan-yuga.dts @@ -373,21 +373,21 @@ cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; - pinctrl-0 = <&sdcc3_pins>, <&sdcc3_cd_pin_a>; + pinctrl-0 = <&sdcc3_default_state>, <&sdcc3_cd_pin_a>; status = "okay"; }; &tlmm_pinmux { - gsbi5_uart_pin_a: gsbi5-uart-pin-active { - rx { + gsbi5_uart_pin_a: gsbi5-uart-pin-active-state { + rx-pins { pins = "gpio52"; function = "gsbi5"; drive-strength = <2>; bias-pull-up; }; - tx { + tx-pins { pins = "gpio51"; function = "gsbi5"; drive-strength = <4>; @@ -396,7 +396,7 @@ }; - sdcc3_cd_pin_a: sdcc3-cd-pin-active { + sdcc3_cd_pin_a: sdcc3-cd-pin-active-state { pins = "gpio26"; function = "gpio"; diff --git a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi index 769e151747c3..ac7494ed633e 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-apq8064.dtsi @@ -302,7 +302,7 @@ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&ps_hold>; + pinctrl-0 = <&ps_hold_default_state>; }; sfpb_wrapper_mutex: syscon@1200000 { @@ -435,8 +435,8 @@ gsbi1_i2c: i2c@12460000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c1_pins>; - pinctrl-1 = <&i2c1_pins_sleep>; + pinctrl-0 = <&i2c1_default_state>; + pinctrl-1 = <&i2c1_sleep_state>; pinctrl-names = "default", "sleep"; reg = <0x12460000 0x1000>; interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; @@ -465,8 +465,8 @@ gsbi2_i2c: i2c@124a0000 { compatible = "qcom,i2c-qup-v1.1.1"; reg = <0x124a0000 0x1000>; - pinctrl-0 = <&i2c2_pins>; - pinctrl-1 = <&i2c2_pins_sleep>; + pinctrl-0 = <&i2c2_default_state>; + pinctrl-1 = <&i2c2_sleep_state>; pinctrl-names = "default", "sleep"; interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>; @@ -489,8 +489,8 @@ ranges; gsbi3_i2c: i2c@16280000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c3_pins>; - pinctrl-1 = <&i2c3_pins_sleep>; + pinctrl-0 = <&i2c3_default_state>; + pinctrl-1 = <&i2c3_sleep_state>; pinctrl-names = "default", "sleep"; reg = <0x16280000 0x1000>; interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>; @@ -528,8 +528,8 @@ gsbi4_i2c: i2c@16380000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c4_pins>; - pinctrl-1 = <&i2c4_pins_sleep>; + pinctrl-0 = <&i2c4_default_state>; + pinctrl-1 = <&i2c4_sleep_state>; pinctrl-names = "default", "sleep"; reg = <0x16380000 0x1000>; interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>; @@ -565,8 +565,8 @@ compatible = "qcom,spi-qup-v1.1.1"; reg = <0x1a280000 0x1000>; interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; - pinctrl-0 = <&spi5_default>; - pinctrl-1 = <&spi5_sleep>; + pinctrl-0 = <&spi5_default_state>; + pinctrl-1 = <&spi5_sleep_state>; pinctrl-names = "default", "sleep"; clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>; clock-names = "core", "iface"; @@ -599,8 +599,8 @@ gsbi6_i2c: i2c@16580000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c6_pins>; - pinctrl-1 = <&i2c6_pins_sleep>; + pinctrl-0 = <&i2c6_default_state>; + pinctrl-1 = <&i2c6_sleep_state>; pinctrl-names = "default", "sleep"; reg = <0x16580000 0x1000>; interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; @@ -635,8 +635,8 @@ gsbi7_i2c: i2c@16680000 { compatible = "qcom,i2c-qup-v1.1.1"; - pinctrl-0 = <&i2c7_pins>; - pinctrl-1 = <&i2c7_pins_sleep>; + pinctrl-0 = <&i2c7_default_state>; + pinctrl-1 = <&i2c7_sleep_state>; pinctrl-names = "default", "sleep"; reg = <0x16680000 0x1000>; interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; @@ -871,7 +871,6 @@ compatible = "qcom,apq8064-sata-phy"; status = "disabled"; reg = <0x1b400000 0x200>; - reg-names = "phy_mem"; clocks = <&gcc SATA_PHY_CFG_CLK>; clock-names = "cfg"; #phy-cells = <0>; @@ -890,9 +889,9 @@ <&gcc SATA_PMALIVE_CLK>; clock-names = "slave_iface", "iface", - "bus", + "core", "rxoob", - "core_pmalive"; + "pmalive"; assigned-clocks = <&gcc SATA_RXOOB_CLK>, <&gcc SATA_PMALIVE_CLK>; @@ -945,7 +944,7 @@ dmas = <&sdcc4bam 2>, <&sdcc4bam 1>; dma-names = "tx", "rx"; pinctrl-names = "default"; - pinctrl-0 = <&sdc4_gpios>; + pinctrl-0 = <&sdc4_default_state>; }; sdcc4bam: dma-controller@121c2000 { @@ -962,7 +961,7 @@ status = "disabled"; compatible = "arm,pl18x", "arm,primecell"; pinctrl-names = "default"; - pinctrl-0 = <&sdcc1_pins>; + pinctrl-0 = <&sdcc1_default_state>; arm,primecell-periphid = <0x00051180>; reg = <0x12400000 0x2000>; interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi index 2b52e5d5eb51..014e6c5ee889 100644 --- a/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-apq8084.dtsi @@ -792,7 +792,7 @@ qcom,smd-edge = <15>; rpm-requests { - compatible = "qcom,rpm-apq8084"; + compatible = "qcom,rpm-apq8084", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; regulators-0 { diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi index da67d55fa557..0d23c03fae33 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4018-ap120c-ac.dtsi @@ -28,46 +28,42 @@ }; &tlmm { - i2c0_pins: i2c0_pinmux { - mux_i2c { - function = "blsp_i2c0"; - pins = "gpio58", "gpio59"; - drive-strength = <16>; - bias-disable; - }; + i2c0_pins: i2c0-state { + function = "blsp_i2c0"; + pins = "gpio58", "gpio59"; + drive-strength = <16>; + bias-disable; }; - mdio_pins: mdio_pinmux { - mux_mdio { + mdio_pins: mdio-state { + mdio-pins { pins = "gpio53"; function = "mdio"; bias-pull-up; }; - mux_mdc { + mdc-pins { pins = "gpio52"; function = "mdc"; bias-pull-up; }; }; - serial0_pins: serial0_pinmux { - mux_uart { - pins = "gpio60", "gpio61"; - function = "blsp_uart0"; - bias-disable; - }; + serial0_pins: serial0-state { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; }; - spi0_pins: spi0_pinmux { - mux_spi { + spi0_pins: spi0-state { + spi0-pins { function = "blsp_spi0"; pins = "gpio55", "gpio56", "gpio57"; drive-strength = <12>; bias-disable; }; - mux_cs { + spi0-cs-pins { function = "gpio"; pins = "gpio54", "gpio4"; drive-strength = <2>; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts b/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts index 365fbac417fd..ac3b30072a22 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq4018-jalapeno.dts @@ -11,40 +11,35 @@ }; &tlmm { - mdio_pins: mdio_pinmux { - pinmux_1 { + mdio_pins: mdio-state { + mdio-pins { pins = "gpio53"; function = "mdio"; + bias-pull-up; }; - pinmux_2 { + mdc-pins { pins = "gpio52"; function = "mdc"; - }; - - pinconf { - pins = "gpio52", "gpio53"; bias-pull-up; }; }; - serial_pins: serial_pinmux { - mux { - pins = "gpio60", "gpio61"; - function = "blsp_uart0"; - bias-disable; - }; + serial_pins: serial-state{ + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; }; - spi_0_pins: spi_0_pinmux { - pin { + spi_0_pins: spi-0-state { + spi0-pins { function = "blsp_spi0"; pins = "gpio55", "gpio56", "gpio57"; drive-strength = <2>; bias-disable; }; - pin_cs { + spi0-cs-pins { function = "gpio"; pins = "gpio54", "gpio59"; drive-strength = <2>; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi index f7ac8f9d0b6f..efbe89dd4793 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk01.1.dtsi @@ -34,30 +34,22 @@ }; &tlmm { - serial_pins: serial_pinmux { - mux { - pins = "gpio60", "gpio61"; - function = "blsp_uart0"; - bias-disable; - }; + serial_pins: serial-state { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; }; - spi_0_pins: spi_0_pinmux { - pinmux { - function = "blsp_spi0"; - pins = "gpio55", "gpio56", "gpio57"; - }; - pinmux_cs { - function = "gpio"; - pins = "gpio54"; - }; - pinconf { + spi_0_pins: spi-0-state { + spi0-pins { pins = "gpio55", "gpio56", "gpio57"; + function = "blsp_spi0"; drive-strength = <12>; bias-disable; }; - pinconf_cs { + spi0-cs-pins { pins = "gpio54"; + function = "gpio"; drive-strength = <2>; bias-disable; output-high; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi index 374af6dd360a..91e296d2ea82 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk04.1.dtsi @@ -24,26 +24,26 @@ soc { pinctrl@1000000 { - serial_0_pins: serial0-pinmux { + serial_0_pins: serial0-state { pins = "gpio16", "gpio17"; function = "blsp_uart0"; bias-disable; }; - serial_1_pins: serial1-pinmux { + serial_1_pins: serial1-state { pins = "gpio8", "gpio9", "gpio10", "gpio11"; function = "blsp_uart1"; bias-disable; }; - spi_0_pins: spi-0-pinmux { - pinmux { + spi_0_pins: spi-0-state { + spi0-pins { function = "blsp_spi0"; pins = "gpio13", "gpio14", "gpio15"; bias-disable; }; - pinmux_cs { + spi0-cs-pins { function = "gpio"; pins = "gpio12"; bias-disable; @@ -51,13 +51,13 @@ }; }; - i2c_0_pins: i2c-0-pinmux { + i2c_0_pins: i2c-0-state { pins = "gpio20", "gpio21"; function = "blsp_i2c0"; bias-disable; }; - nand_pins: nand-pins { + nand_pins: nand-state { pins = "gpio53", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59", "gpio60", "gpio62", "gpio63", diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts index ea2987fcbff8..41c5874f6f97 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c1.dts @@ -19,20 +19,20 @@ }; pinctrl@1000000 { - serial_1_pins: serial1-pinmux { + serial_1_pins: serial1-state { pins = "gpio8", "gpio9", "gpio10", "gpio11"; function = "blsp_uart1"; bias-disable; }; - spi_0_pins: spi-0-pinmux { - pinmux { + spi_0_pins: spi-0-state { + spi0-pins { function = "blsp_spi0"; pins = "gpio13", "gpio14", "gpio15"; bias-disable; }; - pinmux_cs { + spio-cs-pins { function = "gpio"; pins = "gpio12"; bias-disable; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts index bd3553dd2070..67ee99d69757 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1-c2.dts @@ -9,7 +9,7 @@ soc { pinctrl@1000000 { - serial_1_pins: serial1-pinmux { + serial_1_pins: serial1-state { pins = "gpio8", "gpio9"; function = "blsp_uart1"; bias-disable; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi index 7ef635997efa..cc88cf5f0d9b 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq4019-ap.dk07.1.dtsi @@ -24,19 +24,19 @@ soc { pinctrl@1000000 { - serial_0_pins: serial0-pinmux { + serial_0_pins: serial0-state { pins = "gpio16", "gpio17"; function = "blsp_uart0"; bias-disable; }; - i2c_0_pins: i2c-0-pinmux { + i2c_0_pins: i2c-0-state { pins = "gpio20", "gpio21"; function = "blsp_i2c0"; bias-disable; }; - nand_pins: nand-pins { + nand_pins: nand-state { pins = "gpio53", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59", "gpio60", "gpio62", "gpio63", diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts b/arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts index a654d3c22c4f..5a8bf1a6f559 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-ap148.dts @@ -7,12 +7,11 @@ soc { pinmux@800000 { - buttons_pins: buttons_pins { - mux { - pins = "gpio54", "gpio65"; - drive-strength = <2>; - bias-pull-up; - }; + buttons_pins: buttons-state { + pins = "gpio54", "gpio65"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts index 12e806adcda8..f09da9460c86 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-rb3011.dts @@ -404,59 +404,49 @@ }; &qcom_pinmux { - buttons_pins: buttons_pins { - mux { - pins = "gpio66"; - drive-strength = <16>; - bias-disable; - }; + buttons_pins: buttons-state { + pins = "gpio66"; + function = "gpio"; + drive-strength = <16>; + bias-disable; }; - leds_pins: leds_pins { - mux { - pins = "gpio33"; - drive-strength = <16>; - bias-disable; - }; + leds_pins: leds-state { + pins = "gpio33"; + function = "gpio"; + drive-strength = <16>; + bias-disable; }; - mdio1_pins: mdio1_pins { - mux { - pins = "gpio10", "gpio11"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; + mdio1_pins: mdio1-state { + pins = "gpio10", "gpio11"; + function = "gpio"; + drive-strength = <8>; + bias-disable; }; - sw0_reset_pin: sw0_reset_pin { - mux { - pins = "gpio16"; - drive-strength = <16>; - function = "gpio"; - bias-disable; - input-disable; - }; + sw0_reset_pin: sw0-reset-state { + pins = "gpio16"; + drive-strength = <16>; + function = "gpio"; + bias-disable; + input-disable; }; - sw1_reset_pin: sw1_reset_pin { - mux { - pins = "gpio17"; - drive-strength = <16>; - function = "gpio"; - bias-disable; - input-disable; - }; + sw1_reset_pin: sw1-reset-state { + pins = "gpio17"; + drive-strength = <16>; + function = "gpio"; + bias-disable; + input-disable; }; - usb1_pwr_en_pins: usb1_pwr_en_pins { - mux { - pins = "gpio4"; - function = "gpio"; - drive-strength = <16>; - bias-disable; - output-high; - }; + usb1_pwr_en_pins: usb1-pwr-en-state { + pins = "gpio4"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-high; }; }; diff --git a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi index da0fd75f4711..759a59c2bdbc 100644 --- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi @@ -399,70 +399,58 @@ #interrupt-cells = <2>; interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; - pcie0_pins: pcie0_pinmux { - mux { - pins = "gpio3"; - function = "pcie1_rst"; - drive-strength = <12>; - bias-disable; - }; + pcie0_pins: pcie0-state { + pins = "gpio3"; + function = "pcie1_rst"; + drive-strength = <12>; + bias-disable; }; - pcie1_pins: pcie1_pinmux { - mux { - pins = "gpio48"; - function = "pcie2_rst"; - drive-strength = <12>; - bias-disable; - }; + pcie1_pins: pcie1-state { + pins = "gpio48"; + function = "pcie2_rst"; + drive-strength = <12>; + bias-disable; }; - pcie2_pins: pcie2_pinmux { - mux { - pins = "gpio63"; - function = "pcie3_rst"; - drive-strength = <12>; - bias-disable; - }; + pcie2_pins: pcie2-state { + pins = "gpio63"; + function = "pcie3_rst"; + drive-strength = <12>; + bias-disable; }; - i2c4_pins: i2c4-default { + i2c4_pins: i2c4-state { pins = "gpio12", "gpio13"; function = "gsbi4"; drive-strength = <12>; bias-disable; }; - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - drive-strength = <10>; - bias-none; - }; + spi_pins: spi-state { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + drive-strength = <10>; + bias-disable; }; - leds_pins: leds_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", - "gpio26", "gpio53"; - function = "gpio"; - drive-strength = <2>; - bias-pull-down; - output-low; - }; + leds_pins: leds-state { + pins = "gpio7", "gpio8", "gpio9", + "gpio26", "gpio53"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + output-low; }; - buttons_pins: buttons_pins { - mux { - pins = "gpio54"; - drive-strength = <2>; - bias-pull-up; - }; + buttons_pins: buttons-state { + pins = "gpio54"; + drive-strength = <2>; + bias-pull-up; }; - nand_pins: nand_pins { - mux { + nand_pins: nand-state { + nand-pins { pins = "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", @@ -473,14 +461,14 @@ bias-disable; }; - pullups { + nand-pullup-pins { pins = "gpio39"; function = "nand"; drive-strength = <10>; bias-pull-up; }; - hold { + nand-hold-pins { pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"; @@ -490,25 +478,21 @@ }; }; - mdio0_pins: mdio0-pins { - mux { - pins = "gpio0", "gpio1"; - function = "mdio"; - drive-strength = <8>; - bias-disable; - }; + mdio0_pins: mdio0-state { + pins = "gpio0", "gpio1"; + function = "mdio"; + drive-strength = <8>; + bias-disable; }; - rgmii2_pins: rgmii2-pins { - mux { - pins = "gpio27", "gpio28", "gpio29", - "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", - "gpio60", "gpio61", "gpio62"; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; + rgmii2_pins: rgmii2-state { + pins = "gpio27", "gpio28", "gpio29", + "gpio30", "gpio31", "gpio32", + "gpio51", "gpio52", "gpio59", + "gpio60", "gpio61", "gpio62"; + function = "rgmii2"; + drive-strength = <8>; + bias-disable; }; }; @@ -1292,7 +1276,7 @@ <&gcc SATA_A_CLK>, <&gcc SATA_RXOOB_CLK>, <&gcc SATA_PMALIVE_CLK>; - clock-names = "slave_face", "iface", "core", + clock-names = "slave_iface", "iface", "core", "rxoob", "pmalive"; assigned-clocks = <&gcc SATA_RXOOB_CLK>, <&gcc SATA_PMALIVE_CLK>; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi index 8839b23fc693..ca76bf8af75e 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-common.dtsi @@ -84,6 +84,32 @@ }; }; +&blsp1_i2c2 { + status = "okay"; + + magnetometer: magnetometer@c { + compatible = "asahi-kasei,ak09911"; + reg = <0x0c>; + + vdd-supply = <&pm8226_l15>; + vid-supply = <&pm8226_l6>; + }; + + accelerometer: accelerometer@1e { + compatible = "kionix,kx022-1020"; + reg = <0x1e>; + + interrupts-extended = <&tlmm 63 IRQ_TYPE_EDGE_RISING>; + + vdd-supply = <&pm8226_l15>; + vddio-supply = <&pm8226_l6>; + + mount-matrix = "1", "0", "0", + "0", "-1", "0", + "0", "0", "1"; + }; +}; + &blsp1_i2c5 { status = "okay"; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-moneypenny.dts b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-moneypenny.dts index 992b7115b5f8..a28a83cb5340 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-moneypenny.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8226-microsoft-moneypenny.dts @@ -10,6 +10,9 @@ #include "qcom-msm8226-microsoft-common.dtsi" +/* This device has no magnetometer */ +/delete-node/ &magnetometer; + / { model = "Nokia Lumia 630"; compatible = "microsoft,moneypenny", "qcom,msm8226"; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi index b2f92ad6499a..3a685ff7e8cc 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8226.dtsi @@ -12,6 +12,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/power/qcom-rpmpd.h> #include <dt-bindings/reset/qcom,gcc-msm8974.h> +#include <dt-bindings/thermal/thermal.h> / { #address-cells = <1>; @@ -44,8 +45,11 @@ device_type = "cpu"; reg = <0>; next-level-cache = <&L2>; + clocks = <&apcs>; + operating-points-v2 = <&cpu_opp_table>; qcom,acc = <&acc0>; qcom,saw = <&saw0>; + #cooling-cells = <2>; }; CPU1: cpu@1 { @@ -54,8 +58,11 @@ device_type = "cpu"; reg = <1>; next-level-cache = <&L2>; + clocks = <&apcs>; + operating-points-v2 = <&cpu_opp_table>; qcom,acc = <&acc1>; qcom,saw = <&saw1>; + #cooling-cells = <2>; }; CPU2: cpu@2 { @@ -64,8 +71,11 @@ device_type = "cpu"; reg = <2>; next-level-cache = <&L2>; + clocks = <&apcs>; + operating-points-v2 = <&cpu_opp_table>; qcom,acc = <&acc2>; qcom,saw = <&saw2>; + #cooling-cells = <2>; }; CPU3: cpu@3 { @@ -74,8 +84,11 @@ device_type = "cpu"; reg = <3>; next-level-cache = <&L2>; + clocks = <&apcs>; + operating-points-v2 = <&cpu_opp_table>; qcom,acc = <&acc3>; qcom,saw = <&saw3>; + #cooling-cells = <2>; }; L2: l2-cache { @@ -98,6 +111,29 @@ reg = <0x0 0x0>; }; + cpu_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + }; + + opp-787200000 { + opp-hz = /bits/ 64 <787200000>; + }; + + /* Higher CPU frequencies need speedbin support */ + }; + pmu { compatible = "arm,cortex-a7-pmu"; interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4) | @@ -121,11 +157,11 @@ smd-edge { interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 8 0>; + mboxes = <&apcs 0>; qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8226"; + compatible = "qcom,rpm-msm8226", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { @@ -199,7 +235,7 @@ interrupt-parent = <&intc>; interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 8 10>; + mboxes = <&apcs 10>; qcom,local-pid = <0>; qcom,remote-pid = <2>; @@ -231,9 +267,75 @@ #interrupt-cells = <3>; }; - apcs: syscon@f9011000 { - compatible = "syscon"; + apcs: mailbox@f9011000 { + compatible = "qcom,msm8226-apcs-kpss-global", + "qcom,msm8916-apcs-kpss-global", "syscon"; reg = <0xf9011000 0x1000>; + #mbox-cells = <1>; + clocks = <&a7pll>, <&gcc GPLL0_VOTE>; + clock-names = "pll", "aux"; + #clock-cells = <0>; + }; + + a7pll: clock@f9016000 { + compatible = "qcom,msm8226-a7pll"; + reg = <0xf9016000 0x40>; + #clock-cells = <0>; + clocks = <&xo_board>; + clock-names = "xo"; + operating-points-v2 = <&a7pll_opp_table>; + + a7pll_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-768000000 { + opp-hz = /bits/ 64 <768000000>; + }; + + opp-787200000 { + opp-hz = /bits/ 64 <787200000>; + }; + + opp-998400000 { + opp-hz = /bits/ 64 <998400000>; + }; + + opp-1094400000 { + opp-hz = /bits/ 64 <1094400000>; + }; + + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; + }; + + opp-1305600000 { + opp-hz = /bits/ 64 <1305600000>; + }; + + opp-1344000000 { + opp-hz = /bits/ 64 <1344000000>; + }; + + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; + }; + + opp-1497600000 { + opp-hz = /bits/ 64 <1497600000>; + }; + + opp-1593600000 { + opp-hz = /bits/ 64 <1593600000>; + }; + + opp-1689600000 { + opp-hz = /bits/ 64 <1689600000>; + }; + + opp-1785600000 { + opp-hz = /bits/ 64 <1785600000>; + }; + }; }; saw_l2: power-manager@f9012000 { @@ -571,7 +673,7 @@ #reset-cells = <1>; #power-domain-cells = <1>; - clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + clocks = <&xo_board>, <&sleep_clk>; clock-names = "xo", "sleep_clk"; @@ -1130,7 +1232,7 @@ smd-edge { interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 8 8>; + mboxes = <&apcs 8>; qcom,smd-edge = <1>; label = "lpass"; @@ -1159,6 +1261,16 @@ thermal-sensors = <&tsens 5>; + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + trips { cpu_alert0: trip0 { temperature = <75000>; @@ -1180,6 +1292,16 @@ thermal-sensors = <&tsens 2>; + cooling-maps { + map0 { + trip = <&cpu_alert1>; + cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + trips { cpu_alert1: trip0 { temperature = <75000>; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8926-microsoft-tesla.dts b/arch/arm/boot/dts/qcom/qcom-msm8926-microsoft-tesla.dts index 53a6d4e85959..55077a5f2e34 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8926-microsoft-tesla.dts +++ b/arch/arm/boot/dts/qcom/qcom-msm8926-microsoft-tesla.dts @@ -13,6 +13,9 @@ /* This device has touchscreen on i2c1 instead */ /delete-node/ &touchscreen; +/* The magnetometer used on this device is currently unknown */ +/delete-node/ &magnetometer; + / { model = "Nokia Lumia 830"; compatible = "microsoft,tesla", "qcom,msm8926", "qcom,msm8226"; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi index 15568579459a..1bd87170252d 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi @@ -136,7 +136,7 @@ qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8974"; + compatible = "qcom,rpm-msm8974", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { @@ -149,7 +149,7 @@ }; }; - reserved-memory { + reserved_memory: reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte-common.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte-common.dtsi index b5443fd5b425..d3959741d2ea 100644 --- a/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte-common.dtsi +++ b/arch/arm/boot/dts/qcom/qcom-msm8974pro-samsung-klte-common.dtsi @@ -438,6 +438,19 @@ }; }; +&reserved_memory { + ramoops@3e8e0000 { + compatible = "ramoops"; + reg = <0x3e8e0000 0x200000>; + + console-size = <0x100000>; + record-size = <0x10000>; + ftrace-size = <0x10000>; + pmsg-size = <0x80000>; + ecc-size = <8>; + }; +}; + &remoteproc_adsp { status = "okay"; cx-supply = <&pma8084_s2>; diff --git a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts index e32c73d32f0a..2f84e2805712 100644 --- a/arch/arm/boot/dts/rockchip/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rockchip/rk3036-kylin.dts @@ -325,8 +325,8 @@ &i2c2 { status = "okay"; - rt5616: rt5616@1b { - compatible = "rt5616"; + rt5616: audio-codec@1b { + compatible = "realtek,rt5616"; reg = <0x1b>; clocks = <&cru SCLK_I2S_OUT>; clock-names = "mclk"; diff --git a/arch/arm/boot/dts/rockchip/rk3036.dtsi b/arch/arm/boot/dts/rockchip/rk3036.dtsi index 96279d1e02fe..63b9912be06a 100644 --- a/arch/arm/boot/dts/rockchip/rk3036.dtsi +++ b/arch/arm/boot/dts/rockchip/rk3036.dtsi @@ -384,12 +384,13 @@ }; }; - acodec: acodec-ana@20030000 { - compatible = "rk3036-codec"; + acodec: audio-codec@20030000 { + compatible = "rockchip,rk3036-codec"; reg = <0x20030000 0x4000>; - rockchip,grf = <&grf>; clock-names = "acodec_pclk"; clocks = <&cru PCLK_ACODEC>; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -399,7 +400,6 @@ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cru PCLK_HDMI>; clock-names = "pclk"; - rockchip,grf = <&grf>; pinctrl-names = "default"; pinctrl-0 = <&hdmi_ctl>; #sound-dai-cells = <0>; @@ -553,11 +553,11 @@ }; spi: spi@20074000 { - compatible = "rockchip,rockchip-spi"; + compatible = "rockchip,rk3036-spi"; reg = <0x20074000 0x1000>; interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cru PCLK_SPI>, <&cru SCLK_SPI>; - clock-names = "apb-pclk","spi_pclk"; + clocks = <&cru SCLK_SPI>, <&cru PCLK_SPI>; + clock-names = "spiclk", "apb_pclk"; dmas = <&pdma 8>, <&pdma 9>; dma-names = "tx", "rx"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/rockchip/rk3128.dtsi b/arch/arm/boot/dts/rockchip/rk3128.dtsi index 23e633387c24..d4572146d135 100644 --- a/arch/arm/boot/dts/rockchip/rk3128.dtsi +++ b/arch/arm/boot/dts/rockchip/rk3128.dtsi @@ -254,6 +254,30 @@ }; }; + vpu: video-codec@10106000 { + compatible = "rockchip,rk3128-vpu", "rockchip,rk3066-vpu"; + reg = <0x10106000 0x800>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "vepu", "vdpu"; + clocks = <&cru ACLK_VDPU>, <&cru HCLK_VDPU>, + <&cru ACLK_VEPU>, <&cru HCLK_VEPU>; + clock-names = "aclk_vdpu", "hclk_vdpu", + "aclk_vepu", "hclk_vepu"; + iommus = <&vpu_mmu>; + power-domains = <&power RK3128_PD_VIDEO>; + }; + + vpu_mmu: iommu@10106800 { + compatible = "rockchip,iommu"; + reg = <0x10106800 0x100>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_VEPU>, <&cru HCLK_VDPU>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3128_PD_VIDEO>; + #iommu-cells = <0>; + }; + vop: vop@1010e000 { compatible = "rockchip,rk3126-vop"; reg = <0x1010e000 0x300>; @@ -429,7 +453,7 @@ compatible = "rockchip,sfc"; reg = <0x1020c000 0x8000>; interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cru SCLK_SFC>, <&cru 479>; + clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; clock-names = "clk_sfc", "hclk_sfc"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts b/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts index 2d9994379eb2..89ca2f8d3809 100644 --- a/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts +++ b/arch/arm/boot/dts/rockchip/rv1108-elgin-r1.dts @@ -168,8 +168,8 @@ pinctrl-0 = <&spim1_clk &spim1_cs0 &spim1_tx &spim1_rx>; status = "okay"; - dh2228fv: dac@0 { - compatible = "rohm,dh2228fv"; + display: display@0 { + compatible = "elgin,jg10309-01"; reg = <0>; spi-max-frequency = <24000000>; spi-cpha; diff --git a/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi b/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi index 06b1d7f2d858..35ef6732281f 100644 --- a/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi +++ b/arch/arm/boot/dts/rockchip/rv1126-pinctrl.dtsi @@ -97,6 +97,156 @@ <0 RK_PC3 1 &pcfg_pull_none_drv_level_0_smt>; }; }; + i2c3 { + /omit-if-no-ref/ + i2c3m0_xfer: i2c3m0-xfer { + rockchip,pins = + /* i2c3_scl_m0 */ + <3 RK_PA4 5 &pcfg_pull_none>, + /* i2c3_sda_m0 */ + <3 RK_PA5 5 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + i2c3m1_xfer: i2c3m1-xfer { + rockchip,pins = + /* i2c3_scl_m1 */ + <2 RK_PD4 7 &pcfg_pull_none>, + /* i2c3_sda_m1 */ + <2 RK_PD5 7 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + i2c3m2_xfer: i2c3m2-xfer { + rockchip,pins = + /* i2c3_scl_m2 */ + <1 RK_PD6 3 &pcfg_pull_none>, + /* i2c3_sda_m2 */ + <1 RK_PD7 3 &pcfg_pull_none>; + }; + }; + i2s0 { + i2s0m0_lrck_tx: i2s0m0-lrck-tx { + rockchip,pins = + /* i2s0_lrck_tx_m0 */ + <3 RK_PD3 1 &pcfg_pull_none>; + }; + i2s0m0_lrck_rx: i2s0m0-lrck-rx { + rockchip,pins = + /* i2s0_lrck_rx_m0 */ + <3 RK_PD4 1 &pcfg_pull_none>; + }; + i2s0m0_mclk: i2s0m0-mclk { + rockchip,pins = + /* i2s0_mclk_m0 */ + <3 RK_PD2 1 &pcfg_pull_none>; + }; + i2s0m0_sclk_rx: i2s0m0-sclk-rx { + rockchip,pins = + /* i2s0_sclk_rx_m0 */ + <3 RK_PD1 1 &pcfg_pull_none>; + }; + i2s0m0_sclk_tx: i2s0m0-sclk-tx { + rockchip,pins = + /* i2s0_sclk_tx_m0 */ + <3 RK_PD0 1 &pcfg_pull_none>; + }; + i2s0m0_sdi0: i2s0m0-sdi0 { + rockchip,pins = + /* i2s0_sdi0_m0 */ + <3 RK_PD6 1 &pcfg_pull_none>; + }; + i2s0m0_sdo0: i2s0m0-sdo0 { + rockchip,pins = + /* i2s0_sdo0_m0 */ + <3 RK_PD5 1 &pcfg_pull_none>; + }; + i2s0m0_sdo1_sdi3: i2s0m0-sdo1-sdi3 { + rockchip,pins = + /* i2s0_sdo1_sdi3_m0 */ + <3 RK_PD7 1 &pcfg_pull_none>; + }; + i2s0m0_sdo2_sdi2: i2s0m0-sdo2-sdi2 { + rockchip,pins = + /* i2s0_sdo2_sdi2_m0 */ + <4 RK_PA0 1 &pcfg_pull_none>; + }; + i2s0m0_sdo3_sdi1: i2s0m0-sdo3-sdi1 { + rockchip,pins = + /* i2s0_sdo3_sdi1_m0 */ + <4 RK_PA1 1 &pcfg_pull_none>; + }; + i2s0m1_lrck_tx: i2s0m1-lrck-tx { + rockchip,pins = + /* i2s0_lrck_tx_m1 */ + <3 RK_PA5 3 &pcfg_pull_none>; + }; + i2s0m1_lrck_rx: i2s0m1-lrck-rx { + rockchip,pins = + /* i2s0_lrck_rx_m1 */ + <3 RK_PB2 3 &pcfg_pull_none>; + }; + i2s0m1_mclk: i2s0m1-mclk { + rockchip,pins = + /* i2s0_mclk_m1 */ + <3 RK_PB0 3 &pcfg_pull_none>; + }; + i2s0m1_sclk_rx: i2s0m1-sclk-rx { + rockchip,pins = + /* i2s0_sclk_rx_m1 */ + <3 RK_PB1 3 &pcfg_pull_none>; + }; + i2s0m1_sclk_tx: i2s0m1-sclk-tx { + rockchip,pins = + /* i2s0_sclk_tx_m1 */ + <3 RK_PA4 3 &pcfg_pull_none>; + }; + i2s0m1_sdi0: i2s0m1-sdi0 { + rockchip,pins = + /* i2s0_sdi0_m1 */ + <3 RK_PA7 3 &pcfg_pull_none>; + }; + i2s0m1_sdo0: i2s0m1-sdo0 { + rockchip,pins = + /* i2s0_sdo0_m1 */ + <3 RK_PA6 3 &pcfg_pull_none>; + }; + i2s0m1_sdo1_sdi3: i2s0m1-sdo1-sdi3 { + rockchip,pins = + /* i2s0_sdo1_sdi3_m1 */ + <3 RK_PB3 3 &pcfg_pull_none>; + }; + i2s0m1_sdo2_sdi2: i2s0m1-sdo2-sdi2 { + rockchip,pins = + /* i2s0_sdo2_sdi2_m1 */ + <3 RK_PB4 3 &pcfg_pull_none>; + }; + i2s0m1_sdo3_sdi1: i2s0m1-sdo3-sdi1 { + rockchip,pins = + /* i2s0_sdo3_sdi1_m1 */ + <3 RK_PB5 3 &pcfg_pull_none>; + }; + }; + pwm0 { + /omit-if-no-ref/ + pwm0m0_pins: pwm0m0-pins { + rockchip,pins = + /* pwm0_pin_m0 */ + <0 RK_PB6 3 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm0m1_pins: pwm0m1-pins { + rockchip,pins = + /* pwm0_pin_m1 */ + <2 RK_PB3 5 &pcfg_pull_none>; + }; + }; + pwm1 { + /omit-if-no-ref/ + pwm1m0_pins: pwm1m0-pins { + rockchip,pins = + /* pwm1_pin_m0 */ + <0 RK_PB7 3 &pcfg_pull_none>; + }; + }; pwm2 { /omit-if-no-ref/ pwm2m0_pins: pwm2m0-pins { @@ -104,6 +254,106 @@ /* pwm2_pin_m0 */ <0 RK_PC0 3 &pcfg_pull_none>; }; + /omit-if-no-ref/ + pwm2m1_pins: pwm2m1-pins { + rockchip,pins = + /* pwm2_pin_m1 */ + <2 RK_PB1 5 &pcfg_pull_none>; + }; + }; + pwm3 { + /omit-if-no-ref/ + pwm3m0_pins: pwm3m0-pins { + rockchip,pins = + /* pwm3_pin_m0 */ + <0 RK_PC1 3 &pcfg_pull_none>; + }; + }; + pwm4 { + /omit-if-no-ref/ + pwm4m0_pins: pwm4m0-pins { + rockchip,pins = + /* pwm4_pin_m0 */ + <0 RK_PC2 3 &pcfg_pull_none>; + }; + }; + pwm5 { + /omit-if-no-ref/ + pwm5m0_pins: pwm5m0-pins { + rockchip,pins = + /* pwm5_pin_m0 */ + <0 RK_PC3 3 &pcfg_pull_none>; + }; + }; + pwm6 { + /omit-if-no-ref/ + pwm6m0_pins: pwm6m0-pins { + rockchip,pins = + /* pwm6_pin_m0 */ + <0 RK_PB2 3 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm6m1_pins: pwm6m1-pins { + rockchip,pins = + /* pwm6_pin_m1 */ + <2 RK_PD4 5 &pcfg_pull_none>; + }; + }; + pwm7 { + /omit-if-no-ref/ + pwm7m0_pins: pwm7m0-pins { + rockchip,pins = + /* pwm7_pin_m0 */ + <0 RK_PB1 3 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm7m1_pins: pwm7m1-pins { + rockchip,pins = + /* pwm7_pin_m1 */ + <3 RK_PA0 5 &pcfg_pull_none>; + }; + }; + pwm8 { + /omit-if-no-ref/ + pwm8m0_pins: pwm8m0-pins { + rockchip,pins = + /* pwm8_pin_m0 */ + <3 RK_PA4 6 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm8m1_pins: pwm8m1-pins { + rockchip,pins = + /* pwm8_pin_m1 */ + <2 RK_PD7 5 &pcfg_pull_none>; + }; + }; + pwm9 { + /omit-if-no-ref/ + pwm9m0_pins: pwm9m0-pins { + rockchip,pins = + /* pwm9_pin_m0 */ + <3 RK_PA5 6 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm9m1_pins: pwm9m1-pins { + rockchip,pins = + /* pwm9_pin_m1 */ + <2 RK_PD6 5 &pcfg_pull_none>; + }; + }; + pwm10 { + /omit-if-no-ref/ + pwm10m0_pins: pwm10m0-pins { + rockchip,pins = + /* pwm10_pin_m0 */ + <3 RK_PA6 6 &pcfg_pull_none>; + }; + /omit-if-no-ref/ + pwm10m1_pins: pwm10m1-pins { + rockchip,pins = + /* pwm10_pin_m1 */ + <2 RK_PD5 5 &pcfg_pull_none>; + }; }; pwm11 { /omit-if-no-ref/ @@ -112,6 +362,12 @@ /* pwm11_pin_m0 */ <3 RK_PA7 6 &pcfg_pull_none>; }; + /omit-if-no-ref/ + pwm11m1_pins: pwm11m1-pins { + rockchip,pins = + /* pwm11_pin_m1 */ + <3 RK_PA1 5 &pcfg_pull_none>; + }; }; rgmii { /omit-if-no-ref/ diff --git a/arch/arm/boot/dts/rockchip/rv1126.dtsi b/arch/arm/boot/dts/rockchip/rv1126.dtsi index bb603cae13df..434846b85c95 100644 --- a/arch/arm/boot/dts/rockchip/rv1126.dtsi +++ b/arch/arm/boot/dts/rockchip/rv1126.dtsi @@ -22,6 +22,7 @@ aliases { i2c0 = &i2c0; i2c2 = &i2c2; + i2c3 = &i2c3; serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; @@ -268,6 +269,28 @@ status = "disabled"; }; + pwm0: pwm@ff430000 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff430000 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm0m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm1: pwm@ff430010 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff430010 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + pwm2: pwm@ff430020 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff430020 0x10>; @@ -279,6 +302,61 @@ status = "disabled"; }; + pwm3: pwm@ff430030 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff430030 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM0>, <&pmucru PCLK_PWM0>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm3m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm4: pwm@ff440000 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff440000 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM1>, <&pmucru PCLK_PWM1>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm4m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm5: pwm@ff440010 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff440010 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM1>, <&pmucru PCLK_PWM1>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm5m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm6: pwm@ff440020 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff440020 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM1>, <&pmucru PCLK_PWM1>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm6m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm7: pwm@ff440030 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff440030 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&pmucru CLK_PWM1>, <&pmucru PCLK_PWM1>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm7m0_pins>; + #pwm-cells = <3>; + status = "disabled"; + }; + pmucru: clock-controller@ff480000 { compatible = "rockchip,rv1126-pmucru"; reg = <0xff480000 0x1000>; @@ -308,6 +386,53 @@ clock-names = "apb_pclk"; }; + i2c3: i2c@ff520000 { + compatible = "rockchip,rv1126-i2c", "rockchip,rk3399-i2c"; + reg = <0xff520000 0x1000>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru CLK_I2C3>, <&cru PCLK_I2C3>; + clock-names = "i2c", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3m0_xfer>; + rockchip,grf = <&pmugrf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm8: pwm@ff550000 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff550000 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + pinctrl-0 = <&pwm8m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm9: pwm@ff550010 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff550010 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + pinctrl-0 = <&pwm9m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm10: pwm@ff550020 { + compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; + reg = <0xff550020 0x10>; + clock-names = "pwm", "pclk"; + clocks = <&cru CLK_PWM2>, <&cru PCLK_PWM2>; + pinctrl-0 = <&pwm10m0_pins>; + pinctrl-names = "default"; + #pwm-cells = <3>; + status = "disabled"; + }; + pwm11: pwm@ff550030 { compatible = "rockchip,rv1126-pwm", "rockchip,rk3328-pwm"; reg = <0xff550030 0x10>; @@ -419,6 +544,32 @@ clock-names = "pclk", "timer"; }; + i2s0: i2s@ff800000 { + compatible = "rockchip,rv1126-i2s-tdm"; + reg = <0xff800000 0x1000>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru MCLK_I2S0_TX>, <&cru MCLK_I2S0_RX>, <&cru HCLK_I2S0>; + clock-names = "mclk_tx", "mclk_rx", "hclk"; + dmas = <&dmac 20>, <&dmac 19>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0m0_sclk_tx>, + <&i2s0m0_sclk_rx>, + <&i2s0m0_mclk>, + <&i2s0m0_lrck_tx>, + <&i2s0m0_lrck_rx>, + <&i2s0m0_sdi0>, + <&i2s0m0_sdo0>, + <&i2s0m0_sdo1_sdi3>, + <&i2s0m0_sdo2_sdi2>, + <&i2s0m0_sdo3_sdi1>; + resets = <&cru SRST_I2S0_TX_M>, <&cru SRST_I2S0_RX_M>; + reset-names = "tx-m", "rx-m"; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + vop: vop@ffb00000 { compatible = "rockchip,rv1126-vop"; reg = <0xffb00000 0x200>, <0xffb00a00 0x400>; diff --git a/arch/arm/boot/dts/st/Makefile b/arch/arm/boot/dts/st/Makefile index 015903d09323..eab3a9bd435f 100644 --- a/arch/arm/boot/dts/st/Makefile +++ b/arch/arm/boot/dts/st/Makefile @@ -35,8 +35,11 @@ dtb-$(CONFIG_ARCH_STM32) += \ stm32mp151a-prtt1c.dtb \ stm32mp151a-prtt1s.dtb \ stm32mp151a-dhcor-testbench.dtb \ + stm32mp151c-mecio1r0.dtb \ + stm32mp151c-mect1s.dtb \ stm32mp153c-dhcom-drc02.dtb \ stm32mp153c-dhcor-drc-compact.dtb \ + stm32mp153c-mecio1r1.dtb \ stm32mp157a-avenger96.dtb \ stm32mp157a-dhcor-avenger96.dtb \ stm32mp157a-dk1.dtb \ diff --git a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi index c9f588a65094..8db1ec4a3b26 100644 --- a/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32mp13-pinctrl.dtsi @@ -94,14 +94,20 @@ /omit-if-no-ref/ eth1_rgmii_sleep_pins_a: eth1-rgmii-sleep-0 { pins1 { + pinmux = <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */ + <STM32_PINMUX('G', 2, AF11)>; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + + pins2 { pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */ <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */ <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */ <STM32_PINMUX('E', 5, ANALOG)>, /* ETH_RGMII_TXD3 */ <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */ <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_RGMII_GTX_CLK */ - <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */ - <STM32_PINMUX('G', 2, ANALOG)>, /* ETH_MDC */ <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */ <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */ <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD1 */ @@ -178,14 +184,20 @@ /omit-if-no-ref/ eth2_rgmii_sleep_pins_a: eth2-rgmii-sleep-0 { pins1 { + pinmux = <STM32_PINMUX('B', 6, AF11)>, /* ETH_MDIO */ + <STM32_PINMUX('G', 5, AF10)>; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + + pins2 { pinmux = <STM32_PINMUX('F', 7, ANALOG)>, /* ETH_RGMII_TXD0 */ <STM32_PINMUX('G', 11, ANALOG)>, /* ETH_RGMII_TXD1 */ <STM32_PINMUX('G', 1, ANALOG)>, /* ETH_RGMII_TXD2 */ <STM32_PINMUX('E', 6, ANALOG)>, /* ETH_RGMII_TXD3 */ <STM32_PINMUX('F', 6, ANALOG)>, /* ETH_RGMII_TX_CTL */ <STM32_PINMUX('G', 3, ANALOG)>, /* ETH_RGMII_GTX_CLK */ - <STM32_PINMUX('B', 6, ANALOG)>, /* ETH_MDIO */ - <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_MDC */ <STM32_PINMUX('F', 4, ANALOG)>, /* ETH_RGMII_RXD0 */ <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_RXD1 */ <STM32_PINMUX('H', 6, ANALOG)>, /* ETH_RGMII_RXD2 */ diff --git a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts index bacb70b4256b..853dc21449d9 100644 --- a/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts +++ b/arch/arm/boot/dts/st/stm32mp135f-dhcor-dhsbc.dts @@ -75,6 +75,8 @@ }; ðernet1 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <ðernet_mac1_address>; phy-handle = <ðphy1>; phy-mode = "rgmii-id"; pinctrl-0 = <ð1_rgmii_pins_a>; @@ -94,14 +96,36 @@ interrupt-parent = <&gpiog>; interrupts = <12 IRQ_TYPE_LEVEL_LOW>; reg = <1>; + realtek,clkout-disable; reset-assert-us = <15000>; reset-deassert-us = <55000>; reset-gpios = <&gpioa 11 GPIO_ACTIVE_LOW>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_WAN; + linux,default-trigger = "netdev"; + }; + + led@1 { + reg = <1>; + color = <LED_COLOR_ID_YELLOW>; + function = LED_FUNCTION_WAN; + linux,default-trigger = "netdev"; + }; + }; }; }; }; ðernet2 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <ðernet_mac2_address>; phy-handle = <ðphy2>; phy-mode = "rgmii-id"; pinctrl-0 = <ð2_rgmii_pins_a>; @@ -121,9 +145,29 @@ interrupt-parent = <&gpiog>; interrupts = <15 IRQ_TYPE_LEVEL_LOW>; reg = <1>; + realtek,clkout-disable; reset-assert-us = <15000>; reset-deassert-us = <55000>; reset-gpios = <&gpiog 8 GPIO_ACTIVE_LOW>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_LAN; + linux,default-trigger = "netdev"; + }; + + led@1 { + reg = <1>; + color = <LED_COLOR_ID_YELLOW>; + function = LED_FUNCTION_LAN; + linux,default-trigger = "netdev"; + }; + }; }; }; }; diff --git a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi index ae83e7b10232..70e132dc6147 100644 --- a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi @@ -2229,6 +2229,9 @@ <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */ <STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */ <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; }; }; diff --git a/arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts index 75874eafde11..8e1dd84e0c0a 100644 --- a/arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts +++ b/arch/arm/boot/dts/st/stm32mp151a-prtt1a.dts @@ -28,16 +28,12 @@ }; }; -&pwm5_pins_a { - pins { - pinmux = <STM32_PINMUX('A', 0, AF2)>; /* TIM5_CH1 */ - }; +&{pwm5_pins_a/pins} { + pinmux = <STM32_PINMUX('A', 0, AF2)>; /* TIM5_CH1 */ }; -&pwm5_sleep_pins_a { - pins { - pinmux = <STM32_PINMUX('A', 0, ANALOG)>; /* TIM5_CH1 */ - }; +&{pwm5_sleep_pins_a/pins} { + pinmux = <STM32_PINMUX('A', 0, ANALOG)>; /* TIM5_CH1 */ }; &timers5 { diff --git a/arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts index c90d815f906b..3b33b7093b68 100644 --- a/arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts +++ b/arch/arm/boot/dts/st/stm32mp151a-prtt1c.dts @@ -168,52 +168,42 @@ status = "okay"; }; -&sdmmc2_b4_od_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */ - <STM32_PINMUX('B', 7, AF10)>, /* SDMMC2_D1 */ - <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */ - <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */ - }; +&{sdmmc2_b4_od_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */ + <STM32_PINMUX('B', 7, AF10)>, /* SDMMC2_D1 */ + <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */ + <STM32_PINMUX('B', 4, AF9)>; /* SDMMC2_D3 */ }; -&sdmmc2_b4_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */ - <STM32_PINMUX('B', 7, AF10)>, /* SDMMC2_D1 */ - <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */ - <STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */ - <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */ - }; +&{sdmmc2_b4_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */ + <STM32_PINMUX('B', 7, AF10)>, /* SDMMC2_D1 */ + <STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */ + <STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */ + <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */ }; -&sdmmc2_b4_sleep_pins_a { - pins { - pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */ - <STM32_PINMUX('B', 7, ANALOG)>, /* SDMMC2_D1 */ - <STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */ - <STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */ - <STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */ - <STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */ - }; +&{sdmmc2_b4_sleep_pins_a/pins} { + pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */ + <STM32_PINMUX('B', 7, ANALOG)>, /* SDMMC2_D1 */ + <STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */ + <STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */ + <STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */ + <STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */ }; -&sdmmc2_d47_pins_a { - pins { - pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */ - <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */ - <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */ - <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */ - }; +&{sdmmc2_d47_pins_a/pins} { + pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */ + <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */ + <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */ + <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */ }; -&sdmmc2_d47_sleep_pins_a { - pins { - pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */ - <STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */ - <STM32_PINMUX('C', 6, ANALOG)>, /* SDMMC2_D6 */ - <STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */ - }; +&{sdmmc2_d47_sleep_pins_a/pins} { + pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* SDMMC2_D4 */ + <STM32_PINMUX('A', 9, ANALOG)>, /* SDMMC2_D5 */ + <STM32_PINMUX('C', 6, ANALOG)>, /* SDMMC2_D6 */ + <STM32_PINMUX('D', 3, ANALOG)>; /* SDMMC2_D7 */ }; &sdmmc3 { @@ -238,34 +228,28 @@ }; }; -&sdmmc3_b4_od_pins_b { - pins1 { - pinmux = <STM32_PINMUX('D', 1, AF10)>, /* SDMMC3_D0 */ - <STM32_PINMUX('D', 4, AF10)>, /* SDMMC3_D1 */ - <STM32_PINMUX('D', 5, AF10)>, /* SDMMC3_D2 */ - <STM32_PINMUX('D', 7, AF10)>; /* SDMMC3_D3 */ - }; +&{sdmmc3_b4_od_pins_b/pins1} { + pinmux = <STM32_PINMUX('D', 1, AF10)>, /* SDMMC3_D0 */ + <STM32_PINMUX('D', 4, AF10)>, /* SDMMC3_D1 */ + <STM32_PINMUX('D', 5, AF10)>, /* SDMMC3_D2 */ + <STM32_PINMUX('D', 7, AF10)>; /* SDMMC3_D3 */ }; -&sdmmc3_b4_pins_b { - pins1 { - pinmux = <STM32_PINMUX('D', 1, AF10)>, /* SDMMC3_D0 */ - <STM32_PINMUX('D', 4, AF10)>, /* SDMMC3_D1 */ - <STM32_PINMUX('D', 5, AF10)>, /* SDMMC3_D2 */ - <STM32_PINMUX('D', 7, AF10)>, /* SDMMC3_D3 */ - <STM32_PINMUX('D', 0, AF10)>; /* SDMMC3_CMD */ - }; +&{sdmmc3_b4_pins_b/pins1} { + pinmux = <STM32_PINMUX('D', 1, AF10)>, /* SDMMC3_D0 */ + <STM32_PINMUX('D', 4, AF10)>, /* SDMMC3_D1 */ + <STM32_PINMUX('D', 5, AF10)>, /* SDMMC3_D2 */ + <STM32_PINMUX('D', 7, AF10)>, /* SDMMC3_D3 */ + <STM32_PINMUX('D', 0, AF10)>; /* SDMMC3_CMD */ }; -&sdmmc3_b4_sleep_pins_b { - pins { - pinmux = <STM32_PINMUX('D', 1, ANALOG)>, /* SDMMC3_D0 */ - <STM32_PINMUX('D', 4, ANALOG)>, /* SDMMC3_D1 */ - <STM32_PINMUX('D', 5, ANALOG)>, /* SDMMC3_D2 */ - <STM32_PINMUX('D', 7, ANALOG)>, /* SDMMC3_D3 */ - <STM32_PINMUX('G', 15, ANALOG)>, /* SDMMC3_CK */ - <STM32_PINMUX('D', 0, ANALOG)>; /* SDMMC3_CMD */ - }; +&{sdmmc3_b4_sleep_pins_b/pins} { + pinmux = <STM32_PINMUX('D', 1, ANALOG)>, /* SDMMC3_D0 */ + <STM32_PINMUX('D', 4, ANALOG)>, /* SDMMC3_D1 */ + <STM32_PINMUX('D', 5, ANALOG)>, /* SDMMC3_D2 */ + <STM32_PINMUX('D', 7, ANALOG)>, /* SDMMC3_D3 */ + <STM32_PINMUX('G', 15, ANALOG)>, /* SDMMC3_CK */ + <STM32_PINMUX('D', 0, ANALOG)>; /* SDMMC3_CMD */ }; &spi1 { diff --git a/arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi b/arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi index 3938d357e198..98a31c2b5d45 100644 --- a/arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi +++ b/arch/arm/boot/dts/st/stm32mp151a-prtt1l.dtsi @@ -69,30 +69,27 @@ status = "okay"; }; -ðernet0_rmii_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 12, AF11)>, /* ETH1_RMII_TXD0 */ - <STM32_PINMUX('B', 13, AF11)>, /* ETH1_RMII_TXD1 */ - <STM32_PINMUX('B', 11, AF11)>; /* ETH1_RMII_TX_EN */ - }; - pins2 { - pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH1_RMII_RXD0 */ - <STM32_PINMUX('C', 5, AF11)>, /* ETH1_RMII_RXD1 */ - <STM32_PINMUX('A', 1, AF11)>, /* ETH1_RMII_REF_CLK input */ - <STM32_PINMUX('A', 7, AF11)>; /* ETH1_RMII_CRS_DV */ - }; +&{ethernet0_rmii_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 12, AF11)>, /* ETH1_RMII_TXD0 */ + <STM32_PINMUX('B', 13, AF11)>, /* ETH1_RMII_TXD1 */ + <STM32_PINMUX('B', 11, AF11)>; /* ETH1_RMII_TX_EN */ }; -ðernet0_rmii_sleep_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 12, ANALOG)>, /* ETH1_RMII_TXD0 */ - <STM32_PINMUX('B', 13, ANALOG)>, /* ETH1_RMII_TXD1 */ - <STM32_PINMUX('B', 11, ANALOG)>, /* ETH1_RMII_TX_EN */ - <STM32_PINMUX('C', 4, ANALOG)>, /* ETH1_RMII_RXD0 */ - <STM32_PINMUX('C', 5, ANALOG)>, /* ETH1_RMII_RXD1 */ - <STM32_PINMUX('A', 1, ANALOG)>, /* ETH1_RMII_REF_CLK */ - <STM32_PINMUX('A', 7, ANALOG)>; /* ETH1_RMII_CRS_DV */ - }; +&{ethernet0_rmii_pins_a/pins2} { + pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH1_RMII_RXD0 */ + <STM32_PINMUX('C', 5, AF11)>, /* ETH1_RMII_RXD1 */ + <STM32_PINMUX('A', 1, AF11)>, /* ETH1_RMII_REF_CLK input */ + <STM32_PINMUX('A', 7, AF11)>; /* ETH1_RMII_CRS_DV */ +}; + +&{ethernet0_rmii_sleep_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 12, ANALOG)>, /* ETH1_RMII_TXD0 */ + <STM32_PINMUX('B', 13, ANALOG)>, /* ETH1_RMII_TXD1 */ + <STM32_PINMUX('B', 11, ANALOG)>, /* ETH1_RMII_TX_EN */ + <STM32_PINMUX('C', 4, ANALOG)>, /* ETH1_RMII_RXD0 */ + <STM32_PINMUX('C', 5, ANALOG)>, /* ETH1_RMII_RXD1 */ + <STM32_PINMUX('A', 1, ANALOG)>, /* ETH1_RMII_REF_CLK */ + <STM32_PINMUX('A', 7, ANALOG)>; /* ETH1_RMII_CRS_DV */ }; &iwdg2 { @@ -122,12 +119,11 @@ }; }; -&qspi_bk1_pins_a { - pins1 { - bias-pull-up; - drive-push-pull; - slew-rate = <1>; - }; +&{qspi_bk1_pins_a/pins} { + /delete-property/ bias-disable; + bias-pull-up; + drive-push-pull; + slew-rate = <1>; }; &rng1 { @@ -147,22 +143,24 @@ status = "okay"; }; -&sdmmc1_b4_od_pins_a { - pins1 { - bias-pull-up; - }; - pins2 { - bias-pull-up; - }; +&{sdmmc1_b4_od_pins_a/pins1} { + /delete-property/ bias-disable; + bias-pull-up; }; -&sdmmc1_b4_pins_a { - pins1 { - bias-pull-up; - }; - pins2 { - bias-pull-up; - }; +&{sdmmc1_b4_od_pins_a/pins2} { + /delete-property/ bias-disable; + bias-pull-up; +}; + +&{sdmmc1_b4_pins_a/pins1} { + /delete-property/ bias-disable; + bias-pull-up; +}; + +&{sdmmc1_b4_pins_a/pins2} { + /delete-property/ bias-disable; + bias-pull-up; }; &uart4 { @@ -175,34 +173,30 @@ status = "okay"; }; -&uart4_idle_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 9, ANALOG)>; /* UART4_TX */ - }; - pins2 { - pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ - bias-pull-up; - }; +&{uart4_idle_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 9, ANALOG)>; /* UART4_TX */ }; -&uart4_pins_a { - pins1 { - pinmux = <STM32_PINMUX('B', 9, AF8)>; /* UART4_TX */ - bias-disable; - drive-push-pull; - slew-rate = <0>; - }; - pins2 { - pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ - bias-pull-up; - }; +&{uart4_idle_pins_a/pins2} { + pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ + /delete-property/ bias-disable; + bias-pull-up; }; -&uart4_sleep_pins_a { - pins { - pinmux = <STM32_PINMUX('B', 9, ANALOG)>, /* UART4_TX */ - <STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */ - }; +&{uart4_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 9, AF8)>; /* UART4_TX */ + slew-rate = <0>; +}; + +&{uart4_pins_a/pins2} { + pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ + /delete-property/ bias-disable; + bias-pull-up; +}; + +&{uart4_sleep_pins_a/pins} { + pinmux = <STM32_PINMUX('B', 9, ANALOG)>, /* UART4_TX */ + <STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */ }; &usbh_ehci { diff --git a/arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts b/arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts index ad25929e64e6..b6be61b159e7 100644 --- a/arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts +++ b/arch/arm/boot/dts/st/stm32mp151a-prtt1s.dts @@ -36,18 +36,14 @@ }; }; -&i2c1_pins_a { - pins { - pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */ - <STM32_PINMUX('D', 13, AF5)>; /* I2C1_SDA */ - }; +&{i2c1_pins_a/pins} { + pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */ + <STM32_PINMUX('D', 13, AF5)>; /* I2C1_SDA */ }; -&i2c1_sleep_pins_a { - pins { - pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */ - <STM32_PINMUX('D', 13, ANALOG)>; /* I2C1_SDA */ - }; +&{i2c1_sleep_pins_a/pins} { + pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */ + <STM32_PINMUX('D', 13, ANALOG)>; /* I2C1_SDA */ }; &mdio0 { diff --git a/arch/arm/boot/dts/st/stm32mp151c-mecio1r0.dts b/arch/arm/boot/dts/st/stm32mp151c-mecio1r0.dts new file mode 100644 index 000000000000..a5ea1431c399 --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp151c-mecio1r0.dts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Protonic Holland + * Author: David Jander <david@protonic.nl> + */ +/dts-v1/; + +#include "stm32mp151.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include "stm32mp15x-mecio1-io.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> + +/ { + model = "Protonic MECIO1r0"; + compatible = "prt,mecio1r0", "st,stm32mp151"; + + led { + compatible = "gpio-leds"; + + led-0 { + color = <LED_COLOR_ID_RED>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 13 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 14 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&clk_hse { + clock-frequency = <25000000>; +}; + +ðernet0 { + assigned-clocks = <&rcc ETHCK_K>, <&rcc PLL3_Q>; + assigned-clock-parents = <&rcc PLL3_Q>; + assigned-clock-rates = <125000000>; /* Clock PLL3 to 625Mhz in tf-a. */ + st,eth-clk-sel; +}; diff --git a/arch/arm/boot/dts/st/stm32mp151c-mect1s.dts b/arch/arm/boot/dts/st/stm32mp151c-mect1s.dts new file mode 100644 index 000000000000..a1b8c3646e98 --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp151c-mect1s.dts @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Protonic Holland + * Author: David Jander <david@protonic.nl> + */ +/dts-v1/; + +#include "stm32mp151.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> + +/ { + model = "Protonic MECT1S"; + compatible = "prt,mect1s", "st,stm32mp151"; + + chosen { + stdout-path = "serial0:1500000n8"; + }; + + aliases { + serial0 = &uart4; + ethernet0 = ðernet0; + ethernet1 = ðernet1; + ethernet2 = ðernet2; + ethernet3 = ðernet3; + ethernet4 = ðernet4; + }; + + v3v3: regulator-v3v3 { + compatible = "regulator-fixed"; + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + v5v: regulator-v5v { + compatible = "regulator-fixed"; + regulator-name = "v5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + led { + compatible = "gpio-leds"; + + led-0 { + color = <LED_COLOR_ID_RED>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + }; + + led-1 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&clk_hse { + clock-frequency = <24000000>; +}; + +&clk_lse { + status = "disabled"; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rmii_pins_a>; + pinctrl-1 = <ðernet0_rmii_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rmii"; + max-speed = <100>; + st,eth-clk-sel; + + fixed-link { + speed = <100>; + full-duplex; + }; + + mdio0: mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + }; +}; + +&{ethernet0_rmii_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 12, AF11)>, /* ETH1_RMII_TXD0 */ + <STM32_PINMUX('B', 13, AF11)>, /* ETH1_RMII_TXD1 */ + <STM32_PINMUX('B', 11, AF11)>, /* ETH1_RMII_TX_EN */ + <STM32_PINMUX('A', 2, AF11)>, /* ETH1_MDIO */ + <STM32_PINMUX('C', 1, AF11)>; /* ETH1_MDC */ +}; + +&{ethernet0_rmii_pins_a/pins2} { + pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH1_RMII_RXD0 */ + <STM32_PINMUX('C', 5, AF11)>, /* ETH1_RMII_RXD1 */ + <STM32_PINMUX('A', 1, AF11)>, /* ETH1_RMII_REF_CLK input */ + <STM32_PINMUX('A', 7, AF11)>; /* ETH1_RMII_CRS_DV */ +}; + +&{ethernet0_rmii_sleep_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 12, ANALOG)>, /* ETH1_RMII_TXD0 */ + <STM32_PINMUX('B', 13, ANALOG)>, /* ETH1_RMII_TXD1 */ + <STM32_PINMUX('B', 11, ANALOG)>, /* ETH1_RMII_TX_EN */ + <STM32_PINMUX('C', 4, ANALOG)>, /* ETH1_RMII_RXD0 */ + <STM32_PINMUX('C', 5, ANALOG)>, /* ETH1_RMII_RXD1 */ + <STM32_PINMUX('A', 1, ANALOG)>, /* ETH1_RMII_REF_CLK */ + <STM32_PINMUX('A', 7, ANALOG)>; /* ETH1_RMII_CRS_DV */ +}; + +&mdio0 { + /* All this DP83TG720R PHYs can't be probed before switch@0 is + * probed so we need to use compatible with PHYid + */ + /* TI DP83TG720R */ + t1_phy0: ethernet-phy@8 { + compatible = "ethernet-phy-id2000.a284"; + reg = <8>; + interrupts-extended = <&gpioi 5 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpioh 13 GPIO_ACTIVE_LOW>; + reset-assert-us = <10>; + reset-deassert-us = <35>; + }; + + /* TI DP83TG720R */ + t1_phy1: ethernet-phy@c { + compatible = "ethernet-phy-id2000.a284"; + reg = <12>; + interrupts-extended = <&gpioj 0 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpioh 14 GPIO_ACTIVE_LOW>; + reset-assert-us = <10>; + reset-deassert-us = <35>; + }; + + /* TI DP83TG720R */ + t1_phy2: ethernet-phy@4 { + compatible = "ethernet-phy-id2000.a284"; + reg = <4>; + interrupts-extended = <&gpioi 7 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpioh 15 GPIO_ACTIVE_LOW>; + reset-assert-us = <10>; + reset-deassert-us = <35>; + }; + + /* TI DP83TG720R */ + t1_phy3: ethernet-phy@d { + compatible = "ethernet-phy-id2000.a284"; + reg = <13>; + interrupts-extended = <&gpioi 15 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpioi 13 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <1000>; + }; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a + &qspi_bk1_pins_a + &qspi_cs1_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a + &qspi_bk1_sleep_pins_a + &qspi_cs1_sleep_pins_a>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&{qspi_bk1_pins_a/pins} { + /delete-property/ bias-disable; + bias-pull-up; + drive-push-pull; + slew-rate = <1>; +}; + +&spi2 { + pinctrl-0 = <&spi2_pins_b>; + pinctrl-names = "default"; + cs-gpios = <&gpioj 3 GPIO_ACTIVE_LOW>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + + switch@0 { + compatible = "nxp,sja1105q"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-rx-delay-us = <1>; + spi-tx-delay-us = <1>; + spi-cpha; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + ethernet1: port@0 { + reg = <0>; + label = "t10"; + phy-mode = "rgmii-id"; + phy-handle = <&t1_phy0>; + }; + + ethernet2: port@1 { + reg = <1>; + label = "t11"; + phy-mode = "rgmii-id"; + phy-handle = <&t1_phy1>; + }; + + ethernet3: port@2 { + reg = <2>; + label = "t12"; + phy-mode = "rgmii-id"; + phy-handle = <&t1_phy2>; + }; + + ethernet4: port@3 { + reg = <3>; + label = "t13"; + phy-mode = "rgmii-id"; + phy-handle = <&t1_phy3>; + }; + + port@4 { + reg = <4>; + label = "cpu"; + ethernet = <ðernet0>; + phy-mode = "rmii"; + + /* RGMII mode is not working properly, using RMII instead. */ + fixed-link { + speed = <100>; + full-duplex; + }; + }; + }; + }; +}; + +&uart4 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&usbh_ehci { + status = "okay"; +}; + +&usbotg_hs { + dr_mode = "host"; + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + vbus-supply = <&v5v>; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&v3v3>; +}; + +&usbphyc_port1 { + phy-supply = <&v3v3>; +}; diff --git a/arch/arm/boot/dts/st/stm32mp153c-mecio1r1.dts b/arch/arm/boot/dts/st/stm32mp153c-mecio1r1.dts new file mode 100644 index 000000000000..16b814c19350 --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp153c-mecio1r1.dts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Protonic Holland + * Author: David Jander <david@protonic.nl> + */ +/dts-v1/; + +#include "stm32mp153.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include "stm32mp15x-mecio1-io.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> + +/ { + model = "Protonic MECIO1r1"; + compatible = "prt,mecio1r1", "st,stm32mp153"; + + led { + compatible = "gpio-leds"; + + led-0 { + color = <LED_COLOR_ID_RED>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + }; + + led-1 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DEBUG; + gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&clk_hse { + clock-frequency = <24000000>; +}; + +&m_can1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can1_pins_b>; + pinctrl-1 = <&m_can1_sleep_pins_b>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/st/stm32mp15x-mecio1-io.dtsi b/arch/arm/boot/dts/st/stm32mp15x-mecio1-io.dtsi new file mode 100644 index 000000000000..915ba2526f45 --- /dev/null +++ b/arch/arm/boot/dts/st/stm32mp15x-mecio1-io.dtsi @@ -0,0 +1,527 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Protonic Holland + * Author: David Jander <david@protonic.nl> + */ + +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + chosen { + stdout-path = "serial0:1500000n8"; + }; + + aliases { + serial0 = &uart4; + ethernet0 = ðernet0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; + spi4 = &spi4; + spi5 = &spi5; + spi6 = &spi6; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x10000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + }; + + v3v3: regulator-v3v3 { + compatible = "regulator-fixed"; + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + v5v: regulator-v5v { + compatible = "regulator-fixed"; + regulator-name = "v5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&adc { + /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ + pinctrl-0 = <&adc12_pins_mecsbc>; + pinctrl-names = "default"; + vdd-supply = <&v3v3>; + vdda-supply = <&v3v3>; + vref-supply = <&v3v3>; + status = "okay"; +}; + +&adc1 { + status = "okay"; + + channel@0 { + reg = <0>; + /* 16.5 ck_cycles sampling time */ + st,min-sample-time-ns = <5000>; + label = "p24v_stp"; + }; + + channel@1 { + reg = <1>; + st,min-sample-time-ns = <5000>; + label = "p24v_hpdcm"; + }; + + channel@2 { + reg = <2>; + st,min-sample-time-ns = <5000>; + label = "ain0"; + }; + + channel@3 { + reg = <3>; + st,min-sample-time-ns = <5000>; + label = "hpdcm1_i2"; + }; + + channel@5 { + reg = <5>; + st,min-sample-time-ns = <5000>; + label = "hpout1_i"; + }; + + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + label = "ain1"; + }; + + channel@9 { + reg = <9>; + st,min-sample-time-ns = <5000>; + label = "hpout0_i"; + }; + + channel@10 { + reg = <10>; + st,min-sample-time-ns = <5000>; + label = "phint0_ain"; + }; + + channel@13 { + reg = <13>; + st,min-sample-time-ns = <5000>; + label = "phint1_ain"; + }; + + channel@15 { + reg = <15>; + st,min-sample-time-ns = <5000>; + label = "hpdcm0_i1"; + }; + + channel@16 { + reg = <16>; + st,min-sample-time-ns = <5000>; + label = "lsin"; + }; + + channel@18 { + reg = <18>; + st,min-sample-time-ns = <5000>; + label = "hpdcm0_i2"; + }; + + channel@19 { + reg = <19>; + st,min-sample-time-ns = <5000>; + label = "hpdcm1_i1"; + }; +}; + +&adc2 { + status = "okay"; + + channel@2 { + reg = <2>; + /* 16.5 ck_cycles sampling time */ + st,min-sample-time-ns = <5000>; + label = "ain2"; + }; + + channel@6 { + reg = <6>; + st,min-sample-time-ns = <5000>; + label = "ain3"; + }; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rgmii_pins_x>; + pinctrl-1 = <ðernet0_rgmii_sleep_pins_x>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; + st,eth-clk-sel; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@8 { + reg = <8>; + interrupts-extended = <&gpiog 7 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpiog 10 GPIO_ACTIVE_LOW>; + reset-assert-us = <10>; + reset-deassert-us = <35>; + }; + }; +}; + +&gpiod { + gpio-line-names = "", "", "", "", + "", "", "", "", + "", "", "", "", + "STP_RESETN", "STP_ENABLEN", "HPOUT0", "HPOUT0_ALERTN"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog_d_mecsbc>; +}; + +&gpioe { + gpio-line-names = "HPOUT0_RESETN", "HPOUT1", "HPOUT1_ALERTN", "", + "", "", "HPOUT1_RESETN", + "LPOUT0", "LPOUT0_ALERTN", "GPOUT0_RESETN", + "LPOUT1", "LPOUT1_ALERTN", "GPOUT1_RESETN", + "LPOUT2", "LPOUT2_ALERTN", "GPOUT2_RESETN"; +}; + +&gpiof { + gpio-line-names = "LPOUT3", "LPOUT3_ALERTN", "GPOUT3_RESETN", + "LPOUT4", "LPOUT4_ALERTN", "GPOUT4_RESETN", + "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiog { + gpio-line-names = "LPOUT5", "LPOUT5_ALERTN", "", "LPOUT5_RESETN", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpioh { + gpio-line-names = "", "", "", "", + "", "", "", "", + "GPIO0_RESETN", "", "", "", + "", "", "", ""; +}; + +&gpioi { + gpio-line-names = "", "", "", "", + "", "", "", "", + "HPDCM0_SLEEPN", "HPDCM1_SLEEPN", "GPIO1_RESETN", "", + "", "", "", ""; +}; + +&gpioj { + gpio-line-names = "HSIN10", "HSIN11", "HSIN12", "HSIN13", + "HSIN14", "HSIN15", "", "", + "", "", "", "", + "", "RTD_RESETN", "", ""; +}; + +&gpiok { + gpio-line-names = "", "", "HSIN0", "HSIN1", + "HSIN2", "HSIN3", "HSIN4", "HSIN5"; +}; + +&gpioz { + gpio-line-names = "", "", "", "HSIN6", + "HSIN7", "HSIN8", "HSIN9", ""; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + pinctrl-1 = <&i2c2_sleep_pins_a>; + status = "okay"; + + gpio0: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "HSIN0_BIAS", "HSIN1_BIAS", "HSIN2_BIAS", "HSIN3_BIAS", + "", "", "HSIN_VREF0_LVL", "HSIN_VREF1_LVL", + "HSIN4_BIAS", "HSIN5_BIAS", "HSIN6_BIAS", "HSIN9_BIAS", + "", "", "", ""; + }; + + gpio1: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "HSIN8_BIAS", "HSIN9_BIAS", "HSIN10_BIAS", "HSIN11_BIAS", + "", "", "HSIN_VREF2_LVL", "HSIN_VREF3_LVL", + "HSIN12_BIAS", "HSIN13_BIAS", "HSIN14_BIAS", "HSIN15_BIAS", + "", "", "LSIN8_BIAS", "LSIN9_BIAS"; + }; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a + &qspi_bk1_pins_a + &qspi_cs1_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a + &qspi_bk1_sleep_pins_a + &qspi_cs1_sleep_pins_a>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <104000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&{qspi_bk1_pins_a/pins} { + pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */ + <STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */ + <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */ + <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */ + /delete-property/ bias-disable; + bias-pull-up; +}; + +&timers1 { + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + + hpdcm0_pwm: pwm { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pwm1_pins_mecio1>; + pinctrl-1 = <&pwm1_sleep_pins_mecio1>; + status = "okay"; + }; +}; + +&timers8 { + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + + hpdcm1_pwm: pwm { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pwm8_pins_mecio1>; + pinctrl-1 = <&pwm8_sleep_pins_mecio1>; + status = "okay"; + }; +}; + +&uart4 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&{uart4_pins_a/pins1} { + pinmux = <STM32_PINMUX('B', 9, AF8)>; /* UART4_TX */ +}; + +&{uart4_pins_a/pins2} { + pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */ + /delete-property/ bias-disable; + bias-pull-up; +}; + +&usbotg_hs { + dr_mode = "host"; + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + vbus-supply = <&v5v>; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&v3v3>; +}; + +&usbphyc_port1 { + phy-supply = <&v3v3>; +}; + +&pinctrl { + adc12_pins_mecsbc: adc12-ain-mecsbc-0 { + pins { + pinmux = <STM32_PINMUX('F', 11, ANALOG)>, /* ADC1_INP2 */ + <STM32_PINMUX('F', 12, ANALOG)>, /* ADC1_INP6 */ + <STM32_PINMUX('F', 13, ANALOG)>, /* ADC2_INP2 */ + <STM32_PINMUX('F', 14, ANALOG)>, /* ADC2_INP6 */ + <STM32_PINMUX('A', 0, ANALOG)>, /* ADC1_INP16 */ + <STM32_PINMUX('A', 3, ANALOG)>, /* ADC1_INP15 */ + <STM32_PINMUX('A', 4, ANALOG)>, /* ADC1_INP18 */ + <STM32_PINMUX('A', 5, ANALOG)>, /* ADC1_INP19 */ + <STM32_PINMUX('A', 6, ANALOG)>, /* ADC1_INP3 */ + <STM32_PINMUX('B', 0, ANALOG)>, /* ADC1_INP9 */ + <STM32_PINMUX('B', 1, ANALOG)>, /* ADC1_INP5 */ + <STM32_PINMUX('C', 0, ANALOG)>, /* ADC1_INP10 */ + <STM32_PINMUX('C', 3, ANALOG)>; /* ADC1_INP13 */ + }; + }; + + pinctrl_hog_d_mecsbc: hog-d-0 { + pins { + pinmux = <STM32_PINMUX('D', 12, GPIO)>; /* STP_RESETn */ + bias-pull-up; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm1_pins_mecio1: pwm1-mecio1-0 { + pins { + pinmux = <STM32_PINMUX('A', 8, AF1)>, /* TIM1_CH1 */ + <STM32_PINMUX('A', 8, AF1)>; /* TIM1_CH2 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm1_sleep_pins_mecio1: pwm1-sleep-mecio1-0 { + pins { + pinmux = <STM32_PINMUX('A', 8, ANALOG)>, /* TIM1_CH1 */ + <STM32_PINMUX('A', 8, ANALOG)>; /* TIM1_CH2 */ + }; + }; + + pwm8_pins_mecio1: pwm8-mecio1-0 { + pins { + pinmux = <STM32_PINMUX('I', 5, AF3)>, /* TIM8_CH1 */ + <STM32_PINMUX('I', 6, AF3)>; /* TIM8_CH2 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm8_sleep_pins_mecio1: pwm8-sleep-mecio1-0 { + pins { + pinmux = <STM32_PINMUX('I', 5, ANALOG)>, /* TIM8_CH1 */ + <STM32_PINMUX('I', 6, ANALOG)>; /* TIM8_CH2 */ + }; + }; + + ethernet0_rgmii_pins_x: rgmii-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */ + <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */ + <STM32_PINMUX('B', 12, AF11)>, /* ETH_RGMII_TXD0 */ + <STM32_PINMUX('B', 13, AF11)>, /* ETH_RGMII_TXD1 */ + <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */ + <STM32_PINMUX('B', 8, AF11)>, /* ETH_RGMII_TXD3 */ + <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */ + <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */ + <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */ + <STM32_PINMUX('H', 6, AF11)>, /* ETH_RGMII_RXD2 */ + <STM32_PINMUX('H', 7, AF11)>, /* ETH_RGMII_RXD3 */ + <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */ + <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_sleep_pins_x: rgmii-sleep-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */ + <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */ + <STM32_PINMUX('B', 12, ANALOG)>, /* ETH_RGMII_TXD0 */ + <STM32_PINMUX('B', 13, ANALOG)>, /* ETH_RGMII_TXD1 */ + <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */ + <STM32_PINMUX('B', 8, ANALOG)>, /* ETH_RGMII_TXD3 */ + <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */ + <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */ + <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */ + <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */ + <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */ + <STM32_PINMUX('H', 6, ANALOG)>, /* ETH_RGMII_RXD2 */ + <STM32_PINMUX('H', 7, ANALOG)>, /* ETH_RGMII_RXD3 */ + <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */ + <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */ + }; + }; +}; diff --git a/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi index 466d9701add0..171d7c7658fa 100644 --- a/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi +++ b/arch/arm/boot/dts/st/stm32mp15xx-dhcom-pdk2.dtsi @@ -192,15 +192,11 @@ sgtl5000_tx_endpoint: endpoint@0 { reg = <0>; remote-endpoint = <&sai2a_endpoint>; - frame-master = <&sgtl5000_tx_endpoint>; - bitclock-master = <&sgtl5000_tx_endpoint>; }; sgtl5000_rx_endpoint: endpoint@1 { reg = <1>; remote-endpoint = <&sai2b_endpoint>; - frame-master = <&sgtl5000_rx_endpoint>; - bitclock-master = <&sgtl5000_rx_endpoint>; }; }; @@ -245,10 +241,12 @@ sai2a_port: port { sai2a_endpoint: endpoint { remote-endpoint = <&sgtl5000_tx_endpoint>; + bitclock-master; dai-format = "i2s"; - mclk-fs = <512>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <16>; + frame-master; + mclk-fs = <256>; }; }; }; @@ -263,10 +261,12 @@ sai2b_port: port { sai2b_endpoint: endpoint { remote-endpoint = <&sgtl5000_rx_endpoint>; + bitclock-master; dai-format = "i2s"; - mclk-fs = <512>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <16>; + frame-master; + mclk-fs = <256>; }; }; }; diff --git a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi index 2d0216840ff5..a0fb431aec84 100644 --- a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi @@ -221,10 +221,14 @@ reg = <0x50>; vcc-supply = <&ldo4_reg>; - #address-cells = <1>; - #size-cells = <1>; - baseboard_data: baseboard_data@0 { - reg = <0 0x100>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + baseboard_data: baseboard_data@0 { + reg = <0 0x100>; + }; }; }; }; @@ -239,40 +243,60 @@ cape_eeprom0: cape_eeprom0@54 { compatible = "atmel,24c256"; reg = <0x54>; - #address-cells = <1>; - #size-cells = <1>; - cape0_data: cape_data@0 { - reg = <0 0x100>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + cape0_data: cape_data@0 { + reg = <0 0x100>; + }; }; }; cape_eeprom1: cape_eeprom1@55 { compatible = "atmel,24c256"; reg = <0x55>; - #address-cells = <1>; - #size-cells = <1>; - cape1_data: cape_data@0 { - reg = <0 0x100>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + cape1_data: cape_data@0 { + reg = <0 0x100>; + }; }; }; cape_eeprom2: cape_eeprom2@56 { compatible = "atmel,24c256"; reg = <0x56>; - #address-cells = <1>; - #size-cells = <1>; - cape2_data: cape_data@0 { - reg = <0 0x100>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + cape2_data: cape_data@0 { + reg = <0 0x100>; + }; }; }; cape_eeprom3: cape_eeprom3@57 { compatible = "atmel,24c256"; reg = <0x57>; - #address-cells = <1>; - #size-cells = <1>; - cape3_data: cape_data@0 { - reg = <0 0x100>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + cape3_data: cape_data@0 { + reg = <0 0x100>; + }; }; }; }; @@ -385,7 +409,7 @@ /* Support GPIO reset on revision C3 boards */ reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; reset-assert-us = <300>; - reset-deassert-us = <6500>; + reset-deassert-us = <13000>; }; }; diff --git a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts index 801399702547..8878da773d67 100644 --- a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts @@ -317,10 +317,14 @@ compatible = "atmel,24c256"; reg = <0x50>; - #address-cells = <1>; - #size-cells = <1>; - baseboard_data: baseboard_data@0 { - reg = <0 0x100>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + baseboard_data: baseboard_data@0 { + reg = <0 0x100>; + }; }; }; }; diff --git a/arch/arm/boot/dts/ti/omap/am335x-nano.dts b/arch/arm/boot/dts/ti/omap/am335x-nano.dts index 26b5510cb3d1..56929059f5af 100644 --- a/arch/arm/boot/dts/ti/omap/am335x-nano.dts +++ b/arch/arm/boot/dts/ti/omap/am335x-nano.dts @@ -231,7 +231,7 @@ }; temperature-sensor@48 { - compatible = "lm75"; + compatible = "national,lm75"; reg = <0x48>; }; diff --git a/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi b/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi index 625db3bcd365..287d209a0ea9 100644 --- a/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-regor.dtsi @@ -5,6 +5,9 @@ * */ +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/am33xx.h> + / { model = "Phytec AM335x phyBOARD-REGOR"; compatible = "phytec,am335x-regor", "phytec,am335x-phycore-som", "ti,am33xx"; @@ -188,7 +191,7 @@ pinctrl-single,pins = < AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0) AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0) - AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLUP, MUX_MODE0) + AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) >; }; }; @@ -198,4 +201,9 @@ pinctrl-0 = <&uart1_rs485_pins>; status = "okay"; linux,rs485-enabled-at-boot-time; + /* + * un-intuitively, yet with the default (active-high), + * am335x RTS is high on idle and gets low on active ! + */ + rs485-rts-active-low; }; diff --git a/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi b/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi index cb27ff464dbe..d0c290d7d062 100644 --- a/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi +++ b/arch/arm/boot/dts/ti/omap/am335x-wega.dtsi @@ -14,7 +14,7 @@ simple-audio-card,format = "i2s"; simple-audio-card,bitclock-master = <&sound_iface_main>; simple-audio-card,frame-master = <&sound_iface_main>; - simple-audio-card,mclk-fs = <32>; + simple-audio-card,mclk-fs = <512>; simple-audio-card,widgets = "Line", "Line In", "Line", "Line Out", @@ -27,13 +27,12 @@ "LINE1L", "Line In", "LINE1R", "Line In"; - simple-audio-card,cpu { + sound_iface_main: simple-audio-card,cpu { sound-dai = <&mcasp0>; }; - sound_iface_main: simple-audio-card,codec { + simple-audio-card,codec { sound-dai = <&tlv320aic3007>; - clocks = <&mcasp0_fck>; }; }; diff --git a/arch/arm/boot/dts/ti/omap/omap3-n900.dts b/arch/arm/boot/dts/ti/omap/omap3-n900.dts index 07c5b963af78..4bde3342bb95 100644 --- a/arch/arm/boot/dts/ti/omap/omap3-n900.dts +++ b/arch/arm/boot/dts/ti/omap/omap3-n900.dts @@ -781,7 +781,7 @@ mount-matrix = "-1", "0", "0", "0", "1", "0", - "0", "0", "1"; + "0", "0", "-1"; }; cam1: camera@3e { diff --git a/arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi b/arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi index dfb1fbafe3aa..33b02e05ce82 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zturn-common.dtsi @@ -97,9 +97,9 @@ status = "okay"; clock-frequency = <400000>; - stlm75@49 { + temperature-sensor@49 { status = "okay"; - compatible = "lm75"; + compatible = "st,stlm75"; reg = <0x49>; }; diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index 6eabe2313c9a..2022a7fca0f9 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig @@ -16,6 +16,7 @@ CONFIG_ARCH_AT91=y CONFIG_SOC_AT91RM9200=y CONFIG_SOC_AT91SAM9=y CONFIG_SOC_SAM9X60=y +CONFIG_SOC_SAM9X7=y # CONFIG_ATMEL_CLOCKSOURCE_PIT is not set CONFIG_AEABI=y CONFIG_UACCESS_WITH_MEMCPY=y diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig index 0376a65e8bc1..e19c1039fb93 100644 --- a/arch/arm/configs/hisi_defconfig +++ b/arch/arm/configs/hisi_defconfig @@ -43,6 +43,7 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_PL022=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 62734530a3d6..9a5f5c439b87 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -413,6 +413,7 @@ CONFIG_I2C_AT91=m CONFIG_I2C_BCM2835=y CONFIG_I2C_CADENCE=y CONFIG_I2C_DAVINCI=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_DIGICOLOR=m CONFIG_I2C_EMEV2=m diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index f2ca5c9131b5..e1cb170c2bf0 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -277,6 +277,7 @@ CONFIG_HW_RANDOM=y CONFIG_I2C_CHARDEV=m CONFIG_I2C_MUX_PCA954x=m CONFIG_I2C_MUX_PINCTRL=m +CONFIG_I2C_DESIGNWARE_CORE=m CONFIG_I2C_DESIGNWARE_PLATFORM=m CONFIG_I2C_GPIO=y CONFIG_I2C_PXA_SLAVE=y diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 56925adfe842..0e380e450a62 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -24,6 +24,7 @@ CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig index e82c3866b810..294906c8f16e 100644 --- a/arch/arm/configs/socfpga_defconfig +++ b/arch/arm/configs/socfpga_defconfig @@ -83,6 +83,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=2 CONFIG_SERIAL_8250_DW=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_CADENCE_QUADSPI=y diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig index c8128a6180e7..a8f992fdb30d 100644 --- a/arch/arm/configs/spear13xx_defconfig +++ b/arch/arm/configs/spear13xx_defconfig @@ -62,6 +62,7 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_RAW_DRIVER=y CONFIG_I2C=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_PL022=y diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig index 97ea2e9a6f07..8dc5a388759c 100644 --- a/arch/arm/configs/spear3xx_defconfig +++ b/arch/arm/configs/spear3xx_defconfig @@ -42,6 +42,7 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_RAW_DRIVER=y CONFIG_I2C=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_PL022=y diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig index a7a3413ac968..4e9e1a6ff381 100644 --- a/arch/arm/configs/spear6xx_defconfig +++ b/arch/arm/configs/spear6xx_defconfig @@ -33,6 +33,7 @@ CONFIG_STMMAC_ETH=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_I2C=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_PL022=y diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index 847b7a003356..5ff49a5e9afc 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -166,10 +166,9 @@ config CRYPTO_AES_ARM config CRYPTO_AES_ARM_BS tristate "Ciphers: AES, modes: ECB/CBC/CTR/XTS (bit-sliced NEON)" depends on KERNEL_MODE_NEON + select CRYPTO_AES_ARM select CRYPTO_SKCIPHER select CRYPTO_LIB_AES - select CRYPTO_AES - select CRYPTO_CBC select CRYPTO_SIMD help Length-preserving ciphers: AES cipher algorithms (FIPS-197) @@ -183,8 +182,15 @@ config CRYPTO_AES_ARM_BS Bit sliced AES gives around 45% speedup on Cortex-A15 for CTR mode and for XTS mode encryption, CBC and XTS mode decryption speedup is around 25%. (CBC encryption speed is not affected by this driver.) - This implementation does not rely on any lookup tables so it is - believed to be invulnerable to cache timing attacks. + + The bit sliced AES code does not use lookup tables, so it is believed + to be invulnerable to cache timing attacks. However, since the bit + sliced AES code cannot process single blocks efficiently, in certain + cases table-based code with some countermeasures against cache timing + attacks will still be used as a fallback method; specifically CBC + encryption (not CBC decryption), the encryption of XTS tweaks, XTS + ciphertext stealing when the message isn't a multiple of 16 bytes, and + CTR when invoked in a context in which NEON instructions are unusable. config CRYPTO_AES_ARM_CE tristate "Ciphers: AES, modes: ECB/CBC/CTS/CTR/XTS (ARMv8 Crypto Extensions)" diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index b668c97663ec..21df5e7f51f9 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -8,7 +8,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/aes.h> #include <crypto/ctr.h> #include <crypto/internal/simd.h> @@ -711,7 +711,7 @@ static int __init aes_init(void) algname = aes_algs[i].base.cra_name + 2; drvname = aes_algs[i].base.cra_driver_name + 2; basename = aes_algs[i].base.cra_driver_name; - simd = simd_skcipher_create_compat(algname, drvname, basename); + simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto unregister_simds; diff --git a/arch/arm/crypto/aes-cipher-glue.c b/arch/arm/crypto/aes-cipher-glue.c index 6dfaef2d8f91..29efb7833960 100644 --- a/arch/arm/crypto/aes-cipher-glue.c +++ b/arch/arm/crypto/aes-cipher-glue.c @@ -9,9 +9,10 @@ #include <crypto/aes.h> #include <crypto/algapi.h> #include <linux/module.h> +#include "aes-cipher.h" -asmlinkage void __aes_arm_encrypt(u32 *rk, int rounds, const u8 *in, u8 *out); -asmlinkage void __aes_arm_decrypt(u32 *rk, int rounds, const u8 *in, u8 *out); +EXPORT_SYMBOL_GPL(__aes_arm_encrypt); +EXPORT_SYMBOL_GPL(__aes_arm_decrypt); static void aes_arm_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { diff --git a/arch/arm/crypto/aes-cipher.h b/arch/arm/crypto/aes-cipher.h new file mode 100644 index 000000000000..d5db2b87eb69 --- /dev/null +++ b/arch/arm/crypto/aes-cipher.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef ARM_CRYPTO_AES_CIPHER_H +#define ARM_CRYPTO_AES_CIPHER_H + +#include <linux/linkage.h> +#include <linux/types.h> + +asmlinkage void __aes_arm_encrypt(const u32 rk[], int rounds, + const u8 *in, u8 *out); +asmlinkage void __aes_arm_decrypt(const u32 rk[], int rounds, + const u8 *in, u8 *out); + +#endif /* ARM_CRYPTO_AES_CIPHER_H */ diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index 201eb35dde37..f6be80b5938b 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -9,24 +9,22 @@ #include <asm/simd.h> #include <crypto/aes.h> #include <crypto/ctr.h> -#include <crypto/internal/cipher.h> #include <crypto/internal/simd.h> #include <crypto/internal/skcipher.h> #include <crypto/scatterwalk.h> #include <crypto/xts.h> #include <linux/module.h> +#include "aes-cipher.h" MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_DESCRIPTION("Bit sliced AES using NEON instructions"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS_CRYPTO("ecb(aes)"); -MODULE_ALIAS_CRYPTO("cbc(aes)-all"); +MODULE_ALIAS_CRYPTO("cbc(aes)"); MODULE_ALIAS_CRYPTO("ctr(aes)"); MODULE_ALIAS_CRYPTO("xts(aes)"); -MODULE_IMPORT_NS(CRYPTO_INTERNAL); - asmlinkage void aesbs_convert_key(u8 out[], u32 const rk[], int rounds); asmlinkage void aesbs_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], @@ -52,13 +50,13 @@ struct aesbs_ctx { struct aesbs_cbc_ctx { struct aesbs_ctx key; - struct crypto_skcipher *enc_tfm; + struct crypto_aes_ctx fallback; }; struct aesbs_xts_ctx { struct aesbs_ctx key; - struct crypto_cipher *cts_tfm; - struct crypto_cipher *tweak_tfm; + struct crypto_aes_ctx fallback; + struct crypto_aes_ctx tweak_key; }; struct aesbs_ctr_ctx { @@ -129,37 +127,49 @@ static int aesbs_cbc_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_aes_ctx rk; int err; - err = aes_expandkey(&rk, in_key, key_len); + err = aes_expandkey(&ctx->fallback, in_key, key_len); if (err) return err; ctx->key.rounds = 6 + key_len / 4; kernel_neon_begin(); - aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); + aesbs_convert_key(ctx->key.rk, ctx->fallback.key_enc, ctx->key.rounds); kernel_neon_end(); - memzero_explicit(&rk, sizeof(rk)); - return crypto_skcipher_setkey(ctx->enc_tfm, in_key, key_len); + return 0; } static int cbc_encrypt(struct skcipher_request *req) { - struct skcipher_request *subreq = skcipher_request_ctx(req); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); + const struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; - skcipher_request_set_tfm(subreq, ctx->enc_tfm); - skcipher_request_set_callback(subreq, - skcipher_request_flags(req), - NULL, NULL); - skcipher_request_set_crypt(subreq, req->src, req->dst, - req->cryptlen, req->iv); + err = skcipher_walk_virt(&walk, req, false); - return crypto_skcipher_encrypt(subreq); + while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + u8 *prev = walk.iv; + + do { + crypto_xor_cpy(dst, src, prev, AES_BLOCK_SIZE); + __aes_arm_encrypt(ctx->fallback.key_enc, + ctx->key.rounds, dst, dst); + prev = dst; + src += AES_BLOCK_SIZE; + dst += AES_BLOCK_SIZE; + nbytes -= AES_BLOCK_SIZE; + } while (nbytes >= AES_BLOCK_SIZE); + memcpy(walk.iv, prev, AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, nbytes); + } + return err; } static int cbc_decrypt(struct skcipher_request *req) @@ -190,30 +200,6 @@ static int cbc_decrypt(struct skcipher_request *req) return err; } -static int cbc_init(struct crypto_skcipher *tfm) -{ - struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); - unsigned int reqsize; - - ctx->enc_tfm = crypto_alloc_skcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(ctx->enc_tfm)) - return PTR_ERR(ctx->enc_tfm); - - reqsize = sizeof(struct skcipher_request); - reqsize += crypto_skcipher_reqsize(ctx->enc_tfm); - crypto_skcipher_set_reqsize(tfm, reqsize); - - return 0; -} - -static void cbc_exit(struct crypto_skcipher *tfm) -{ - struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); - - crypto_free_skcipher(ctx->enc_tfm); -} - static int aesbs_ctr_setkey_sync(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { @@ -271,16 +257,8 @@ static int ctr_encrypt(struct skcipher_request *req) static void ctr_encrypt_one(struct crypto_skcipher *tfm, const u8 *src, u8 *dst) { struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); - unsigned long flags; - - /* - * Temporarily disable interrupts to avoid races where - * cachelines are evicted when the CPU is interrupted - * to do something else. - */ - local_irq_save(flags); - aes_encrypt(&ctx->fallback, dst, src); - local_irq_restore(flags); + + __aes_arm_encrypt(ctx->fallback.key_enc, ctx->key.rounds, src, dst); } static int ctr_encrypt_sync(struct skcipher_request *req) @@ -302,45 +280,23 @@ static int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, return err; key_len /= 2; - err = crypto_cipher_setkey(ctx->cts_tfm, in_key, key_len); + err = aes_expandkey(&ctx->fallback, in_key, key_len); if (err) return err; - err = crypto_cipher_setkey(ctx->tweak_tfm, in_key + key_len, key_len); + err = aes_expandkey(&ctx->tweak_key, in_key + key_len, key_len); if (err) return err; return aesbs_setkey(tfm, in_key, key_len); } -static int xts_init(struct crypto_skcipher *tfm) -{ - struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); - - ctx->cts_tfm = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(ctx->cts_tfm)) - return PTR_ERR(ctx->cts_tfm); - - ctx->tweak_tfm = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(ctx->tweak_tfm)) - crypto_free_cipher(ctx->cts_tfm); - - return PTR_ERR_OR_ZERO(ctx->tweak_tfm); -} - -static void xts_exit(struct crypto_skcipher *tfm) -{ - struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); - - crypto_free_cipher(ctx->tweak_tfm); - crypto_free_cipher(ctx->cts_tfm); -} - static int __xts_crypt(struct skcipher_request *req, bool encrypt, void (*fn)(u8 out[], u8 const in[], u8 const rk[], int rounds, int blocks, u8 iv[], int)) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); + const int rounds = ctx->key.rounds; int tail = req->cryptlen % AES_BLOCK_SIZE; struct skcipher_request subreq; u8 buf[2 * AES_BLOCK_SIZE]; @@ -364,7 +320,7 @@ static int __xts_crypt(struct skcipher_request *req, bool encrypt, if (err) return err; - crypto_cipher_encrypt_one(ctx->tweak_tfm, walk.iv, walk.iv); + __aes_arm_encrypt(ctx->tweak_key.key_enc, rounds, walk.iv, walk.iv); while (walk.nbytes >= AES_BLOCK_SIZE) { unsigned int blocks = walk.nbytes / AES_BLOCK_SIZE; @@ -378,7 +334,7 @@ static int __xts_crypt(struct skcipher_request *req, bool encrypt, kernel_neon_begin(); fn(walk.dst.virt.addr, walk.src.virt.addr, ctx->key.rk, - ctx->key.rounds, blocks, walk.iv, reorder_last_tweak); + rounds, blocks, walk.iv, reorder_last_tweak); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes - blocks * AES_BLOCK_SIZE); @@ -396,9 +352,9 @@ static int __xts_crypt(struct skcipher_request *req, bool encrypt, crypto_xor(buf, req->iv, AES_BLOCK_SIZE); if (encrypt) - crypto_cipher_encrypt_one(ctx->cts_tfm, buf, buf); + __aes_arm_encrypt(ctx->fallback.key_enc, rounds, buf, buf); else - crypto_cipher_decrypt_one(ctx->cts_tfm, buf, buf); + __aes_arm_decrypt(ctx->fallback.key_dec, rounds, buf, buf); crypto_xor(buf, req->iv, AES_BLOCK_SIZE); @@ -439,8 +395,7 @@ static struct skcipher_alg aes_algs[] = { { .base.cra_blocksize = AES_BLOCK_SIZE, .base.cra_ctxsize = sizeof(struct aesbs_cbc_ctx), .base.cra_module = THIS_MODULE, - .base.cra_flags = CRYPTO_ALG_INTERNAL | - CRYPTO_ALG_NEED_FALLBACK, + .base.cra_flags = CRYPTO_ALG_INTERNAL, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -449,8 +404,6 @@ static struct skcipher_alg aes_algs[] = { { .setkey = aesbs_cbc_setkey, .encrypt = cbc_encrypt, .decrypt = cbc_decrypt, - .init = cbc_init, - .exit = cbc_exit, }, { .base.cra_name = "__ctr(aes)", .base.cra_driver_name = "__ctr-aes-neonbs", @@ -500,8 +453,6 @@ static struct skcipher_alg aes_algs[] = { { .setkey = aesbs_xts_setkey, .encrypt = xts_encrypt, .decrypt = xts_decrypt, - .init = xts_init, - .exit = xts_exit, } }; static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)]; @@ -540,7 +491,7 @@ static int __init aes_init(void) algname = aes_algs[i].base.cra_name + 2; drvname = aes_algs[i].base.cra_driver_name + 2; basename = aes_algs[i].base.cra_driver_name; - simd = simd_skcipher_create_compat(algname, drvname, basename); + simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto unregister_simds; diff --git a/arch/arm/crypto/crc32-ce-glue.c b/arch/arm/crypto/crc32-ce-glue.c index 4ff18044af07..20b4dff13e3a 100644 --- a/arch/arm/crypto/crc32-ce-glue.c +++ b/arch/arm/crypto/crc32-ce-glue.c @@ -18,7 +18,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define PMULL_MIN_LEN 64L /* minimum size of buffer * for crc32_pmull_le_16 */ diff --git a/arch/arm/crypto/crct10dif-ce-core.S b/arch/arm/crypto/crct10dif-ce-core.S index 46c02c518a30..2bbf2df9c1e2 100644 --- a/arch/arm/crypto/crct10dif-ce-core.S +++ b/arch/arm/crypto/crct10dif-ce-core.S @@ -112,55 +112,120 @@ FOLD_CONST_L .req q10l FOLD_CONST_H .req q10h + /* + * Pairwise long polynomial multiplication of two 16-bit values + * + * { w0, w1 }, { y0, y1 } + * + * by two 64-bit values + * + * { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 } + * + * where each vector element is a byte, ordered from least to most + * significant. The resulting 80-bit vectors are XOR'ed together. + * + * This can be implemented using 8x8 long polynomial multiplication, by + * reorganizing the input so that each pairwise 8x8 multiplication + * produces one of the terms from the decomposition below, and + * combining the results of each rank and shifting them into place. + * + * Rank + * 0 w0*x0 ^ | y0*z0 ^ + * 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^ + * 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^ + * 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^ + * 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^ + * 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^ + * 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^ + * 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^ + * 8 w1*x7 << 64 | y1*z7 << 64 + * + * The inputs can be reorganized into + * + * { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 } + * { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 } + * + * and after performing 8x8->16 bit long polynomial multiplication of + * each of the halves of the first vector with those of the second one, + * we obtain the following four vectors of 16-bit elements: + * + * a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 } + * b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 } + * c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 } + * d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 } + * + * Results b and c can be XORed together, as the vector elements have + * matching ranks. Then, the final XOR can be pulled forward, and + * applied between the halves of each of the remaining three vectors, + * which are then shifted into place, and XORed together to produce the + * final 80-bit result. + */ + .macro pmull16x64_p8, v16, v64 + vext.8 q11, \v64, \v64, #1 + vld1.64 {q12}, [r4, :128] + vuzp.8 q11, \v64 + vtbl.8 d24, {\v16\()_L-\v16\()_H}, d24 + vtbl.8 d25, {\v16\()_L-\v16\()_H}, d25 + bl __pmull16x64_p8 + veor \v64, q12, q14 + .endm + +__pmull16x64_p8: + vmull.p8 q13, d23, d24 + vmull.p8 q14, d23, d25 + vmull.p8 q15, d22, d24 + vmull.p8 q12, d22, d25 + + veor q14, q14, q15 + veor d24, d24, d25 + veor d26, d26, d27 + veor d28, d28, d29 + vmov.i32 d25, #0 + vmov.i32 d29, #0 + vext.8 q12, q12, q12, #14 + vext.8 q14, q14, q14, #15 + veor d24, d24, d26 + bx lr +ENDPROC(__pmull16x64_p8) + + .macro pmull16x64_p64, v16, v64 + vmull.p64 q11, \v64\()l, \v16\()_L + vmull.p64 \v64, \v64\()h, \v16\()_H + veor \v64, \v64, q11 + .endm + // Fold reg1, reg2 into the next 32 data bytes, storing the result back // into reg1, reg2. - .macro fold_32_bytes, reg1, reg2 - vld1.64 {q11-q12}, [buf]! + .macro fold_32_bytes, reg1, reg2, p + vld1.64 {q8-q9}, [buf]! - vmull.p64 q8, \reg1\()h, FOLD_CONST_H - vmull.p64 \reg1, \reg1\()l, FOLD_CONST_L - vmull.p64 q9, \reg2\()h, FOLD_CONST_H - vmull.p64 \reg2, \reg2\()l, FOLD_CONST_L + pmull16x64_\p FOLD_CONST, \reg1 + pmull16x64_\p FOLD_CONST, \reg2 -CPU_LE( vrev64.8 q11, q11 ) -CPU_LE( vrev64.8 q12, q12 ) - vswp q11l, q11h - vswp q12l, q12h +CPU_LE( vrev64.8 q8, q8 ) +CPU_LE( vrev64.8 q9, q9 ) + vswp q8l, q8h + vswp q9l, q9h veor.8 \reg1, \reg1, q8 veor.8 \reg2, \reg2, q9 - veor.8 \reg1, \reg1, q11 - veor.8 \reg2, \reg2, q12 .endm // Fold src_reg into dst_reg, optionally loading the next fold constants - .macro fold_16_bytes, src_reg, dst_reg, load_next_consts - vmull.p64 q8, \src_reg\()l, FOLD_CONST_L - vmull.p64 \src_reg, \src_reg\()h, FOLD_CONST_H + .macro fold_16_bytes, src_reg, dst_reg, p, load_next_consts + pmull16x64_\p FOLD_CONST, \src_reg .ifnb \load_next_consts vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]! .endif - veor.8 \dst_reg, \dst_reg, q8 veor.8 \dst_reg, \dst_reg, \src_reg .endm - .macro __adrl, out, sym - movw \out, #:lower16:\sym - movt \out, #:upper16:\sym - .endm - -// -// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len); -// -// Assumes len >= 16. -// -ENTRY(crc_t10dif_pmull) - + .macro crct10dif, p // For sizes less than 256 bytes, we can't fold 128 bytes at a time. cmp len, #256 - blt .Lless_than_256_bytes + blt .Lless_than_256_bytes\@ - __adrl fold_consts_ptr, .Lfold_across_128_bytes_consts + mov_l fold_consts_ptr, .Lfold_across_128_bytes_consts // Load the first 128 data bytes. Byte swapping is necessary to make // the bit order match the polynomial coefficient order. @@ -199,27 +264,27 @@ CPU_LE( vrev64.8 q7, q7 ) // While >= 128 data bytes remain (not counting q0-q7), fold the 128 // bytes q0-q7 into them, storing the result back into q0-q7. -.Lfold_128_bytes_loop: - fold_32_bytes q0, q1 - fold_32_bytes q2, q3 - fold_32_bytes q4, q5 - fold_32_bytes q6, q7 +.Lfold_128_bytes_loop\@: + fold_32_bytes q0, q1, \p + fold_32_bytes q2, q3, \p + fold_32_bytes q4, q5, \p + fold_32_bytes q6, q7, \p subs len, len, #128 - bge .Lfold_128_bytes_loop + bge .Lfold_128_bytes_loop\@ // Now fold the 112 bytes in q0-q6 into the 16 bytes in q7. // Fold across 64 bytes. vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]! - fold_16_bytes q0, q4 - fold_16_bytes q1, q5 - fold_16_bytes q2, q6 - fold_16_bytes q3, q7, 1 + fold_16_bytes q0, q4, \p + fold_16_bytes q1, q5, \p + fold_16_bytes q2, q6, \p + fold_16_bytes q3, q7, \p, 1 // Fold across 32 bytes. - fold_16_bytes q4, q6 - fold_16_bytes q5, q7, 1 + fold_16_bytes q4, q6, \p + fold_16_bytes q5, q7, \p, 1 // Fold across 16 bytes. - fold_16_bytes q6, q7 + fold_16_bytes q6, q7, \p // Add 128 to get the correct number of data bytes remaining in 0...127 // (not counting q7), following the previous extra subtraction by 128. @@ -229,25 +294,23 @@ CPU_LE( vrev64.8 q7, q7 ) // While >= 16 data bytes remain (not counting q7), fold the 16 bytes q7 // into them, storing the result back into q7. - blt .Lfold_16_bytes_loop_done -.Lfold_16_bytes_loop: - vmull.p64 q8, q7l, FOLD_CONST_L - vmull.p64 q7, q7h, FOLD_CONST_H - veor.8 q7, q7, q8 + blt .Lfold_16_bytes_loop_done\@ +.Lfold_16_bytes_loop\@: + pmull16x64_\p FOLD_CONST, q7 vld1.64 {q0}, [buf]! CPU_LE( vrev64.8 q0, q0 ) vswp q0l, q0h veor.8 q7, q7, q0 subs len, len, #16 - bge .Lfold_16_bytes_loop + bge .Lfold_16_bytes_loop\@ -.Lfold_16_bytes_loop_done: +.Lfold_16_bytes_loop_done\@: // Add 16 to get the correct number of data bytes remaining in 0...15 // (not counting q7), following the previous extra subtraction by 16. adds len, len, #16 - beq .Lreduce_final_16_bytes + beq .Lreduce_final_16_bytes\@ -.Lhandle_partial_segment: +.Lhandle_partial_segment\@: // Reduce the last '16 + len' bytes where 1 <= len <= 15 and the first // 16 bytes are in q7 and the rest are the remaining data in 'buf'. To // do this without needing a fold constant for each possible 'len', @@ -262,9 +325,9 @@ CPU_LE( vrev64.8 q0, q0 ) vswp q0l, q0h // q1 = high order part of second chunk: q7 left-shifted by 'len' bytes. - __adrl r3, .Lbyteshift_table + 16 - sub r3, r3, len - vld1.8 {q2}, [r3] + mov_l r1, .Lbyteshift_table + 16 + sub r1, r1, len + vld1.8 {q2}, [r1] vtbl.8 q1l, {q7l-q7h}, q2l vtbl.8 q1h, {q7l-q7h}, q2h @@ -282,12 +345,46 @@ CPU_LE( vrev64.8 q0, q0 ) vbsl.8 q2, q1, q0 // Fold the first chunk into the second chunk, storing the result in q7. - vmull.p64 q0, q3l, FOLD_CONST_L - vmull.p64 q7, q3h, FOLD_CONST_H - veor.8 q7, q7, q0 - veor.8 q7, q7, q2 + pmull16x64_\p FOLD_CONST, q3 + veor.8 q7, q3, q2 + b .Lreduce_final_16_bytes\@ + +.Lless_than_256_bytes\@: + // Checksumming a buffer of length 16...255 bytes + + mov_l fold_consts_ptr, .Lfold_across_16_bytes_consts + + // Load the first 16 data bytes. + vld1.64 {q7}, [buf]! +CPU_LE( vrev64.8 q7, q7 ) + vswp q7l, q7h + + // XOR the first 16 data *bits* with the initial CRC value. + vmov.i8 q0h, #0 + vmov.u16 q0h[3], init_crc + veor.8 q7h, q7h, q0h + + // Load the fold-across-16-bytes constants. + vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]! + + cmp len, #16 + beq .Lreduce_final_16_bytes\@ // len == 16 + subs len, len, #32 + addlt len, len, #16 + blt .Lhandle_partial_segment\@ // 17 <= len <= 31 + b .Lfold_16_bytes_loop\@ // 32 <= len <= 255 + +.Lreduce_final_16_bytes\@: + .endm + +// +// u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len); +// +// Assumes len >= 16. +// +ENTRY(crc_t10dif_pmull64) + crct10dif p64 -.Lreduce_final_16_bytes: // Reduce the 128-bit value M(x), stored in q7, to the final 16-bit CRC. // Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'. @@ -320,32 +417,19 @@ CPU_LE( vrev64.8 q0, q0 ) vmov.u16 r0, q0l[0] bx lr +ENDPROC(crc_t10dif_pmull64) -.Lless_than_256_bytes: - // Checksumming a buffer of length 16...255 bytes +ENTRY(crc_t10dif_pmull8) + push {r4, lr} + mov_l r4, .L16x64perm - __adrl fold_consts_ptr, .Lfold_across_16_bytes_consts + crct10dif p8 - // Load the first 16 data bytes. - vld1.64 {q7}, [buf]! CPU_LE( vrev64.8 q7, q7 ) vswp q7l, q7h - - // XOR the first 16 data *bits* with the initial CRC value. - vmov.i8 q0h, #0 - vmov.u16 q0h[3], init_crc - veor.8 q7h, q7h, q0h - - // Load the fold-across-16-bytes constants. - vld1.64 {FOLD_CONSTS}, [fold_consts_ptr, :128]! - - cmp len, #16 - beq .Lreduce_final_16_bytes // len == 16 - subs len, len, #32 - addlt len, len, #16 - blt .Lhandle_partial_segment // 17 <= len <= 31 - b .Lfold_16_bytes_loop // 32 <= len <= 255 -ENDPROC(crc_t10dif_pmull) + vst1.64 {q7}, [r3, :128] + pop {r4, pc} +ENDPROC(crc_t10dif_pmull8) .section ".rodata", "a" .align 4 @@ -379,3 +463,6 @@ ENDPROC(crc_t10dif_pmull) .byte 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f .byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 .byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe , 0x0 + +.L16x64perm: + .quad 0x808080800000000, 0x909090901010101 diff --git a/arch/arm/crypto/crct10dif-ce-glue.c b/arch/arm/crypto/crct10dif-ce-glue.c index 79f3b204d8c0..a8b74523729e 100644 --- a/arch/arm/crypto/crct10dif-ce-glue.c +++ b/arch/arm/crypto/crct10dif-ce-glue.c @@ -19,7 +19,9 @@ #define CRC_T10DIF_PMULL_CHUNK_SIZE 16U -asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len); +asmlinkage u16 crc_t10dif_pmull64(u16 init_crc, const u8 *buf, size_t len); +asmlinkage void crc_t10dif_pmull8(u16 init_crc, const u8 *buf, size_t len, + u8 out[16]); static int crct10dif_init(struct shash_desc *desc) { @@ -29,14 +31,14 @@ static int crct10dif_init(struct shash_desc *desc) return 0; } -static int crct10dif_update(struct shash_desc *desc, const u8 *data, - unsigned int length) +static int crct10dif_update_ce(struct shash_desc *desc, const u8 *data, + unsigned int length) { u16 *crc = shash_desc_ctx(desc); if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) { kernel_neon_begin(); - *crc = crc_t10dif_pmull(*crc, data, length); + *crc = crc_t10dif_pmull64(*crc, data, length); kernel_neon_end(); } else { *crc = crc_t10dif_generic(*crc, data, length); @@ -45,6 +47,27 @@ static int crct10dif_update(struct shash_desc *desc, const u8 *data, return 0; } +static int crct10dif_update_neon(struct shash_desc *desc, const u8 *data, + unsigned int length) +{ + u16 *crcp = shash_desc_ctx(desc); + u8 buf[16] __aligned(16); + u16 crc = *crcp; + + if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) { + kernel_neon_begin(); + crc_t10dif_pmull8(crc, data, length, buf); + kernel_neon_end(); + + crc = 0; + data = buf; + length = sizeof(buf); + } + + *crcp = crc_t10dif_generic(crc, data, length); + return 0; +} + static int crct10dif_final(struct shash_desc *desc, u8 *out) { u16 *crc = shash_desc_ctx(desc); @@ -53,10 +76,22 @@ static int crct10dif_final(struct shash_desc *desc, u8 *out) return 0; } -static struct shash_alg crc_t10dif_alg = { +static struct shash_alg algs[] = {{ + .digestsize = CRC_T10DIF_DIGEST_SIZE, + .init = crct10dif_init, + .update = crct10dif_update_neon, + .final = crct10dif_final, + .descsize = CRC_T10DIF_DIGEST_SIZE, + + .base.cra_name = "crct10dif", + .base.cra_driver_name = "crct10dif-arm-neon", + .base.cra_priority = 150, + .base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +}, { .digestsize = CRC_T10DIF_DIGEST_SIZE, .init = crct10dif_init, - .update = crct10dif_update, + .update = crct10dif_update_ce, .final = crct10dif_final, .descsize = CRC_T10DIF_DIGEST_SIZE, @@ -65,19 +100,19 @@ static struct shash_alg crc_t10dif_alg = { .base.cra_priority = 200, .base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE, .base.cra_module = THIS_MODULE, -}; +}}; static int __init crc_t10dif_mod_init(void) { - if (!(elf_hwcap2 & HWCAP2_PMULL)) + if (!(elf_hwcap & HWCAP_NEON)) return -ENODEV; - return crypto_register_shash(&crc_t10dif_alg); + return crypto_register_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL)); } static void __exit crc_t10dif_mod_exit(void) { - crypto_unregister_shash(&crc_t10dif_alg); + crypto_unregister_shashes(algs, 1 + !!(elf_hwcap2 & HWCAP2_PMULL)); } module_init(crc_t10dif_mod_init); diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c index 3ddf05b4234d..3af997082534 100644 --- a/arch/arm/crypto/ghash-ce-glue.c +++ b/arch/arm/crypto/ghash-ce-glue.c @@ -9,7 +9,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/aes.h> #include <crypto/gcm.h> #include <crypto/b128ops.h> diff --git a/arch/arm/crypto/poly1305-glue.c b/arch/arm/crypto/poly1305-glue.c index 8482e302c45a..4464ffbf8fd1 100644 --- a/arch/arm/crypto/poly1305-glue.c +++ b/arch/arm/crypto/poly1305-glue.c @@ -8,7 +8,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/algapi.h> #include <crypto/internal/hash.h> #include <crypto/internal/poly1305.h> diff --git a/arch/arm/crypto/sha2-ce-glue.c b/arch/arm/crypto/sha2-ce-glue.c index c62ce89dd3e0..aeac45bfbf9f 100644 --- a/arch/arm/crypto/sha2-ce-glue.c +++ b/arch/arm/crypto/sha2-ce-glue.c @@ -16,7 +16,7 @@ #include <asm/hwcap.h> #include <asm/simd.h> #include <asm/neon.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "sha256_glue.h" diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h index a41b503b7dcd..2ec0e5e83fc9 100644 --- a/arch/arm/include/asm/arm_pmuv3.h +++ b/arch/arm/include/asm/arm_pmuv3.h @@ -127,6 +127,12 @@ static inline u32 read_pmuver(void) return (dfr0 >> 24) & 0xf; } +static inline bool pmuv3_has_icntr(void) +{ + /* FEAT_PMUv3_ICNTR not accessible for 32-bit */ + return false; +} + static inline void write_pmcr(u32 val) { write_sysreg(val, PMCR); @@ -152,6 +158,13 @@ static inline u64 read_pmccntr(void) return read_sysreg(PMCCNTR); } +static inline void write_pmicntr(u64 val) {} + +static inline u64 read_pmicntr(void) +{ + return 0; +} + static inline void write_pmcntenset(u32 val) { write_sysreg(val, PMCNTENSET); @@ -177,6 +190,13 @@ static inline void write_pmccfiltr(u32 val) write_sysreg(val, PMCCFILTR); } +static inline void write_pmicfiltr(u64 val) {} + +static inline u64 read_pmicfiltr(void) +{ + return 0; +} + static inline void write_pmovsclr(u32 val) { write_sysreg(val, PMOVSR); @@ -192,6 +212,8 @@ static inline void write_pmuserenr(u32 val) write_sysreg(val, PMUSERENR); } +static inline void write_pmuacr(u64 val) {} + static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {} static inline void kvm_clr_pmu_events(u32 clr) {} static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr) @@ -211,6 +233,7 @@ static inline void kvm_vcpu_pmu_resync_el0(void) {} #define ARMV8_PMU_DFR_VER_V3P1 0x4 #define ARMV8_PMU_DFR_VER_V3P4 0x5 #define ARMV8_PMU_DFR_VER_V3P5 0x6 +#define ARMV8_PMU_DFR_VER_V3P9 0x9 #define ARMV8_PMU_DFR_VER_IMP_DEF 0xF static inline bool pmuv3_implemented(int pmuver) @@ -229,6 +252,11 @@ static inline bool is_pmuv3p5(int pmuver) return pmuver >= ARMV8_PMU_DFR_VER_V3P5; } +static inline bool is_pmuv3p9(int pmuver) +{ + return pmuver >= ARMV8_PMU_DFR_VER_V3P9; +} + static inline u64 read_pmceid0(void) { u64 val = read_sysreg(PMCEID0); diff --git a/arch/arm/include/asm/cpu.h b/arch/arm/include/asm/cpu.h index bd6fdb4b922d..9d8863537aa5 100644 --- a/arch/arm/include/asm/cpu.h +++ b/arch/arm/include/asm/cpu.h @@ -11,7 +11,6 @@ #include <linux/cpu.h> struct cpuinfo_arm { - struct cpu cpu; u32 cpuid; #ifdef CONFIG_SMP unsigned int loops_per_jiffy; diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h index 82ec1ccf1fee..2ce4c5683e6d 100644 --- a/arch/arm/include/asm/dma-iommu.h +++ b/arch/arm/include/asm/dma-iommu.h @@ -24,7 +24,7 @@ struct dma_iommu_mapping { }; struct dma_iommu_mapping * -arm_iommu_create_mapping(const struct bus_type *bus, dma_addr_t base, u64 size); +arm_iommu_create_mapping(struct device *dev, dma_addr_t base, u64 size); void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping); diff --git a/arch/arm/include/asm/hypervisor.h b/arch/arm/include/asm/hypervisor.h index bd61502b9715..8a648e506540 100644 --- a/arch/arm/include/asm/hypervisor.h +++ b/arch/arm/include/asm/hypervisor.h @@ -7,4 +7,6 @@ void kvm_init_hyp_services(void); bool kvm_arm_hyp_service_available(u32 func_id); +static inline void kvm_arch_init_hyp_services(void) { }; + #endif diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index 62af9f7f9e96..ef11b721230e 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -7,10 +7,7 @@ #ifndef _ASMARM_PAGE_H #define _ASMARM_PAGE_H -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +#include <vdso/page.h> #ifndef __ASSEMBLY__ diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index bdbc1e590891..c08f16f2e243 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -8,13 +8,6 @@ #ifndef __ARM_PERF_EVENT_H__ #define __ARM_PERF_EVENT_H__ -#ifdef CONFIG_PERF_EVENTS -struct pt_regs; -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); -extern unsigned long perf_misc_flags(struct pt_regs *regs); -#define perf_misc_flags(regs) perf_misc_flags(regs) -#endif - #define perf_arch_fetch_caller_regs(regs, __ip) { \ (regs)->ARM_pc = (__ip); \ frame_pointer((regs)) = (unsigned long) __builtin_frame_address(0); \ diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index dfab3e982cbf..944fc9955528 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -106,6 +106,11 @@ /* * TTBCR register bits. + * + * The ORGN0 and IRGN0 bits enables different forms of caching when + * walking the translation table. Clearing these bits (which is claimed + * to be the reset default) means "normal memory, [outer|inner] + * non-cacheable" */ #define TTBCR_EAE (1 << 31) #define TTBCR_IMP (1 << 30) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 6c9c16d767cf..f90be312418e 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -12,7 +12,7 @@ #include <linux/string.h> #include <asm/page.h> #include <asm/domain.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/unified.h> #include <asm/pgtable.h> #include <asm/proc-fns.h> diff --git a/arch/arm/include/asm/vdso/gettimeofday.h b/arch/arm/include/asm/vdso/gettimeofday.h index 2134cbd5469f..592d3d015ca7 100644 --- a/arch/arm/include/asm/vdso/gettimeofday.h +++ b/arch/arm/include/asm/vdso/gettimeofday.h @@ -15,8 +15,6 @@ #define VDSO_HAS_CLOCK_GETRES 1 -extern struct vdso_data *__get_datapage(void); - static __always_inline int gettimeofday_fallback( struct __kernel_old_timeval *_tv, struct timezone *_tz) @@ -139,7 +137,7 @@ static __always_inline u64 __arch_get_hw_counter(int clock_mode, static __always_inline const struct vdso_data *__arch_get_vdso_data(void) { - return __get_datapage(); + return _vdso_data; } #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm/include/asm/vdso/vsyscall.h b/arch/arm/include/asm/vdso/vsyscall.h index 47e41ae8ccd0..705414710dcd 100644 --- a/arch/arm/include/asm/vdso/vsyscall.h +++ b/arch/arm/include/asm/vdso/vsyscall.h @@ -4,16 +4,12 @@ #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> #include <asm/cacheflush.h> extern struct vdso_data *vdso_data; extern bool cntvct_ok; -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ static __always_inline struct vdso_data *__arm_get_k_vdso_data(void) { diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index fdb74e64206a..3b78966e750a 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -200,7 +200,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt_virt) mdesc_best = &__mach_desc_GENERIC_DT; - if (!dt_virt || !early_init_dt_verify(dt_virt)) + if (!dt_virt || !early_init_dt_verify(dt_virt, __pa(dt_virt))) return NULL; mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index f01d23a220e6..1dfae1af8e31 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -29,6 +29,12 @@ #include "entry-header.S" #include <asm/probes.h> +#ifdef CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION +#define RELOC_TEXT_NONE .reloc .text, R_ARM_NONE, . +#else +#define RELOC_TEXT_NONE +#endif + /* * Interrupt handling. */ @@ -1065,7 +1071,7 @@ vector_addrexcptn: .globl vector_fiq .section .vectors, "ax", %progbits - .reloc .text, R_ARM_NONE, . + RELOC_TEXT_NONE W(b) vector_rst W(b) vector_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_swi ) @@ -1079,7 +1085,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_swi ) #ifdef CONFIG_HARDEN_BRANCH_HISTORY .section .vectors.bhb.loop8, "ax", %progbits - .reloc .text, R_ARM_NONE, . + RELOC_TEXT_NONE W(b) vector_rst W(b) vector_bhb_loop8_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_loop8_swi ) @@ -1092,7 +1098,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_bhb_loop8_swi ) W(b) vector_bhb_loop8_fiq .section .vectors.bhb.bpiall, "ax", %progbits - .reloc .text, R_ARM_NONE, . + RELOC_TEXT_NONE W(b) vector_rst W(b) vector_bhb_bpiall_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_bpiall_swi ) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1ec35f065617..f22c50d4bd41 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -252,18 +252,23 @@ __create_page_tables: */ add r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ENTRY_ORDER) ldr r6, =(_end - 1) + + /* For XIP, kernel_sec_start/kernel_sec_end are currently in RO memory */ +#ifndef CONFIG_XIP_KERNEL adr_l r5, kernel_sec_start @ _pa(kernel_sec_start) #if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32 str r8, [r5, #4] @ Save physical start of kernel (BE) #else str r8, [r5] @ Save physical start of kernel (LE) #endif +#endif orr r3, r8, r7 @ Add the MMU flags add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ENTRY_ORDER) 1: str r3, [r0], #1 << PMD_ENTRY_ORDER add r3, r3, #1 << SECTION_SHIFT cmp r0, r6 bls 1b +#ifndef CONFIG_XIP_KERNEL eor r3, r3, r7 @ Remove the MMU flags adr_l r5, kernel_sec_end @ _pa(kernel_sec_end) #if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32 @@ -271,8 +276,7 @@ __create_page_tables: #else str r3, [r5] @ Save physical end of kernel (LE) #endif - -#ifdef CONFIG_XIP_KERNEL +#else /* * Map the kernel image separately as it is not located in RAM. */ @@ -407,7 +411,11 @@ ENTRY(secondary_startup) /* * Use the page tables supplied from __cpu_up. */ +#ifdef CONFIG_XIP_KERNEL + ldr r3, =(secondary_data + PLAT_PHYS_OFFSET - PAGE_OFFSET) +#else adr_l r3, secondary_data +#endif mov_l r12, __secondary_switched ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE: diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index dab42d066d06..e1993e28a9ec 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -111,7 +111,7 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs) * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ - if (unlikely(!irq || irq >= nr_irqs)) + if (unlikely(!irq || irq >= irq_get_nr_irqs())) desc = NULL; else desc = irq_to_desc(irq); @@ -151,7 +151,6 @@ void __init init_IRQ(void) #ifdef CONFIG_SPARSE_IRQ int __init arch_probe_nr_irqs(void) { - nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS; - return nr_irqs; + return irq_set_nr_irqs(machine_desc->nr_irqs ? : NR_IRQS); } #endif diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c index 1d230ac9d0eb..a2601b1ef318 100644 --- a/arch/arm/kernel/perf_callchain.c +++ b/arch/arm/kernel/perf_callchain.c @@ -96,20 +96,3 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re arm_get_current_stackframe(regs, &fr); walk_stackframe(&fr, callchain_trace, entry); } - -unsigned long perf_instruction_pointer(struct pt_regs *regs) -{ - return instruction_pointer(regs); -} - -unsigned long perf_misc_flags(struct pt_regs *regs) -{ - int misc = 0; - - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - - return misc; -} diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index d4392e177484..3bb0c4dcfc5c 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c @@ -45,8 +45,15 @@ extern void secondary_startup(void); static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle) { if (psci_ops.cpu_on) +#ifdef CONFIG_XIP_KERNEL + return psci_ops.cpu_on(cpu_logical_map(cpu), + ((phys_addr_t)(&secondary_startup) + - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR)); +#else return psci_ops.cpu_on(cpu_logical_map(cpu), virt_to_idmap(&secondary_startup)); +#endif return -ENODEV; } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7b33b157fca0..e6a857bf0ce6 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -1201,20 +1201,10 @@ void __init setup_arch(char **cmdline_p) mdesc->init_early(); } - -static int __init topology_init(void) +bool arch_cpu_is_hotpluggable(int num) { - int cpu; - - for_each_possible_cpu(cpu) { - struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu); - cpuinfo->cpu.hotpluggable = platform_can_hotplug_cpu(cpu); - register_cpu(&cpuinfo->cpu, cpu); - } - - return 0; + return platform_can_hotplug_cpu(num); } -subsys_initcall(topology_init); #ifdef CONFIG_HAVE_PROC_CPU static int __init proc_cpu_init(void) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 9a14f721a2b0..42a3706e16a6 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -93,7 +93,6 @@ static void twd_timer_stop(void) { struct clock_event_device *clk = raw_cpu_ptr(twd_evt); - twd_shutdown(clk); disable_percpu_irq(clk->irq); } diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index d00f4040a9f5..2944721e82a2 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -235,23 +235,23 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - struct fd f = fdget_raw(fd); + CLASS(fd_raw, f)(fd); struct flock64 flock; - long err = -EBADF; + long err; - if (!f.file) - goto out; + if (fd_empty(f)) + return -EBADF; switch (cmd) { case F_GETLK64: case F_OFD_GETLK: - err = security_file_fcntl(f.file, cmd, arg); + err = security_file_fcntl(fd_file(f), cmd, arg); if (err) break; err = get_oabi_flock(&flock, argp); if (err) break; - err = fcntl_getlk64(f.file, cmd, &flock); + err = fcntl_getlk64(fd_file(f), cmd, &flock); if (!err) err = put_oabi_flock(&flock, argp); break; @@ -259,20 +259,18 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, case F_SETLKW64: case F_OFD_SETLK: case F_OFD_SETLKW: - err = security_file_fcntl(f.file, cmd, arg); + err = security_file_fcntl(fd_file(f), cmd, arg); if (err) break; err = get_oabi_flock(&flock, argp); if (err) break; - err = fcntl_setlk64(fd, f.file, cmd, &flock); + err = fcntl_setlk64(fd, fd_file(f), cmd, &flock); break; default: err = sys_fcntl64(fd, cmd, arg); break; } - fdput(f); -out: return err; } diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 480e307501bb..6ea645939573 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -570,6 +570,7 @@ static int bad_syscall(int n, struct pt_regs *regs) static inline int __do_cache_op(unsigned long start, unsigned long end) { + unsigned int ua_flags; int ret; do { @@ -578,7 +579,9 @@ __do_cache_op(unsigned long start, unsigned long end) if (fatal_signal_pending(current)) return 0; + ua_flags = uaccess_save_and_enable(); ret = flush_icache_user_range(start, start + chunk); + uaccess_restore(ua_flags); if (ret) return ret; diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c index d499ad461b00..29dd2f3c62fe 100644 --- a/arch/arm/kernel/vdso.c +++ b/arch/arm/kernel/vdso.c @@ -14,7 +14,6 @@ #include <linux/of.h> #include <linux/printk.h> #include <linux/slab.h> -#include <linux/timekeeper_internal.h> #include <linux/vmalloc.h> #include <asm/arch_timer.h> #include <asm/barrier.h> diff --git a/arch/arm/lib/xor-neon.c b/arch/arm/lib/xor-neon.c index 522510baed49..cf57fca97908 100644 --- a/arch/arm/lib/xor-neon.c +++ b/arch/arm/lib/xor-neon.c @@ -8,6 +8,7 @@ #include <linux/raid/xor.h> #include <linux/module.h> +MODULE_DESCRIPTION("NEON accelerated XOR implementation"); MODULE_LICENSE("GPL"); #ifndef __ARM_NEON__ diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index a8c022b4c053..344f5305f69a 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -141,11 +141,27 @@ config SOC_SAM9X60 help Select this if you are using Microchip's SAM9X60 SoC +config SOC_SAM9X7 + bool "SAM9X7" + depends on ARCH_MULTI_V5 + select ATMEL_AIC5_IRQ + select ATMEL_PM if PM + select CPU_ARM926T + select HAVE_AT91_USB_CLK + select HAVE_AT91_GENERATED_CLK + select HAVE_AT91_SAM9X60_PLL + select MEMORY + select PINCTRL_AT91 + select SOC_SAM_V4_V5 + select SRAM if PM + help + Select this if you are using Microchip's SAM9X7 SoC + comment "Clocksource driver selection" config ATMEL_CLOCKSOURCE_PIT bool "Periodic Interval Timer (PIT) support" - depends on SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAMA5 + depends on SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAM9X7 || SOC_SAMA5 default SOC_AT91SAM9 || SOC_SAMA5 select ATMEL_PIT help @@ -155,7 +171,7 @@ config ATMEL_CLOCKSOURCE_PIT config ATMEL_CLOCKSOURCE_TCB bool "Timer Counter Blocks (TCB) support" - default SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAMA5 + default SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAM9X60 || SOC_SAM9X7 || SOC_SAMA5 select ATMEL_TCB_CLKSRC help Select this to get a high precision clocksource based on a @@ -166,7 +182,7 @@ config ATMEL_CLOCKSOURCE_TCB config MICROCHIP_CLOCKSOURCE_PIT64B bool "64-bit Periodic Interval Timer (PIT64B) support" - default SOC_SAM9X60 || SOC_SAMA7 + default SOC_SAM9X60 || SOC_SAM9X7 || SOC_SAMA7 select MICROCHIP_PIT64B help Select this to get a high resolution clockevent (SAM9X60) or diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 794bd12ab0a8..7d8a7bc44e65 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9.o obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o +obj-$(CONFIG_SOC_SAM9X7) += sam9x7.o obj-$(CONFIG_SOC_SAMA5) += sama5.o sam_secure.o obj-$(CONFIG_SOC_SAMA7) += sama7.o obj-$(CONFIG_SOC_SAMV7) += samv7.o diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 0c3960a8b3eb..acf0b3c82a30 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -12,6 +12,7 @@ extern void __init at91rm9200_pm_init(void); extern void __init at91sam9_pm_init(void); extern void __init sam9x60_pm_init(void); +extern void __init sam9x7_pm_init(void); extern void __init sama5_pm_init(void); extern void __init sama5d2_pm_init(void); extern void __init sama7_pm_init(void); @@ -19,6 +20,7 @@ extern void __init sama7_pm_init(void); static inline void __init at91rm9200_pm_init(void) { } static inline void __init at91sam9_pm_init(void) { } static inline void __init sam9x60_pm_init(void) { } +static inline void __init sam9x7_pm_init(void) { } static inline void __init sama5_pm_init(void) { } static inline void __init sama5d2_pm_init(void) { } static inline void __init sama7_pm_init(void) { } diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 345b91dc6627..b9b995f8a36e 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -233,6 +233,13 @@ static const struct of_device_id sama7g5_ws_ids[] = { { /* sentinel */ } }; +static const struct of_device_id sam9x7_ws_ids[] = { + { .compatible = "microchip,sam9x7-rtc", .data = &ws_info[1] }, + { .compatible = "microchip,sam9x7-rtt", .data = &ws_info[4] }, + { .compatible = "microchip,sam9x7-gem", .data = &ws_info[5] }, + { /* sentinel */ } +}; + static int at91_pm_config_ws(unsigned int pm_mode, bool set) { const struct wakeup_source_info *wsi; @@ -1361,6 +1368,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = { { .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] }, { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] }, { .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] }, + { .compatible = "microchip,sam9x7-pmc", .data = &pmc_infos[4] }, { .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] }, { /* sentinel */ }, }; @@ -1499,6 +1507,27 @@ void __init sam9x60_pm_init(void) soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws; } +void __init sam9x7_pm_init(void) +{ + static const int modes[] __initconst = { + AT91_PM_STANDBY, AT91_PM_ULP0, + }; + int ret; + + if (!IS_ENABLED(CONFIG_SOC_SAM9X7)) + return; + + at91_pm_modes_validate(modes, ARRAY_SIZE(modes)); + ret = at91_dt_ramc(false); + if (ret) + return; + + at91_pm_init(NULL); + + soc_pm.ws_ids = sam9x7_ws_ids; + soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws; +} + void __init at91sam9_pm_init(void) { int ret; diff --git a/arch/arm/mach-at91/sam9x7.c b/arch/arm/mach-at91/sam9x7.c new file mode 100644 index 000000000000..e1ff30b5b09b --- /dev/null +++ b/arch/arm/mach-at91/sam9x7.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Setup code for SAM9X7. + * + * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries + * + * Author: Varshini Rajendran <varshini.rajendran@microchip.com> + */ + +#include <linux/of.h> +#include <linux/of_platform.h> + +#include <asm/mach/arch.h> + +#include "generic.h" + +static void __init sam9x7_init(void) +{ + of_platform_default_populate(NULL, NULL, NULL); + + sam9x7_pm_init(); +} + +static const char * const sam9x7_dt_board_compat[] __initconst = { + "microchip,sam9x7", + NULL +}; + +DT_MACHINE_START(sam9x7_dt, "Microchip SAM9X7") + /* Maintainer: Microchip */ + .init_machine = sam9x7_init, + .dt_compat = sam9x7_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 7318d8789e24..24bc6e18d806 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -185,6 +185,7 @@ config ARCH_BRCMSTB select ARCH_HAS_RESET_CONTROLLER select ARM_AMBA select ARM_GIC + select ARM_GIC_V3 select ARM_ERRATA_798181 if SMP select HAVE_ARM_ARCH_TIMER select ZONE_DMA if ARM_LPAE diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 450883ea0e73..31d22a5d8e1e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o pdata-quirks.o obj-y += da8xx-dt.o # Power Management -obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_HAVE_CLK) += pm_domain.o ifeq ($(CONFIG_SUSPEND),y) obj-$(CONFIG_ARCH_DAVINCI_DA850) += pm.o sleep.o diff --git a/arch/arm/mach-davinci/common.h b/arch/arm/mach-davinci/common.h index 8aa6d4fc3f6f..81a2b06b46e9 100644 --- a/arch/arm/mach-davinci/common.h +++ b/arch/arm/mach-davinci/common.h @@ -52,7 +52,6 @@ struct davinci_soc_info { extern struct davinci_soc_info davinci_soc_info; extern void davinci_common_init(const struct davinci_soc_info *soc_info); -extern void davinci_init_ide(void); void davinci_init_late(void); #ifdef CONFIG_SUSPEND diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c deleted file mode 100644 index 78a1575c387d..000000000000 --- a/arch/arm/mach-davinci/cpuidle.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * CPU idle for DaVinci SoCs - * - * Copyright (C) 2009 Texas Instruments Incorporated. https://www.ti.com/ - * - * Derived from Marvell Kirkwood CPU idle code - * (arch/arm/mach-kirkwood/cpuidle.c) - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/cpuidle.h> -#include <linux/io.h> -#include <linux/export.h> -#include <asm/cpuidle.h> - -#include "cpuidle.h" -#include "ddr2.h" - -#define DAVINCI_CPUIDLE_MAX_STATES 2 - -static void __iomem *ddr2_reg_base; -static bool ddr2_pdown; - -static void davinci_save_ddr_power(int enter, bool pdown) -{ - u32 val; - - val = __raw_readl(ddr2_reg_base + DDR2_SDRCR_OFFSET); - - if (enter) { - if (pdown) - val |= DDR2_SRPD_BIT; - else - val &= ~DDR2_SRPD_BIT; - val |= DDR2_LPMODEN_BIT; - } else { - val &= ~(DDR2_SRPD_BIT | DDR2_LPMODEN_BIT); - } - - __raw_writel(val, ddr2_reg_base + DDR2_SDRCR_OFFSET); -} - -/* Actual code that puts the SoC in different idle states */ -static __cpuidle int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - davinci_save_ddr_power(1, ddr2_pdown); - cpu_do_idle(); - davinci_save_ddr_power(0, ddr2_pdown); - - return index; -} - -static struct cpuidle_driver davinci_idle_driver = { - .name = "cpuidle-davinci", - .owner = THIS_MODULE, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = davinci_enter_idle, - .exit_latency = 10, - .target_residency = 10000, - .name = "DDR SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = DAVINCI_CPUIDLE_MAX_STATES, -}; - -static int __init davinci_cpuidle_probe(struct platform_device *pdev) -{ - struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "cannot get platform data\n"); - return -ENOENT; - } - - ddr2_reg_base = pdata->ddr2_ctlr_base; - - ddr2_pdown = pdata->ddr2_pdown; - - return cpuidle_register(&davinci_idle_driver, NULL); -} - -static struct platform_driver davinci_cpuidle_driver = { - .driver = { - .name = "cpuidle-davinci", - }, -}; - -static int __init davinci_cpuidle_init(void) -{ - return platform_driver_probe(&davinci_cpuidle_driver, - davinci_cpuidle_probe); -} -device_initcall(davinci_cpuidle_init); - diff --git a/arch/arm/mach-davinci/cpuidle.h b/arch/arm/mach-davinci/cpuidle.h deleted file mode 100644 index 976d43073597..000000000000 --- a/arch/arm/mach-davinci/cpuidle.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * TI DaVinci cpuidle platform support - * - * 2009 (C) Texas Instruments, Inc. https://www.ti.com/ - */ -#ifndef _MACH_DAVINCI_CPUIDLE_H -#define _MACH_DAVINCI_CPUIDLE_H - -struct davinci_cpuidle_config { - u32 ddr2_pdown; - void __iomem *ddr2_ctlr_base; -}; - -#endif diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 6939166c33c2..5e73a725d5da 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -21,7 +21,6 @@ #include "common.h" #include "cputype.h" #include "da8xx.h" -#include "cpuidle.h" #include "irqs.h" #include "sram.h" diff --git a/arch/arm/mach-davinci/mux.h b/arch/arm/mach-davinci/mux.h index 38f0e427291e..05fd3902df65 100644 --- a/arch/arm/mach-davinci/mux.h +++ b/arch/arm/mach-davinci/mux.h @@ -654,14 +654,9 @@ enum davinci_da850_index { #ifdef CONFIG_DAVINCI_MUX /* setup pin muxing */ extern int davinci_cfg_reg(unsigned long reg_cfg); -extern int davinci_cfg_reg_list(const short pins[]); #else /* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */ static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; } -static inline int davinci_cfg_reg_list(const short pins[]) -{ - return 0; -} #endif diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 3aea90bbb41a..35e978514591 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -82,7 +82,7 @@ static void __init dove_clk_init(void) { struct clk *usb0, *usb1, *sata, *pex0, *pex1, *sdio0, *sdio1; struct clk *nand, *camera, *i2s0, *i2s1, *crypto, *ac97, *pdma; - struct clk *xor0, *xor1, *ge, *gephy; + struct clk *xor0, *xor1, *ge; tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, dove_tclk); @@ -102,7 +102,7 @@ static void __init dove_clk_init(void) pdma = dove_register_gate("pdma", "tclk", CLOCK_GATING_BIT_PDMA); xor0 = dove_register_gate("xor0", "tclk", CLOCK_GATING_BIT_XOR0); xor1 = dove_register_gate("xor1", "tclk", CLOCK_GATING_BIT_XOR1); - gephy = dove_register_gate("gephy", "tclk", CLOCK_GATING_BIT_GIGA_PHY); + dove_register_gate("gephy", "tclk", CLOCK_GATING_BIT_GIGA_PHY); ge = dove_register_gate("ge", "gephy", CLOCK_GATING_BIT_GBE); orion_clkdev_add(NULL, "orion_spi.0", tclk); diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index 703f3d232a60..812b71dcf60e 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -3,27 +3,27 @@ menuconfig ARCH_EP93XX bool "EP93xx-based" depends on ATAGS depends on ARCH_MULTI_V4T + # CONFIG_ARCH_MULTI_V7 is not set depends on CPU_LITTLE_ENDIAN + select ARCH_HAS_RESET_CONTROLLER select ARCH_SPARSEMEM_ENABLE select ARM_AMBA select ARM_VIC + select ARM_APPENDED_DTB # Old Redboot bootloaders deployed + select ARM_ATAG_DTB_COMPAT # we need this to update dt memory node + select COMMON_CLK_EP93XX + select EP93XX_TIMER select CLKSRC_MMIO select CPU_ARM920T select GPIOLIB + select PINCTRL + select PINCTRL_EP93XX help This enables support for the Cirrus EP93xx series of CPUs. if ARCH_EP93XX -menu "Cirrus EP93xx Implementation Options" - -config EP93XX_SOC_COMMON - bool - default y - select SOC_BUS - select LEDS_GPIO_REGISTER - -comment "EP93xx Platforms" +# menu "EP93xx Platforms" config MACH_BK3 bool "Support Liebherr BK3.1" @@ -103,6 +103,6 @@ config MACH_VISION_EP9307 Say 'Y' here if you want your kernel to support the Vision Engraving Systems EP9307 SoM. -endmenu +# endmenu endif diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile deleted file mode 100644 index 62e37403df14..000000000000 --- a/arch/arm/mach-ep93xx/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux kernel. -# -obj-y := core.o clock.o timer-ep93xx.o - -obj-$(CONFIG_EP93XX_DMA) += dma.o - -obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o -obj-$(CONFIG_MACH_TS72XX) += ts72xx.o -obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c deleted file mode 100644 index 85a496ddc619..000000000000 --- a/arch/arm/mach-ep93xx/clock.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/clock.c - * Clock control for Cirrus EP93xx chips. - * - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - */ - -#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/string.h> -#include <linux/io.h> -#include <linux/spinlock.h> -#include <linux/clkdev.h> -#include <linux/clk-provider.h> -#include <linux/soc/cirrus/ep93xx.h> - -#include "hardware.h" - -#include <asm/div64.h> - -#include "soc.h" - -static DEFINE_SPINLOCK(clk_lock); - -static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; -static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; -static char pclk_divisors[] = { 1, 2, 4, 8 }; - -static char adc_divisors[] = { 16, 4 }; -static char sclk_divisors[] = { 2, 4 }; -static char lrclk_divisors[] = { 32, 64, 128 }; - -static const char * const mux_parents[] = { - "xtali", - "pll1", - "pll2" -}; - -/* - * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS - */ -static unsigned long calc_pll_rate(unsigned long long rate, u32 config_word) -{ - int i; - - rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ - rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ - do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ - for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */ - rate >>= 1; - - return (unsigned long)rate; -} - -struct clk_psc { - struct clk_hw hw; - void __iomem *reg; - u8 bit_idx; - u32 mask; - u8 shift; - u8 width; - char *div; - u8 num_div; - spinlock_t *lock; -}; - -#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw) - -static int ep93xx_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = readl(psc->reg); - - return (val & BIT(psc->bit_idx)) ? 1 : 0; -} - -static int ep93xx_clk_enable(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val |= BIT(psc->bit_idx); - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); - - return 0; -} - -static void ep93xx_clk_disable(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val &= ~BIT(psc->bit_idx); - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); -} - -static const struct clk_ops clk_ep93xx_gate_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, -}; - -static struct clk_hw *ep93xx_clk_register_gate(const char *name, - const char *parent_name, - void __iomem *reg, - u8 bit_idx) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &clk_ep93xx_gate_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - - psc->reg = reg; - psc->bit_idx = bit_idx; - psc->hw.init = &init; - psc->lock = &clk_lock; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - - return &psc->hw; -} - -static u8 ep93xx_mux_get_parent(struct clk_hw *hw) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg); - - if (!(val & EP93XX_SYSCON_CLKDIV_ESEL)) - return 0; - - if (!(val & EP93XX_SYSCON_CLKDIV_PSEL)) - return 1; - - return 2; -} - -static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long flags = 0; - u32 val; - - if (index >= ARRAY_SIZE(mux_parents)) - return -EINVAL; - - if (psc->lock) - spin_lock_irqsave(psc->lock, flags); - - val = __raw_readl(psc->reg); - val &= ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL); - - - if (index != 0) { - val |= EP93XX_SYSCON_CLKDIV_ESEL; - val |= (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0; - } - - ep93xx_syscon_swlocked_write(val, psc->reg); - - if (psc->lock) - spin_unlock_irqrestore(psc->lock, flags); - - return 0; -} - -static bool is_best(unsigned long rate, unsigned long now, - unsigned long best) -{ - return abs(rate - now) < abs(rate - best); -} - -static int ep93xx_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - unsigned long rate = req->rate; - struct clk *best_parent = NULL; - unsigned long __parent_rate; - unsigned long best_rate = 0, actual_rate, mclk_rate; - unsigned long best_parent_rate; - int __div = 0, __pdiv = 0; - int i; - - /* - * Try the two pll's and the external clock - * Because the valid predividers are 2, 2.5 and 3, we multiply - * all the clocks by 2 to avoid floating point math. - * - * This is based on the algorithm in the ep93xx raster guide: - * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf - * - */ - for (i = 0; i < ARRAY_SIZE(mux_parents); i++) { - struct clk *parent = clk_get_sys(mux_parents[i], NULL); - - __parent_rate = clk_get_rate(parent); - mclk_rate = __parent_rate * 2; - - /* Try each predivider value */ - for (__pdiv = 4; __pdiv <= 6; __pdiv++) { - __div = mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) - continue; - - actual_rate = mclk_rate / (__pdiv * __div); - if (is_best(rate, actual_rate, best_rate)) { - best_rate = actual_rate; - best_parent_rate = __parent_rate; - best_parent = parent; - } - } - } - - if (!best_parent) - return -EINVAL; - - req->best_parent_rate = best_parent_rate; - req->best_parent_hw = __clk_get_hw(best_parent); - req->rate = best_rate; - - return 0; -} - -static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long rate = 0; - u32 val = __raw_readl(psc->reg); - int __pdiv = ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03); - int __div = val & 0x7f; - - if (__div > 0) - rate = (parent_rate * 2) / ((__pdiv + 3) * __div); - - return rate; -} - -static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - int pdiv = 0, div = 0; - unsigned long best_rate = 0, actual_rate, mclk_rate; - int __div = 0, __pdiv = 0; - u32 val; - - mclk_rate = parent_rate * 2; - - for (__pdiv = 4; __pdiv <= 6; __pdiv++) { - __div = mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) - continue; - - actual_rate = mclk_rate / (__pdiv * __div); - if (is_best(rate, actual_rate, best_rate)) { - pdiv = __pdiv - 3; - div = __div; - best_rate = actual_rate; - } - } - - if (!best_rate) - return -EINVAL; - - val = __raw_readl(psc->reg); - - /* Clear old dividers */ - val &= ~0x37f; - - /* Set the new pdiv and div bits for the new clock rate */ - val |= (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; - ep93xx_syscon_swlocked_write(val, psc->reg); - - return 0; -} - -static const struct clk_ops clk_ddiv_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, - .get_parent = ep93xx_mux_get_parent, - .set_parent = ep93xx_mux_set_parent_lock, - .determine_rate = ep93xx_mux_determine_rate, - .recalc_rate = ep93xx_ddiv_recalc_rate, - .set_rate = ep93xx_ddiv_set_rate, -}; - -static struct clk_hw *clk_hw_register_ddiv(const char *name, - void __iomem *reg, - u8 bit_idx) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &clk_ddiv_ops; - init.flags = 0; - init.parent_names = mux_parents; - init.num_parents = ARRAY_SIZE(mux_parents); - - psc->reg = reg; - psc->bit_idx = bit_idx; - psc->lock = &clk_lock; - psc->hw.init = &init; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - return &psc->hw; -} - -static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg); - u8 index = (val & psc->mask) >> psc->shift; - - if (index > psc->num_div) - return 0; - - return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]); -} - -static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - unsigned long best = 0, now, maxdiv; - int i; - - maxdiv = psc->div[psc->num_div - 1]; - - for (i = 0; i < psc->num_div; i++) { - if ((rate * psc->div[i]) == *parent_rate) - return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); - - now = DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); - - if (is_best(rate, now, best)) - best = now; - } - - if (!best) - best = DIV_ROUND_UP_ULL(*parent_rate, maxdiv); - - return best; -} - -static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_psc *psc = to_clk_psc(hw); - u32 val = __raw_readl(psc->reg) & ~psc->mask; - int i; - - for (i = 0; i < psc->num_div; i++) - if (rate == parent_rate / psc->div[i]) { - val |= i << psc->shift; - break; - } - - if (i == psc->num_div) - return -EINVAL; - - ep93xx_syscon_swlocked_write(val, psc->reg); - - return 0; -} - -static const struct clk_ops ep93xx_div_ops = { - .enable = ep93xx_clk_enable, - .disable = ep93xx_clk_disable, - .is_enabled = ep93xx_clk_is_enabled, - .recalc_rate = ep93xx_div_recalc_rate, - .round_rate = ep93xx_div_round_rate, - .set_rate = ep93xx_div_set_rate, -}; - -static struct clk_hw *clk_hw_register_div(const char *name, - const char *parent_name, - void __iomem *reg, - u8 enable_bit, - u8 shift, - u8 width, - char *clk_divisors, - u8 num_div) -{ - struct clk_init_data init; - struct clk_psc *psc; - struct clk *clk; - - psc = kzalloc(sizeof(*psc), GFP_KERNEL); - if (!psc) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &ep93xx_div_ops; - init.flags = 0; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = 1; - - psc->reg = reg; - psc->bit_idx = enable_bit; - psc->mask = GENMASK(shift + width - 1, shift); - psc->shift = shift; - psc->div = clk_divisors; - psc->num_div = num_div; - psc->lock = &clk_lock; - psc->hw.init = &init; - - clk = clk_register(NULL, &psc->hw); - if (IS_ERR(clk)) { - kfree(psc); - return ERR_CAST(clk); - } - return &psc->hw; -} - -struct ep93xx_gate { - unsigned int bit; - const char *dev_id; - const char *con_id; -}; - -static struct ep93xx_gate ep93xx_uarts[] = { - {EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL}, - {EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL}, - {EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL}, -}; - -static void __init ep93xx_uart_clock_init(void) -{ - unsigned int i; - struct clk_hw *hw; - u32 value; - unsigned int clk_uart_div; - - value = __raw_readl(EP93XX_SYSCON_PWRCNT); - if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD) - clk_uart_div = 1; - else - clk_uart_div = 2; - - hw = clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart_div); - - /* parenting uart gate clocks to uart clock */ - for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) { - hw = ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id, - "uart", - EP93XX_SYSCON_DEVCFG, - ep93xx_uarts[i].bit); - - clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id); - } -} - -static struct ep93xx_gate ep93xx_dmas[] = { - {EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"}, - {EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"}, -}; - -static void __init ep93xx_dma_clock_init(void) -{ - unsigned int i; - struct clk_hw *hw; - int ret; - - for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) { - hw = clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id, - "hclk", 0, - EP93XX_SYSCON_PWRCNT, - ep93xx_dmas[i].bit, - 0, - &clk_lock); - - ret = clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, ep93xx_dmas[i].con_id); - } -} - -static int __init ep93xx_clock_init(void) -{ - u32 value; - struct clk_hw *hw; - unsigned long clk_pll1_rate; - unsigned long clk_f_rate; - unsigned long clk_h_rate; - unsigned long clk_p_rate; - unsigned long clk_pll2_rate; - unsigned int clk_f_div; - unsigned int clk_h_div; - unsigned int clk_p_div; - unsigned int clk_usb_div; - unsigned long clk_spi_div; - - hw = clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_RATE); - clk_hw_register_clkdev(hw, NULL, "xtali"); - - /* Determine the bootloader configured pll1 rate */ - value = __raw_readl(EP93XX_SYSCON_CLKSET1); - if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1)) - clk_pll1_rate = EP93XX_EXT_CLK_RATE; - else - clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value); - - hw = clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate); - clk_hw_register_clkdev(hw, NULL, "pll1"); - - /* Initialize the pll1 derived clocks */ - clk_f_div = fclk_divisors[(value >> 25) & 0x7]; - clk_h_div = hclk_divisors[(value >> 20) & 0x7]; - clk_p_div = pclk_divisors[(value >> 18) & 0x3]; - - hw = clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div); - clk_f_rate = clk_get_rate(hw->clk); - hw = clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div); - clk_h_rate = clk_get_rate(hw->clk); - hw = clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div); - clk_p_rate = clk_get_rate(hw->clk); - - clk_hw_register_clkdev(hw, "apb_pclk", NULL); - - ep93xx_dma_clock_init(); - - /* Determine the bootloader configured pll2 rate */ - value = __raw_readl(EP93XX_SYSCON_CLKSET2); - if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2)) - clk_pll2_rate = EP93XX_EXT_CLK_RATE; - else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN) - clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value); - else - clk_pll2_rate = 0; - - hw = clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate); - clk_hw_register_clkdev(hw, NULL, "pll2"); - - /* Initialize the pll2 derived clocks */ - /* - * These four bits set the divide ratio between the PLL2 - * output and the USB clock. - * 0000 - Divide by 1 - * 0001 - Divide by 2 - * 0010 - Divide by 3 - * 0011 - Divide by 4 - * 0100 - Divide by 5 - * 0101 - Divide by 6 - * 0110 - Divide by 7 - * 0111 - Divide by 8 - * 1000 - Divide by 9 - * 1001 - Divide by 10 - * 1010 - Divide by 11 - * 1011 - Divide by 12 - * 1100 - Divide by 13 - * 1101 - Divide by 14 - * 1110 - Divide by 15 - * 1111 - Divide by 1 - * On power-on-reset these bits are reset to 0000b. - */ - clk_usb_div = (((value >> 28) & 0xf) + 1); - hw = clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_usb_div); - hw = clk_hw_register_gate(NULL, "ohci-platform", - "usb_clk", 0, - EP93XX_SYSCON_PWRCNT, - EP93XX_SYSCON_PWRCNT_USH_EN, - 0, - &clk_lock); - clk_hw_register_clkdev(hw, NULL, "ohci-platform"); - - /* - * EP93xx SSP clock rate was doubled in version E2. For more information - * see: - * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf - */ - clk_spi_div = 1; - if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2) - clk_spi_div = 2; - hw = clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, clk_spi_div); - clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0"); - - /* pwm clock */ - hw = clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1); - clk_hw_register_clkdev(hw, "pwm_clk", NULL); - - pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n", - clk_pll1_rate / 1000000, clk_pll2_rate / 1000000); - pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", - clk_f_rate / 1000000, clk_h_rate / 1000000, - clk_p_rate / 1000000); - - ep93xx_uart_clock_init(); - - /* touchscreen/adc clock */ - hw = clk_hw_register_div("ep93xx-adc", - "xtali", - EP93XX_SYSCON_KEYTCHCLKDIV, - EP93XX_SYSCON_KEYTCHCLKDIV_TSEN, - EP93XX_SYSCON_KEYTCHCLKDIV_ADIV, - 1, - adc_divisors, - ARRAY_SIZE(adc_divisors)); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-adc"); - - /* keypad clock */ - hw = clk_hw_register_div("ep93xx-keypad", - "xtali", - EP93XX_SYSCON_KEYTCHCLKDIV, - EP93XX_SYSCON_KEYTCHCLKDIV_KEN, - EP93XX_SYSCON_KEYTCHCLKDIV_KDIV, - 1, - adc_divisors, - ARRAY_SIZE(adc_divisors)); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad"); - - /* On reset PDIV and VDIV is set to zero, while PDIV zero - * means clock disable, VDIV shouldn't be zero. - * So i set both dividers to minimum. - */ - /* ENA - Enable CLK divider. */ - /* PDIV - 00 - Disable clock */ - /* VDIV - at least 2 */ - /* Check and enable video clk registers */ - value = __raw_readl(EP93XX_SYSCON_VIDCLKDIV); - value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; - ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV); - - /* check and enable i2s clk registers */ - value = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); - value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; - ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV); - - /* video clk */ - hw = clk_hw_register_ddiv("ep93xx-fb", - EP93XX_SYSCON_VIDCLKDIV, - EP93XX_SYSCON_CLKDIV_ENABLE); - - clk_hw_register_clkdev(hw, NULL, "ep93xx-fb"); - - /* i2s clk */ - hw = clk_hw_register_ddiv("mclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_CLKDIV_ENABLE); - - clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s"); - - /* i2s sclk */ -#define EP93XX_I2SCLKDIV_SDIV_SHIFT 16 -#define EP93XX_I2SCLKDIV_SDIV_WIDTH 1 - hw = clk_hw_register_div("sclk", - "mclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_I2SCLKDIV_SENA, - EP93XX_I2SCLKDIV_SDIV_SHIFT, - EP93XX_I2SCLKDIV_SDIV_WIDTH, - sclk_divisors, - ARRAY_SIZE(sclk_divisors)); - - clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s"); - - /* i2s lrclk */ -#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT 17 -#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH 3 - hw = clk_hw_register_div("lrclk", - "sclk", - EP93XX_SYSCON_I2SCLKDIV, - EP93XX_SYSCON_I2SCLKDIV_SENA, - EP93XX_I2SCLKDIV_LRDIV32_SHIFT, - EP93XX_I2SCLKDIV_LRDIV32_WIDTH, - lrclk_divisors, - ARRAY_SIZE(lrclk_divisors)); - - clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s"); - - return 0; -} -postcore_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c deleted file mode 100644 index 8b1ec60a9a46..000000000000 --- a/arch/arm/mach-ep93xx/core.c +++ /dev/null @@ -1,1018 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/core.c - * Core routines for Cirrus EP93xx chips. - * - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> - * - * Thanks go to Michael Burian and Ray Lehtiniemi for their key - * role in the ep93xx linux community. - */ - -#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> -#include <linux/sys_soc.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/leds.h> -#include <linux/uaccess.h> -#include <linux/termios.h> -#include <linux/amba/bus.h> -#include <linux/amba/serial.h> -#include <linux/mtd/physmap.h> -#include <linux/i2c.h> -#include <linux/gpio/machine.h> -#include <linux/spi/spi.h> -#include <linux/export.h> -#include <linux/irqchip/arm-vic.h> -#include <linux/reboot.h> -#include <linux/usb/ohci_pdriver.h> -#include <linux/random.h> - -#include "hardware.h" -#include <linux/platform_data/video-ep93xx.h> -#include <linux/platform_data/keypad-ep93xx.h> -#include <linux/platform_data/spi-ep93xx.h> -#include <linux/soc/cirrus/ep93xx.h> - -#include "gpio-ep93xx.h" - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include "soc.h" -#include "irqs.h" - -/************************************************************************* - * Static I/O mappings that are needed for all EP93xx platforms - *************************************************************************/ -static struct map_desc ep93xx_io_desc[] __initdata = { - { - .virtual = EP93XX_AHB_VIRT_BASE, - .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), - .length = EP93XX_AHB_SIZE, - .type = MT_DEVICE, - }, { - .virtual = EP93XX_APB_VIRT_BASE, - .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), - .length = EP93XX_APB_SIZE, - .type = MT_DEVICE, - }, -}; - -void __init ep93xx_map_io(void) -{ - iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); -} - -/************************************************************************* - * EP93xx IRQ handling - *************************************************************************/ -void __init ep93xx_init_irq(void) -{ - vic_init(EP93XX_VIC1_BASE, IRQ_EP93XX_VIC0, EP93XX_VIC1_VALID_IRQ_MASK, 0); - vic_init(EP93XX_VIC2_BASE, IRQ_EP93XX_VIC1, EP93XX_VIC2_VALID_IRQ_MASK, 0); -} - - -/************************************************************************* - * EP93xx System Controller Software Locked register handling - *************************************************************************/ - -/* - * syscon_swlock prevents anything else from writing to the syscon - * block while a software locked register is being written. - */ -static DEFINE_SPINLOCK(syscon_swlock); - -void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) -{ - unsigned long flags; - - spin_lock_irqsave(&syscon_swlock, flags); - - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(val, reg); - - spin_unlock_irqrestore(&syscon_swlock, flags); -} - -void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&syscon_swlock, flags); - - val = __raw_readl(EP93XX_SYSCON_DEVCFG); - val &= ~clear_bits; - val |= set_bits; - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(val, EP93XX_SYSCON_DEVCFG); - - spin_unlock_irqrestore(&syscon_swlock, flags); -} - -/** - * ep93xx_chip_revision() - returns the EP93xx chip revision - * - * See "platform.h" for more information. - */ -unsigned int ep93xx_chip_revision(void) -{ - unsigned int v; - - v = __raw_readl(EP93XX_SYSCON_SYSCFG); - v &= EP93XX_SYSCON_SYSCFG_REV_MASK; - v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; - return v; -} -EXPORT_SYMBOL_GPL(ep93xx_chip_revision); - -/************************************************************************* - * EP93xx GPIO - *************************************************************************/ -static struct resource ep93xx_gpio_resource[] = { - DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO0MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO1MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO2MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO3MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO4MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO5MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO6MUX), - DEFINE_RES_IRQ(IRQ_EP93XX_GPIO7MUX), -}; - -static struct platform_device ep93xx_gpio_device = { - .name = "gpio-ep93xx", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_gpio_resource), - .resource = ep93xx_gpio_resource, -}; - -/************************************************************************* - * EP93xx peripheral handling - *************************************************************************/ -#define EP93XX_UART_MCR_OFFSET (0x0100) - -static void ep93xx_uart_set_mctrl(struct amba_device *dev, - void __iomem *base, unsigned int mctrl) -{ - unsigned int mcr; - - mcr = 0; - if (mctrl & TIOCM_RTS) - mcr |= 2; - if (mctrl & TIOCM_DTR) - mcr |= 1; - - __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET); -} - -static struct amba_pl010_data ep93xx_uart_data = { - .set_mctrl = ep93xx_uart_set_mctrl, -}; - -static AMBA_APB_DEVICE(uart1, "apb:uart1", 0x00041010, EP93XX_UART1_PHYS_BASE, - { IRQ_EP93XX_UART1 }, &ep93xx_uart_data); - -static AMBA_APB_DEVICE(uart2, "apb:uart2", 0x00041010, EP93XX_UART2_PHYS_BASE, - { IRQ_EP93XX_UART2 }, NULL); - -static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE, - { IRQ_EP93XX_UART3 }, &ep93xx_uart_data); - -static struct resource ep93xx_rtc_resource[] = { - DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c), -}; - -static struct platform_device ep93xx_rtc_device = { - .name = "ep93xx-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_rtc_resource), - .resource = ep93xx_rtc_resource, -}; - -/************************************************************************* - * EP93xx OHCI USB Host - *************************************************************************/ - -static struct clk *ep93xx_ohci_host_clock; - -static int ep93xx_ohci_power_on(struct platform_device *pdev) -{ - if (!ep93xx_ohci_host_clock) { - ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(ep93xx_ohci_host_clock)) - return PTR_ERR(ep93xx_ohci_host_clock); - } - - return clk_prepare_enable(ep93xx_ohci_host_clock); -} - -static void ep93xx_ohci_power_off(struct platform_device *pdev) -{ - clk_disable(ep93xx_ohci_host_clock); -} - -static struct usb_ohci_pdata ep93xx_ohci_pdata = { - .power_on = ep93xx_ohci_power_on, - .power_off = ep93xx_ohci_power_off, - .power_suspend = ep93xx_ohci_power_off, -}; - -static struct resource ep93xx_ohci_resources[] = { - DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), - DEFINE_RES_IRQ(IRQ_EP93XX_USB), -}; - -static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_ohci_device = { - .name = "ohci-platform", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, - .dev = { - .dma_mask = &ep93xx_ohci_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &ep93xx_ohci_pdata, - }, -}; - -/************************************************************************* - * EP93xx physmap'ed flash - *************************************************************************/ -static struct physmap_flash_data ep93xx_flash_data; - -static struct resource ep93xx_flash_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device ep93xx_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &ep93xx_flash_data, - }, - .num_resources = 1, - .resource = &ep93xx_flash_resource, -}; - -/** - * ep93xx_register_flash() - Register the external flash device. - * @width: bank width in octets - * @start: resource start address - * @size: resource size - */ -void __init ep93xx_register_flash(unsigned int width, - resource_size_t start, resource_size_t size) -{ - ep93xx_flash_data.width = width; - - ep93xx_flash_resource.start = start; - ep93xx_flash_resource.end = start + size - 1; - - platform_device_register(&ep93xx_flash); -} - - -/************************************************************************* - * EP93xx ethernet peripheral handling - *************************************************************************/ -static struct ep93xx_eth_data ep93xx_eth_data; - -static struct resource ep93xx_eth_resource[] = { - DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000), - DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET), -}; - -static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_eth_device = { - .name = "ep93xx-eth", - .id = -1, - .dev = { - .platform_data = &ep93xx_eth_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_eth_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_eth_resource), - .resource = ep93xx_eth_resource, -}; - -/** - * ep93xx_register_eth - Register the built-in ethernet platform device. - * @data: platform specific ethernet configuration (__initdata) - * @copy_addr: flag indicating that the MAC address should be copied - * from the IndAd registers (as programmed by the bootloader) - */ -void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) -{ - if (copy_addr) - memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); - - ep93xx_eth_data = *data; - platform_device_register(&ep93xx_eth_device); -} - - -/************************************************************************* - * EP93xx i2c peripheral handling - *************************************************************************/ - -/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */ -static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = { - .dev_id = "i2c-gpio.0", - .table = { - /* Use local offsets on gpiochip/port "G" */ - GPIO_LOOKUP_IDX("G", 1, NULL, 0, - GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), - GPIO_LOOKUP_IDX("G", 0, NULL, 1, - GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), - { } - }, -}; - -static struct platform_device ep93xx_i2c_device = { - .name = "i2c-gpio", - .id = 0, - .dev = { - .platform_data = NULL, - }, -}; - -/** - * ep93xx_register_i2c - Register the i2c platform device. - * @devices: platform specific i2c bus device information (__initdata) - * @num: the number of devices on the i2c bus - */ -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) -{ - /* - * FIXME: this just sets the two pins as non-opendrain, as no - * platforms tries to do that anyway. Flag the applicable lines - * as open drain in the GPIO_LOOKUP above and the driver or - * gpiolib will handle open drain/open drain emulation as need - * be. Right now i2c-gpio emulates open drain which is not - * optimal. - */ - __raw_writel((0 << 1) | (0 << 0), - EP93XX_GPIO_EEDRIVE); - - i2c_register_board_info(0, devices, num); - gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table); - platform_device_register(&ep93xx_i2c_device); -} - -/************************************************************************* - * EP93xx SPI peripheral handling - *************************************************************************/ -static struct ep93xx_spi_info ep93xx_spi_master_data; - -static struct resource ep93xx_spi_resources[] = { - DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18), - DEFINE_RES_IRQ(IRQ_EP93XX_SSP), -}; - -static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_spi_device = { - .name = "ep93xx-spi", - .id = 0, - .dev = { - .platform_data = &ep93xx_spi_master_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_spi_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_spi_resources), - .resource = ep93xx_spi_resources, -}; - -/** - * ep93xx_register_spi() - registers spi platform device - * @info: ep93xx board specific spi master info (__initdata) - * @devices: SPI devices to register (__initdata) - * @num: number of SPI devices to register - * - * This function registers platform device for the EP93xx SPI controller and - * also makes sure that SPI pins are muxed so that I2S is not using those pins. - */ -void __init ep93xx_register_spi(struct ep93xx_spi_info *info, - struct spi_board_info *devices, int num) -{ - /* - * When SPI is used, we need to make sure that I2S is muxed off from - * SPI pins. - */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP); - - ep93xx_spi_master_data = *info; - spi_register_board_info(devices, num); - platform_device_register(&ep93xx_spi_device); -} - -/************************************************************************* - * EP93xx LEDs - *************************************************************************/ -static const struct gpio_led ep93xx_led_pins[] __initconst = { - { - .name = "platform:grled", - }, { - .name = "platform:rdled", - }, -}; - -static const struct gpio_led_platform_data ep93xx_led_data __initconst = { - .num_leds = ARRAY_SIZE(ep93xx_led_pins), - .leds = ep93xx_led_pins, -}; - -static struct gpiod_lookup_table ep93xx_leds_gpio_table = { - .dev_id = "leds-gpio", - .table = { - /* Use local offsets on gpiochip/port "E" */ - GPIO_LOOKUP_IDX("E", 0, NULL, 0, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("E", 1, NULL, 1, GPIO_ACTIVE_HIGH), - { } - }, -}; - -/************************************************************************* - * EP93xx pwm peripheral handling - *************************************************************************/ -static struct resource ep93xx_pwm0_resource[] = { - DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10), -}; - -static struct platform_device ep93xx_pwm0_device = { - .name = "ep93xx-pwm", - .id = 0, - .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), - .resource = ep93xx_pwm0_resource, -}; - -static struct resource ep93xx_pwm1_resource[] = { - DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10), -}; - -static struct platform_device ep93xx_pwm1_device = { - .name = "ep93xx-pwm", - .id = 1, - .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), - .resource = ep93xx_pwm1_resource, -}; - -void __init ep93xx_register_pwm(int pwm0, int pwm1) -{ - if (pwm0) - platform_device_register(&ep93xx_pwm0_device); - - /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ - if (pwm1) - platform_device_register(&ep93xx_pwm1_device); -} - -int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) -{ - int err; - - if (pdev->id == 0) { - err = 0; - } else if (pdev->id == 1) { - err = gpio_request(EP93XX_GPIO_LINE_EGPIO14, - dev_name(&pdev->dev)); - if (err) - return err; - err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0); - if (err) - goto fail; - - /* PWM 1 output on EGPIO[14] */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG); - } else { - err = -ENODEV; - } - - return err; - -fail: - gpio_free(EP93XX_GPIO_LINE_EGPIO14); - return err; -} -EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio); - -void ep93xx_pwm_release_gpio(struct platform_device *pdev) -{ - if (pdev->id == 1) { - gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14); - gpio_free(EP93XX_GPIO_LINE_EGPIO14); - - /* EGPIO[14] used for GPIO */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG); - } -} -EXPORT_SYMBOL(ep93xx_pwm_release_gpio); - - -/************************************************************************* - * EP93xx video peripheral handling - *************************************************************************/ -static struct ep93xxfb_mach_info ep93xxfb_data; - -static struct resource ep93xx_fb_resource[] = { - DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800), -}; - -static struct platform_device ep93xx_fb_device = { - .name = "ep93xx-fb", - .id = -1, - .dev = { - .platform_data = &ep93xxfb_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_fb_resource), - .resource = ep93xx_fb_resource, -}; - -/* The backlight use a single register in the framebuffer's register space */ -#define EP93XX_RASTER_REG_BRIGHTNESS 0x20 - -static struct resource ep93xx_bl_resources[] = { - DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE + - EP93XX_RASTER_REG_BRIGHTNESS, 0x04), -}; - -static struct platform_device ep93xx_bl_device = { - .name = "ep93xx-bl", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_bl_resources), - .resource = ep93xx_bl_resources, -}; - -/** - * ep93xx_register_fb - Register the framebuffer platform device. - * @data: platform specific framebuffer configuration (__initdata) - */ -void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) -{ - ep93xxfb_data = *data; - platform_device_register(&ep93xx_fb_device); - platform_device_register(&ep93xx_bl_device); -} - - -/************************************************************************* - * EP93xx matrix keypad peripheral handling - *************************************************************************/ -static struct ep93xx_keypad_platform_data ep93xx_keypad_data; - -static struct resource ep93xx_keypad_resource[] = { - DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c), - DEFINE_RES_IRQ(IRQ_EP93XX_KEY), -}; - -static struct platform_device ep93xx_keypad_device = { - .name = "ep93xx-keypad", - .id = -1, - .dev = { - .platform_data = &ep93xx_keypad_data, - }, - .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), - .resource = ep93xx_keypad_resource, -}; - -/** - * ep93xx_register_keypad - Register the keypad platform device. - * @data: platform specific keypad configuration (__initdata) - */ -void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data) -{ - ep93xx_keypad_data = *data; - platform_device_register(&ep93xx_keypad_device); -} - -int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) -{ - int err; - int i; - - for (i = 0; i < 8; i++) { - err = gpio_request(EP93XX_GPIO_LINE_C(i), dev_name(&pdev->dev)); - if (err) - goto fail_gpio_c; - err = gpio_request(EP93XX_GPIO_LINE_D(i), dev_name(&pdev->dev)); - if (err) - goto fail_gpio_d; - } - - /* Enable the keypad controller; GPIO ports C and D used for keypad */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK); - - return 0; - -fail_gpio_d: - gpio_free(EP93XX_GPIO_LINE_C(i)); -fail_gpio_c: - for (--i; i >= 0; --i) { - gpio_free(EP93XX_GPIO_LINE_C(i)); - gpio_free(EP93XX_GPIO_LINE_D(i)); - } - return err; -} -EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio); - -void ep93xx_keypad_release_gpio(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < 8; i++) { - gpio_free(EP93XX_GPIO_LINE_C(i)); - gpio_free(EP93XX_GPIO_LINE_D(i)); - } - - /* Disable the keypad controller; GPIO ports C and D used for GPIO */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK); -} -EXPORT_SYMBOL(ep93xx_keypad_release_gpio); - -/************************************************************************* - * EP93xx I2S audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_i2s_resource[] = { - DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), - DEFINE_RES_IRQ(IRQ_EP93XX_SAI), -}; - -static struct platform_device ep93xx_i2s_device = { - .name = "ep93xx-i2s", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), - .resource = ep93xx_i2s_resource, -}; - -static struct platform_device ep93xx_pcm_device = { - .name = "ep93xx-pcm-audio", - .id = -1, -}; - -void __init ep93xx_register_i2s(void) -{ - platform_device_register(&ep93xx_i2s_device); - platform_device_register(&ep93xx_pcm_device); -} - -#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ - EP93XX_SYSCON_DEVCFG_I2SONAC97) - -#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ - EP93XX_SYSCON_I2SCLKDIV_SPOL) - -int ep93xx_i2s_acquire(void) -{ - unsigned val; - - ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97, - EP93XX_SYSCON_DEVCFG_I2S_MASK); - - /* - * This is potentially racy with the clock api for i2s_mclk, sclk and - * lrclk. Since the i2s driver is the only user of those clocks we - * rely on it to prevent parallel use of this function and the - * clock api for the i2s clocks. - */ - val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); - val &= ~EP93XX_I2SCLKDIV_MASK; - val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL; - ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); - - return 0; -} -EXPORT_SYMBOL(ep93xx_i2s_acquire); - -void ep93xx_i2s_release(void) -{ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); -} -EXPORT_SYMBOL(ep93xx_i2s_release); - -/************************************************************************* - * EP93xx AC97 audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_ac97_resources[] = { - DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac), - DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR), -}; - -static struct platform_device ep93xx_ac97_device = { - .name = "ep93xx-ac97", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_ac97_resources), - .resource = ep93xx_ac97_resources, -}; - -void __init ep93xx_register_ac97(void) -{ - /* - * Make sure that the AC97 pins are not used by I2S. - */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); - - platform_device_register(&ep93xx_ac97_device); - platform_device_register(&ep93xx_pcm_device); -} - -/************************************************************************* - * EP93xx Watchdog - *************************************************************************/ -static struct resource ep93xx_wdt_resources[] = { - DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08), -}; - -static struct platform_device ep93xx_wdt_device = { - .name = "ep93xx-wdt", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_wdt_resources), - .resource = ep93xx_wdt_resources, -}; - -/************************************************************************* - * EP93xx IDE - *************************************************************************/ -static struct resource ep93xx_ide_resources[] = { - DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), - DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), -}; - -static struct platform_device ep93xx_ide_device = { - .name = "ep93xx-ide", - .id = -1, - .dev = { - .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .num_resources = ARRAY_SIZE(ep93xx_ide_resources), - .resource = ep93xx_ide_resources, -}; - -void __init ep93xx_register_ide(void) -{ - platform_device_register(&ep93xx_ide_device); -} - -int ep93xx_ide_acquire_gpio(struct platform_device *pdev) -{ - int err; - int i; - - err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev)); - if (err) - return err; - err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev)); - if (err) - goto fail_egpio15; - for (i = 2; i < 8; i++) { - err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev)); - if (err) - goto fail_gpio_e; - } - for (i = 4; i < 8; i++) { - err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev)); - if (err) - goto fail_gpio_g; - } - for (i = 0; i < 8; i++) { - err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev)); - if (err) - goto fail_gpio_h; - } - - /* GPIO ports E[7:2], G[7:4] and H used by IDE */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); - return 0; - -fail_gpio_h: - for (--i; i >= 0; --i) - gpio_free(EP93XX_GPIO_LINE_H(i)); - i = 8; -fail_gpio_g: - for (--i; i >= 4; --i) - gpio_free(EP93XX_GPIO_LINE_G(i)); - i = 8; -fail_gpio_e: - for (--i; i >= 2; --i) - gpio_free(EP93XX_GPIO_LINE_E(i)); - gpio_free(EP93XX_GPIO_LINE_EGPIO15); -fail_egpio15: - gpio_free(EP93XX_GPIO_LINE_EGPIO2); - return err; -} -EXPORT_SYMBOL(ep93xx_ide_acquire_gpio); - -void ep93xx_ide_release_gpio(struct platform_device *pdev) -{ - int i; - - for (i = 2; i < 8; i++) - gpio_free(EP93XX_GPIO_LINE_E(i)); - for (i = 4; i < 8; i++) - gpio_free(EP93XX_GPIO_LINE_G(i)); - for (i = 0; i < 8; i++) - gpio_free(EP93XX_GPIO_LINE_H(i)); - gpio_free(EP93XX_GPIO_LINE_EGPIO15); - gpio_free(EP93XX_GPIO_LINE_EGPIO2); - - - /* GPIO ports E[7:2], G[7:4] and H used by GPIO */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); -} -EXPORT_SYMBOL(ep93xx_ide_release_gpio); - -/************************************************************************* - * EP93xx ADC - *************************************************************************/ -static struct resource ep93xx_adc_resources[] = { - DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28), - DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH), -}; - -static struct platform_device ep93xx_adc_device = { - .name = "ep93xx-adc", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_adc_resources), - .resource = ep93xx_adc_resources, -}; - -void __init ep93xx_register_adc(void) -{ - /* Power up ADC, deactivate Touch Screen Controller */ - ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN, - EP93XX_SYSCON_DEVCFG_ADCPD); - - platform_device_register(&ep93xx_adc_device); -} - -/************************************************************************* - * EP93xx Security peripheral - *************************************************************************/ - -/* - * The Maverick Key is 256 bits of micro fuses blown at the factory during - * manufacturing to uniquely identify a part. - * - * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key - */ -#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -#define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400) -#define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410) -#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) -#define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450) -#define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460) -#define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500) -#define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504) -#define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520) -#define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524) -#define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700) -#define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704) -#define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708) -#define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c) - -static char ep93xx_soc_id[33]; - -static const char __init *ep93xx_get_soc_id(void) -{ - unsigned int id, id2, id3, id4, id5; - - if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1) - return "bad Hamming code"; - - id = __raw_readl(EP93XX_SECURITY_UNIQID); - id2 = __raw_readl(EP93XX_SECURITY_UNIQID2); - id3 = __raw_readl(EP93XX_SECURITY_UNIQID3); - id4 = __raw_readl(EP93XX_SECURITY_UNIQID4); - id5 = __raw_readl(EP93XX_SECURITY_UNIQID5); - - if (id != id2) - return "invalid"; - - /* Toss the unique ID into the entropy pool */ - add_device_randomness(&id2, 4); - add_device_randomness(&id3, 4); - add_device_randomness(&id4, 4); - add_device_randomness(&id5, 4); - - snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id), - "%08x%08x%08x%08x", id2, id3, id4, id5); - - return ep93xx_soc_id; -} - -static const char __init *ep93xx_get_soc_rev(void) -{ - int rev = ep93xx_chip_revision(); - - switch (rev) { - case EP93XX_CHIP_REV_D0: - return "D0"; - case EP93XX_CHIP_REV_D1: - return "D1"; - case EP93XX_CHIP_REV_E0: - return "E0"; - case EP93XX_CHIP_REV_E1: - return "E1"; - case EP93XX_CHIP_REV_E2: - return "E2"; - default: - return "unknown"; - } -} - -static const char __init *ep93xx_get_machine_name(void) -{ - return kasprintf(GFP_KERNEL,"%s", machine_desc->name); -} - -static struct device __init *ep93xx_init_soc(void) -{ - struct soc_device_attribute *soc_dev_attr; - struct soc_device *soc_dev; - - soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); - if (!soc_dev_attr) - return NULL; - - soc_dev_attr->machine = ep93xx_get_machine_name(); - soc_dev_attr->family = "Cirrus Logic EP93xx"; - soc_dev_attr->revision = ep93xx_get_soc_rev(); - soc_dev_attr->soc_id = ep93xx_get_soc_id(); - - soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR(soc_dev)) { - kfree(soc_dev_attr->machine); - kfree(soc_dev_attr); - return NULL; - } - - return soc_device_to_device(soc_dev); -} - -struct device __init *ep93xx_init_devices(void) -{ - struct device *parent; - - /* Disallow access to MaverickCrunch initially */ - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); - - /* Default all ports to GPIO */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK | - EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); - - parent = ep93xx_init_soc(); - - /* Get the GPIO working early, other devices need it */ - platform_device_register(&ep93xx_gpio_device); - - amba_device_register(&uart1_device, &iomem_resource); - amba_device_register(&uart2_device, &iomem_resource); - amba_device_register(&uart3_device, &iomem_resource); - - platform_device_register(&ep93xx_rtc_device); - platform_device_register(&ep93xx_ohci_device); - platform_device_register(&ep93xx_wdt_device); - - gpiod_add_lookup_table(&ep93xx_leds_gpio_table); - gpio_led_register_device(-1, &ep93xx_led_data); - - return parent; -} - -void ep93xx_restart(enum reboot_mode mode, const char *cmd) -{ - /* - * Set then clear the SWRST bit to initiate a software reset - */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST); - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST); - - while (1) - ; -} diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c deleted file mode 100644 index 74515acab8ef..000000000000 --- a/arch/arm/mach-ep93xx/dma.c +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/dma.c - * - * Platform support code for the EP93xx dmaengine driver. - * - * Copyright (C) 2011 Mika Westerberg - * - * This work is based on the original dma-m2p implementation with - * following copyrights: - * - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - * Copyright (C) 2006 Applied Data Systems - * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com> - */ - -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> - -#include <linux/platform_data/dma-ep93xx.h> -#include "hardware.h" - -#include "soc.h" - -#define DMA_CHANNEL(_name, _base, _irq) \ - { .name = (_name), .base = (_base), .irq = (_irq) } - -/* - * DMA M2P channels. - * - * On the EP93xx chip the following peripherals my be allocated to the 10 - * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive). - * - * I2S contains 3 Tx and 3 Rx DMA Channels - * AAC contains 3 Tx and 3 Rx DMA Channels - * UART1 contains 1 Tx and 1 Rx DMA Channels - * UART2 contains 1 Tx and 1 Rx DMA Channels - * UART3 contains 1 Tx and 1 Rx DMA Channels - * IrDA contains 1 Tx and 1 Rx DMA Channels - * - * Registers are mapped statically in ep93xx_map_io(). - */ -static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = { - DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0), - DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1), - DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2), - DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3), - DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4), - DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5), - DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6), - DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7), - DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8), - DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9), -}; - -static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = { - .channels = ep93xx_dma_m2p_channels, - .num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels), -}; - -static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_dma_m2p_device = { - .name = "ep93xx-dma-m2p", - .id = -1, - .dev = { - .platform_data = &ep93xx_dma_m2p_data, - .dma_mask = &ep93xx_dma_m2p_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* - * DMA M2M channels. - * - * There are 2 M2M channels which support memcpy/memset and in addition simple - * hardware requests from/to SSP and IDE. We do not implement an external - * hardware requests. - * - * Registers are mapped statically in ep93xx_map_io(). - */ -static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = { - DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0), - DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1), -}; - -static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = { - .channels = ep93xx_dma_m2m_channels, - .num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels), -}; - -static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32); - -static struct platform_device ep93xx_dma_m2m_device = { - .name = "ep93xx-dma-m2m", - .id = -1, - .dev = { - .platform_data = &ep93xx_dma_m2m_data, - .dma_mask = &ep93xx_dma_m2m_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static int __init ep93xx_dma_init(void) -{ - platform_device_register(&ep93xx_dma_m2p_device); - platform_device_register(&ep93xx_dma_m2m_device); - return 0; -} -arch_initcall(ep93xx_dma_init); diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c deleted file mode 100644 index dbdb822a0100..000000000000 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ /dev/null @@ -1,368 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/edb93xx.c - * Cirrus Logic EDB93xx Development Board support. - * - * EDB93XX, EDB9301, EDB9307A - * Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com> - * - * EDB9302 - * Copyright (C) 2006 George Kashperko <george@chas.com.ua> - * - * EDB9302A, EDB9315, EDB9315A - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - * - * EDB9307 - * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> - * - * EDB9312 - * Copyright (C) 2006 Infosys Technologies Limited - * Toufeeq Hussain <toufeeq_hussain@infosys.com> - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/spi/spi.h> -#include <linux/gpio/machine.h> - -#include <sound/cs4271.h> - -#include "hardware.h" -#include <linux/platform_data/video-ep93xx.h> -#include <linux/platform_data/spi-ep93xx.h> -#include "gpio-ep93xx.h" - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> - -#include "soc.h" - -static void __init edb93xx_register_flash(void) -{ - if (machine_is_edb9307() || machine_is_edb9312() || - machine_is_edb9315()) { - ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M); - } else { - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M); - } -} - -static struct ep93xx_eth_data __initdata edb93xx_eth_data = { - .phy_id = 1, -}; - - -/************************************************************************* - * EDB93xx i2c peripheral handling - *************************************************************************/ - -static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = { - { - I2C_BOARD_INFO("isl1208", 0x6f), - }, -}; - -static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = { - { - I2C_BOARD_INFO("ds1337", 0x68), - }, -}; - -static void __init edb93xx_register_i2c(void) -{ - if (machine_is_edb9302a() || machine_is_edb9307a() || - machine_is_edb9315a()) { - ep93xx_register_i2c(edb93xxa_i2c_board_info, - ARRAY_SIZE(edb93xxa_i2c_board_info)); - } else if (machine_is_edb9302() || machine_is_edb9307() - || machine_is_edb9312() || machine_is_edb9315()) { - ep93xx_register_i2c(edb93xx_i2c_board_info, - ARRAY_SIZE(edb93xx_i2c_board_info)); - } -} - - -/************************************************************************* - * EDB93xx SPI peripheral handling - *************************************************************************/ -static struct cs4271_platform_data edb93xx_cs4271_data = { - /* Intentionally left blank */ -}; - -static struct spi_board_info edb93xx_spi_board_info[] __initdata = { - { - .modalias = "cs4271", - .platform_data = &edb93xx_cs4271_data, - .max_speed_hz = 6000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_3, - }, -}; - -static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info edb93xx_spi_info __initdata = { - /* Intentionally left blank */ -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9301_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("A", 1, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9302_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("H", 2, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table edb93xx_cs4272_edb9315_gpio_table = { - .dev_id = "spi0.0", /* CS0 on SPI0 */ - .table = { - GPIO_LOOKUP("B", 6, "reset", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static void __init edb93xx_register_spi(void) -{ - if (machine_is_edb9301() || machine_is_edb9302()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9301_gpio_table); - else if (machine_is_edb9302a() || machine_is_edb9307a()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9302_gpio_table); - else if (machine_is_edb9315a()) - gpiod_add_lookup_table(&edb93xx_cs4272_edb9315_gpio_table); - - gpiod_add_lookup_table(&edb93xx_spi_cs_gpio_table); - ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info, - ARRAY_SIZE(edb93xx_spi_board_info)); -} - - -/************************************************************************* - * EDB93xx I2S - *************************************************************************/ -static struct platform_device edb93xx_audio_device = { - .name = "edb93xx-audio", - .id = -1, -}; - -static int __init edb93xx_has_audio(void) -{ - return (machine_is_edb9301() || machine_is_edb9302() || - machine_is_edb9302a() || machine_is_edb9307a() || - machine_is_edb9315a()); -} - -static void __init edb93xx_register_i2s(void) -{ - if (edb93xx_has_audio()) { - ep93xx_register_i2s(); - platform_device_register(&edb93xx_audio_device); - } -} - - -/************************************************************************* - * EDB93xx pwm - *************************************************************************/ -static void __init edb93xx_register_pwm(void) -{ - if (machine_is_edb9301() || - machine_is_edb9302() || machine_is_edb9302a()) { - /* EP9301 and EP9302 only have pwm.1 (EGPIO14) */ - ep93xx_register_pwm(0, 1); - } else if (machine_is_edb9307() || machine_is_edb9307a()) { - /* EP9307 only has pwm.0 (PWMOUT) */ - ep93xx_register_pwm(1, 0); - } else { - /* EP9312 and EP9315 have both */ - ep93xx_register_pwm(1, 1); - } -} - - -/************************************************************************* - * EDB93xx framebuffer - *************************************************************************/ -static struct ep93xxfb_mach_info __initdata edb93xxfb_info = { - .flags = 0, -}; - -static int __init edb93xx_has_fb(void) -{ - /* These platforms have an ep93xx with video capability */ - return machine_is_edb9307() || machine_is_edb9307a() || - machine_is_edb9312() || machine_is_edb9315() || - machine_is_edb9315a(); -} - -static void __init edb93xx_register_fb(void) -{ - if (!edb93xx_has_fb()) - return; - - if (machine_is_edb9307a() || machine_is_edb9315a()) - edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0; - else - edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3; - - ep93xx_register_fb(&edb93xxfb_info); -} - - -/************************************************************************* - * EDB93xx IDE - *************************************************************************/ -static int __init edb93xx_has_ide(void) -{ - /* - * Although EDB9312 and EDB9315 do have IDE capability, they have - * INTRQ line wired as pull-up, which makes using IDE interface - * problematic. - */ - return machine_is_edb9312() || machine_is_edb9315() || - machine_is_edb9315a(); -} - -static void __init edb93xx_register_ide(void) -{ - if (!edb93xx_has_ide()) - return; - - ep93xx_register_ide(); -} - - -static void __init edb93xx_init_machine(void) -{ - ep93xx_init_devices(); - edb93xx_register_flash(); - ep93xx_register_eth(&edb93xx_eth_data, 1); - edb93xx_register_i2c(); - edb93xx_register_spi(); - edb93xx_register_i2s(); - edb93xx_register_pwm(); - edb93xx_register_fb(); - edb93xx_register_ide(); - ep93xx_register_adc(); -} - - -#ifdef CONFIG_MACH_EDB9301 -MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") - /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9302 -MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") - /* Maintainer: George Kashperko <george@chas.com.ua> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9302A -MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") - /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9307 -MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") - /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9307A -MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") - /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9312 -MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") - /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9315 -MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") - /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif - -#ifdef CONFIG_MACH_EDB9315A -MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") - /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ep93xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = edb93xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END -#endif diff --git a/arch/arm/mach-ep93xx/ep93xx-regs.h b/arch/arm/mach-ep93xx/ep93xx-regs.h deleted file mode 100644 index 8fa3646de0a4..000000000000 --- a/arch/arm/mach-ep93xx/ep93xx-regs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_EP93XX_REGS_H -#define __ASM_ARCH_EP93XX_REGS_H - -/* - * EP93xx linux memory map: - * - * virt phys size - * fe800000 5M per-platform mappings - * fed00000 80800000 2M APB - * fef00000 80000000 1M AHB - */ - -#define EP93XX_AHB_PHYS_BASE 0x80000000 -#define EP93XX_AHB_VIRT_BASE 0xfef00000 -#define EP93XX_AHB_SIZE 0x00100000 - -#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x)) -#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x)) - -#define EP93XX_APB_PHYS_BASE 0x80800000 -#define EP93XX_APB_VIRT_BASE 0xfed00000 -#define EP93XX_APB_SIZE 0x00200000 - -#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x)) -#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x)) - -/* APB UARTs */ -#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000) -#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000) - -#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000) -#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000) - -#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000) -#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000) - -#endif diff --git a/arch/arm/mach-ep93xx/gpio-ep93xx.h b/arch/arm/mach-ep93xx/gpio-ep93xx.h deleted file mode 100644 index 7b46eb7e5507..000000000000 --- a/arch/arm/mach-ep93xx/gpio-ep93xx.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Include file for the EP93XX GPIO controller machine specifics */ - -#ifndef __GPIO_EP93XX_H -#define __GPIO_EP93XX_H - -#include "ep93xx-regs.h" - -#define EP93XX_GPIO_PHYS_BASE EP93XX_APB_PHYS(0x00040000) -#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) -#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) -#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) -#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0) -#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) -#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8) - -/* GPIO port A. */ -#define EP93XX_GPIO_LINE_A(x) ((x) + 0) -#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) -#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) -#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) -#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) -#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) -#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) -#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) -#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) - -/* GPIO port B. */ -#define EP93XX_GPIO_LINE_B(x) ((x) + 8) -#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) -#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) -#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) -#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) -#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) -#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) -#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) -#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) - -/* GPIO port C. */ -#define EP93XX_GPIO_LINE_C(x) ((x) + 40) -#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) -#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) -#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) -#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) -#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) -#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) -#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) -#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) - -/* GPIO port D. */ -#define EP93XX_GPIO_LINE_D(x) ((x) + 24) -#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) -#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) -#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) -#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) -#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) -#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) -#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) -#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) - -/* GPIO port E. */ -#define EP93XX_GPIO_LINE_E(x) ((x) + 32) -#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) -#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) -#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) -#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) -#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) -#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) -#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) -#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) - -/* GPIO port F. */ -#define EP93XX_GPIO_LINE_F(x) ((x) + 16) -#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) -#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) -#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) -#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) -#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) -#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) -#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) -#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) - -/* GPIO port G. */ -#define EP93XX_GPIO_LINE_G(x) ((x) + 48) -#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) -#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) -#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) -#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) -#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) -#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) -#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) -#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) - -/* GPIO port H. */ -#define EP93XX_GPIO_LINE_H(x) ((x) + 56) -#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) -#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) -#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) -#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) -#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) -#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) -#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) -#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) - -/* maximum value for gpio line identifiers */ -#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) - -/* maximum value for irq capable line identifiers */ -#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) - -#endif /* __GPIO_EP93XX_H */ diff --git a/arch/arm/mach-ep93xx/hardware.h b/arch/arm/mach-ep93xx/hardware.h deleted file mode 100644 index e7d850e04782..000000000000 --- a/arch/arm/mach-ep93xx/hardware.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/hardware.h - */ - -#ifndef __ASM_ARCH_HARDWARE_H -#define __ASM_ARCH_HARDWARE_H - -#include "platform.h" - -/* - * The EP93xx has two external crystal oscillators. To generate the - * required high-frequency clocks, the processor uses two phase-locked- - * loops (PLLs) to multiply the incoming external clock signal to much - * higher frequencies that are then divided down by programmable dividers - * to produce the needed clocks. The PLLs operate independently of one - * another. - */ -#define EP93XX_EXT_CLK_RATE 14745600 -#define EP93XX_EXT_RTC_RATE 32768 - -#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4) -#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16) - -#endif diff --git a/arch/arm/mach-ep93xx/irqs.h b/arch/arm/mach-ep93xx/irqs.h deleted file mode 100644 index 353201b90c66..000000000000 --- a/arch/arm/mach-ep93xx/irqs.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_IRQS_H -#define __ASM_ARCH_IRQS_H - -#define IRQ_EP93XX_VIC0 1 - -#define IRQ_EP93XX_COMMRX (IRQ_EP93XX_VIC0 + 2) -#define IRQ_EP93XX_COMMTX (IRQ_EP93XX_VIC0 + 3) -#define IRQ_EP93XX_TIMER1 (IRQ_EP93XX_VIC0 + 4) -#define IRQ_EP93XX_TIMER2 (IRQ_EP93XX_VIC0 + 5) -#define IRQ_EP93XX_AACINTR (IRQ_EP93XX_VIC0 + 6) -#define IRQ_EP93XX_DMAM2P0 (IRQ_EP93XX_VIC0 + 7) -#define IRQ_EP93XX_DMAM2P1 (IRQ_EP93XX_VIC0 + 8) -#define IRQ_EP93XX_DMAM2P2 (IRQ_EP93XX_VIC0 + 9) -#define IRQ_EP93XX_DMAM2P3 (IRQ_EP93XX_VIC0 + 10) -#define IRQ_EP93XX_DMAM2P4 (IRQ_EP93XX_VIC0 + 11) -#define IRQ_EP93XX_DMAM2P5 (IRQ_EP93XX_VIC0 + 12) -#define IRQ_EP93XX_DMAM2P6 (IRQ_EP93XX_VIC0 + 13) -#define IRQ_EP93XX_DMAM2P7 (IRQ_EP93XX_VIC0 + 14) -#define IRQ_EP93XX_DMAM2P8 (IRQ_EP93XX_VIC0 + 15) -#define IRQ_EP93XX_DMAM2P9 (IRQ_EP93XX_VIC0 + 16) -#define IRQ_EP93XX_DMAM2M0 (IRQ_EP93XX_VIC0 + 17) -#define IRQ_EP93XX_DMAM2M1 (IRQ_EP93XX_VIC0 + 18) -#define IRQ_EP93XX_GPIO0MUX (IRQ_EP93XX_VIC0 + 19) -#define IRQ_EP93XX_GPIO1MUX (IRQ_EP93XX_VIC0 + 20) -#define IRQ_EP93XX_GPIO2MUX (IRQ_EP93XX_VIC0 + 21) -#define IRQ_EP93XX_GPIO3MUX (IRQ_EP93XX_VIC0 + 22) -#define IRQ_EP93XX_UART1RX (IRQ_EP93XX_VIC0 + 23) -#define IRQ_EP93XX_UART1TX (IRQ_EP93XX_VIC0 + 24) -#define IRQ_EP93XX_UART2RX (IRQ_EP93XX_VIC0 + 25) -#define IRQ_EP93XX_UART2TX (IRQ_EP93XX_VIC0 + 26) -#define IRQ_EP93XX_UART3RX (IRQ_EP93XX_VIC0 + 27) -#define IRQ_EP93XX_UART3TX (IRQ_EP93XX_VIC0 + 28) -#define IRQ_EP93XX_KEY (IRQ_EP93XX_VIC0 + 29) -#define IRQ_EP93XX_TOUCH (IRQ_EP93XX_VIC0 + 30) -#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc - -#define IRQ_EP93XX_VIC1 (IRQ_EP93XX_VIC0 + 32) - -#define IRQ_EP93XX_EXT0 (IRQ_EP93XX_VIC1 + 0) -#define IRQ_EP93XX_EXT1 (IRQ_EP93XX_VIC1 + 1) -#define IRQ_EP93XX_EXT2 (IRQ_EP93XX_VIC1 + 2) -#define IRQ_EP93XX_64HZ (IRQ_EP93XX_VIC1 + 3) -#define IRQ_EP93XX_WATCHDOG (IRQ_EP93XX_VIC1 + 4) -#define IRQ_EP93XX_RTC (IRQ_EP93XX_VIC1 + 5) -#define IRQ_EP93XX_IRDA (IRQ_EP93XX_VIC1 + 6) -#define IRQ_EP93XX_ETHERNET (IRQ_EP93XX_VIC1 + 7) -#define IRQ_EP93XX_EXT3 (IRQ_EP93XX_VIC1 + 8) -#define IRQ_EP93XX_PROG (IRQ_EP93XX_VIC1 + 9) -#define IRQ_EP93XX_1HZ (IRQ_EP93XX_VIC1 + 10) -#define IRQ_EP93XX_VSYNC (IRQ_EP93XX_VIC1 + 11) -#define IRQ_EP93XX_VIDEO_FIFO (IRQ_EP93XX_VIC1 + 12) -#define IRQ_EP93XX_SSP1RX (IRQ_EP93XX_VIC1 + 13) -#define IRQ_EP93XX_SSP1TX (IRQ_EP93XX_VIC1 + 14) -#define IRQ_EP93XX_GPIO4MUX (IRQ_EP93XX_VIC1 + 15) -#define IRQ_EP93XX_GPIO5MUX (IRQ_EP93XX_VIC1 + 16) -#define IRQ_EP93XX_GPIO6MUX (IRQ_EP93XX_VIC1 + 17) -#define IRQ_EP93XX_GPIO7MUX (IRQ_EP93XX_VIC1 + 18) -#define IRQ_EP93XX_TIMER3 (IRQ_EP93XX_VIC1 + 19) -#define IRQ_EP93XX_UART1 (IRQ_EP93XX_VIC1 + 20) -#define IRQ_EP93XX_SSP (IRQ_EP93XX_VIC1 + 21) -#define IRQ_EP93XX_UART2 (IRQ_EP93XX_VIC1 + 22) -#define IRQ_EP93XX_UART3 (IRQ_EP93XX_VIC1 + 23) -#define IRQ_EP93XX_USB (IRQ_EP93XX_VIC1 + 24) -#define IRQ_EP93XX_ETHERNET_PME (IRQ_EP93XX_VIC1 + 25) -#define IRQ_EP93XX_DSP (IRQ_EP93XX_VIC1 + 26) -#define IRQ_EP93XX_GPIO_AB (IRQ_EP93XX_VIC1 + 27) -#define IRQ_EP93XX_SAI (IRQ_EP93XX_VIC1 + 28) -#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff - -#define NR_EP93XX_IRQS (IRQ_EP93XX_VIC1 + 32 + 24) - -#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) -#define EP93XX_BOARD_IRQS 32 - -#endif diff --git a/arch/arm/mach-ep93xx/platform.h b/arch/arm/mach-ep93xx/platform.h deleted file mode 100644 index 5fb1b919133f..000000000000 --- a/arch/arm/mach-ep93xx/platform.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/platform.h - */ - -#ifndef __ASSEMBLY__ - -#include <linux/platform_data/eth-ep93xx.h> -#include <linux/reboot.h> - -struct device; -struct i2c_board_info; -struct spi_board_info; -struct platform_device; -struct ep93xxfb_mach_info; -struct ep93xx_keypad_platform_data; -struct ep93xx_spi_info; - -void ep93xx_map_io(void); -void ep93xx_init_irq(void); - -void ep93xx_register_flash(unsigned int width, - resource_size_t start, resource_size_t size); - -void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); -void ep93xx_register_i2c(struct i2c_board_info *devices, int num); -void ep93xx_register_spi(struct ep93xx_spi_info *info, - struct spi_board_info *devices, int num); -void ep93xx_register_fb(struct ep93xxfb_mach_info *data); -void ep93xx_register_pwm(int pwm0, int pwm1); -void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); -void ep93xx_register_i2s(void); -void ep93xx_register_ac97(void); -void ep93xx_register_ide(void); -void ep93xx_register_adc(void); - -struct device *ep93xx_init_devices(void); -extern void ep93xx_timer_init(void); - -void ep93xx_restart(enum reboot_mode, const char *); - -#endif diff --git a/arch/arm/mach-ep93xx/soc.h b/arch/arm/mach-ep93xx/soc.h deleted file mode 100644 index 3245ebbd5069..000000000000 --- a/arch/arm/mach-ep93xx/soc.h +++ /dev/null @@ -1,212 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * arch/arm/mach-ep93xx/soc.h - * - * Copyright (C) 2012 Open Kernel Labs <www.ok-labs.com> - * Copyright (C) 2012 Ryan Mallon <rmallon@gmail.com> - */ - -#ifndef _EP93XX_SOC_H -#define _EP93XX_SOC_H - -#include "ep93xx-regs.h" -#include "irqs.h" - -/* - * EP93xx Physical Memory Map: - * - * The ASDO pin is sampled at system reset to select a synchronous or - * asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up) - * the synchronous boot mode is selected. When ASDO is "0" (i.e - * pulled-down) the asynchronous boot mode is selected. - * - * In synchronous boot mode nSDCE3 is decoded starting at physical address - * 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous - * boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3 - * decoded at 0xf0000000. - * - * There is known errata for the EP93xx dealing with External Memory - * Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design - * Guidelines" for more information. This document can be found at: - * - * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf - */ - -#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */ -#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */ -#define EP93XX_CS1_PHYS_BASE 0x10000000 -#define EP93XX_CS2_PHYS_BASE 0x20000000 -#define EP93XX_CS3_PHYS_BASE 0x30000000 -#define EP93XX_PCMCIA_PHYS_BASE 0x40000000 -#define EP93XX_CS6_PHYS_BASE 0x60000000 -#define EP93XX_CS7_PHYS_BASE 0x70000000 -#define EP93XX_SDCE0_PHYS_BASE 0xc0000000 -#define EP93XX_SDCE1_PHYS_BASE 0xd0000000 -#define EP93XX_SDCE2_PHYS_BASE 0xe0000000 -#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */ -#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */ - -/* AHB peripherals */ -#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000) - -#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000) -#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000) - -#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000) -#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) - -#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000) -#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) - -#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) - -#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000) - -#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000) - -#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000) - -#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000) -#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000) - -#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000) - -#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000) - -/* APB peripherals */ -#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) - -#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000) -#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) - -#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) - -#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000) -#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) - -#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000) -#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000) - -#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000) - -#define EP93XX_KEY_MATRIX_PHYS_BASE EP93XX_APB_PHYS(0x000f0000) -#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000) - -#define EP93XX_ADC_PHYS_BASE EP93XX_APB_PHYS(0x00100000) -#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000) -#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000) - -#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000) -#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000) - -#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000) -#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000) - -#define EP93XX_WATCHDOG_PHYS_BASE EP93XX_APB_PHYS(0x00140000) -#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) - -/* System controller */ -#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000) -#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x)) -#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00) -#define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04) -#define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31) -#define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29) -#define EP93XX_SYSCON_PWRCNT_USH_EN 28 -#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27 -#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17 -#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16 -#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08) -#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) -#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20) -#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23) -#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24) -#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19) -#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18) -#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80) -#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31) -#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30) -#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29) -#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28) -#define EP93XX_SYSCON_DEVCFG_GONK (1<<27) -#define EP93XX_SYSCON_DEVCFG_TONG (1<<26) -#define EP93XX_SYSCON_DEVCFG_MONG (1<<25) -#define EP93XX_SYSCON_DEVCFG_U3EN 24 -#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23) -#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22) -#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21) -#define EP93XX_SYSCON_DEVCFG_U2EN 20 -#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19) -#define EP93XX_SYSCON_DEVCFG_U1EN 18 -#define EP93XX_SYSCON_DEVCFG_TIN (1<<17) -#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15) -#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14) -#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13) -#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12) -#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11) -#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10) -#define EP93XX_SYSCON_DEVCFG_PONG (1<<9) -#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8) -#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7) -#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6) -#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4) -#define EP93XX_SYSCON_DEVCFG_RAS (1<<3) -#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) -#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) -#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) -#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84) -#define EP93XX_SYSCON_CLKDIV_ENABLE 15 -#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) -#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) -#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 -#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c) -#define EP93XX_SYSCON_I2SCLKDIV_SENA 31 -#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29) -#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19) -#define EP93XX_I2SCLKDIV_SDIV (1 << 16) -#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17) -#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17) -#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17) -#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17) -#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) -#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31 -#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16 -#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15 -#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0) -#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c) -#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000) -#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28) -#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8) -#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7) -#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6) -#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5) -#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4) -#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3) -#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1) -#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0) -#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) - -/* EP93xx System Controller software locked register write */ -void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg); -void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits); - -static inline void ep93xx_devcfg_set_bits(unsigned int bits) -{ - ep93xx_devcfg_set_clear(bits, 0x00); -} - -static inline void ep93xx_devcfg_clear_bits(unsigned int bits) -{ - ep93xx_devcfg_set_clear(0x00, bits); -} - -#endif /* _EP93XX_SOC_H */ diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c deleted file mode 100644 index a9efa7bc2fa1..000000000000 --- a/arch/arm/mach-ep93xx/timer-ep93xx.c +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> -#include <linux/sched_clock.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <asm/mach/time.h> -#include "soc.h" -#include "platform.h" - -/************************************************************************* - * Timer handling for EP93xx - ************************************************************************* - * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and - * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate - * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, - * is free-running, and can't generate interrupts. - * - * The 508 kHz timers are ideal for use for the timer interrupt, as the - * most common values of HZ divide 508 kHz nicely. We pick the 32 bit - * timer (timer 3) to get as long sleep intervals as possible when using - * CONFIG_NO_HZ. - * - * The higher clock rate of timer 4 makes it a better choice than the - * other timers for use as clock source and for sched_clock(), providing - * a stable 40 bit time base. - ************************************************************************* - */ -#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) -#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) -#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) -#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7) -#define EP93XX_TIMER123_CONTROL_MODE (1 << 6) -#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3) -#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) -#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) -#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) -#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8) -#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) -#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) -#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) -#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) - -#define EP93XX_TIMER123_RATE 508469 -#define EP93XX_TIMER4_RATE 983040 - -static u64 notrace ep93xx_read_sched_clock(void) -{ - u64 ret; - - ret = readl(EP93XX_TIMER4_VALUE_LOW); - ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); - return ret; -} - -static u64 ep93xx_clocksource_read(struct clocksource *c) -{ - u64 ret; - - ret = readl(EP93XX_TIMER4_VALUE_LOW); - ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); - return (u64) ret; -} - -static int ep93xx_clkevt_set_next_event(unsigned long next, - struct clock_event_device *evt) -{ - /* Default mode: periodic, off, 508 kHz */ - u32 tmode = EP93XX_TIMER123_CONTROL_MODE | - EP93XX_TIMER123_CONTROL_CLKSEL; - - /* Clear timer */ - writel(tmode, EP93XX_TIMER3_CONTROL); - - /* Set next event */ - writel(next, EP93XX_TIMER3_LOAD); - writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE, - EP93XX_TIMER3_CONTROL); - return 0; -} - - -static int ep93xx_clkevt_shutdown(struct clock_event_device *evt) -{ - /* Disable timer */ - writel(0, EP93XX_TIMER3_CONTROL); - - return 0; -} - -static struct clock_event_device ep93xx_clockevent = { - .name = "timer1", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = ep93xx_clkevt_shutdown, - .set_state_oneshot = ep93xx_clkevt_shutdown, - .tick_resume = ep93xx_clkevt_shutdown, - .set_next_event = ep93xx_clkevt_set_next_event, - .rating = 300, -}; - -static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* Writing any value clears the timer interrupt */ - writel(1, EP93XX_TIMER3_CLEAR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -void __init ep93xx_timer_init(void) -{ - int irq = IRQ_EP93XX_TIMER3; - unsigned long flags = IRQF_TIMER | IRQF_IRQPOLL; - - /* Enable and register clocksource and sched_clock on timer 4 */ - writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE, - EP93XX_TIMER4_VALUE_HIGH); - clocksource_mmio_init(NULL, "timer4", - EP93XX_TIMER4_RATE, 200, 40, - ep93xx_clocksource_read); - sched_clock_register(ep93xx_read_sched_clock, 40, - EP93XX_TIMER4_RATE); - - /* Set up clockevent on timer 3 */ - if (request_irq(irq, ep93xx_timer_interrupt, flags, "ep93xx timer", - &ep93xx_clockevent)) - pr_err("Failed to request irq %d (ep93xx timer)\n", irq); - clockevents_config_and_register(&ep93xx_clockevent, - EP93XX_TIMER123_RATE, - 1, - 0xffffffffU); -} diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c deleted file mode 100644 index d3de7283ecb3..000000000000 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/ts72xx.c - * Technologic Systems TS72xx SBC support. - * - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/mtd/platnand.h> -#include <linux/spi/spi.h> -#include <linux/spi/flash.h> -#include <linux/spi/mmc_spi.h> -#include <linux/mmc/host.h> -#include <linux/platform_data/spi-ep93xx.h> -#include <linux/gpio/machine.h> - -#include "gpio-ep93xx.h" -#include "hardware.h" - -#include <asm/mach-types.h> -#include <asm/mach/map.h> -#include <asm/mach/arch.h> - -#include "soc.h" -#include "ts72xx.h" - -/************************************************************************* - * IO map - *************************************************************************/ -static struct map_desc ts72xx_io_desc[] __initdata = { - { - .virtual = (unsigned long)TS72XX_MODEL_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE), - .length = TS72XX_MODEL_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_OPTIONS_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE), - .length = TS72XX_OPTIONS_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_OPTIONS2_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), - .length = TS72XX_OPTIONS2_SIZE, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)TS72XX_CPLDVER_VIRT_BASE, - .pfn = __phys_to_pfn(TS72XX_CPLDVER_PHYS_BASE), - .length = TS72XX_CPLDVER_SIZE, - .type = MT_DEVICE, - } -}; - -static void __init ts72xx_map_io(void) -{ - ep93xx_map_io(); - iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); -} - - -/************************************************************************* - * NAND flash - *************************************************************************/ -#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */ -#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */ - -static void ts72xx_nand_hwcontrol(struct nand_chip *chip, - int cmd, unsigned int ctrl) -{ - if (ctrl & NAND_CTRL_CHANGE) { - void __iomem *addr = chip->legacy.IO_ADDR_R; - unsigned char bits; - - addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE); - - bits = __raw_readb(addr) & ~0x07; - bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */ - bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */ - bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */ - - __raw_writeb(bits, addr); - } - - if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, chip->legacy.IO_ADDR_W); -} - -static int ts72xx_nand_device_ready(struct nand_chip *chip) -{ - void __iomem *addr = chip->legacy.IO_ADDR_R; - - addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); - - return !!(__raw_readb(addr) & 0x20); -} - -#define TS72XX_BOOTROM_PART_SIZE (SZ_16K) -#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) - -static struct mtd_partition ts72xx_nand_parts[] = { - { - .name = "TS-BOOTROM", - .offset = 0, - .size = TS72XX_BOOTROM_PART_SIZE, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "Linux", - .offset = MTDPART_OFS_RETAIN, - .size = TS72XX_REDBOOT_PART_SIZE, - /* leave so much for last partition */ - }, { - .name = "RedBoot", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static struct platform_nand_data ts72xx_nand_data = { - .chip = { - .nr_chips = 1, - .chip_offset = 0, - .chip_delay = 15, - }, - .ctrl = { - .cmd_ctrl = ts72xx_nand_hwcontrol, - .dev_ready = ts72xx_nand_device_ready, - }, -}; - -static struct resource ts72xx_nand_resource[] = { - { - .start = 0, /* filled in later */ - .end = 0, /* filled in later */ - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ts72xx_nand_flash = { - .name = "gen_nand", - .id = -1, - .dev.platform_data = &ts72xx_nand_data, - .resource = ts72xx_nand_resource, - .num_resources = ARRAY_SIZE(ts72xx_nand_resource), -}; - -static void __init ts72xx_register_flash(struct mtd_partition *parts, int n, - resource_size_t start) -{ - /* - * TS7200 has NOR flash all other TS72xx board have NAND flash. - */ - if (board_is_ts7200()) { - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M); - } else { - ts72xx_nand_resource[0].start = start; - ts72xx_nand_resource[0].end = start + SZ_16M - 1; - - ts72xx_nand_data.chip.partitions = parts; - ts72xx_nand_data.chip.nr_partitions = n; - - platform_device_register(&ts72xx_nand_flash); - } -} - -/************************************************************************* - * RTC M48T86 - *************************************************************************/ -#define TS72XX_RTC_INDEX_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x00800000) -#define TS72XX_RTC_DATA_PHYS_BASE (EP93XX_CS1_PHYS_BASE + 0x01700000) - -static struct resource ts72xx_rtc_resources[] = { - DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01), - DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01), -}; - -static struct platform_device ts72xx_rtc_device = { - .name = "rtc-m48t86", - .id = -1, - .resource = ts72xx_rtc_resources, - .num_resources = ARRAY_SIZE(ts72xx_rtc_resources), -}; - -/************************************************************************* - * Watchdog (in CPLD) - *************************************************************************/ -#define TS72XX_WDT_CONTROL_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03800000) -#define TS72XX_WDT_FEED_PHYS_BASE (EP93XX_CS2_PHYS_BASE + 0x03c00000) - -static struct resource ts72xx_wdt_resources[] = { - DEFINE_RES_MEM(TS72XX_WDT_CONTROL_PHYS_BASE, 0x01), - DEFINE_RES_MEM(TS72XX_WDT_FEED_PHYS_BASE, 0x01), -}; - -static struct platform_device ts72xx_wdt_device = { - .name = "ts72xx-wdt", - .id = -1, - .resource = ts72xx_wdt_resources, - .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), -}; - -/************************************************************************* - * ETH - *************************************************************************/ -static struct ep93xx_eth_data __initdata ts72xx_eth_data = { - .phy_id = 1, -}; - -/************************************************************************* - * SPI SD/MMC host - *************************************************************************/ -#define BK3_EN_SDCARD_PHYS_BASE 0x12400000 -#define BK3_EN_SDCARD_PWR 0x0 -#define BK3_DIS_SDCARD_PWR 0x0C -static void bk3_mmc_spi_setpower(struct device *dev, unsigned int vdd) -{ - void __iomem *pwr_sd = ioremap(BK3_EN_SDCARD_PHYS_BASE, SZ_4K); - - if (!pwr_sd) { - pr_err("Failed to enable SD card power!"); - return; - } - - pr_debug("%s: SD card pwr %s VDD:0x%x\n", __func__, - !!vdd ? "ON" : "OFF", vdd); - - if (!!vdd) - __raw_writeb(BK3_EN_SDCARD_PWR, pwr_sd); - else - __raw_writeb(BK3_DIS_SDCARD_PWR, pwr_sd); - - iounmap(pwr_sd); -} - -static struct mmc_spi_platform_data bk3_spi_mmc_data = { - .detect_delay = 500, - .powerup_msecs = 100, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .caps = MMC_CAP_NONREMOVABLE, - .setpower = bk3_mmc_spi_setpower, -}; - -/************************************************************************* - * SPI Bus - SD card access - *************************************************************************/ -static struct spi_board_info bk3_spi_board_info[] __initdata = { - { - .modalias = "mmc_spi", - .platform_data = &bk3_spi_mmc_data, - .max_speed_hz = 7.4E6, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_0, - }, -}; - -/* - * This is a stub -> the FGPIO[3] pin is not connected on the schematic - * The all work is performed automatically by !SPI_FRAME (SFRM1) and - * goes through CPLD - */ -static struct gpiod_lookup_table bk3_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP("F", 3, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info bk3_spi_master __initdata = { - .use_dma = 1, -}; - -/************************************************************************* - * TS72XX support code - *************************************************************************/ -#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX) - -/* Relative to EP93XX_CS1_PHYS_BASE */ -#define TS73XX_FPGA_LOADER_BASE 0x03c00000 - -static struct resource ts73xx_fpga_resources[] = { - { - .start = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE, - .end = EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ts73xx_fpga_device = { - .name = "ts73xx-fpga-mgr", - .id = -1, - .resource = ts73xx_fpga_resources, - .num_resources = ARRAY_SIZE(ts73xx_fpga_resources), -}; - -#endif - -/************************************************************************* - * SPI Bus - *************************************************************************/ -static struct spi_board_info ts72xx_spi_devices[] __initdata = { - { - .modalias = "tmp122", - .max_speed_hz = 2 * 1000 * 1000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -static struct gpiod_lookup_table ts72xx_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - /* DIO_17 */ - GPIO_LOOKUP("F", 2, "cs", GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info ts72xx_spi_info __initdata = { - /* Intentionally left blank */ -}; - -static void __init ts72xx_init_machine(void) -{ - ep93xx_init_devices(); - ts72xx_register_flash(ts72xx_nand_parts, ARRAY_SIZE(ts72xx_nand_parts), - is_ts9420_installed() ? - EP93XX_CS7_PHYS_BASE : EP93XX_CS6_PHYS_BASE); - platform_device_register(&ts72xx_rtc_device); - platform_device_register(&ts72xx_wdt_device); - - ep93xx_register_eth(&ts72xx_eth_data, 1); -#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX) - if (board_is_ts7300()) - platform_device_register(&ts73xx_fpga_device); -#endif - gpiod_add_lookup_table(&ts72xx_spi_cs_gpio_table); - ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices, - ARRAY_SIZE(ts72xx_spi_devices)); -} - -MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") - /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ts72xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = ts72xx_init_machine, - .restart = ep93xx_restart, -MACHINE_END - -/************************************************************************* - * EP93xx I2S audio peripheral handling - *************************************************************************/ -static struct resource ep93xx_i2s_resource[] = { - DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), - DEFINE_RES_IRQ_NAMED(IRQ_EP93XX_SAI, "spilink i2s slave"), -}; - -static struct platform_device ep93xx_i2s_device = { - .name = "ep93xx-spilink-i2s", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), - .resource = ep93xx_i2s_resource, -}; - -/************************************************************************* - * BK3 support code - *************************************************************************/ -static struct mtd_partition bk3_nand_parts[] = { - { - .name = "System", - .offset = 0x00000000, - .size = 0x01e00000, - }, { - .name = "Data", - .offset = 0x01e00000, - .size = 0x05f20000 - }, { - .name = "RedBoot", - .offset = 0x07d20000, - .size = 0x002e0000, - .mask_flags = MTD_WRITEABLE, /* force RO */ - }, -}; - -static void __init bk3_init_machine(void) -{ - ep93xx_init_devices(); - - ts72xx_register_flash(bk3_nand_parts, ARRAY_SIZE(bk3_nand_parts), - EP93XX_CS6_PHYS_BASE); - - ep93xx_register_eth(&ts72xx_eth_data, 1); - - gpiod_add_lookup_table(&bk3_spi_cs_gpio_table); - ep93xx_register_spi(&bk3_spi_master, bk3_spi_board_info, - ARRAY_SIZE(bk3_spi_board_info)); - - /* Configure ep93xx's I2S to use AC97 pins */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); - platform_device_register(&ep93xx_i2s_device); -} - -MACHINE_START(BK3, "Liebherr controller BK3.1") - /* Maintainer: Lukasz Majewski <lukma@denx.de> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS, - .map_io = ts72xx_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = bk3_init_machine, - .restart = ep93xx_restart, -MACHINE_END diff --git a/arch/arm/mach-ep93xx/ts72xx.h b/arch/arm/mach-ep93xx/ts72xx.h deleted file mode 100644 index 00b4941d29c9..000000000000 --- a/arch/arm/mach-ep93xx/ts72xx.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/arm/mach-ep93xx/include/mach/ts72xx.h - */ - -/* - * TS72xx memory map: - * - * virt phys size - * febff000 22000000 4K model number register (bits 0-2) - * febfe000 22400000 4K options register - * febfd000 22800000 4K options register #2 - * febfc000 23400000 4K CPLD version register - */ - -#ifndef __TS72XX_H_ -#define __TS72XX_H_ - -#define TS72XX_MODEL_PHYS_BASE 0x22000000 -#define TS72XX_MODEL_VIRT_BASE IOMEM(0xfebff000) -#define TS72XX_MODEL_SIZE 0x00001000 - -#define TS72XX_MODEL_TS7200 0x00 -#define TS72XX_MODEL_TS7250 0x01 -#define TS72XX_MODEL_TS7260 0x02 -#define TS72XX_MODEL_TS7300 0x03 -#define TS72XX_MODEL_TS7400 0x04 -#define TS72XX_MODEL_MASK 0x07 - - -#define TS72XX_OPTIONS_PHYS_BASE 0x22400000 -#define TS72XX_OPTIONS_VIRT_BASE IOMEM(0xfebfe000) -#define TS72XX_OPTIONS_SIZE 0x00001000 - -#define TS72XX_OPTIONS_COM2_RS485 0x02 -#define TS72XX_OPTIONS_MAX197 0x01 - - -#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000 -#define TS72XX_OPTIONS2_VIRT_BASE IOMEM(0xfebfd000) -#define TS72XX_OPTIONS2_SIZE 0x00001000 - -#define TS72XX_OPTIONS2_TS9420 0x04 -#define TS72XX_OPTIONS2_TS9420_BOOT 0x02 - -#define TS72XX_CPLDVER_PHYS_BASE 0x23400000 -#define TS72XX_CPLDVER_VIRT_BASE IOMEM(0xfebfc000) -#define TS72XX_CPLDVER_SIZE 0x00001000 - -#ifndef __ASSEMBLY__ - -static inline int ts72xx_model(void) -{ - return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK; -} - -static inline int board_is_ts7200(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7200; -} - -static inline int board_is_ts7250(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7250; -} - -static inline int board_is_ts7260(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7260; -} - -static inline int board_is_ts7300(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7300; -} - -static inline int board_is_ts7400(void) -{ - return ts72xx_model() == TS72XX_MODEL_TS7400; -} - -static inline int is_max197_installed(void) -{ - return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) & - TS72XX_OPTIONS_MAX197); -} - -static inline int is_ts9420_installed(void) -{ - return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & - TS72XX_OPTIONS2_TS9420); -} -#endif -#endif /* __TS72XX_H_ */ diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c deleted file mode 100644 index 9471938df64c..000000000000 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * arch/arm/mach-ep93xx/vision_ep9307.c - * Vision Engraving Systems EP9307 SoM support. - * - * Copyright (C) 2008-2011 Vision Engraving Systems - * H Hartley Sweeten <hsweeten@visionengravers.com> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/gpio/machine.h> -#include <linux/fb.h> -#include <linux/io.h> -#include <linux/mtd/partitions.h> -#include <linux/i2c.h> -#include <linux/platform_data/pca953x.h> -#include <linux/spi/spi.h> -#include <linux/spi/flash.h> -#include <linux/spi/mmc_spi.h> -#include <linux/mmc/host.h> - -#include <sound/cs4271.h> - -#include "hardware.h" -#include <linux/platform_data/video-ep93xx.h> -#include <linux/platform_data/spi-ep93xx.h> -#include "gpio-ep93xx.h" - -#include <asm/mach-types.h> -#include <asm/mach/map.h> -#include <asm/mach/arch.h> - -#include "soc.h" - -/************************************************************************* - * Static I/O mappings for the FPGA - *************************************************************************/ -#define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE -#define VISION_VIRT_BASE 0xfebff000 - -static struct map_desc vision_io_desc[] __initdata = { - { - .virtual = VISION_VIRT_BASE, - .pfn = __phys_to_pfn(VISION_PHYS_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; - -static void __init vision_map_io(void) -{ - ep93xx_map_io(); - - iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc)); -} - -/************************************************************************* - * Ethernet - *************************************************************************/ -static struct ep93xx_eth_data vision_eth_data __initdata = { - .phy_id = 1, -}; - -/************************************************************************* - * Framebuffer - *************************************************************************/ -#define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1 - -static int vision_lcd_setup(struct platform_device *pdev) -{ - int err; - - err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH, - dev_name(&pdev->dev)); - if (err) - return err; - - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS | - EP93XX_SYSCON_DEVCFG_RASONP3 | - EP93XX_SYSCON_DEVCFG_EXVC); - - return 0; -} - -static void vision_lcd_teardown(struct platform_device *pdev) -{ - gpio_free(VISION_LCD_ENABLE); -} - -static void vision_lcd_blank(int blank_mode, struct fb_info *info) -{ - if (blank_mode) - gpio_set_value(VISION_LCD_ENABLE, 0); - else - gpio_set_value(VISION_LCD_ENABLE, 1); -} - -static struct ep93xxfb_mach_info ep93xxfb_info __initdata = { - .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, - .setup = vision_lcd_setup, - .teardown = vision_lcd_teardown, - .blank = vision_lcd_blank, -}; - - -/************************************************************************* - * GPIO Expanders - *************************************************************************/ -#define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1) -#define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16) -#define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16) -#define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16) - -static struct pca953x_platform_data pca953x_74_gpio_data = { - .gpio_base = PCA9539_74_GPIO_BASE, - .irq_base = EP93XX_BOARD_IRQ(0), -}; - -static struct pca953x_platform_data pca953x_75_gpio_data = { - .gpio_base = PCA9539_75_GPIO_BASE, - .irq_base = -1, -}; - -static struct pca953x_platform_data pca953x_76_gpio_data = { - .gpio_base = PCA9539_76_GPIO_BASE, - .irq_base = -1, -}; - -static struct pca953x_platform_data pca953x_77_gpio_data = { - .gpio_base = PCA9539_77_GPIO_BASE, - .irq_base = -1, -}; - -/************************************************************************* - * I2C Bus - *************************************************************************/ - -static struct i2c_board_info vision_i2c_info[] __initdata = { - { - I2C_BOARD_INFO("isl1208", 0x6f), - .irq = IRQ_EP93XX_EXT1, - }, { - I2C_BOARD_INFO("pca9539", 0x74), - .platform_data = &pca953x_74_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x75), - .platform_data = &pca953x_75_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x76), - .platform_data = &pca953x_76_gpio_data, - }, { - I2C_BOARD_INFO("pca9539", 0x77), - .platform_data = &pca953x_77_gpio_data, - }, -}; - -/************************************************************************* - * SPI CS4271 Audio Codec - *************************************************************************/ -static struct cs4271_platform_data vision_cs4271_data = { - /* Intentionally left blank */ -}; - -/************************************************************************* - * SPI Flash - *************************************************************************/ -static struct mtd_partition vision_spi_flash_partitions[] = { - { - .name = "SPI bootstrap", - .offset = 0, - .size = SZ_4K, - }, { - .name = "Bootstrap config", - .offset = MTDPART_OFS_APPEND, - .size = SZ_4K, - }, { - .name = "System config", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct flash_platform_data vision_spi_flash_data = { - .name = "SPI Flash", - .parts = vision_spi_flash_partitions, - .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions), -}; - -/************************************************************************* - * SPI SD/MMC host - *************************************************************************/ -static struct mmc_spi_platform_data vision_spi_mmc_data = { - .detect_delay = 100, - .powerup_msecs = 100, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .caps2 = MMC_CAP2_RO_ACTIVE_HIGH, -}; - -static struct gpiod_lookup_table vision_spi_mmc_gpio_table = { - .dev_id = "mmc_spi.2", /* "mmc_spi @ CS2 */ - .table = { - /* Card detect */ - GPIO_LOOKUP_IDX("B", 7, NULL, 0, GPIO_ACTIVE_LOW), - /* Write protect */ - GPIO_LOOKUP_IDX("F", 0, NULL, 1, GPIO_ACTIVE_HIGH), - { }, - }, -}; - -/************************************************************************* - * SPI Bus - *************************************************************************/ -static struct spi_board_info vision_spi_board_info[] __initdata = { - { - .modalias = "cs4271", - .platform_data = &vision_cs4271_data, - .max_speed_hz = 6000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_3, - }, { - .modalias = "sst25l", - .platform_data = &vision_spi_flash_data, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 1, - .mode = SPI_MODE_3, - }, { - .modalias = "mmc_spi", - .platform_data = &vision_spi_mmc_data, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 2, - .mode = SPI_MODE_3, - }, -}; - -static struct gpiod_lookup_table vision_spi_cs4271_gpio_table = { - .dev_id = "spi0.0", /* cs4271 @ CS0 */ - .table = { - /* RESET */ - GPIO_LOOKUP_IDX("H", 2, NULL, 0, GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct gpiod_lookup_table vision_spi_cs_gpio_table = { - .dev_id = "spi0", - .table = { - GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("G", 2, "cs", 2, GPIO_ACTIVE_LOW), - { }, - }, -}; - -static struct ep93xx_spi_info vision_spi_master __initdata = { - .use_dma = 1, -}; - -/************************************************************************* - * I2S Audio - *************************************************************************/ -static struct platform_device vision_audio_device = { - .name = "edb93xx-audio", - .id = -1, -}; - -static void __init vision_register_i2s(void) -{ - ep93xx_register_i2s(); - platform_device_register(&vision_audio_device); -} - -/************************************************************************* - * Machine Initialization - *************************************************************************/ -static void __init vision_init_machine(void) -{ - ep93xx_init_devices(); - ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M); - ep93xx_register_eth(&vision_eth_data, 1); - ep93xx_register_fb(&ep93xxfb_info); - ep93xx_register_pwm(1, 0); - - /* - * Request the gpio expander's interrupt gpio line now to prevent - * the kernel from doing a WARN in gpiolib:gpio_ensure_requested(). - */ - if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN, - "pca9539:74")) - pr_warn("cannot request interrupt gpio for pca9539:74\n"); - - vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)); - - ep93xx_register_i2c(vision_i2c_info, - ARRAY_SIZE(vision_i2c_info)); - gpiod_add_lookup_table(&vision_spi_cs4271_gpio_table); - gpiod_add_lookup_table(&vision_spi_mmc_gpio_table); - gpiod_add_lookup_table(&vision_spi_cs_gpio_table); - ep93xx_register_spi(&vision_spi_master, vision_spi_board_info, - ARRAY_SIZE(vision_spi_board_info)); - vision_register_i2s(); -} - -MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307") - /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */ - .atag_offset = 0x100, - .nr_irqs = NR_EP93XX_IRQS + EP93XX_BOARD_IRQS, - .map_io = vision_map_io, - .init_irq = ep93xx_init_irq, - .init_time = ep93xx_timer_init, - .init_machine = vision_init_machine, - .restart = ep93xx_restart, -MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 9ababf4ac210..3feb31ab556e 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -7,37 +7,15 @@ #include <linux/of_platform.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> -#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <asm/mach/arch.h> #include "common.h" #include "cpuidle.h" -static void __init imx6sx_enet_clk_sel(void) -{ - struct regmap *gpr; - - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); - if (!IS_ERR(gpr)) { - regmap_update_bits(gpr, IOMUXC_GPR1, - IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0); - regmap_update_bits(gpr, IOMUXC_GPR1, - IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0); - } else { - pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); - } -} - -static inline void imx6sx_enet_init(void) -{ - imx6sx_enet_clk_sel(); -} - static void __init imx6sx_init_machine(void) { of_platform_default_populate(NULL, NULL, NULL); - imx6sx_enet_init(); imx_anatop_init(); imx6sx_pm_init(); } diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c index 9587885fb1ac..87632ae0201c 100644 --- a/arch/arm/mach-imx/mach-imx7d.c +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -48,7 +48,7 @@ static void __init imx7d_enet_clk_sel(void) } } -static inline void imx7d_enet_init(void) +static void __init imx7d_enet_init(void) { imx7d_enet_phy_init(); imx7d_enet_clk_sel(); diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig index 35730d3696d0..138599545c24 100644 --- a/arch/arm/mach-lpc32xx/Kconfig +++ b/arch/arm/mach-lpc32xx/Kconfig @@ -8,5 +8,6 @@ config ARCH_LPC32XX select CLKSRC_LPC32XX select CPU_ARM926T select GPIOLIB + select LPC32XX_DMAMUX if AMBA_PL08X help Support for the NXP LPC32XX family of processors diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index fd5d0c8ff695..04ad651d13a0 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -86,6 +86,9 @@ static int __init mvebu_scan_mem(unsigned long node, const char *uname, base = dt_mem_next_cell(dt_root_addr_cells, ®); size = dt_mem_next_cell(dt_root_size_cells, ®); + if (size < MVEBU_DDR_TRAINING_AREA_SZ) + pr_warn("Too little memory to reserve for DDR training\n"); + memblock_reserve(base, MVEBU_DDR_TRAINING_AREA_SZ); } diff --git a/arch/arm/mach-omap1/omap-dma.c b/arch/arm/mach-omap1/omap-dma.c index 9ee472f8ead1..f091f78631d0 100644 --- a/arch/arm/mach-omap1/omap-dma.c +++ b/arch/arm/mach-omap1/omap-dma.c @@ -59,19 +59,6 @@ static struct omap_dma_dev_attr *d; static int enable_1510_mode; static u32 errata; -struct dma_link_info { - int *linked_dmach_q; - int no_of_lchs_linked; - - int q_count; - int q_tail; - int q_head; - - int chain_state; - int chain_mode; - -}; - static int dma_lch_count; static int dma_chan_count; static int omap_dma_reserve_channels; diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h index d4373a5c4697..b2763fb097ea 100644 --- a/arch/arm/mach-omap1/pm.h +++ b/arch/arm/mach-omap1/pm.h @@ -114,13 +114,9 @@ extern void omap1_pm_suspend(void); extern void omap1510_cpu_suspend(unsigned long, unsigned long); extern void omap1610_cpu_suspend(unsigned long, unsigned long); -extern void omap1510_idle_loop_suspend(void); -extern void omap1610_idle_loop_suspend(void); extern unsigned int omap1510_cpu_suspend_sz; extern unsigned int omap1610_cpu_suspend_sz; -extern unsigned int omap1510_idle_loop_suspend_sz; -extern unsigned int omap1610_idle_loop_suspend_sz; #ifdef CONFIG_OMAP_SERIAL_WAKE extern void omap_serial_wake_trigger(int enable); diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 7ad74db951f6..f18ef45e2fe1 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -333,7 +333,7 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) omap_pm_ops.scu_prepare(cpu, power_state); /* - * CPU never retuns back if targeted power state is OFF mode. + * CPU never returns back if targeted power state is OFF mode. * CPU ONLINE follows normal CPU ONLINE ptah via * omap4_secondary_startup(). */ diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index fca7869c8075..800980057373 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -315,7 +315,7 @@ static struct omap_device *omap_device_alloc(struct platform_device *pdev, od->hwmods_cnt = oh_cnt; - hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + hwmods = kmemdup_array(ohs, oh_cnt, sizeof(*hwmods), GFP_KERNEL); if (!hwmods) goto oda_exit2; diff --git a/arch/arm/mach-orion5x/board-mss2.c b/arch/arm/mach-orion5x/board-mss2.c index b0f16d223adf..9e3d69891d2f 100644 --- a/arch/arm/mach-orion5x/board-mss2.c +++ b/arch/arm/mach-orion5x/board-mss2.c @@ -82,5 +82,5 @@ static void mss2_power_off(void) void __init mss2_init(void) { /* register mss2 specific power-off method */ - pm_power_off = mss2_power_off; + register_platform_power_off(mss2_power_off); } diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 062109efa0ec..fcd38ff7ca45 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -700,7 +700,7 @@ static void __init dns323_init(void) if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) pr_err("DNS-323: failed to setup power-off GPIO\n"); - pm_power_off = dns323a_power_off; + register_platform_power_off(dns323a_power_off); break; case DNS323_REV_B1: /* 5182 built-in SATA init */ @@ -717,7 +717,7 @@ static void __init dns323_init(void) if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) pr_err("DNS-323: failed to setup power-off GPIO\n"); - pm_power_off = dns323b_power_off; + register_platform_power_off(dns323b_power_off); break; case DNS323_REV_C1: /* 5182 built-in SATA init */ @@ -727,7 +727,7 @@ static void __init dns323_init(void) if (gpio_request(DNS323C_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(DNS323C_GPIO_POWER_OFF, 0) != 0) pr_err("DNS-323: failed to setup power-off GPIO\n"); - pm_power_off = dns323c_power_off; + register_platform_power_off(dns323c_power_off); /* Now, -this- should theoretically be done by the sata_mv driver * once I figure out what's going on there. Maybe the behaviour diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index acba06618080..339b10891808 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -373,7 +373,7 @@ static void __init kurobox_pro_init(void) i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1); /* register Kurobox Pro specific power-off method */ - pm_power_off = kurobox_pro_power_off; + register_platform_power_off(kurobox_pro_power_off); } #ifdef CONFIG_MACH_KUROBOX_PRO diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index b7327a612835..5b0249f109cd 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -238,7 +238,7 @@ static void __init mv2120_init(void) if (gpio_request(MV2120_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(MV2120_GPIO_POWER_OFF, 1) != 0) pr_err("mv2120: failed to setup power-off GPIO\n"); - pm_power_off = mv2120_power_off; + register_platform_power_off(mv2120_power_off); } /* Warning: HP uses a wrong mach-type (=526) in their bootloader */ diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c index 6ad9740b426b..4afd9b4c71a9 100644 --- a/arch/arm/mach-orion5x/net2big-setup.c +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -423,7 +423,7 @@ static void __init net2big_init(void) if (gpio_request(NET2BIG_GPIO_POWER_OFF, "power-off") == 0 && gpio_direction_output(NET2BIG_GPIO_POWER_OFF, 0) == 0) - pm_power_off = net2big_power_off; + register_platform_power_off(net2big_power_off); else pr_err("net2big: failed to configure power-off GPIO\n"); diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c index 23a5521c6833..a9f01859d101 100644 --- a/arch/arm/mach-orion5x/terastation_pro2-setup.c +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -349,7 +349,7 @@ static void __init tsp2_init(void) i2c_register_board_info(0, &tsp2_i2c_rtc, 1); /* register Terastation Pro II specific power-off method */ - pm_power_off = tsp2_power_off; + register_platform_power_off(tsp2_power_off); } MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live") diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index bab8ba0e01ab..de9092e992c5 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -314,7 +314,7 @@ static void __init qnap_ts209_init(void) i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1); /* register tsx09 specific power-off method */ - pm_power_off = qnap_tsx09_power_off; + register_platform_power_off(qnap_tsx09_power_off); } MACHINE_START(TS209, "QNAP TS-109/TS-209") diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c index 8131982c10d9..725688aa5cba 100644 --- a/arch/arm/mach-orion5x/ts409-setup.c +++ b/arch/arm/mach-orion5x/ts409-setup.c @@ -312,7 +312,7 @@ static void __init qnap_ts409_init(void) platform_device_register(&ts409_leds); /* register tsx09 specific power-off method */ - pm_power_off = qnap_tsx09_power_off; + register_platform_power_off(qnap_tsx09_power_off); } MACHINE_START(TS409, "QNAP TS-409") diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 452bf7aac1fa..33533e35720f 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -378,38 +378,56 @@ static const uint32_t spitz_keymap[] = { KEY(6, 8, KEY_RIGHT), }; -static const struct matrix_keymap_data spitz_keymap_data = { - .keymap = spitz_keymap, - .keymap_size = ARRAY_SIZE(spitz_keymap), +static const struct software_node_ref_args spitz_mkp_row_gpios[] = { + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 12, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 17, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 91, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 34, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 36, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 38, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 39, GPIO_ACTIVE_HIGH), }; -static const uint32_t spitz_row_gpios[] = - { 12, 17, 91, 34, 36, 38, 39 }; -static const uint32_t spitz_col_gpios[] = - { 88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114 }; - -static struct matrix_keypad_platform_data spitz_mkp_pdata = { - .keymap_data = &spitz_keymap_data, - .row_gpios = spitz_row_gpios, - .col_gpios = spitz_col_gpios, - .num_row_gpios = ARRAY_SIZE(spitz_row_gpios), - .num_col_gpios = ARRAY_SIZE(spitz_col_gpios), - .col_scan_delay_us = 10, - .debounce_ms = 10, - .wakeup = 1, +static const struct software_node_ref_args spitz_mkp_col_gpios[] = { + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 88, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 23, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 24, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 25, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 26, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 27, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 52, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 103, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 107, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 108, GPIO_ACTIVE_HIGH), + SOFTWARE_NODE_REFERENCE(&pxa2xx_gpiochip_node, 114, GPIO_ACTIVE_HIGH), }; -static struct platform_device spitz_mkp_device = { +static const struct property_entry spitz_mkp_properties[] = { + PROPERTY_ENTRY_U32_ARRAY("linux,keymap", spitz_keymap), + PROPERTY_ENTRY_REF_ARRAY("row-gpios", spitz_mkp_row_gpios), + PROPERTY_ENTRY_REF_ARRAY("col-gpios", spitz_mkp_col_gpios), + PROPERTY_ENTRY_U32("col-scan-delay-us", 10), + PROPERTY_ENTRY_U32("debounce-delay-ms", 10), + PROPERTY_ENTRY_BOOL("wakeup-source"), + { } +}; + +static const struct platform_device_info spitz_mkp_info __initconst = { .name = "matrix-keypad", - .id = -1, - .dev = { - .platform_data = &spitz_mkp_pdata, - }, + .id = PLATFORM_DEVID_NONE, + .properties = spitz_mkp_properties, }; + static void __init spitz_mkp_init(void) { - platform_device_register(&spitz_mkp_device); + struct platform_device *pd; + int err; + + pd = platform_device_register_full(&spitz_mkp_info); + err = PTR_ERR_OR_ZERO(pd); + if (err) + pr_err("failed to create keypad device: %d\n", err); } #else static inline void spitz_mkp_init(void) {} @@ -419,45 +437,82 @@ static inline void spitz_mkp_init(void) {} * GPIO keys ******************************************************************************/ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) -static struct gpio_keys_button spitz_gpio_keys[] = { - { - .type = EV_PWR, - .code = KEY_SUSPEND, - .gpio = SPITZ_GPIO_ON_KEY, - .desc = "On Off", - .wakeup = 1, - }, - /* Two buttons detecting the lid state */ - { - .type = EV_SW, - .code = 0, - .gpio = SPITZ_GPIO_SWA, - .desc = "Display Down", - }, - { - .type = EV_SW, - .code = 1, - .gpio = SPITZ_GPIO_SWB, - .desc = "Lid Closed", - }, +static const struct software_node spitz_gpio_keys_node = { + .name = "spitz-gpio-keys", }; -static struct gpio_keys_platform_data spitz_gpio_keys_platform_data = { - .buttons = spitz_gpio_keys, - .nbuttons = ARRAY_SIZE(spitz_gpio_keys), +static const struct property_entry spitz_suspend_key_props[] = { + PROPERTY_ENTRY_U32("linux,input-type", EV_PWR), + PROPERTY_ENTRY_U32("linux,code", KEY_SUSPEND), + PROPERTY_ENTRY_GPIO("gpios", &pxa2xx_gpiochip_node, + SPITZ_GPIO_ON_KEY, GPIO_ACTIVE_HIGH), + PROPERTY_ENTRY_STRING("label", "On Off"), + PROPERTY_ENTRY_BOOL("wakeup-source"), + { } }; -static struct platform_device spitz_gpio_keys_device = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &spitz_gpio_keys_platform_data, - }, +static const struct software_node spitz_suspend_key_node = { + .parent = &spitz_gpio_keys_node, + .properties = spitz_suspend_key_props, +}; + +static const struct property_entry spitz_sw1_props[] = { + PROPERTY_ENTRY_U32("linux,input-type", EV_SW), + PROPERTY_ENTRY_U32("linux,code", 0), + PROPERTY_ENTRY_GPIO("gpios", &pxa2xx_gpiochip_node, + SPITZ_GPIO_SWA, GPIO_ACTIVE_HIGH), + PROPERTY_ENTRY_STRING("label", "Display Down"), + { } +}; + +static const struct software_node spitz_sw1_node = { + .parent = &spitz_gpio_keys_node, + .properties = spitz_sw1_props, +}; + +static const struct property_entry spitz_sw2_props[] = { + PROPERTY_ENTRY_U32("linux,input-type", EV_SW), + PROPERTY_ENTRY_U32("linux,code", 1), + PROPERTY_ENTRY_GPIO("gpios", &pxa2xx_gpiochip_node, + SPITZ_GPIO_SWB, GPIO_ACTIVE_HIGH), + PROPERTY_ENTRY_STRING("label", "Lid Closed"), + { } +}; + +static const struct software_node spitz_sw2_node = { + .parent = &spitz_gpio_keys_node, + .properties = spitz_sw2_props, +}; + +static const struct software_node *spitz_gpio_keys_swnodes[] = { + &spitz_gpio_keys_node, + &spitz_suspend_key_node, + &spitz_sw1_node, + &spitz_sw2_node, + NULL }; static void __init spitz_keys_init(void) { - platform_device_register(&spitz_gpio_keys_device); + struct platform_device_info keys_info = { + .name = "gpio-keys", + .id = PLATFORM_DEVID_NONE, + }; + struct platform_device *pd; + int err; + + err = software_node_register_node_group(spitz_gpio_keys_swnodes); + if (err) { + pr_err("failed to register gpio-keys software nodes: %d\n", err); + return; + } + + keys_info.fwnode = software_node_fwnode(&spitz_gpio_keys_node); + + pd = platform_device_register_full(&keys_info); + err = PTR_ERR_OR_ZERO(pd); + if (err) + pr_err("failed to create gpio-keys device: %d\n", err); } #else static inline void spitz_keys_init(void) {} diff --git a/arch/arm/mach-s3c/irq-uart-s3c64xx.h b/arch/arm/mach-s3c/irq-uart-s3c64xx.h index 78eccdce95a7..e754b0359c8a 100644 --- a/arch/arm/mach-s3c/irq-uart-s3c64xx.h +++ b/arch/arm/mach-s3c/irq-uart-s3c64xx.h @@ -12,5 +12,3 @@ struct s3c_uart_irq { unsigned int parent_irq; }; -extern void s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs); - diff --git a/arch/arm/mach-s3c/mach-crag6410-module.c b/arch/arm/mach-s3c/mach-crag6410-module.c index 2de1a89f6e99..4ffcf024b09d 100644 --- a/arch/arm/mach-s3c/mach-crag6410-module.c +++ b/arch/arm/mach-s3c/mach-crag6410-module.c @@ -446,7 +446,7 @@ static int wlf_gf_module_probe(struct i2c_client *i2c) } static const struct i2c_device_id wlf_gf_module_id[] = { - { "wlf-gf-module", 0 }, + { "wlf-gf-module" }, { } }; diff --git a/arch/arm/mach-s3c/pm.h b/arch/arm/mach-s3c/pm.h index 35d266ab6958..d48d15088525 100644 --- a/arch/arm/mach-s3c/pm.h +++ b/arch/arm/mach-s3c/pm.h @@ -48,8 +48,6 @@ extern unsigned long s3c_pm_flags; /* from sleep.S */ -extern int s3c2410_cpu_suspend(unsigned long); - #ifdef CONFIG_PM_SLEEP extern int s3c_irq_wake(struct irq_data *data, unsigned int state); extern void s3c_cpu_resume(void); diff --git a/arch/arm/mach-s3c/s3c64xx.h b/arch/arm/mach-s3c/s3c64xx.h index 92258e4f60f6..0505728f3f7b 100644 --- a/arch/arm/mach-s3c/s3c64xx.h +++ b/arch/arm/mach-s3c/s3c64xx.h @@ -23,17 +23,6 @@ struct device_node; void s3c64xx_set_xtal_freq(unsigned long freq); void s3c64xx_set_xusbxti_freq(unsigned long freq); -#ifdef CONFIG_CPU_S3C6400 - -extern int s3c6400_init(void); -extern void s3c6400_init_irq(void); -extern void s3c6400_map_io(void); - -#else -#define s3c6400_map_io NULL -#define s3c6400_init NULL -#endif - #ifdef CONFIG_CPU_S3C6410 extern int s3c6410_init(void); diff --git a/arch/arm/mach-versatile/platsmp-realview.c b/arch/arm/mach-versatile/platsmp-realview.c index 6965a1de727b..d38b2e174257 100644 --- a/arch/arm/mach-versatile/platsmp-realview.c +++ b/arch/arm/mach-versatile/platsmp-realview.c @@ -70,6 +70,7 @@ static void __init realview_smp_prepare_cpus(unsigned int max_cpus) return; } map = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(map)) { pr_err("PLATSMP: No syscon regmap\n"); return; diff --git a/arch/arm/mach-versatile/spc.c b/arch/arm/mach-versatile/spc.c index 5e44170e1a9a..790092734cf6 100644 --- a/arch/arm/mach-versatile/spc.c +++ b/arch/arm/mach-versatile/spc.c @@ -73,7 +73,7 @@ /* * Even though the SPC takes max 3-5 ms to complete any OPP/COMMS - * operation, the operation could start just before jiffie is about + * operation, the operation could start just before jiffy is about * to be incremented. So setting timeout value of 20ms = 2jiffies@100Hz */ #define TIMEOUT_US 20000 diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index f8dd0b3cc8e0..3c6ddb1afdc4 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -22,7 +22,7 @@ #include <asm/cp15.h> #include <asm/system_info.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/opcodes.h> #include "fault.h" diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index 97db5397c320..fecac107fd0d 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c @@ -39,7 +39,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) /* * Cache support for v7m is optional, so can be treated as * coherent if no cache has been detected. Note that it is not - * enough to check if MPU is in use or not since in absense of + * enough to check if MPU is in use or not since in absence of * MPU system memory map is used. */ dev->dma_coherent = cacheid ? coherent : true; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 5adf1769eee4..88c2d68a69c9 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1532,7 +1532,7 @@ static const struct dma_map_ops iommu_ops = { /** * arm_iommu_create_mapping - * @bus: pointer to the bus holding the client device (for IOMMU calls) + * @dev: pointer to the client device (for IOMMU calls) * @base: start address of the valid IO address space * @size: maximum size of the valid IO address space * @@ -1544,7 +1544,7 @@ static const struct dma_map_ops iommu_ops = { * arm_iommu_attach_device function. */ struct dma_iommu_mapping * -arm_iommu_create_mapping(const struct bus_type *bus, dma_addr_t base, u64 size) +arm_iommu_create_mapping(struct device *dev, dma_addr_t base, u64 size) { unsigned int bits = size >> PAGE_SHIFT; unsigned int bitmap_size = BITS_TO_LONGS(bits) * sizeof(long); @@ -1585,9 +1585,11 @@ arm_iommu_create_mapping(const struct bus_type *bus, dma_addr_t base, u64 size) spin_lock_init(&mapping->lock); - mapping->domain = iommu_domain_alloc(bus); - if (!mapping->domain) + mapping->domain = iommu_paging_domain_alloc(dev); + if (IS_ERR(mapping->domain)) { + err = PTR_ERR(mapping->domain); goto err4; + } kref_init(&mapping->kref); return mapping; @@ -1718,7 +1720,7 @@ static void arm_setup_iommu_dma_ops(struct device *dev) dma_base = dma_range_map_min(dev->dma_range_map); size = dma_range_map_max(dev->dma_range_map) - dma_base; } - mapping = arm_iommu_create_mapping(dev->bus, dma_base, size); + mapping = arm_iommu_create_mapping(dev, dma_base, size); if (IS_ERR(mapping)) { pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n", size, dev_name(dev)); diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 2286c2ea60ec..831793cd6ff9 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -61,7 +61,7 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, return ret; } -#if USE_SPLIT_PTE_PTLOCKS +#if defined(CONFIG_SPLIT_PTE_PTLOCKS) /* * If we are using split PTE locks, then we need to take the page * lock here. Otherwise we are using shared mm->page_table_lock @@ -80,10 +80,10 @@ static inline void do_pte_unlock(spinlock_t *ptl) { spin_unlock(ptl); } -#else /* !USE_SPLIT_PTE_PTLOCKS */ +#else /* !defined(CONFIG_SPLIT_PTE_PTLOCKS) */ static inline void do_pte_lock(spinlock_t *ptl) {} static inline void do_pte_unlock(spinlock_t *ptl) {} -#endif /* USE_SPLIT_PTE_PTLOCKS */ +#endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, unsigned long pfn) diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 448e57c6f653..4a833e89782a 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -84,8 +84,15 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start, unsigned long addr, end; unsigned long next; +#ifdef CONFIG_XIP_KERNEL + addr = (phys_addr_t)(text_start) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR; + end = (phys_addr_t)(text_end) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + + CONFIG_XIP_PHYS_ADDR; +#else addr = virt_to_idmap(text_start); end = virt_to_idmap(text_end); +#endif pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end); prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index d65d0e6ed10a..3dbb383c26d5 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -28,7 +28,8 @@ */ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, + unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; @@ -78,8 +79,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) + const unsigned long len, const unsigned long pgoff, + const unsigned long flags, vm_flags_t vm_flags) { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 3f774856ca67..f5b7a16c5803 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1403,18 +1403,6 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) } /* - * Map the kernel if it is XIP. - * It is always first in the modulearea. - */ -#ifdef CONFIG_XIP_KERNEL - map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); - map.virtual = MODULES_VADDR; - map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; - map.type = MT_ROM; - create_mapping(&map); -#endif - - /* * Map the cache flushing regions. */ #ifdef FLUSH_BASE @@ -1603,12 +1591,27 @@ static void __init map_kernel(void) * This will only persist until we turn on proper memory management later on * and we remap the whole kernel with page granularity. */ +#ifdef CONFIG_XIP_KERNEL + phys_addr_t kernel_nx_start = kernel_sec_start; +#else phys_addr_t kernel_x_start = kernel_sec_start; phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); phys_addr_t kernel_nx_start = kernel_x_end; +#endif phys_addr_t kernel_nx_end = kernel_sec_end; struct map_desc map; + /* + * Map the kernel if it is XIP. + * It is always first in the modulearea. + */ +#ifdef CONFIG_XIP_KERNEL + map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); + map.virtual = MODULES_VADDR; + map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; + map.type = MT_ROM; + create_mapping(&map); +#else map.pfn = __phys_to_pfn(kernel_x_start); map.virtual = __phys_to_virt(kernel_x_start); map.length = kernel_x_end - kernel_x_start; @@ -1618,7 +1621,7 @@ static void __init map_kernel(void) /* If the nx part is small it may end up covered by the tail of the RWX section */ if (kernel_x_end == kernel_nx_end) return; - +#endif map.pfn = __phys_to_pfn(kernel_nx_start); map.virtual = __phys_to_virt(kernel_nx_start); map.length = kernel_nx_end - kernel_nx_start; @@ -1638,7 +1641,7 @@ static void __init early_paging_init(const struct machine_desc *mdesc) { pgtables_remap *lpae_pgtables_remap; unsigned long pa_pgd; - unsigned int cr, ttbcr; + u32 cr, ttbcr, tmp; long long offset; if (!mdesc->pv_fixup) @@ -1688,7 +1691,9 @@ static void __init early_paging_init(const struct machine_desc *mdesc) cr = get_cr(); set_cr(cr & ~(CR_I | CR_C)); ttbcr = cpu_get_ttbcr(); - cpu_set_ttbcr(ttbcr & ~(3 << 8 | 3 << 10)); + /* Disable all kind of caching of the translation table */ + tmp = ttbcr & ~(TTBCR_ORGN0_MASK | TTBCR_IRGN0_MASK); + cpu_set_ttbcr(tmp); flush_cache_all(); /* @@ -1762,6 +1767,11 @@ void __init paging_init(const struct machine_desc *mdesc) { void *zero_page; +#ifdef CONFIG_XIP_KERNEL + /* Store the kernel RW RAM region start/end in these variables */ + kernel_sec_start = CONFIG_PHYS_OFFSET & SECTION_MASK; + kernel_sec_end = round_up(__pa(_end), SECTION_SIZE); +#endif pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n", kernel_sec_start, kernel_sec_end); diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 5fb9a6aecb00..2cd933342679 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -94,7 +94,7 @@ SYM_TYPED_FUNC_START(cpu_v7_dcache_clean_area) ret lr SYM_FUNC_END(cpu_v7_dcache_clean_area) -#ifdef CONFIG_ARM_PSCI +#if defined(CONFIG_ARM_PSCI) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) .arch_extension sec SYM_TYPED_FUNC_START(cpu_v7_smc_switch_mm) stmfd sp!, {r0 - r3} diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 23c98203c40f..49eeb2ad8dbd 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -477,3 +477,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile index 01067a2bc43b..8a306bbec4a0 100644 --- a/arch/arm/vdso/Makefile +++ b/arch/arm/vdso/Makefile @@ -5,7 +5,7 @@ include $(srctree)/lib/vdso/Makefile hostprogs := vdsomunge -obj-vdso := vgettimeofday.o datapage.o note.o +obj-vdso := vgettimeofday.o note.o # Build rules targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds diff --git a/arch/arm/vdso/datapage.S b/arch/arm/vdso/datapage.S deleted file mode 100644 index 9cd73b725d9f..000000000000 --- a/arch/arm/vdso/datapage.S +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include <linux/linkage.h> -#include <asm/asm-offsets.h> - - .align 2 -.L_vdso_data_ptr: - .long _start - . - VDSO_DATA_SIZE - -ENTRY(__get_datapage) - .fnstart - adr r0, .L_vdso_data_ptr - ldr r1, [r0] - add r0, r0, r1 - bx lr - .fnend -ENDPROC(__get_datapage) diff --git a/arch/arm/vdso/vdso.lds.S b/arch/arm/vdso/vdso.lds.S index 165d1d2eb76b..9bfa0f52923c 100644 --- a/arch/arm/vdso/vdso.lds.S +++ b/arch/arm/vdso/vdso.lds.S @@ -11,6 +11,7 @@ */ #include <linux/const.h> +#include <asm/asm-offsets.h> #include <asm/page.h> #include <asm/vdso.h> @@ -19,7 +20,7 @@ OUTPUT_ARCH(arm) SECTIONS { - PROVIDE(_start = .); + PROVIDE(_vdso_data = . - VDSO_DATA_SIZE); . = SIZEOF_HEADERS; diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h index 3c7938fd40aa..32090b0fb250 100644 --- a/arch/arm/vfp/vfpinstr.h +++ b/arch/arm/vfp/vfpinstr.h @@ -64,33 +64,37 @@ #ifdef CONFIG_AS_VFP_VMRS_FPINST -#define fmrx(_vfp_) ({ \ - u32 __v; \ - asm(".fpu vfpv2\n" \ - "vmrs %0, " #_vfp_ \ - : "=r" (__v) : : "cc"); \ - __v; \ - }) - -#define fmxr(_vfp_,_var_) \ - asm(".fpu vfpv2\n" \ - "vmsr " #_vfp_ ", %0" \ - : : "r" (_var_) : "cc") +#define fmrx(_vfp_) ({ \ + u32 __v; \ + asm volatile (".fpu vfpv2\n" \ + "vmrs %0, " #_vfp_ \ + : "=r" (__v) : : "cc"); \ + __v; \ +}) + +#define fmxr(_vfp_, _var_) ({ \ + asm volatile (".fpu vfpv2\n" \ + "vmsr " #_vfp_ ", %0" \ + : : "r" (_var_) : "cc"); \ +}) #else #define vfpreg(_vfp_) #_vfp_ -#define fmrx(_vfp_) ({ \ - u32 __v; \ - asm("mrc p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmrx %0, " #_vfp_ \ - : "=r" (__v) : : "cc"); \ - __v; \ - }) - -#define fmxr(_vfp_,_var_) \ - asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \ - : : "r" (_var_) : "cc") +#define fmrx(_vfp_) ({ \ + u32 __v; \ + asm volatile ("mrc p10, 7, %0, " vfpreg(_vfp_) "," \ + "cr0, 0 @ fmrx %0, " #_vfp_ \ + : "=r" (__v) : : "cc"); \ + __v; \ +}) + +#define fmxr(_vfp_, _var_) ({ \ + asm volatile ("mcr p10, 7, %0, " vfpreg(_vfp_) "," \ + "cr0, 0 @ fmxr " #_vfp_ ", %0" \ + : : "r" (_var_) : "cc"); \ +}) #endif diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a2f8ff354ca6..d743737bf9ce 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -21,9 +21,11 @@ config ARM64 select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE select ARCH_HAS_CACHE_LINE_SIZE + select ARCH_HAS_CC_PLATFORM select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VM_PGTABLE + select ARCH_HAS_DMA_OPS if XEN select ARCH_HAS_DMA_PREP_COHERENT select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_FAST_MULTIPLIER @@ -34,14 +36,18 @@ config ARM64 select ARCH_HAS_KERNEL_FPU_SUPPORT if KERNEL_MODE_NEON select ARCH_HAS_KEEPINITRD select ARCH_HAS_MEMBARRIER_SYNC_CORE + select ARCH_HAS_MEM_ENCRYPT select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE + select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT select ARCH_HAS_PTE_DEVMAP select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_HW_PTE_YOUNG select ARCH_HAS_SETUP_DMA_OPS select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_SET_MEMORY + select ARCH_HAS_MEM_ENCRYPT + select ARCH_HAS_FORCE_DMA_UNENCRYPTED select ARCH_STACKWALK select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_MODULE_RWX @@ -99,6 +105,8 @@ config ARM64 select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_PAGE_TABLE_CHECK select ARCH_SUPPORTS_PER_VMA_LOCK + select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE + select ARCH_SUPPORTS_RT select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT select ARCH_WANT_DEFAULT_BPF_JIT @@ -196,7 +204,8 @@ config ARM64 select HAVE_DMA_CONTIGUOUS select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE_WITH_ARGS \ - if $(cc-option,-fpatchable-function-entry=2) + if (GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS || \ + CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS) select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS \ if DYNAMIC_FTRACE_WITH_ARGS && DYNAMIC_FTRACE_WITH_CALL_OPS select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS \ @@ -231,7 +240,7 @@ config ARM64 select HAVE_FUNCTION_ARG_ACCESS_API select MMU_GATHER_RCU_TABLE_FREE select HAVE_RSEQ - select HAVE_RUST if CPU_LITTLE_ENDIAN + select HAVE_RUST if RUSTC_SUPPORTS_ARM64 select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HAVE_KPROBES @@ -262,19 +271,30 @@ config ARM64 select TRACE_IRQFLAGS_NMI_SUPPORT select HAVE_SOFTIRQ_ON_OWN_STACK select USER_STACKTRACE_SUPPORT + select VDSO_GETRANDOM help ARM 64-bit (AArch64) Linux support. +config RUSTC_SUPPORTS_ARM64 + def_bool y + depends on CPU_LITTLE_ENDIAN + # Shadow call stack is only supported on certain rustc versions. + # + # When using the UNWIND_PATCH_PAC_INTO_SCS option, rustc version 1.80+ is + # required due to use of the -Zfixed-x18 flag. + # + # Otherwise, rustc version 1.82+ is required due to use of the + # -Zsanitizer=shadow-call-stack flag. + depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 || RUSTC_VERSION >= 108000 && UNWIND_PATCH_PAC_INTO_SCS + config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS def_bool CC_IS_CLANG # https://github.com/ClangBuiltLinux/linux/issues/1507 depends on AS_IS_GNU || (AS_IS_LLVM && (LD_IS_LLD || LD_VERSION >= 23600)) - select HAVE_DYNAMIC_FTRACE_WITH_ARGS config GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS def_bool CC_IS_GCC depends on $(cc-option,-fpatchable-function-entry=2) - select HAVE_DYNAMIC_FTRACE_WITH_ARGS config 64BIT def_bool y @@ -423,7 +443,7 @@ config AMPERE_ERRATUM_AC03_CPU_38 default y help This option adds an alternative code sequence to work around Ampere - erratum AC03_CPU_38 on AmpereOne. + errata AC03_CPU_38 and AC04_CPU_10 on AmpereOne. The affected design reports FEAT_HAFDBS as not implemented in ID_AA64MMFR1_EL1.HAFDBS, but (V)TCR_ELx.{HA,HD} are not RES0 @@ -1080,6 +1100,7 @@ config ARM64_ERRATUM_3194386 * ARM Cortex-A78C erratum 3324346 * ARM Cortex-A78C erratum 3324347 * ARM Cortex-A710 erratam 3324338 + * ARM Cortex-A715 errartum 3456084 * ARM Cortex-A720 erratum 3456091 * ARM Cortex-A725 erratum 3456106 * ARM Cortex-X1 erratum 3324344 @@ -1090,6 +1111,7 @@ config ARM64_ERRATUM_3194386 * ARM Cortex-X925 erratum 3324334 * ARM Neoverse-N1 erratum 3324349 * ARM Neoverse N2 erratum 3324339 + * ARM Neoverse-N3 erratum 3456111 * ARM Neoverse-V1 erratum 3324341 * ARM Neoverse V2 erratum 3324336 * ARM Neoverse-V3 erratum 3312417 @@ -1558,6 +1580,9 @@ config ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG config ARCH_SUPPORTS_CRASH_DUMP def_bool y +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION def_bool CRASH_RESERVE @@ -2100,7 +2125,8 @@ config ARM64_MTE depends on ARM64_PAN select ARCH_HAS_SUBPAGE_FAULTS select ARCH_USES_HIGH_VMA_FLAGS - select ARCH_USES_PG_ARCH_X + select ARCH_USES_PG_ARCH_2 + select ARCH_USES_PG_ARCH_3 help Memory Tagging (part of the ARMv8.5 Extensions) provides architectural support for run-time, always-on detection of @@ -2137,6 +2163,68 @@ config ARM64_EPAN if the cpu does not implement the feature. endmenu # "ARMv8.7 architectural features" +config AS_HAS_MOPS + def_bool $(as-instr,.arch_extension mops) + +menu "ARMv8.9 architectural features" + +config ARM64_POE + prompt "Permission Overlay Extension" + def_bool y + select ARCH_USES_HIGH_VMA_FLAGS + select ARCH_HAS_PKEYS + help + The Permission Overlay Extension is used to implement Memory + Protection Keys. Memory Protection Keys provides a mechanism for + enforcing page-based protections, but without requiring modification + of the page tables when an application changes protection domains. + + For details, see Documentation/core-api/protection-keys.rst + + If unsure, say y. + +config ARCH_PKEY_BITS + int + default 3 + +config ARM64_HAFT + bool "Support for Hardware managed Access Flag for Table Descriptors" + depends on ARM64_HW_AFDBM + default y + help + The ARMv8.9/ARMv9.5 introduces the feature Hardware managed Access + Flag for Table descriptors. When enabled an architectural executed + memory access will update the Access Flag in each Table descriptor + which is accessed during the translation table walk and for which + the Access Flag is 0. The Access Flag of the Table descriptor use + the same bit of PTE_AF. + + The feature will only be enabled if all the CPUs in the system + support this feature. If unsure, say Y. + +endmenu # "ARMv8.9 architectural features" + +menu "v9.4 architectural features" + +config ARM64_GCS + bool "Enable support for Guarded Control Stack (GCS)" + default y + select ARCH_HAS_USER_SHADOW_STACK + select ARCH_USES_HIGH_VMA_FLAGS + depends on !UPROBES + help + Guarded Control Stack (GCS) provides support for a separate + stack with restricted access which contains only return + addresses. This can be used to harden against some attacks + by comparing return address used by the program with what is + stored in the GCS, and may also be used to efficiently obtain + the call stack for applications such as profiling. + + The feature is detected at runtime, and will remain disabled + if the system does not implement the feature. + +endmenu # "v9.4 architectural features" + config ARM64_SVE bool "ARM Scalable Vector Extension support" default y @@ -2172,6 +2260,7 @@ config ARM64_SME bool "ARM Scalable Matrix Extension support" default y depends on ARM64_SVE + depends on BROKEN help The Scalable Matrix Extension (SME) is an extension to the AArch64 execution state which utilises a substantial subset of the SVE diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index f6bc3da1ef11..9efd3f37c2fd 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -10,7 +10,7 @@ # # Copyright (C) 1995-2001 by Russell King -LDFLAGS_vmlinux :=--no-undefined -X +LDFLAGS_vmlinux :=--no-undefined -X --pic-veneer ifeq ($(CONFIG_RELOCATABLE), y) # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour @@ -57,9 +57,11 @@ KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) ifneq ($(CONFIG_UNWIND_TABLES),y) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables KBUILD_AFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables +KBUILD_RUSTFLAGS += -Cforce-unwind-tables=n else KBUILD_CFLAGS += -fasynchronous-unwind-tables KBUILD_AFLAGS += -fasynchronous-unwind-tables +KBUILD_RUSTFLAGS += -Cforce-unwind-tables=y -Zuse-sync-unwind=n endif ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) @@ -114,6 +116,7 @@ endif ifeq ($(CONFIG_SHADOW_CALL_STACK), y) KBUILD_CFLAGS += -ffixed-x18 +KBUILD_RUSTFLAGS += -Zfixed-x18 endif ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile index 607a67a649c4..b5a08333bc57 100644 --- a/arch/arm64/boot/Makefile +++ b/arch/arm64/boot/Makefile @@ -17,7 +17,7 @@ OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S targets := Image Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo \ - Image.zst image.fit + Image.zst Image.xz image.fit $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) @@ -40,6 +40,9 @@ $(obj)/Image.lzo: $(obj)/Image FORCE $(obj)/Image.zst: $(obj)/Image FORCE $(call if_changed,zstd) +$(obj)/Image.xz: $(obj)/Image FORCE + $(call if_changed,xzkern) + $(obj)/image.fit: $(obj)/Image $(obj)/dts/dtbs-list FORCE $(call if_changed,fit) diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 0db7b60b49a1..00bed412ee31 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -49,5 +49,6 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero2w.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero3.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-transpeed-8k618-t.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-2024.dtb -dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-h.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-plus.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h700-anbernic-rg35xx-sp.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index e868ca5ae753..a5c3920e0f04 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -263,6 +263,14 @@ polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&ths 1>; + + trips { + gpu0_crit: gpu0-crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; }; gpu1_thermal: gpu1-thermal { @@ -270,6 +278,14 @@ polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&ths 2>; + + trips { + gpu1_crit: gpu1-crit { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts index b69032c44557..526443bb736c 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo-plus2.dts @@ -45,16 +45,40 @@ startup-delay-us = <100000>; enable-active-high; gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_vcc3v3>; + }; + + reg_gmac_2v5: gmac-2v5 { + /* 2V5 supply for GMAC PHY IO */ + compatible = "regulator-fixed"; + regulator-name = "gmac-2v5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + vin-supply = <®_vcc3v3>; + }; + + reg_vcc5v: regulator-vcc5v { + /* board 5V supply from micro USB or pin headers */ + compatible = "regulator-fixed"; + regulator-name = "vcc-5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; }; reg_vcc3v3: vcc3v3 { + /* board 3V3 supply by SY8089A */ compatible = "regulator-fixed"; regulator-name = "vcc3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <®_vcc5v>; }; vdd_cpux: gpio-regulator { + /* cpu voltage regulator MP2143DJ */ compatible = "regulator-gpio"; regulator-name = "vdd-cpux"; regulator-type = "voltage"; @@ -66,6 +90,7 @@ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; gpios-states = <0x1>; states = <1100000 0>, <1300000 1>; + vin-supply = <®_vcc5v>; }; wifi_pwrseq: pwrseq { @@ -146,6 +171,18 @@ status = "okay"; }; +&pio { + vcc-pa-supply = <®_vcc3v3>; + vcc-pc-supply = <®_vcc3v3>; + vcc-pd-supply = <®_gmac_2v5>; + vcc-pf-supply = <®_vcc3v3>; + vcc-pg-supply = <®_vcc3v3>; +}; + +&r_pio { + vcc-pl-supply = <®_vcc3v3>; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pa_pins>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi index b29ce7321317..e88c1fbac6ac 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi @@ -914,6 +914,8 @@ dmas = <&dma 48>, <&dma 48>; dma-names = "rx", "tx"; resets = <&r_ccu RST_R_APB2_I2C>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pins>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts index afb49e65859f..80ccab7b5ba7 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts @@ -21,6 +21,12 @@ serial0 = &uart0; }; + battery: battery { + compatible = "simple-battery"; + constant-charge-current-max-microamp = <1024000>; + voltage-max-design-microvolt = <4200000>; + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -201,12 +207,12 @@ vcc-pi-supply = <®_cldo3>; }; -&r_rsb { +&r_i2c { status = "okay"; - axp717: pmic@3a3 { + axp717: pmic@34 { compatible = "x-powers,axp717"; - reg = <0x3a3>; + reg = <0x34>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&nmi_intc>; @@ -217,6 +223,16 @@ vin3-supply = <®_vcc5v>; vin4-supply = <®_vcc5v>; + axp_adc: adc { + compatible = "x-powers,axp717-adc"; + #io-channel-cells = <1>; + }; + + battery_power: battery-power { + compatible = "x-powers,axp717-battery-power-supply"; + monitored-battery = <&battery>; + }; + regulators { reg_dcdc1: dcdc1 { regulator-always-on; @@ -307,6 +323,11 @@ /* unused */ }; }; + + usb_power: usb-power { + compatible = "x-powers,axp717-usb-power-supply"; + input-current-limit-microamp = <1500000>; + }; }; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-sp.dts b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-sp.dts new file mode 100644 index 000000000000..0cf16dc903cd --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-sp.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Copyright (C) 2024 Ryan Walklin <ryan@testtoast.com>. + * Copyright (C) 2024 Chris Morgan <macroalpha82@gmail.com>. + */ + +#include <dt-bindings/input/gpio-keys.h> +#include "sun50i-h700-anbernic-rg35xx-plus.dts" + +/ { + model = "Anbernic RG35XX SP"; + compatible = "anbernic,rg35xx-sp", "allwinner,sun50i-h700"; + + gpio-keys-lid { + compatible = "gpio-keys"; + + lid-switch { + label = "Lid Switch"; + gpios = <&pio 4 7 GPIO_ACTIVE_LOW>; /* PE7 */ + linux,can-disable; + linux,code = <SW_LID>; + linux,input-type = <EV_SW>; + wakeup-event-action = <EV_ACT_DEASSERTED>; + wakeup-source; + }; + }; +}; + +&r_i2c { + rtc_ext: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index 29417f04f886..2fbda8419c65 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -2,6 +2,7 @@ dtb-$(CONFIG_ARCH_MESON) += amlogic-a4-a113l2-ba400.dtb dtb-$(CONFIG_ARCH_MESON) += amlogic-a5-a113x2-av400.dtb dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c302x-aw409.dtb +dtb-$(CONFIG_ARCH_MESON) += amlogic-c3-c308l-aw419.dtb dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-an400.dtb dtb-$(CONFIG_ARCH_MESON) += amlogic-t7-a311d2-khadas-vim4.dtb dtb-$(CONFIG_ARCH_MESON) += meson-a1-ad401.dtb diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi index b6106ad4a072..54d7a2d56ef6 100644 --- a/arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/amlogic-a4-common.dtsi @@ -52,6 +52,12 @@ #size-cells = <2>; ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>; + watchdog@2100 { + compatible = "amlogic,a4-wdt", "amlogic,t7-wdt"; + reg = <0x0 0x2100 0x0 0x10>; + clocks = <&xtal>; + }; + uart_b: serial@7a000 { compatible = "amlogic,a4-uart", "amlogic,meson-s4-uart"; @@ -61,6 +67,14 @@ clock-names = "xtal", "pclk", "baud"; status = "disabled"; }; + + sec_ao: ao-secure@10220 { + compatible = "amlogic,a4-ao-secure", + "amlogic,meson-gx-ao-secure", + "syscon"; + reg = <0x0 0x10220 0x0 0x140>; + amlogic,has-chip-id; + }; }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi index 43f68a7da2f7..17a6316de891 100644 --- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi +++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi @@ -4,6 +4,7 @@ */ #include "amlogic-a4-common.dtsi" +#include <dt-bindings/power/amlogic,a5-pwrc.h> / { cpus { #address-cells = <2>; @@ -37,4 +38,13 @@ enable-method = "psci"; }; }; + + sm: secure-monitor { + compatible = "amlogic,meson-gxbb-sm"; + + pwrc: power-controller { + compatible = "amlogic,a5-pwrc"; + #power-domain-cells = <1>; + }; + }; }; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts b/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts index edce8850b338..a6736ad2a648 100644 --- a/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts +++ b/arch/arm64/boot/dts/amlogic/amlogic-c3-c302x-aw409.dts @@ -16,14 +16,245 @@ aliases { serial0 = &uart_b; + spi0 = &spifc; }; memory@0 { device_type = "memory"; reg = <0x0 0x0 0x0 0x10000000>; }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 9 MiB reserved for ARM Trusted Firmware */ + secmon_reserved: secmon@7f00000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x07f00000 0x0 0x900000>; + no-map; + }; + }; + + main_12v: regulator-main-12v { + compatible = "regulator-fixed"; + regulator-name = "12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_5v: regulator-vcc-5v { + compatible = "regulator-fixed"; + regulator-name = "VCC5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddq: regulator-vddq { + compatible = "regulator-fixed"; + regulator-name = "VDDQ"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddao_3v3: regulator-vddao-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddao_1v8: regulator-vddao-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + ddr4_2v5: regulator-ddr4-2v5 { + compatible = "regulator-fixed"; + regulator-name = "DDR4_2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_3v3: regulator-vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_1v8: regulator-vcc-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_1v8: regulator-vdd-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDD1V8_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vddio_b: regulator-vddio-3v3-b { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_B"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + sdcard: regulator-sdcard { + compatible = "regulator-fixed"; + regulator-name = "SDCARD_POWER"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vddao_3v3>; + gpio = <&gpio GPIOA_4 GPIO_ACTIVE_LOW>; + regulator-boot-on; + regulator-always-on; + }; }; &uart_b { status = "okay"; }; + +&nand { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + + nand@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + nand-on-flash-bbt; + + partition@0 { + label = "boot"; + reg = <0x0 0x00200000>; + }; + partition@200000 { + label = "env"; + reg = <0x00200000 0x00400000>; + }; + partition@600000 { + label = "system"; + reg = <0x00600000 0x00a00000>; + }; + partition@1000000 { + label = "rootfs"; + reg = <0x01000000 0x03000000>; + }; + partition@4000000 { + label = "media"; + reg = <0x04000000 0x8000000>; + }; + }; +}; + +ðmac { + status = "okay"; + phy-handle = <&internal_ephy>; + phy-mode = "rmii"; +}; + +&spifc { + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&spifc_pins>; + pinctrl-names = "default"; + + nand@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <83000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + status = "disabled"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "boot"; + reg = <0 0x200000>; + }; + + partition@200000 { + label = "env"; + reg = <0x200000 0x400000>; + }; + + partition@600000 { + label = "system"; + reg = <0x600000 0xa00000>; + }; + + partition@1000000 { + label = "rootfs"; + reg = <0x1000000 0x3000000>; + }; + + partition@4000000 { + label = "data"; + reg = <0x4000000 0x8000000>; + }; + }; + }; +}; + +&sd { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-1 = <&sdcard_clk_gate_pins>; + pinctrl-names = "default","clk-gate"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <50000000>; + disable-wp; + + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; + vmmc-supply = <&sdcard>; + vqmmc-supply = <&sdcard>; +}; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3-c308l-aw419.dts b/arch/arm64/boot/dts/amlogic/amlogic-c3-c308l-aw419.dts new file mode 100644 index 000000000000..45f8631f9feb --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/amlogic-c3-c308l-aw419.dts @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Amlogic, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "amlogic-c3.dtsi" + +/ { + model = "Amlogic C308l aw419 Development Board"; + compatible = "amlogic,aw419", "amlogic,c3"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_b; + spi0 = &spifc; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 9 MiB reserved for ARM Trusted Firmware */ + secmon_reserved: secmon@7f00000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x07f00000 0x0 0x900000>; + no-map; + }; + }; + + main_12v: regulator-main-12v { + compatible = "regulator-fixed"; + regulator-name = "12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_5v: regulator-vcc-5v { + compatible = "regulator-fixed"; + regulator-name = "VCC5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddq: regulator-vddq { + compatible = "regulator-fixed"; + regulator-name = "VDDQ"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddao_3v3: regulator-vddao-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&main_12v>; + regulator-boot-on; + regulator-always-on; + }; + + vddao_1v8: regulator-vddao-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + ddr4_2v5: regulator-ddr4-2v5 { + compatible = "regulator-fixed"; + regulator-name = "DDR4_2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_3v3: regulator-vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vddao_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_1v8: regulator-vcc-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_1v8: regulator-vdd-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDD1V8_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + vddio_b: regulator-vddio-3v3-b { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_B"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3>; + regulator-boot-on; + regulator-always-on; + }; + + sdcard: regulator-sdcard { + compatible = "regulator-fixed"; + regulator-name = "SDCARD_POWER"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vddao_3v3>; + gpio = <&gpio GPIOA_4 GPIO_ACTIVE_LOW>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&uart_b { + status = "okay"; +}; + +&nand { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + + nand@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + nand-on-flash-bbt; + + partition@0 { + label = "boot"; + reg = <0x0 0x00200000>; + }; + partition@200000 { + label = "env"; + reg = <0x00200000 0x00400000>; + }; + partition@600000 { + label = "system"; + reg = <0x00600000 0x00a00000>; + }; + partition@1000000 { + label = "rootfs"; + reg = <0x01000000 0x03000000>; + }; + partition@4000000 { + label = "media"; + reg = <0x04000000 0x8000000>; + }; + }; +}; + +ðmac { + status = "okay"; + phy-handle = <&internal_ephy>; + phy-mode = "rmii"; +}; + +&spifc { + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&spifc_pins>; + pinctrl-names = "default"; + + nand@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <83000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + status = "disabled"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "boot"; + reg = <0 0x200000>; + }; + + partition@200000 { + label = "env"; + reg = <0x200000 0x400000>; + }; + + partition@600000 { + label = "system"; + reg = <0x600000 0xa00000>; + }; + + partition@1000000 { + label = "rootfs"; + reg = <0x1000000 0x3000000>; + }; + + partition@4000000 { + label = "data"; + reg = <0x4000000 0x8000000>; + }; + }; + }; +}; + +&sd { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-1 = <&sdcard_clk_gate_pins>; + pinctrl-names = "default","clk-gate"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <50000000>; + disable-wp; + + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; + vmmc-supply = <&sdcard>; + vqmmc-supply = <&sdcard>; +}; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi index f8fb060c49ae..d0cda759c25d 100644 --- a/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi +++ b/arch/arm64/boot/dts/amlogic/amlogic-c3.dtsi @@ -7,6 +7,11 @@ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/reset/amlogic,c3-reset.h> +#include <dt-bindings/clock/amlogic,c3-pll-clkc.h> +#include <dt-bindings/clock/amlogic,c3-scmi-clkc.h> +#include <dt-bindings/clock/amlogic,c3-peripherals-clkc.h> +#include <dt-bindings/power/amlogic,c3-pwrc.h> +#include <dt-bindings/gpio/amlogic-c3-gpio.h> / { cpus { @@ -57,6 +62,34 @@ }; }; + sram@7f50e00 { + compatible = "mmio-sram"; + reg = <0x0 0x07f50e00 0x0 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x07f50e00 0x100>; + + scmi_shmem: sram@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x100>; + }; + }; + + firmware { + scmi: scmi { + compatible = "arm,scmi-smc"; + arm,smc-id = <0x820000C1>; + shmem = <&scmi_shmem>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; @@ -82,6 +115,44 @@ #size-cells = <2>; ranges = <0x0 0x0 0x0 0xfe000000 0x0 0x480000>; + clkc_periphs: clock-controller@0 { + compatible = "amlogic,c3-peripherals-clkc"; + reg = <0x0 0x0 0x0 0x49c>; + #clock-cells = <1>; + clocks = <&xtal>, + <&scmi_clk CLKID_OSC>, + <&scmi_clk CLKID_FIXED_PLL_OSC>, + <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_DIV2P5>, + <&clkc_pll CLKID_FCLK_DIV3>, + <&clkc_pll CLKID_FCLK_DIV4>, + <&clkc_pll CLKID_FCLK_DIV5>, + <&clkc_pll CLKID_FCLK_DIV7>, + <&clkc_pll CLKID_GP0_PLL>, + <&scmi_clk CLKID_GP1_PLL_OSC>, + <&clkc_pll CLKID_HIFI_PLL>, + <&scmi_clk CLKID_SYS_CLK>, + <&scmi_clk CLKID_AXI_CLK>, + <&scmi_clk CLKID_SYS_PLL_DIV16>, + <&scmi_clk CLKID_CPU_CLK_DIV16>; + clock-names = "xtal_24m", + "oscin", + "fix", + "fdiv2", + "fdiv2p5", + "fdiv3", + "fdiv4", + "fdiv5", + "fdiv7", + "gp0", + "gp1", + "hifi", + "sysclk", + "axiclk", + "sysplldiv16", + "cpudiv16"; + }; + reset: reset-controller@2000 { compatible = "amlogic,c3-reset"; reg = <0x0 0x2000 0x0 0x98>; @@ -98,16 +169,247 @@ compatible = "amlogic,c3-periphs-pinctrl"; #address-cells = <2>; #size-cells = <2>; - ranges; + ranges = <0x0 0x0 0x0 0x4000 0x0 0x02de>; - gpio: bank@4000 { - reg = <0x0 0x4000 0x0 0x004c>, - <0x0 0x4100 0x0 0x01de>; + gpio: bank@0 { + reg = <0x0 0x0 0x0 0x004c>, + <0x0 0x100 0x0 0x01de>; reg-names = "mux", "gpio"; gpio-controller; #gpio-cells = <2>; gpio-ranges = <&periphs_pinctrl 0 0 55>; }; + + i2c0_pins1: i2c0-pins1 { + mux { + groups = "i2c0_sda_e", + "i2c0_scl_e"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c0_pins2: i2c0-pins2 { + mux { + groups = "i2c0_sda_d", + "i2c0_scl_d"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_pins1: i2c1-pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_scl_x"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_pins2: i2c1-pins2 { + mux { + groups = "i2c1_sda_d", + "i2c1_scl_d"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_pins3: i2c1-pins3 { + mux { + groups = "i2c1_sda_a", + "i2c1_scl_a"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c1_pins4: i2c1-pins4 { + mux { + groups = "i2c1_sda_b", + "i2c1_scl_b"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c2_pins1: i2c2-pins1 { + mux { + groups = "i2c2_sda", + "i2c2_scl"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_pins1: i2c3-pins1 { + mux { + groups = "i2c3_sda_c", + "i2c3_scl_c"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_pins2: i2c3-pins2 { + mux { + groups = "i2c3_sda_x", + "i2c3_scl_x"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + i2c3_pins3: i2c3-pins3 { + mux { + groups = "i2c3_sda_d", + "i2c3_scl_d"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <3000>; + }; + }; + + nand_pins: nand-pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr"; + function = "nand"; + input-enable; + }; + }; + + sdcard_pins: sdcard-pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + }; + + sdcard_clk_gate_pins: sdcard-clk-cmd-pins { + mux { + groups = "GPIOC_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + sdio_m_clk_gate_pins: sdio-m-clk-cmd-pins { + mux { + groups = "sdio_clk"; + function = "sdio"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + sdio_m_pins: sdio-m-all-pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + }; + + spicc0_pins1: spicc0-pins1 { + mux { + groups = "spi_a_mosi_b", + "spi_a_miso_b", + "spi_a_clk_b"; + function = "spi_a"; + drive-strength-microamp = <3000>; + }; + }; + + spicc0_pins2: spicc0-pins2 { + mux { + groups = "spi_a_mosi_c", + "spi_a_miso_c", + "spi_a_clk_c"; + function = "spi_a"; + drive-strength-microamp = <3000>; + }; + }; + + spicc0_pins3: spicc0-pins3 { + mux { + groups = "spi_a_mosi_x", + "spi_a_miso_x", + "spi_a_clk_x"; + function = "spi_a"; + drive-strength-microamp = <3000>; + }; + }; + + spicc1_pins1: spicc1-pins1 { + mux { + groups = "spi_b_mosi_d", + "spi_b_miso_d", + "spi_b_clk_d"; + function = "spi_b"; + drive-strength-microamp = <3000>; + }; + }; + + spicc1_pins2: spicc1-pins2 { + mux { + groups = "spi_b_mosi_x", + "spi_b_miso_x", + "spi_b_clk_x"; + function = "spi_b"; + drive-strength-microamp = <3000>; + }; + }; + + spifc_pins: spifc-pins { + mux { + groups = "spif_mo", + "spif_mi", + "spif_clk", + "spif_cs", + "spif_hold", + "spif_wp", + "spif_clk_loop"; + function = "spif"; + drive-strength-microamp = <4000>; + }; + }; }; gpio_intc: interrupt-controller@4080 { @@ -119,16 +421,207 @@ <10 11 12 13 14 15 16 17 18 19 20 21>; }; + clkc_pll: clock-controller@8000 { + compatible = "amlogic,c3-pll-clkc"; + reg = <0x0 0x8000 0x0 0x1a4>; + #clock-cells = <1>; + clocks = <&scmi_clk CLKID_TOP_PLL_OSC>, + <&scmi_clk CLKID_MCLK_PLL_OSC>, + <&scmi_clk CLKID_FIXED_PLL_OSC>; + clock-names = "top", + "mclk", + "fix"; + }; + + eth_phy: mdio-multiplexer@28000 { + compatible = "amlogic,g12a-mdio-mux"; + reg = <0x0 0x28000 0x0 0xa4>; + + clocks = <&clkc_periphs CLKID_SYS_ETH_PHY>, + <&xtal>, + <&clkc_pll CLKID_FCLK_50M>; + clock-names = "pclk", "clkin0", "clkin1"; + mdio-parent-bus = <&mdio0>; + #address-cells = <1>; + #size-cells = <0>; + + ext_mdio: mdio@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + int_mdio: mdio@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + internal_ephy: ethernet_phy@8 { + compatible = "ethernet-phy-id0180.3301", + "ethernet-phy-ieee802.3-c22"; + interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + reg = <8>; + max-speed = <100>; + }; + }; + }; + + spicc0: spi@50000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x50000 0x0 0x44>; + interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc_periphs CLKID_SYS_SPICC_0>, + <&clkc_periphs CLKID_SPICC_A>; + clock-names = "core", "pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@52000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x52000 0x0 0x44>; + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc_periphs CLKID_SYS_SPICC_1>, + <&clkc_periphs CLKID_SPICC_B>; + clock-names = "core", "pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spifc: spi@56000 { + compatible = "amlogic,a1-spifc"; + reg = <0x0 0x56000 0x0 0x290>; + interrupts = <GIC_SPI 182 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_periphs CLKID_SPIFC>; + clock-names = "core"; + status = "disabled"; + }; + + i2c0: i2c@66000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x66000 0x0 0x24>; + interrupts = <GIC_SPI 160 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc_periphs CLKID_SYS_I2C_M_A>; + status = "disabled"; + }; + + i2c1: i2c@68000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x68000 0x0 0x24>; + interrupts = <GIC_SPI 161 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc_periphs CLKID_SYS_I2C_M_B>; + status = "disabled"; + }; + + i2c2: i2c@6a000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x6a000 0x0 0x24>; + interrupts = <GIC_SPI 162 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc_periphs CLKID_SYS_I2C_M_C>; + status = "disabled"; + }; + + i2c3: i2c@6c000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x6c000 0x0 0x24>; + interrupts = <GIC_SPI 163 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc_periphs CLKID_SYS_I2C_M_D>; + status = "disabled"; + }; + uart_b: serial@7a000 { compatible = "amlogic,meson-s4-uart", "amlogic,meson-ao-uart"; reg = <0x0 0x7a000 0x0 0x18>; interrupts = <GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; status = "disabled"; - clocks = <&xtal>, <&xtal>, <&xtal>; + clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_B>, <&xtal>; clock-names = "xtal", "pclk", "baud"; }; + sec_ao: ao-secure@10220 { + compatible = "amlogic,c3-ao-secure", + "amlogic,meson-gx-ao-secure", + "syscon"; + reg = <0x0 0x10220 0x0 0x140>; + amlogic,has-chip-id; + }; + + sdio: mmc@88000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x88000 0x0 0x800>; + interrupts = <GIC_SPI 176 IRQ_TYPE_EDGE_RISING>; + power-domains = <&pwrc PWRC_C3_SDIOA_ID>; + clocks = <&clkc_periphs CLKID_SYS_SD_EMMC_A>, + <&clkc_periphs CLKID_SD_EMMC_A>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core","clkin0", "clkin1"; + no-mmc; + no-sd; + resets = <&reset RESET_SD_EMMC_A>; + status = "disabled"; + }; + + sd: mmc@8a000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x8a000 0x0 0x800>; + interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>; + power-domains = <&pwrc PWRC_C3_SDCARD_ID>; + clocks = <&clkc_periphs CLKID_SYS_SD_EMMC_B>, + <&clkc_periphs CLKID_SD_EMMC_B>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + no-mmc; + no-sdio; + resets = <&reset RESET_SD_EMMC_B>; + status = "disabled"; + }; + + nand: nand-controller@8d000 { + compatible = "amlogic,meson-axg-nfc"; + reg = <0x0 0x8d000 0x0 0x200>, + <0x0 0x8C000 0x0 0x4>; + reg-names = "nfc", "emmc"; + interrupts = <GIC_SPI 87 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_periphs CLKID_SYS_SD_EMMC_C>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core", "device"; + status = "disabled"; + }; + }; + + ethmac: ethernet@fdc00000 { + compatible = "amlogic,meson-g12a-dwmac", + "snps,dwmac-3.70a", + "snps,dwmac"; + reg = <0x0 0xfdc00000 0x0 0x10000>, + <0x0 0xfe024000 0x0 0x8>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + power-domains = <&pwrc PWRC_C3_ETH_ID>; + clocks = <&clkc_periphs CLKID_SYS_ETH_MAC>, + <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_50M>; + clock-names = "stmmaceth", "clkin0", "clkin1"; + rx-fifo-depth = <4096>; + tx-fifo-depth = <2048>; + status = "disabled"; + + mdio0: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi index c23efc6c7ac0..ec743cad57db 100644 --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi @@ -194,6 +194,14 @@ interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; status = "disabled"; }; + + sec_ao: ao-secure@10220 { + compatible = "amlogic,t7-ao-secure", + "amlogic,meson-gx-ao-secure", + "syscon"; + reg = <0x0 0x10220 0x0 0x140>; + amlogic,has-chip-id; + }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts index 7ed526f45175..9611775b81ee 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts +++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts @@ -268,6 +268,10 @@ "Speaker1 Right", "SPK1 OUT_D", "Linein AINL", "Linein", "Linein AINR", "Linein"; + clocks = <&clkc CLKID_HIFI_PLL>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_HIFI_PLL>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts index af211d8f3952..a457b3f4397b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-fbx8am.dts @@ -176,6 +176,10 @@ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3", "SPDIFOUT_A IN 2", "FRDDR_C OUT 3"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts index 15b9bc280706..c779a5da7d1e 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts @@ -138,6 +138,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts index 61cb8135a392..ea51341f031b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts @@ -201,6 +201,10 @@ "TODDR_B IN 1", "TDMIN_B OUT", "TODDR_C IN 1", "TDMIN_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts index 0e239939ade6..f70a46967e2b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts @@ -238,6 +238,10 @@ "Lineout", "10U2 OUTL", "Lineout", "10U2 OUTR"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts index 05c7a1e3f1b7..32f98a192494 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts @@ -158,6 +158,10 @@ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3", "SPDIFOUT_A IN 2", "FRDDR_C OUT 3"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-cm4io.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-cm4io.dts index 13d478f9c891..2d74456e685d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-cm4io.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-cm4io.dts @@ -70,6 +70,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dts index 003efed529ba..0f48c32bec97 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dts @@ -79,6 +79,10 @@ "LINPUT1", "Mic Jack", "Mic Jack", "MICB"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi index 6a346cb86a53..d4e1990b5f26 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-bananapi.dtsi @@ -194,6 +194,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi index 3a24c2411552..de35fa2d7a6d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi @@ -38,6 +38,12 @@ "SPDIFOUT_A IN 0", "FRDDR_A OUT 3", "SPDIFOUT_A IN 1", "FRDDR_B OUT 3", "SPDIFOUT_A IN 2", "FRDDR_C OUT 3"; + + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-gsking-x.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-gsking-x.dts index bb73e10b5e74..369c5cf889b6 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-gsking-x.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-gsking-x.dts @@ -48,6 +48,10 @@ "TDMOUT_A IN 2", "FRDDR_C OUT 1", "TDM_A Playback", "TDMOUT_A OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts index 6eeedd54ab91..654449afd3a4 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts @@ -49,6 +49,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts index 0da386cabe1a..e20311386745 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts @@ -37,6 +37,10 @@ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3", "SPDIFOUT_A IN 2", "FRDDR_C OUT 3"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts index eed2a23047ca..e21831dfceee 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts @@ -234,6 +234,10 @@ "Internal Speakers", "Speaker Amplifier OUTL", "Internal Speakers", "Speaker Amplifier OUTR"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi index 86eb81112232..3bca8023638d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi @@ -95,6 +95,10 @@ "Lineout", "U19 OUTL", "Lineout", "U19 OUTR"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2l.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2l.dts index e26f3e3258e1..1b9097a30251 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2l.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2l.dts @@ -39,6 +39,10 @@ "TODDR_B IN 6", "TDMIN_LB OUT", "TODDR_C IN 6", "TDMIN_LB OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts index 8445701100d0..39feba7f2d08 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts @@ -176,6 +176,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts index 6396f190d703..4c1a75b926ee 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts +++ b/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6.dts @@ -32,6 +32,10 @@ "SPDIFOUT_A IN 1", "FRDDR_B OUT 3", "SPDIFOUT_A IN 2", "FRDDR_C OUT 3"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-libretech-pc.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-libretech-pc.dtsi index efd662a452e8..d38c3a224fbe 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx-libretech-pc.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx-libretech-pc.dtsi @@ -194,6 +194,10 @@ "AU2 INR", "ACODEC LORN", "7J4-14 LEFT", "AU2 OUTL", "7J4-11 RIGHT", "AU2 OUTR"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi index 08d6b69ba469..45ccddd1aaf0 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi @@ -129,6 +129,10 @@ "AU2 INR", "ACODEC LORN", "Lineout", "AU2 OUTL", "Lineout", "AU2 OUTR"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts index f28452b9f00f..073b47ce8c3c 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-kii-pro.dts @@ -45,6 +45,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "KII-PRO"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts index 1fd2e56e6b08..cf2e2ef81680 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts @@ -135,6 +135,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "NANOPI-K2"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts index cca129ce2c58..7d7dde93fff3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts @@ -142,6 +142,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "NEXBOX-A95X"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts index c37cc6b036cd..959bd8d77a82 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts @@ -177,6 +177,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "ODROID-C2"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts index 7f94716876d3..bfac00e76ba3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts @@ -68,6 +68,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "P200"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts index 6f81eed83bec..c10f66031ecd 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts @@ -17,6 +17,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "P201"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi index 255e93a0b36d..3807a184810b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi @@ -108,6 +108,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "VEGA-S95"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts index af9ea32a2876..ec281a9e9e77 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts @@ -16,6 +16,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "WETEK-HUB"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts index 376760d86766..924414861b72 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts @@ -48,6 +48,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "WETEK-PLAY2"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts index 90ef9c17d80b..c6132fb71dfc 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts @@ -123,6 +123,10 @@ "Speaker", "9J5-2 RIGHT"; audio-routing = "9J5-3 LEFT", "ACODEC LOLN", "9J5-2 RIGHT", "ACODEC LORN"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts index 08a4718219b1..c5e2306ad7a4 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts @@ -128,6 +128,10 @@ "AU2 INR", "ACODEC LORN", "Lineout", "AU2 OUTL", "Lineout", "AU2 OUTR"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts index fea65f20523a..a80f0ea2773b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts @@ -67,6 +67,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "KHADAS-VIM"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc-v2.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc-v2.dts index 63b20860067c..6cbdfde00e12 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc-v2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc-v2.dts @@ -160,6 +160,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "LIBRETECH-CC-V2"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts index 8b26c9661be1..401064b0428d 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts @@ -142,6 +142,10 @@ "AU2 INR", "ACODEC LORN", "Lineout", "AU2 OUTL", "Lineout", "AU2 OUTR"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts index 9b4ea6a49398..8b41e340f919 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts @@ -50,6 +50,10 @@ "AU2 INR", "ACODEC LORN", "Lineout", "AU2 OUTL", "Lineout", "AU2 OUTR"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts index de996e930b82..a9c5881c9783 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts @@ -90,6 +90,11 @@ "AU2 INR", "ACODEC LORN", "Lineout", "AU2 OUTL", "Lineout", "AU2 OUTR"; + + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts b/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts index 1221f4545130..942df754a0ed 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxlx-s905l-p271.dts @@ -38,10 +38,6 @@ }; }; -&saradc { - compatible = "amlogic,meson-gxlx-saradc", "amlogic,meson-saradc"; -}; - &usb { dr_mode = "host"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts index 07e7c3bedea0..96a3dd2d8a99 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts @@ -150,6 +150,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "KHADAS-VIM2"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts index ad2dd4ad0a31..773107cc47dd 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts @@ -86,6 +86,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "NEXBOX-A1"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts index d05dde8da5c5..7356d3b628b1 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts @@ -101,6 +101,10 @@ sound { compatible = "amlogic,gx-sound-card"; model = "RBOX-PRO"; + clocks = <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>; + assigned-clocks = <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>, <&clkc CLKID_MPLL2>; diff --git a/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi index e78cc9b577a0..7daa9b122d5c 100644 --- a/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi @@ -182,6 +182,10 @@ "TODDR_B IN 0", "TDMIN_A OUT", "TODDR_C IN 0", "TDMIN_A OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi b/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi index 082b72703cdf..929e4720ae76 100644 --- a/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-libretech-cottonwood.dtsi @@ -200,6 +200,10 @@ <&tdmin_a>, <&tdmin_b>, <&tdmin_c>, <&dioo2133>; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts index 983caddc409c..6730c44642d2 100644 --- a/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts +++ b/arch/arm64/boot/dts/amlogic/meson-s4-s805x2-aq222.dts @@ -34,6 +34,111 @@ no-map; }; }; + + sdio_32k: sdio-32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&sdio_32k>; + clock-names = "ext_clock"; + }; + + main_12v: regulator-main-12v { + compatible = "regulator-fixed"; + regulator-name = "12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + }; + + vddao_3v3: regulator-vddao-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&main_12v>; + regulator-always-on; + }; + + vddio_ao1v8: regulator-vddio-ao1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_AO1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vddao_3v3>; + regulator-always-on; + }; + + /* SY8120B1ABC DC/DC Regulator. */ + vddcpu: regulator-vddcpu { + compatible = "pwm-regulator"; + + regulator-name = "VDDCPU"; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; + + vin-supply = <&main_12v>; + + pwms = <&pwm_ij 1 1500 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + /* Voltage Duty-Cycle */ + voltage-table = <1049000 0>, + <1039000 3>, + <1029000 6>, + <1019000 9>, + <1009000 12>, + <999000 14>, + <989000 17>, + <979000 20>, + <969000 23>, + <959000 26>, + <949000 29>, + <939000 31>, + <929000 34>, + <919000 37>, + <909000 40>, + <899000 43>, + <889000 45>, + <879000 48>, + <869000 51>, + <859000 54>, + <849000 56>, + <839000 59>, + <829000 62>, + <819000 65>, + <809000 68>, + <799000 70>, + <789000 73>, + <779000 76>, + <769000 79>, + <759000 81>, + <749000 84>, + <739000 87>, + <729000 89>, + <719000 92>, + <709000 95>, + <699000 98>, + <689000 100>; + }; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins1>; + pinctrl-names = "default"; +}; + +&pwm_ij { + status = "okay"; }; &uart_b { @@ -46,6 +151,40 @@ pinctrl-names = "default"; }; +&sdio { + pinctrl-0 = <&sdio_pins>; + pinctrl-1 = <&sdio_clk_gate_pins>; + pinctrl-names = "default", "clk-gate"; + #address-cells = <1>; + #size-cells = <0>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr50; + sd-uhs-sdr104; + max-frequency = <200000000>; + non-removable; + disable-wp; + no-sd; + no-mmc; + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_ao1v8>; +}; + +&sd { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-1 = <&sdcard_clk_gate_pins>; + pinctrl-names = "default", "clk-gate"; + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <200000000>; + disable-wp; + + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddao_3v3>; +}; + &nand { status = "okay"; #address-cells = <1>; @@ -90,3 +229,9 @@ pinctrl-0 = <&spicc0_pins_x>; cs-gpios = <&gpio GPIOX_10 GPIO_ACTIVE_LOW>; }; + +ðmac { + status = "okay"; + phy-handle = <&internal_ephy>; + phy-mode = "rmii"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi index b686eacb9662..957577d986c0 100644 --- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi @@ -10,6 +10,7 @@ #include <dt-bindings/clock/amlogic,s4-pll-clkc.h> #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h> #include <dt-bindings/power/meson-s4-power.h> +#include <dt-bindings/reset/amlogic,meson-s4-reset.h> / { cpus { @@ -466,6 +467,93 @@ }; }; + sdcard_pins: sdcard-pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_clk_c", + "sdcard_cmd_c"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + }; + + sdcard_clk_gate_pins: sdcard-clk-gate-pins { + mux { + groups = "GPIOC_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + emmc_pins: emmc-pins { + mux-0 { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "emmc_cmd"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + mux-1 { + groups = "emmc_clk"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + }; + + emmc_ds_pins: emmc-ds-pins { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + emmc_clk_gate_pins: emmc-clk-gate-pins { + mux { + groups = "GPIOB_8"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + + sdio_pins: sdio-pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + bias-pull-up; + drive-strength-microamp = <4000>; + }; + }; + + sdio_clk_gate_pins: sdio-clk-gate-pins { + mux { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <4000>; + }; + }; + spicc0_pins_x: spicc0-pins_x { mux { groups = "spi_a_mosi_x", @@ -675,6 +763,14 @@ #reset-cells = <1>; }; + sec_ao: ao-secure@10220 { + compatible = "amlogic,s4-ao-secure", + "amlogic,meson-gx-ao-secure", + "syscon"; + reg = <0x0 0x10220 0x0 0x140>; + amlogic,has-chip-id; + }; + ir: ir@84040 { compatible = "amlogic,meson-s4-ir"; reg = <0x0 0x84040 0x0 0x30>; @@ -712,5 +808,45 @@ compatible = "snps,dwmac-mdio"; }; }; + + sdio: mmc@fe088000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xfe088000 0x0 0x800>; + interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc_periphs CLKID_SDEMMC_A>, + <&xtal>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_A>; + cap-sdio-irq; + keep-power-in-suspend; + status = "disabled"; + }; + + sd: mmc@fe08a000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xfe08a000 0x0 0x800>; + interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_periphs CLKID_SDEMMC_B>, + <&clkc_periphs CLKID_SD_EMMC_B>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; + status = "disabled"; + }; + + emmc: mmc@fe08c000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xfe08c000 0x0 0x800>; + interrupts = <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_periphs CLKID_NAND>, + <&xtal>, + <&clkc_pll CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_NAND_EMMC>; + no-sdio; + no-sd; + status = "disabled"; + }; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air-gbit.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air-gbit.dts index 9b2eb6e42651..3c43d3490e14 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air-gbit.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air-gbit.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air.dts index 6e34fd80ed71..445c1671ede7 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-a95xf3-air.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m2-pro.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m2-pro.dts index 586034316ec3..eeaff22edade 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m2-pro.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m2-pro.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts index f045bf851638..697855fec476 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts @@ -57,6 +57,10 @@ "Lineout", "ACODEC LOLP", "Lineout", "ACODEC LORP"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max.dts index e6e9410d40cb..7b3a014d4cde 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi index 951eb8e3f0c0..7b0e9817a615 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi @@ -174,6 +174,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts index 3581e14cbf18..2e3397e55da2 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts @@ -239,6 +239,10 @@ "TODDR_B IN 1", "TDMIN_B OUT", "TODDR_C IN 1", "TDMIN_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts index fc9b961133cd..e4a3a2a8ad06 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air.dts index 9ea969255b4f..fff92e0d6dd5 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air.dts @@ -22,6 +22,10 @@ "TDMOUT_B IN 2", "FRDDR_C OUT 1", "TDM_B Playback", "TDMOUT_B OUT"; + clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clocks = <&clkc CLKID_MPLL2>, <&clkc CLKID_MPLL0>, <&clkc CLKID_MPLL1>; diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index 532401bc9c66..6ad4703925dc 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -997,7 +997,7 @@ compatible = "apm,xgene-mdio"; #address-cells = <1>; #size-cells = <0>; - menetphy: menetphy@3 { + menetphy: ethernet-phy@3 { compatible = "ethernet-phy-id001c.c915"; reg = <0x3>; }; diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi index 93f1e7c026b8..083be35495b3 100644 --- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi +++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi @@ -18,7 +18,9 @@ #address-cells = <2>; #size-cells = <2>; - chosen { }; + chosen { + stdout-path = "serial0:115200n8"; + }; aliases { serial0 = &v2m_serial0; diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts index 85f1c15cc65d..19973ab4ea6b 100644 --- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts +++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts @@ -24,7 +24,9 @@ #address-cells = <2>; #size-cells = <2>; - chosen { }; + chosen { + stdout-path = "serial0:115200n8"; + }; aliases { serial0 = &v2m_serial0; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts index afdf954206f1..7f7226711d4b 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts @@ -23,7 +23,9 @@ #address-cells = <2>; #size-cells = <2>; - chosen { }; + chosen { + stdout-path = "serial0:115200n8"; + }; aliases { serial0 = &v2m_serial0; diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile index 8b4591ddd27c..92565e9781ad 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile @@ -6,6 +6,7 @@ DTC_FLAGS := -@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \ bcm2711-rpi-4-b.dtb \ bcm2711-rpi-cm4-io.dtb \ + bcm2712-rpi-5-b.dtb \ bcm2837-rpi-3-a-plus.dtb \ bcm2837-rpi-3-b.dtb \ bcm2837-rpi-3-b-plus.dtb \ diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts new file mode 100644 index 000000000000..2bdbb6780242 --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include "bcm2712.dtsi" + +/ { + compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; + model = "Raspberry Pi 5"; + + aliases { + serial10 = &uart10; + }; + + chosen: chosen { + stdout-path = "serial10:115200n8"; + }; + + /* Will be filled by the bootloader */ + memory@0 { + device_type = "memory"; + reg = <0 0 0 0x28000000>; + }; + + sd_io_1v8_reg: sd-io-1v8-reg { + compatible = "regulator-gpio"; + regulator-name = "vdd-sd-io"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + regulator-settling-time-us = <5000>; + gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; + states = <1800000 1>, + <3300000 0>; + }; + + sd_vcc_reg: sd-vcc-reg { + compatible = "regulator-fixed"; + regulator-name = "vcc-sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + enable-active-high; + gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; + }; +}; + +/* The Debug UART, on Rpi5 it's on JST-SH 1.0mm 3-pin connector + * labeled "UART", i.e. the interface with the system console. + */ +&uart10 { + status = "okay"; +}; + +/* SDIO1 is used to drive the SD card */ +&sdio1 { + vqmmc-supply = <&sd_io_1v8_reg>; + vmmc-supply = <&sd_vcc_reg>; + bus-width = <4>; + sd-uhs-sdr50; + sd-uhs-ddr50; + sd-uhs-sdr104; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi new file mode 100644 index 000000000000..6e5a984c1d4e --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "brcm,bcm2712"; + + #address-cells = <2>; + #size-cells = <2>; + + interrupt-parent = <&gicv2>; + + clocks { + /* The oscillator is the root of the clock tree. */ + clk_osc: clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "osc"; + clock-frequency = <54000000>; + }; + + clk_vpu: clk-vpu { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <750000000>; + clock-output-names = "vpu-clock"; + }; + + clk_uart: clk-uart { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <9216000>; + clock-output-names = "uart-clock"; + }; + + clk_emmc2: clk-emmc2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <200000000>; + clock-output-names = "emmc2-clock"; + }; + }; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + + /* Source for L1 d/i cache-line-size, cache-sets, cache-size + * https://developer.arm.com/documentation/100798/0401/L1-memory-system/About-the-L1-memory-system?lang=en + * Source for L2 cache-line-size and cache-sets: + * https://developer.arm.com/documentation/100798/0401/L2-memory-system/About-the-L2-memory-system?lang=en + * and for cache-size: + * https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712 + */ + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + reg = <0x000>; + enable-method = "psci"; + d-cache-size = <0x10000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + i-cache-size = <0x10000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + next-level-cache = <&l2_cache_l0>; + + l2_cache_l0: l2-cache-l0 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <128>; + cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + reg = <0x100>; + enable-method = "psci"; + d-cache-size = <0x10000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + i-cache-size = <0x10000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + next-level-cache = <&l2_cache_l1>; + + l2_cache_l1: l2-cache-l1 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <128>; + cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + reg = <0x200>; + enable-method = "psci"; + d-cache-size = <0x10000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + i-cache-size = <0x10000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + next-level-cache = <&l2_cache_l2>; + + l2_cache_l2: l2-cache-l2 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <128>; + cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + reg = <0x300>; + enable-method = "psci"; + d-cache-size = <0x10000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + i-cache-size = <0x10000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set + next-level-cache = <&l2_cache_l3>; + + l2_cache_l3: l2-cache-l3 { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <128>; + cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + }; + + /* Source for cache-line-size and cache-sets: + * https://developer.arm.com/documentation/100453/0401/L3-cache?lang=en + * Source for cache-size: + * https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712 + */ + l3_cache: l3-cache { + compatible = "cache"; + cache-size = <0x200000>; + cache-line-size = <64>; + cache-sets = <2048>; // 2MiB(size)/64(line-size)=32768ways/16-way set + cache-level = <3>; + cache-unified; + }; + }; + + psci { + method = "smc"; + compatible = "arm,psci-1.0", "arm,psci-0.2"; + }; + + rmem: reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + atf@0 { + reg = <0x0 0x0 0x0 0x80000>; + no-map; + }; + + cma: linux,cma { + compatible = "shared-dma-pool"; + size = <0x0 0x4000000>; /* 64MB */ + reusable; + linux,cma-default; + alloc-ranges = <0x0 0x00000000 0x0 0x40000000>; + }; + }; + + soc: soc@107c000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x10 0x00000000 0x80000000>; + #address-cells = <1>; + #size-cells = <1>; + + sdio1: mmc@fff000 { + compatible = "brcm,bcm2712-sdhci", + "brcm,sdhci-brcmstb"; + reg = <0x00fff000 0x260>, + <0x00fff400 0x200>; + reg-names = "host", "cfg"; + interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk_emmc2>; + clock-names = "sw_sdio"; + mmc-ddr-3_3v; + }; + + system_timer: timer@7c003000 { + compatible = "brcm,bcm2835-system-timer"; + reg = <0x7c003000 0x1000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <1000000>; + }; + + mailbox: mailbox@7c013880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7c013880 0x40>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <0>; + }; + + local_intc: interrupt-controller@7cd00000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x7cd00000 0x100>; + }; + + uart10: serial@7d001000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7d001000 0x200>; + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk_uart>, <&clk_vpu>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x00241011>; + status = "disabled"; + }; + + interrupt-controller@7d517000 { + compatible = "brcm,bcm7271-l2-intc"; + reg = <0x7d517000 0x10>; + interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + }; + + gio_aon: gpio@7d517c00 { + compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio"; + reg = <0x7d517c00 0x40>; + gpio-controller; + #gpio-cells = <2>; + brcm,gpio-bank-widths = <17 6>; + /* The lack of 'interrupt-controller' property here is intended: + * don't use GIO_AON as an interrupt controller because it will + * clash with the firmware monitoring the PMIC interrupt via the VPU. + */ + }; + + gicv2: interrupt-controller@7fff9000 { + compatible = "arm,gic-400"; + reg = <0x7fff9000 0x1000>, + <0x7fffa000 0x2000>, + <0x7fffc000 0x2000>, + <0x7fffe000 0x2000>; + interrupt-controller; + #interrupt-cells = <3>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 12 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>; + }; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts b/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts index 47a389d9ff7d..9d74fa6bfed9 100644 --- a/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts +++ b/arch/arm64/boot/dts/exynos/exynos7885-jackpotlte.dts @@ -32,7 +32,7 @@ device_type = "memory"; reg = <0x0 0x80000000 0x3da00000>, <0x0 0xc0000000 0x40000000>, - <0x8 0x80000000 0x40000000>; + <0x8 0x80000000 0x80000000>; }; gpio-keys { diff --git a/arch/arm64/boot/dts/exynos/exynosautov9.dtsi b/arch/arm64/boot/dts/exynos/exynosautov9.dtsi index 0248329da49a..b36292a7db64 100644 --- a/arch/arm64/boot/dts/exynos/exynosautov9.dtsi +++ b/arch/arm64/boot/dts/exynos/exynosautov9.dtsi @@ -251,6 +251,52 @@ "dout_fsys2_clkcmu_ethernet"; }; + cmu_dpum: clock-controller@18c00000 { + compatible = "samsung,exynosautov9-cmu-dpum"; + reg = <0x18c00000 0x8000>; + #clock-cells = <1>; + + clocks = <&xtcxo>, + <&cmu_top DOUT_CLKCMU_DPUM_BUS>; + clock-names = "oscclk", "bus"; + }; + + sysmmu_dpum_0: sysmmu@18c80000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x18c80000 0x10000>; + interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_dpum CLK_GOUT_DPUM_SYSMMU_D0_CLK>; + clock-names = "sysmmu"; + #iommu-cells = <0>; + }; + + sysmmu_dpum_1: sysmmu@18c90000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x18c90000 0x10000>; + interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_dpum CLK_GOUT_DPUM_SYSMMU_D1_CLK>; + clock-names = "sysmmu"; + #iommu-cells = <0>; + }; + + sysmmu_dpum_2: sysmmu@18ca0000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x18ca0000 0x10000>; + interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_dpum CLK_GOUT_DPUM_SYSMMU_D2_CLK>; + clock-names = "sysmmu"; + #iommu-cells = <0>; + }; + + sysmmu_dpum_3: sysmmu@18cb0000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x18cb0000 0x10000>; + interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_dpum CLK_GOUT_DPUM_SYSMMU_D3_CLK>; + clock-names = "sysmmu"; + #iommu-cells = <0>; + }; + cmu_core: clock-controller@1b030000 { compatible = "samsung,exynosautov9-cmu-core"; reg = <0x1b030000 0x8000>; diff --git a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi index c1c8566d74f5..91882b37fdb3 100644 --- a/arch/arm64/boot/dts/exynos/exynosautov920.dtsi +++ b/arch/arm64/boot/dts/exynos/exynosautov920.dtsi @@ -6,6 +6,7 @@ * */ +#include <dt-bindings/clock/samsung,exynosautov920.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/soc/samsung,exynos-usi.h> @@ -38,17 +39,6 @@ clock-output-names = "oscclk"; }; - /* - * FIXME: Keep the stub clock for serial driver, until proper clock - * driver is implemented. - */ - clock_usi: clock-usi { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <200000000>; - clock-output-names = "usi"; - }; - cpus: cpus { #address-cells = <2>; #size-cells = <0>; @@ -192,6 +182,19 @@ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; }; + cmu_peric0: clock-controller@10800000 { + compatible = "samsung,exynosautov920-cmu-peric0"; + reg = <0x10800000 0x8000>; + #clock-cells = <1>; + + clocks = <&xtcxo>, + <&cmu_top DOUT_CLKCMU_PERIC0_NOC>, + <&cmu_top DOUT_CLKCMU_PERIC0_IP>; + clock-names = "oscclk", + "noc", + "ip"; + }; + syscon_peric0: syscon@10820000 { compatible = "samsung,exynosautov920-peric0-sysreg", "syscon"; @@ -213,7 +216,8 @@ #address-cells = <1>; #size-cells = <1>; ranges; - clocks = <&clock_usi>, <&clock_usi>; + clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>, + <&cmu_peric0 CLK_DOUT_PERIC0_USI00_USI>; clock-names = "pclk", "ipclk"; status = "disabled"; @@ -224,7 +228,8 @@ interrupts = <GIC_SPI 764 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&uart0_bus>; - clocks = <&clock_usi>, <&clock_usi>; + clocks = <&cmu_peric0 CLK_MOUT_PERIC0_NOC_USER>, + <&cmu_peric0 CLK_DOUT_PERIC0_USI00_USI>; clock-names = "uart", "clk_uart_baud0"; samsung,uart-fifosize = <256>; status = "disabled"; @@ -254,6 +259,15 @@ interrupts = <GIC_SPI 781 IRQ_TYPE_LEVEL_HIGH>; }; + cmu_top: clock-controller@11000000 { + compatible = "samsung,exynosautov920-cmu-top"; + reg = <0x11000000 0x8000>; + #clock-cells = <1>; + + clocks = <&xtcxo>; + clock-names = "oscclk"; + }; + pinctrl_alive: pinctrl@11850000 { compatible = "samsung,exynosautov920-pinctrl"; reg = <0x11850000 0x10000>; diff --git a/arch/arm64/boot/dts/exynos/google/gs101.dtsi b/arch/arm64/boot/dts/exynos/google/gs101.dtsi index eadb8822e6d4..302c5beb224a 100644 --- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi +++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi @@ -1394,6 +1394,21 @@ pmu_system_controller: system-controller@17460000 { compatible = "google,gs101-pmu", "syscon"; reg = <0x17460000 0x10000>; + + poweroff: syscon-poweroff { + compatible = "syscon-poweroff"; + regmap = <&pmu_system_controller>; + offset = <0x3e9c>; /* PAD_CTRL_PWR_HOLD */ + mask = <0x100>; /* reset value */ + }; + + reboot: syscon-reboot { + compatible = "syscon-reboot"; + regmap = <&pmu_system_controller>; + offset = <0x3a00>; /* SYSTEM_CONFIGURATION */ + mask = <0x2>; /* SWRESET_SYSTEM */ + value = <0x2>; /* reset value */ + }; }; pinctrl_gpio_alive: pinctrl@174d0000 { diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index f04c22b7de72..9d3df8b218a2 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -129,11 +129,11 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw71xx-0x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw72xx-0x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw73xx-0x.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw75xx-0x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7901.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7902.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7903.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7904.dtb -dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw7905-0x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-dahlia.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-verdin-nonwifi-mallow.dtb @@ -174,16 +174,19 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-icore-mx8mp-edimm2.2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-msc-sm2s-ep1.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-navqp.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb +imx8mp-phyboard-pollux-rdk-no-eth-dtbs += imx8mp-phyboard-pollux-rdk.dtb imx8mp-phycore-no-eth.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk-no-eth.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-hdmi.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-lt6.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-skov-revb-mi1010ait-1cp1.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-var-som-symphony.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw71xx-2x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw72xx-2x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw73xx-2x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw74xx.dtb -dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw7905-2x.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-venice-gw75xx-2x.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dahlia.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-verdin-nonwifi-mallow.dtb @@ -238,6 +241,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-tqma8xqp-mba8xx.dtb dtb-$(CONFIG_ARCH_MXC) += imx8ulp-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93-kontron-bl-osm-s.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts index 2517528f684f..75081ce3e9a6 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts @@ -20,6 +20,12 @@ clock-frequency = <25000000>; }; + sc16is7xx_clk: clock-sc16is7xx { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + }; + reg_1p8v: regulator-1p8v { compatible = "regulator-fixed"; regulator-name = "1P8V"; @@ -69,12 +75,6 @@ clocks = <&sc16is7xx_clk>; interrupt-parent = <&gpio1>; interrupts = <13 IRQ_TYPE_EDGE_FALLING>; - - sc16is7xx_clk: clock-sc16is7xx { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <24000000>; - }; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi index e61ea7e0737e..dd479889658d 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi @@ -164,7 +164,6 @@ QORIQ_CLK_PLL_DIV(1)>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; - big-endian; bus-width = <4>; status = "disabled"; }; @@ -183,7 +182,6 @@ QORIQ_CLK_PLL_DIV(1)>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; - big-endian; broken-cd; bus-width = <4>; status = "disabled"; @@ -541,7 +539,6 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; - num-viewport = <2>; bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ @@ -556,7 +553,7 @@ status = "disabled"; }; - rcpm: power-controller@1ee2140 { + rcpm: wakeup-controller@1ee2140 { compatible = "fsl,ls1012a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1ee2140 0x0 0x4>; #fsl,rcpm-wakeup-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts index 195bdbafdf7c..d9fac647f432 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var3-ads2.dts @@ -26,6 +26,13 @@ cooling-levels = <1 128 192 255>; }; + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + sound { #address-cells = <1>; #size-cells = <0>; @@ -107,6 +114,11 @@ clock-names = "mclk"; assigned-clocks = <&mclk>; assigned-clock-rates = <1250000>; + AVDD-supply = <®_3p3v>; + CPVDD-supply = <®_3p3v>; + DBVDD-supply = <®_3p3v>; + DCVDD-supply = <®_3p3v>; + MICVDD-supply = <®_3p3v>; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index 6b6e3ee950e5..7d172d7e5737 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -112,13 +112,6 @@ }; }; - reboot { - compatible = "syscon-reboot"; - regmap = <&rst>; - offset = <0>; - mask = <0x02>; - }; - timer { compatible = "arm,armv8-timer"; interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | @@ -150,6 +143,7 @@ its: msi-controller@6020000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0x06020000 0 0x20000>;/* GIC Translater */ }; }; @@ -175,7 +169,7 @@ }; }; - core-cluster-thermal { + cluster-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 1>; @@ -235,10 +229,16 @@ }; }; - rst: syscon@1e60000 { - compatible = "syscon"; + syscon@1e60000 { + compatible = "fsl,ls1028a-reset", "syscon", "simple-mfd"; reg = <0x0 0x1e60000 0x0 0x10000>; little-endian; + + reboot { + compatible = "syscon-reboot"; + offset = <0>; + mask = <0x02>; + }; }; sfp: efuse@1e80000 { @@ -381,7 +381,6 @@ dmas = <&edma0 0 62>, <&edma0 0 60>; dma-names = "tx", "rx"; spi-num-chipselects = <4>; - little-endian; status = "disabled"; }; @@ -397,7 +396,6 @@ dmas = <&edma0 0 58>, <&edma0 0 56>; dma-names = "tx", "rx"; spi-num-chipselects = <4>; - little-endian; status = "disabled"; }; @@ -413,7 +411,6 @@ dmas = <&edma0 0 54>, <&edma0 0 2>; dma-names = "tx", "rx"; spi-num-chipselects = <3>; - little-endian; status = "disabled"; }; @@ -662,7 +659,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x80 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, @@ -701,7 +698,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x88 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, @@ -1080,7 +1077,7 @@ reg = <0x01 0xf0000000 0x0 0x100000>; #address-cells = <3>; #size-cells = <2>; - msi-parent = <&its>; + msi-parent = <&its 0>; device_type = "pci"; bus-range = <0x0 0x0>; dma-coherent; @@ -1319,7 +1316,7 @@ status = "disabled"; }; - rcpm: power-controller@1e34040 { + rcpm: wakeup-controller@1e34040 { compatible = "fsl,ls1028a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1e34040 0x0 0x1c>; #fsl,rcpm-wakeup-cells = <7>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi index 5c4d7eef8b61..ca7cd7a33c01 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi @@ -29,6 +29,7 @@ enet1: ethernet@e2000 { pcsphy-handle = <&pcsphy1>, <&qsgmiib_pcs1>; + pcs-handle = <&pcsphy1>, <&qsgmiib_pcs1>; pcs-handle-names = "sgmii", "qsgmii"; }; @@ -40,11 +41,13 @@ enet4: ethernet@e8000 { pcsphy-handle = <&pcsphy4>, <&qsgmiib_pcs2>; + pcs-handle = <&pcsphy4>, <&qsgmiib_pcs2>; pcs-handle-names = "sgmii", "qsgmii"; }; enet5: ethernet@ea000 { pcsphy-handle = <&pcsphy5>, <&qsgmiib_pcs3>; + pcs-handle = <&pcsphy5>, <&qsgmiib_pcs3>; pcs-handle-names = "sgmii", "qsgmii"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts index 11b1356e95d5..e850551b16ac 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts @@ -211,7 +211,7 @@ }; &fpga { - mdio-mux-emi1@54 { + mdio-mux@54 { compatible = "mdio-mux-mmioreg", "mdio-mux"; mdio-parent-bus = <&mdio0>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index 17f4e3171120..c0e3e8fa1e79 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -214,7 +214,7 @@ }; }; - core-cluster-thermal { + cluster-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 3>; @@ -431,7 +431,6 @@ clock-frequency = <0>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; - big-endian; bus-width = <4>; }; @@ -439,7 +438,6 @@ compatible = "fsl,qoriq-memory-controller"; reg = <0x0 0x1080000 0x0 0x1000>; interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; - big-endian; }; tmu: tmu@1f00000 { @@ -653,7 +651,7 @@ #interrupt-cells = <2>; }; - uqe: uqe@2400000 { + uqe: uqe-bus@2400000 { #address-cells = <1>; #size-cells = <1>; compatible = "fsl,qe", "simple-bus"; @@ -667,7 +665,6 @@ qeic: qeic@80 { compatible = "fsl,qe-ic"; reg = <0x80 0x80>; - #address-cells = <0>; interrupt-controller; #interrupt-cells = <1>; interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, @@ -675,16 +672,12 @@ }; si1: si@700 { - #address-cells = <1>; - #size-cells = <0>; compatible = "fsl,ls1043-qe-si", "fsl,t1040-qe-si"; reg = <0x700 0x80>; }; siram1: siram@1000 { - #address-cells = <1>; - #size-cells = <1>; compatible = "fsl,ls1043-qe-siram", "fsl,t1040-qe-siram"; reg = <0x1000 0x800>; @@ -804,7 +797,7 @@ QORIQ_CLK_PLL_DIV(1)>; }; - aux_bus: aux-bus { + aux_bus: bus { #address-cells = <2>; #size-cells = <2>; compatible = "simple-bus"; @@ -962,7 +955,7 @@ }; qdma: dma-controller@8380000 { - compatible = "fsl,ls1021a-qdma", "fsl,ls1043a-qdma"; + compatible = "fsl,ls1043a-qdma", "fsl,ls1021a-qdma"; reg = <0x0 0x8380000 0x0 0x1000>, /* Controller regs */ <0x0 0x8390000 0x0 0x10000>, /* Status regs */ <0x0 0x83a0000 0x0 0x40000>; /* Block regs */ @@ -983,7 +976,7 @@ big-endian; }; - rcpm: power-controller@1ee2140 { + rcpm: wakeup-controller@1ee2140 { compatible = "fsl,ls1043a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1ee2140 0x0 0x4>; #fsl,rcpm-wakeup-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi index 4e3345093943..15ff7c569d28 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi @@ -24,6 +24,7 @@ /* these aliases provide the FMan ports mapping */ enet0: ethernet@e0000 { pcsphy-handle = <&qsgmiib_pcs3>; + pcs-handle = <&qsgmiib_pcs3>; pcs-handle-names = "qsgmii"; }; @@ -38,11 +39,13 @@ enet4: ethernet@e8000 { pcsphy-handle = <&pcsphy4>, <&qsgmiib_pcs1>; + pcs-handle = <&pcsphy4>, <&qsgmiib_pcs1>; pcs-handle-names = "sgmii", "qsgmii"; }; enet5: ethernet@ea000 { pcsphy-handle = <&pcsphy5>, <&pcsphy5>; + pcs-handle = <&pcsphy5>, <&pcsphy5>; pcs-handle-names = "sgmii", "qsgmii"; }; @@ -51,6 +54,7 @@ enet7: ethernet@f2000 { pcsphy-handle = <&pcsphy7>, <&qsgmiib_pcs2>, <&pcsphy7>; + pcs-handle = <&pcsphy7>, <&qsgmiib_pcs2>, <&pcsphy7>; pcs-handle-names = "sgmii", "qsgmii", "xfi"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts index e5296e51f656..a1d9102ff32b 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts @@ -237,7 +237,7 @@ #address-cells = <1>; #size-cells = <1>; - mdio-mux-emi1 { + mdio-mux@54 { compatible = "mdio-mux-mmioreg", "mdio-mux"; mdio-parent-bus = <&mdio0>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi index 200e52622f99..0baf256b4400 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi @@ -182,7 +182,7 @@ }; }; - core-cluster-thermal { + cluster-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 3>; @@ -282,7 +282,6 @@ compatible = "fsl,qoriq-memory-controller"; reg = <0x0 0x1080000 0x0 0x1000>; interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; - big-endian; }; ifc: memory-controller@1530000 { @@ -315,7 +314,6 @@ clocks = <&clockgen QORIQ_CLK_HWACCEL 1>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; - big-endian; bus-width = <4>; }; @@ -694,7 +692,6 @@ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(2)>; - big-endian; }; edma0: dma-controller@2c00000 { @@ -715,7 +712,7 @@ QORIQ_CLK_PLL_DIV(2)>; }; - aux_bus: aux-bus { + aux_bus: bus { #address-cells = <2>; #size-cells = <2>; compatible = "simple-bus"; @@ -823,7 +820,7 @@ }; pcie_ep1: pcie_ep@3400000 { - compatible = "fsl,ls1046a-pcie-ep","fsl,ls-pcie-ep"; + compatible = "fsl,ls1046a-pcie-ep"; reg = <0x00 0x03400000 0x0 0x00100000>, <0x40 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -862,7 +859,7 @@ }; pcie_ep2: pcie_ep@3500000 { - compatible = "fsl,ls1046a-pcie-ep","fsl,ls-pcie-ep"; + compatible = "fsl,ls1046a-pcie-ep"; reg = <0x00 0x03500000 0x0 0x00100000>, <0x48 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -901,7 +898,7 @@ }; pcie_ep3: pcie_ep@3600000 { - compatible = "fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"; + compatible = "fsl,ls1046a-pcie-ep"; reg = <0x00 0x03600000 0x0 0x00100000>, <0x50 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -935,7 +932,7 @@ big-endian; }; - rcpm: power-controller@1ee2140 { + rcpm: wakeup-controller@1ee2140 { compatible = "fsl,ls1046a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1ee2140 0x0 0x4>; #fsl,rcpm-wakeup-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts index ee8e932628d1..2df16bfb901c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts @@ -170,6 +170,13 @@ /* IRQ_RTC_B -> IRQ0_B(CPLD) -> IRQ00(CPU), active low */ interrupts-extended = <&extirq 0 IRQ_TYPE_LEVEL_LOW>; }; + + rtc@53 { + compatible = "nxp,pcf2131"; + reg = <0x53>; + /* IRQ_RTC_B -> IRQ0_B(CPLD) -> IRQ00(CPU), active low */ + interrupts-extended = <&extirq 0 IRQ_TYPE_LEVEL_LOW>; + }; }; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts index d4867d6cf47c..bc0d89427fbe 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts @@ -220,7 +220,7 @@ #gpio-cells = <2>; gpio-controller; - admin_led_lower { + admin-led-lower-hog { gpio-hog; gpios = <13 GPIO_ACTIVE_HIGH>; output-low; @@ -323,9 +323,9 @@ reg = <0x580000 0x40000>; }; - partition@5C0000 { + partition@5c0000 { label = "dpc"; - reg = <0x5C0000 0x40000>; + reg = <0x5c0000 0x40000>; }; partition@600000 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi index 8ce4b6aae79d..9d5726378aa0 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi @@ -126,12 +126,13 @@ its: msi-controller@6020000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0x6020000 0 0x20000>; }; }; thermal-zones { - core-cluster-thermal { + cluster-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 0>; @@ -575,7 +576,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x20 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x20 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 109 IRQ_TYPE_LEVEL_HIGH>, @@ -587,7 +588,7 @@ }; pcie_ep1: pcie-ep@3400000 { - compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"; + compatible = "fsl,ls1088a-pcie-ep"; reg = <0x00 0x03400000 0x0 0x00100000>, <0x20 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -614,7 +615,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x28 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x28 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 114 IRQ_TYPE_LEVEL_HIGH>, @@ -626,7 +627,7 @@ }; pcie_ep2: pcie-ep@3500000 { - compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"; + compatible = "fsl,ls1088a-pcie-ep"; reg = <0x00 0x03500000 0x0 0x00100000>, <0x28 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -652,7 +653,7 @@ bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x30 0x00010000 0x0 0x00010000 /* downstream I/O */ 0x82000000 0x0 0x40000000 0x30 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 119 IRQ_TYPE_LEVEL_HIGH>, @@ -664,7 +665,7 @@ }; pcie_ep3: pcie-ep@3600000 { - compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"; + compatible = "fsl,ls1088a-pcie-ep"; reg = <0x00 0x03600000 0x0 0x00100000>, <0x30 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; @@ -964,7 +965,7 @@ compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ - msi-parent = <&its>; + msi-parent = <&its 0>; iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ dma-coherent; #address-cells = <3>; @@ -1033,7 +1034,7 @@ }; }; - rcpm: power-controller@1e34040 { + rcpm: wakeup-controller@1e34040 { compatible = "fsl,ls1088a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1e34040 0x0 0x18>; #fsl,rcpm-wakeup-cells = <6>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi index 9178cd61c786..556d8c5f3180 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi @@ -64,7 +64,7 @@ reg = <3 0 0x1000>; ranges = <0 3 0 0x1000>; - mdio-mux-emi1@54 { + mdio-mux@54 { compatible = "mdio-mux-mmioreg", "mdio-mux"; mdio-parent-bus = <&emdio1>; reg = <0x54 1>; /* BRDCFG4 */ diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi index bde89de2576e..9421fdd7e30e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi @@ -63,20 +63,20 @@ its: msi-controller@6020000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0x6020000 0 0x20000>; }; }; rstcr: syscon@1e60000 { - compatible = "fsl,ls2080a-rstcr", "syscon"; + compatible = "fsl,ls1028a-reset", "syscon", "simple-mfd"; reg = <0x0 0x1e60000 0x0 0x4>; - }; - reboot { - compatible = "syscon-reboot"; - regmap = <&rstcr>; - offset = <0x0>; - mask = <0x2>; + reboot { + compatible = "syscon-reboot"; + offset = <0x0>; + mask = <0x2>; + }; }; thermal-zones { @@ -122,7 +122,7 @@ }; }; - core-cluster1-thermal { + cluster1-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 4>; @@ -151,7 +151,7 @@ }; }; - core-cluster2-thermal { + cluster2-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 5>; @@ -180,7 +180,7 @@ }; }; - core-cluster3-thermal { + cluster3-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 6>; @@ -209,7 +209,7 @@ }; }; - core-cluster4-thermal { + cluster4-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 7>; @@ -758,7 +758,7 @@ compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ - msi-parent = <&its>; + msi-parent = <&its 0>; iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ dma-coherent; #address-cells = <3>; @@ -1075,7 +1075,7 @@ }; pcie1: pcie@3400000 { - compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie"; + compatible = "fsl,ls2080a-pcie"; reg-names = "regs", "config"; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "intr"; @@ -1085,7 +1085,7 @@ dma-coherent; num-viewport = <6>; bus-range = <0x0 0xff>; - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>, @@ -1097,7 +1097,7 @@ }; pcie2: pcie@3500000 { - compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie"; + compatible = "fsl,ls2080a-pcie"; reg-names = "regs", "config"; interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "intr"; @@ -1107,7 +1107,7 @@ dma-coherent; num-viewport = <6>; bus-range = <0x0 0xff>; - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>, @@ -1119,7 +1119,7 @@ }; pcie3: pcie@3600000 { - compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie"; + compatible = "fsl,ls2080a-pcie"; reg-names = "regs", "config"; interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "intr"; @@ -1129,7 +1129,7 @@ dma-coherent; num-viewport = <256>; bus-range = <0x0 0xff>; - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>, @@ -1141,7 +1141,7 @@ }; pcie4: pcie@3700000 { - compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie"; + compatible = "fsl,ls2080a-pcie"; reg-names = "regs", "config"; interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "intr"; @@ -1151,7 +1151,7 @@ dma-coherent; num-viewport = <6>; bus-range = <0x0 0xff>; - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>, @@ -1218,7 +1218,7 @@ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; }; - rcpm: power-controller@1e34040 { + rcpm: wakeup-controller@1e34040 { compatible = "fsl,ls208xa-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1e34040 0x0 0x18>; #fsl,rcpm-wakeup-cells = <6>; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-tqmlx2160a-mblx2160a.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-tqmlx2160a-mblx2160a.dts index da0f58e26b9a..f6a4f8d54301 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-tqmlx2160a-mblx2160a.dts +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-tqmlx2160a-mblx2160a.dts @@ -320,7 +320,7 @@ reg = <1>; peer-hub = <&hub_3_0>; reset-gpios = <&gpioex1 0 GPIO_ACTIVE_LOW>; - vcc-supply = <®_vcc3v3>; + vdd-supply = <®_vcc3v3>; }; hub_3_0: hub@2 { @@ -328,7 +328,7 @@ reg = <2>; peer-hub = <&hub_2_0>; reset-gpios = <&gpioex1 0 GPIO_ACTIVE_LOW>; - vcc-supply = <®_vcc3v3>; + vdd-supply = <®_vcc3v3>; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index 26c7ca31e22e..927ecf66a740 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -398,6 +398,7 @@ its: msi-controller@6020000 { compatible = "arm,gic-v3-its"; msi-controller; + #msi-cells = <1>; reg = <0x0 0x6020000 0 0x20000>; }; }; @@ -492,7 +493,7 @@ }; }; - ddr-cluster5-thermal { + ddr-ctrl5-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 1>; @@ -1078,7 +1079,7 @@ timeout-sec = <30>; }; - rcpm: power-controller@1e34040 { + rcpm: wakeup-controller@1e34040 { compatible = "fsl,lx2160a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1e34040 0x0 0x1c>; #fsl,rcpm-wakeup-cells = <7>; @@ -1181,7 +1182,7 @@ ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, @@ -1209,7 +1210,7 @@ ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, @@ -1237,7 +1238,7 @@ ppio-wins = <24>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, @@ -1265,7 +1266,7 @@ ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, @@ -1293,7 +1294,7 @@ ppio-wins = <24>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, @@ -1321,7 +1322,7 @@ ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ - msi-parent = <&its>; + msi-parent = <&its 0>; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, @@ -1777,7 +1778,7 @@ compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, <0x00000000 0x08340000 0 0x40000>; - msi-parent = <&its>; + msi-parent = <&its 0>; /* iommu-map property is fixed up by u-boot */ iommu-map = <0 &smmu 0 0>; dma-coherent; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index f7a91d43a0ff..575be8115e42 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -34,6 +34,8 @@ dma_subsys: bus@5a000000 { assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; power-domains = <&pd IMX_SC_R_SPI_0>; + dmas = <&edma2 1 0 0>, <&edma2 0 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -50,6 +52,8 @@ dma_subsys: bus@5a000000 { assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; power-domains = <&pd IMX_SC_R_SPI_1>; + dmas = <&edma2 3 0 0>, <&edma2 2 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -66,6 +70,8 @@ dma_subsys: bus@5a000000 { assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; power-domains = <&pd IMX_SC_R_SPI_2>; + dmas = <&edma2 5 0 0>, <&edma2 4 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -82,6 +88,8 @@ dma_subsys: bus@5a000000 { assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; power-domains = <&pd IMX_SC_R_SPI_3>; + dmas = <&edma2 7 0 0>, <&edma2 6 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -303,6 +311,8 @@ dma_subsys: bus@5a000000 { i2c0: i2c@5a800000 { reg = <0x5a800000 0x4000>; + #address-cells = <1>; + #size-cells = <0>; interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>; clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>, <&i2c0_lpcg IMX_LPCG_CLK_4>; @@ -315,6 +325,8 @@ dma_subsys: bus@5a000000 { i2c1: i2c@5a810000 { reg = <0x5a810000 0x4000>; + #address-cells = <1>; + #size-cells = <0>; interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>, <&i2c1_lpcg IMX_LPCG_CLK_4>; @@ -327,6 +339,8 @@ dma_subsys: bus@5a000000 { i2c2: i2c@5a820000 { reg = <0x5a820000 0x4000>; + #address-cells = <1>; + #size-cells = <0>; interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>, <&i2c2_lpcg IMX_LPCG_CLK_4>; @@ -339,6 +353,8 @@ dma_subsys: bus@5a000000 { i2c3: i2c@5a830000 { reg = <0x5a830000 0x4000>; + #address-cells = <1>; + #size-cells = <0>; interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>; clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>, <&i2c3_lpcg IMX_LPCG_CLK_4>; @@ -362,7 +378,7 @@ dma_subsys: bus@5a000000 { assigned-clock-rates = <24000000>; power-domains = <&pd IMX_SC_R_ADC_0>; status = "disabled"; - }; + }; adc1: adc@5a890000 { compatible = "nxp,imx8qxp-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi index 77d2928997b4..d39242c1b9f7 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-img.dtsi @@ -26,7 +26,6 @@ img_subsys: bus@58000000 { assigned-clock-rates = <200000000>, <200000000>; power-domains = <&pd IMX_SC_R_MJPEG_DEC_MP>, <&pd IMX_SC_R_MJPEG_DEC_S0>; - slot = <0>; }; jpegenc: jpegenc@58450000 { @@ -39,7 +38,6 @@ img_subsys: bus@58000000 { assigned-clock-rates = <200000000>, <200000000>; power-domains = <&pd IMX_SC_R_MJPEG_ENC_MP>, <&pd IMX_SC_R_MJPEG_ENC_S0>; - slot = <0>; }; img_jpeg_dec_lpcg: clock-controller@585d0000 { diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi new file mode 100644 index 000000000000..dad0dc8fb431 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8-ss-lvds0.dtsi @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only and MIT + +/* + * Copyright 2024 NXP + */ + +lvds0_subsys: bus@56240000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x56240000 0x0 0x56240000 0x10000>; + + qm_lvds0_lis_lpcg: qxp_mipi1_lis_lpcg: clock-controller@56243000 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56243000 0x4>; + #clock-cells = <1>; + clock-output-names = "lvds0_lis_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1>; + }; + + qm_lvds0_pwm_lpcg: qxp_mipi1_pwm_lpcg: clock-controller@5624300c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5624300c 0x4>; + #clock-cells = <1>; + clock-output-names = "lvds0_pwm_lpcg_clk", + "lvds0_pwm_lpcg_ipg_clk", + "lvds0_pwm_lpcg_32k_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>; + }; + + qm_lvds0_i2c0_lpcg: qxp_mipi1_i2c0_lpcg: clock-controller@56243010 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56243010 0x4>; + #clock-cells = <1>; + clock-output-names = "lvds0_i2c0_lpcg_clk", + "lvds0_i2c0_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + }; + + qm_pwm_lvds0: qxp_pwm_mipi_lvds1: pwm@56244000 { + compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; + reg = <0x56244000 0x1000>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX_SC_R_MIPI_1_PWM_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + #pwm-cells = <3>; + power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>; + status = "disabled"; + }; + + qm_i2c0_lvds0: qxp_i2c0_mipi_lvds1: i2c@56246000 { + compatible = "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x56246000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8>; + clock-names = "per", "ipg"; + assigned-clocks = <&clk IMX_SC_R_MIPI_1_I2C_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lvds1.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lvds1.dtsi new file mode 100644 index 000000000000..12ae4f48e1e1 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8-ss-lvds1.dtsi @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0-only and MIT + +/* + * Copyright 2024 NXP + */ + +lvds1_subsys: bus@57240000 { + compatible = "simple-bus"; + interrupt-parent = <&irqsteer_lvds1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x57240000 0x0 0x57240000 0x10000>; + + irqsteer_lvds1: interrupt-controller@57240000 { + compatible = "fsl,imx8qm-irqsteer", "fsl,imx-irqsteer"; + reg = <0x57240000 0x1000>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <1>; + clocks = <&lvds1_lis_lpcg IMX_LPCG_CLK_4>; + clock-names = "ipg"; + power-domains = <&pd IMX_SC_R_LVDS_1>; + fsl,channel = <0>; + fsl,num-irqs = <32>; + }; + + lvds1_lis_lpcg: clock-controller@57243000 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57243000 0x4>; + #clock-cells = <1>; + clocks = <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_4>; + clock-output-names = "lvds1_lis_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_LVDS_1>; + }; + + lvds1_pwm_lpcg: clock-controller@5724300c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5724300c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_LVDS_1_PWM_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "lvds1_pwm_lpcg_clk", + "lvds1_pwm_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_LVDS_1_PWM_0>; + }; + + lvds1_i2c0_lpcg: clock-controller@57243010 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57243010 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_LVDS_1_I2C_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "lvds1_i2c0_lpcg_clk", + "lvds1_i2c0_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_LVDS_1_I2C_0>; + }; + + lvds1_i2c1_lpcg: clock-controller@57243014 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57243014 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_LVDS_1_I2C_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "lvds1_i2c1_lpcg_clk", + "lvds1_i2c1_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_LVDS_1_I2C_0>; + }; + + pwm_lvds1: pwm@57244000 { + compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; + reg = <0x57244000 0x1000>; + clocks = <&lvds1_pwm_lpcg IMX_LPCG_CLK_4>, + <&lvds1_pwm_lpcg IMX_LPCG_CLK_0>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX_SC_R_LVDS_1_PWM_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + #pwm-cells = <3>; + power-domains = <&pd IMX_SC_R_LVDS_1_PWM_0>; + status = "disabled"; + }; + + i2c0_lvds1: i2c@57246000 { + compatible = "fsl,imx8qm-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x57246000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8>; + clocks = <&lvds1_i2c0_lpcg IMX_LPCG_CLK_0>, + <&lvds1_i2c0_lpcg IMX_LPCG_CLK_4>; + clock-names = "per", "ipg"; + assigned-clocks = <&clk IMX_SC_R_LVDS_1_I2C_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_LVDS_1_I2C_0>; + status = "disabled"; + }; + + i2c1_lvds1: i2c@57247000 { + compatible = "fsl,imx8qm-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x57247000 0x1000>; + interrupts = <9>; + clocks = <&lvds1_i2c1_lpcg IMX_LPCG_CLK_0>, + <&lvds1_i2c1_lpcg IMX_LPCG_CLK_4>; + clock-names = "per", "ipg"; + assigned-clocks = <&clk IMX_SC_R_LVDS_1_I2C_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_LVDS_1_I2C_0>; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-mipi0.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-mipi0.dtsi new file mode 100644 index 000000000000..9c5b0cbdfcbd --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8-ss-mipi0.dtsi @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only and MIT + +/* + * Copyright 2024 NXP + */ + +mipi0_subsys: bus@56220000 { + compatible = "simple-bus"; + interrupt-parent = <&irqsteer_mipi0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x56220000 0x0 0x56220000 0x10000>; + + irqsteer_mipi0: interrupt-controller@56220000 { + compatible = "fsl,imx8qxp-irqsteer", "fsl,imx-irqsteer"; + reg = <0x56220000 0x1000>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <1>; + clocks = <&mipi0_lis_lpcg IMX_LPCG_CLK_0>; + clock-names = "ipg"; + power-domains = <&pd IMX_SC_R_MIPI_0>; + fsl,channel = <0>; + fsl,num-irqs = <32>; + }; + + mipi0_lis_lpcg: clock-controller@56223000 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56223000 0x4>; + #clock-cells = <1>; + power-domains = <&pd IMX_SC_R_MIPI_0>; + }; + + mipi0_pwm_lpcg: clock-controller@5622300c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5622300c 0x4>; + #clock-cells = <1>; + power-domains = <&pd IMX_SC_R_MIPI_0_PWM_0>; + }; + + mipi0_i2c0_lpcg_ipg_clk: clock-controller@56223014 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56223014 0x4>; + #clock-cells = <1>; + clocks = <&mipi0_i2c0_lpcg_ipg_s_clk IMX_LPCG_CLK_0>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c0_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_0>; + }; + + mipi0_i2c0_lpcg_ipg_s_clk: clock-controller@56223018 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56223018 0x4>; + #clock-cells = <1>; + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c0_lpcg_ipg_s_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_0>; + }; + + mipi0_i2c0_lpcg_clk: clock-controller@5622301c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5622301c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_MIPI_0_I2C_0 IMX_SC_PM_CLK_MISC2>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c0_lpcg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_0>; + }; + + mipi0_i2c1_lpcg_ipg_clk: clock-controller@56223024 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56223024 0x4>; + #clock-cells = <1>; + clocks = <&mipi0_i2c1_lpcg_ipg_s_clk IMX_LPCG_CLK_0>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c1_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_1>; + }; + + mipi0_i2c1_lpcg_ipg_s_clk: clock-controller@56223028 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56223028 0x4>; + #clock-cells = <1>; + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c1_lpcg_ipg_s_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_1>; + }; + + mipi0_i2c1_lpcg_clk: clock-controller@5622302c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5622302c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_MIPI_0_I2C_1 IMX_SC_PM_CLK_MISC2>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_i2c1_lpcg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_1>; + }; + + pwm_mipi0: pwm@56224000 { + compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; + reg = <0x56224000 0x1000>; + clocks = <&mipi0_pwm_lpcg IMX_LPCG_CLK_4>, + <&mipi0_pwm_lpcg IMX_LPCG_CLK_0>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX_SC_R_MIPI_0_PWM_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + #pwm-cells = <3>; + power-domains = <&pd IMX_SC_R_MIPI_0_PWM_0>; + status = "disabled"; + }; + + i2c0_mipi0: i2c@56226000 { + compatible = "fsl,imx8qm-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x56226000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8>; + clocks = <&mipi0_i2c0_lpcg_clk IMX_LPCG_CLK_0>, + <&mipi0_i2c0_lpcg_ipg_clk IMX_LPCG_CLK_0>; + clock-names = "per", "ipg"; + assigned-clocks = <&mipi0_i2c0_lpcg_clk IMX_LPCG_CLK_0>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_MIPI_0_I2C_0>; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-mipi1.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-mipi1.dtsi new file mode 100644 index 000000000000..5b1f08e412b2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8-ss-mipi1.dtsi @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0-only and MIT + +/* + * Copyright 2024 NXP + */ + +mipi1_subsys: bus@57220000 { + compatible = "simple-bus"; + interrupt-parent = <&irqsteer_mipi1>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x57220000 0x0 0x57220000 0x10000>; + + irqsteer_mipi1: interrupt-controller@57220000 { + compatible = "fsl,imx8qm-irqsteer", "fsl,imx-irqsteer"; + reg = <0x57220000 0x1000>; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <1>; + clocks = <&mipi1_lis_lpcg IMX_LPCG_CLK_0>; + clock-names = "ipg"; + power-domains = <&pd IMX_SC_R_MIPI_1>; + fsl,channel = <0>; + fsl,num-irqs = <32>; + }; + + mipi1_lis_lpcg: clock-controller@57223000 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57223000 0x4>; + #clock-cells = <1>; + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_lis_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1>; + }; + + mipi1_pwm_lpcg: clock-controller@5722300c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5722300c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_MIPI_1_PWM_0 IMX_SC_PM_CLK_PER>, + <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "mipi1_pwm_lpcg_clk", + "mipi1_pwm_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>; + }; + + mipi1_i2c0_lpcg_clk: clock-controller@5722301c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5722301c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_MIPI_1_I2C_0 IMX_SC_PM_CLK_MISC2>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c0_lpcg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + }; + + mipi1_i2c0_lpcg_ipg_clk: clock-controller@57223014 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57223014 0x4>; + #clock-cells = <1>; + clocks = <&mipi1_i2c0_lpcg_ipg_s_clk IMX_LPCG_CLK_0>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c0_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + }; + + mipi1_i2c0_lpcg_ipg_s_clk: clock-controller@57223018 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57223018 0x4>; + #clock-cells = <1>; + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c0_lpcg_ipg_s_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + }; + + mipi1_i2c1_lpcg_ipg_clk: clock-controller@57223024 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57223024 0x4>; + #clock-cells = <1>; + clocks = <&mipi1_i2c1_lpcg_ipg_s_clk IMX_LPCG_CLK_0>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c1_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_1>; + }; + + mipi1_i2c1_lpcg_ipg_s_clk: clock-controller@57223028 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x57223028 0x4>; + #clock-cells = <1>; + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c1_lpcg_ipg_s_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_1>; + }; + + mipi1_i2c1_lpcg_clk: clock-controller@5722302c { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5722302c 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_MIPI_1_I2C_1 IMX_SC_PM_CLK_MISC2>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi1_i2c1_lpcg_clk"; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_1>; + }; + + pwm_mipi1: pwm@57224000 { + compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; + reg = <0x57224000 0x1000>; + clocks = <&mipi1_pwm_lpcg IMX_LPCG_CLK_4>, + <&mipi1_pwm_lpcg IMX_LPCG_CLK_0>; + clock-names = "ipg", "per"; + assigned-clocks = <&clk IMX_SC_R_MIPI_1_PWM_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + #pwm-cells = <3>; + power-domains = <&pd IMX_SC_R_MIPI_1_PWM_0>; + status = "disabled"; + }; + + i2c0_mipi1: i2c@57226000 { + compatible = "fsl,imx8qm-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x57226000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8>; + interrupt-parent = <&irqsteer_mipi1>; + clocks = <&mipi1_i2c0_lpcg_clk IMX_LPCG_CLK_0>, + <&mipi1_i2c0_lpcg_ipg_clk IMX_LPCG_CLK_0>; + clock-names = "per", "ipg"; + assigned-clocks = <&mipi1_i2c0_lpcg_clk IMX_LPCG_CLK_0>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_MIPI_1_I2C_0>; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi index c6540768bdb9..87211c18d65a 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-vpu.dtsi @@ -15,7 +15,7 @@ vpu: vpu@2c000000 { mu_m0: mailbox@2d000000 { compatible = "fsl,imx6sx-mu"; reg = <0x2d000000 0x20000>; - interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <2>; power-domains = <&pd IMX_SC_R_VPU_MU_0>; status = "disabled"; @@ -24,7 +24,7 @@ vpu: vpu@2c000000 { mu1_m0: mailbox@2d020000 { compatible = "fsl,imx6sx-mu"; reg = <0x2d020000 0x20000>; - interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>; #mbox-cells = <2>; power-domains = <&pd IMX_SC_R_VPU_MU_1>; status = "disabled"; diff --git a/arch/arm64/boot/dts/freescale/imx8dx-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8dx-colibri.dtsi index 66b0fcc6687d..4d1ad052c5b6 100644 --- a/arch/arm64/boot/dts/freescale/imx8dx-colibri.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8dx-colibri.dtsi @@ -9,3 +9,14 @@ / { model = "Toradex Colibri iMX8DX Module"; }; + +&thermal_zones { + pmic-thermal { + cooling-maps { + map0 { + cooling-device = <&A35_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts index 1a74ac3ee4ee..4caaecc19227 100644 --- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts @@ -722,12 +722,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lpspi3>; status = "okay"; - - spidev0: spi@0 { - reg = <0>; - compatible = "rohm,dh2228fv"; - spi-max-frequency = <30000000>; - }; }; &iomuxc { diff --git a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi index 6086dae2e5fb..ea1d5b9c6bae 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi @@ -56,6 +56,20 @@ enable-gpios = <&pca6416_1 2 GPIO_ACTIVE_LOW>; }; + reg_1v5: regulator-1v5 { + compatible = "regulator-fixed"; + regulator-name = "1V5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + }; + + reg_1v8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + reg_audio: regulator-audio { compatible = "regulator-fixed"; regulator-name = "3v3_aud"; @@ -187,6 +201,8 @@ assigned-clock-parents = <&clk IMX8MM_CLK_24M>; assigned-clock-rates = <24000000>; AVDD-supply = <®_camera>; /* 2.8v */ + DVDD-supply = <®_1v5>; + DOVDD-supply = <®_1v8>; powerdown-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mm-beacon-kit.dts index 905c98cb080d..97ff1ddd6318 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-beacon-kit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-beacon-kit.dts @@ -62,8 +62,8 @@ compatible = "adi,adv7535"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hdmi_bridge>; - reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>; - reg-names = "main", "cec", "edid", "packet"; + reg = <0x3d>, <0x3e>, <0x3c>, <0x3f>; + reg-names = "main", "edid", "cec", "packet"; adi,dsi-lanes = <4>; avdd-supply = <®_hdmi>; a2vdd-supply = <®_hdmi>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts index b1f2beb40a98..472c584fb3bd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts @@ -168,7 +168,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_fec1>; phy-mode = "rgmii-id"; - phy-handle = <&fec1_phy>; + phy-handle = <&fec1_phy_bcm>; phy-supply = <&buck4_reg>; fsl,magic-packet; status = "okay"; @@ -178,7 +178,7 @@ #size-cells = <0>; /* Atheros AR8031 PHY */ - fec1_phy: ethernet-phy@0 { + fec1_phy_ath: ethernet-phy@0 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <0>; /* @@ -191,6 +191,7 @@ reset-deassert-us = <10000>; qca,keep-pll-enabled; vddio-supply = <&vddio>; + status = "disabled"; vddio: vddio-regulator { regulator-name = "VDDIO"; @@ -202,6 +203,20 @@ regulator-name = "VDDH"; }; }; + + /* Broadcom BCM54213PE PHY */ + fec1_phy_bcm: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + /* + * Dedicated ENET_INT# and ENET_WOL# signals are + * unused, the PHY does not provide cable detect + * interrupt. + */ + reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + }; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts index 1c4e4d175989..7d2cb74c64ee 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-emtop-baseboard.dts @@ -11,5 +11,53 @@ model = "Emtop Embedded Solutions i.MX8M Mini Baseboard V1"; compatible = "ees,imx8mm-emtop-baseboard", "ees,imx8mm-emtop-som", "fsl,imx8mm"; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + vddio-supply = <&vddio>; + + vddio: vddio-regulator { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + }; + }; +}; +&iomuxc { + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3 + MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19 + >; + }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi index 930e14fec423..5f8336217bb8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi @@ -180,12 +180,21 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts b/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts index 92e62fe31929..5eacbd9611ee 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts @@ -220,6 +220,7 @@ }; &rv3028 { + aux-voltage-chargeable = <1>; trickle-resistor-ohms = <3000>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso index bf3e04651ba0..78f4e8d5814d 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs232.dtso @@ -14,16 +14,11 @@ /dts-v1/; /plugin/; -&{/} { - compatible = "phytec,imx8mm-phygate-tauri-l"; - -}; - &gpio3 { pinctrl-names = "default"; - pinctrcl-0 = <&pinctrl_gpio3_hog>; + pinctrl-0 = <&pinctrl_gpio3_hog>; - uart4_rs485_en { + uart4-rs485-en-hog { gpio-hog; gpios = <20 GPIO_ACTIVE_HIGH>; output-low; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso index f4448cde0407..66288948bdd3 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rs485.dtso @@ -15,16 +15,11 @@ /dts-v1/; /plugin/; -&{/} { - compatible = "phytec,imx8mm-phygate-tauri-l"; - -}; - &gpio3 { pinctrl-names = "default"; - pinctrcl-0 = <&pinctrl_gpio3_hog>; + pinctrl-0 = <&pinctrl_gpio3_hog>; - uart4_rs485_en { + uart4-rs485-en-hog { gpio-hog; gpios = <20 GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso index 107f743fbb1c..4719f5fbad03 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l-rs232-rts-cts.dtso @@ -14,12 +14,6 @@ /dts-v1/; /plugin/; - -&{/} { - compatible = "phytec,imx8mm-phygate-tauri-l"; - -}; - &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts index ba6ce3c7f477..c3835b2d860a 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-phygate-tauri-l.dts @@ -215,6 +215,7 @@ /* RTC */ &rv3028 { + aux-voltage-chargeable = <1>; trickle-resistor-ohms = <3000>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi index ca0205b9019e..8f58c84e14c8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi @@ -83,7 +83,6 @@ }; &i2c1 { - clock-frequency = <100000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; pinctrl-1 = <&pinctrl_i2c1_gpio>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi index d7830df5b6f9..cdfacbc35db5 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi @@ -8,7 +8,6 @@ / { model = "Variscite VAR-SOM-MX8MM module"; - compatible = "variscite,var-som-mx8mm", "fsl,imx8mm"; chosen { stdout-path = &uart4; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso index 4eaf8aabcbff..c09aa80d2ba2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso @@ -13,6 +13,20 @@ &{/} { compatible = "gw,imx8mm-gw72xx-0x", "fsl,imx8mm"; + reg_vana: regulator-2p8v { + compatible = "regulator-fixed"; + regulator-name = "2P8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + reg_vddl: regulator-1p2v { + compatible = "regulator-fixed"; + regulator-name = "1P2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + reg_cam: regulator-cam { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_reg_cam>; @@ -45,6 +59,8 @@ reg = <0x10>; clocks = <&cam24m>; VDIG-supply = <®_cam>; + VANA-supply = <®_vana>; + VDDL-supply = <®_vddl>; port { /* MIPI CSI-2 bus endpoint */ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso index f6ad1a4b8b66..bb2056746f8c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso @@ -15,12 +15,8 @@ /dts-v1/; /plugin/; -&{/} { - compatible = "gw,imx8mm-gw72xx-0x"; -}; - &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-low; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso index c3cd9f2b0db3..45ac8bdce869 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso @@ -18,19 +18,15 @@ /dts-v1/; /plugin/; -&{/} { - compatible = "gw,imx8mm-gw72xx-0x"; -}; - &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-high; line-name = "rs485_en"; }; - rs485_hd { + rs485-hd-hog { gpio-hog; gpios = <2 GPIO_ACTIVE_HIGH>; output-low; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso index cc0a287226ab..30aa620d7004 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso @@ -18,19 +18,15 @@ /dts-v1/; /plugin/; -&{/} { - compatible = "gw,imx8mm-gw72xx-0x"; -}; - &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-high; line-name = "rs485_en"; }; - rs485_hd { + rs485-hd-hog { gpio-hog; gpios = <2 GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso index f3ece4b7fbbd..cfc014eb038d 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso @@ -13,6 +13,20 @@ &{/} { compatible = "gw,imx8mm-gw73xx-0x", "fsl,imx8mm"; + reg_vana: regulator-2p8v { + compatible = "regulator-fixed"; + regulator-name = "2P8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + reg_vddl: regulator-1p2v { + compatible = "regulator-fixed"; + regulator-name = "1P2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + reg_cam: regulator-cam { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_reg_cam>; @@ -45,6 +59,8 @@ reg = <0x10>; clocks = <&cam24m>; VDIG-supply = <®_cam>; + VANA-supply = <®_vana>; + VDDL-supply = <®_vddl>; port { /* MIPI CSI-2 bus endpoint */ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso index 1f8ea20dfafc..9bee7159a67b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso @@ -20,7 +20,7 @@ }; &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-low; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso index 3e6404340d52..e98f50bcec57 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso @@ -23,14 +23,14 @@ }; &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-high; line-name = "rs485_en"; }; - rs485_hd { + rs485-hd-hog { gpio-hog; gpios = <2 GPIO_ACTIVE_HIGH>; output-low; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso index 2c71ab9854cb..e875ff4637bd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso @@ -23,14 +23,14 @@ }; &gpio4 { - rs485_en { + rs485-en-hog { gpio-hog; gpios = <0 GPIO_ACTIVE_HIGH>; output-high; line-name = "rs485_en"; }; - rs485_hd { + rs485-hd-hog { gpio-hog; gpios = <2 GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7905-0x.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx-0x.dts index 914753f062cd..04f06a55da5c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7905-0x.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx-0x.dts @@ -7,11 +7,11 @@ #include "imx8mm.dtsi" #include "imx8mm-venice-gw700x.dtsi" -#include "imx8mm-venice-gw7905.dtsi" +#include "imx8mm-venice-gw75xx.dtsi" / { - model = "Gateworks Venice GW7905-0x i.MX8MM Development Kit"; - compatible = "gateworks,imx8mm-gw7905-0x", "fsl,imx8mm"; + model = "Gateworks Venice GW75xx-0x i.MX8MM Development Kit"; + compatible = "gateworks,imx8mm-gw75xx-0x", "fsl,imx8mm"; chosen { stdout-path = &uart2; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7905.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi index 5eb92005195c..5eb92005195c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7905.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw75xx.dtsi diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts index 136cb30df03a..35ae0faa815b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts @@ -364,6 +364,8 @@ interrupts = <16 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; adc { compatible = "gw,gsc-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts index 1d56f2a6c06a..c11260c26d0b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts @@ -314,6 +314,8 @@ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; adc { compatible = "gw,gsc-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts index 45470160f98f..db1737bf637d 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts @@ -280,6 +280,8 @@ interrupts = <26 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; adc { compatible = "gw,gsc-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts index ef951bc9f0dd..05489a31e7fd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts @@ -330,6 +330,8 @@ interrupts = <26 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; adc { compatible = "gw,gsc-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi index 20018ee2c803..77d14ea459e5 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-beacon-baseboard.dtsi @@ -40,6 +40,20 @@ }; }; + reg_1v5: regulator-1v5 { + compatible = "regulator-fixed"; + regulator-name = "1V5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + }; + + reg_1v8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + reg_audio: regulator-audio { compatible = "regulator-fixed"; regulator-name = "3v3_aud"; @@ -158,6 +172,8 @@ assigned-clock-parents = <&clk IMX8MN_CLK_24M>; assigned-clock-rates = <24000000>; AVDD-supply = <®_camera>; /* 2.8v */ + DVDD-supply = <®_1v5>; + DOVDD-supply = <®_1v8>; powerdown-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mn-beacon-kit.dts index bbd80896db96..1df5ceb11387 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-beacon-kit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-beacon-kit.dts @@ -62,8 +62,8 @@ compatible = "adi,adv7535"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hdmi_bridge>; - reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>; - reg-names = "main", "cec", "edid", "packet"; + reg = <0x3d>, <0x3e>, <0x3c>, <0x3f>; + reg-names = "main", "edid", "cec", "packet"; adi,dsi-lanes = <4>; avdd-supply = <®_hdmi>; a2vdd-supply = <®_hdmi>; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi index 9e0259ddf4bc..33d73f3dc187 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi @@ -124,12 +124,21 @@ "Line Out Jack", "LINEVOUTR"; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; }; sound-micfil { diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts index 72004ab6bda5..0b1fa04f1d67 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts @@ -312,6 +312,8 @@ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; adc { compatible = "gw,gsc-adc"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts index 17e2c19d8455..31c33acb560c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-beacon-kit.dts @@ -105,6 +105,17 @@ }; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_connector: endpoint { + remote-endpoint = <&hdmi_to_connector>; + }; + }; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -211,13 +222,12 @@ simple-audio-card,cpu { sound-dai = <&sai3>; + frame-master; + bitclock-master; }; simple-audio-card,codec { sound-dai = <&wm8962>; - clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>; - frame-master; - bitclock-master; }; }; }; @@ -283,6 +293,26 @@ }; }; +&hdmi_tx { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hdmi>; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + hdmi_to_connector:endpoint { + remote-endpoint = <&hdmi_connector>; + }; + }; + }; +}; + +&hdmi_tx_phy { + status = "okay"; +}; + &i2c2 { clock-frequency = <384000>; pinctrl-names = "default"; @@ -345,6 +375,10 @@ }; }; +&hdmi_pvi { + status = "okay"; +}; + &i2c3 { /* Connected to USB Hub */ usb-typec@52 { @@ -465,6 +499,10 @@ status = "okay"; }; +&lcdif3 { + status = "okay"; +}; + &micfil { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pdm>; @@ -507,10 +545,9 @@ &sai3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai3>; - assigned-clocks = <&clk IMX8MP_CLK_SAI3>, - <&clk IMX8MP_AUDIO_PLL2> ; - assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; - assigned-clock-rates = <12288000>, <361267200>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; fsl,sai-mclk-direction-output; status = "okay"; }; @@ -648,6 +685,15 @@ >; }; + pinctrl_hdmi: hdmigrp { + fsl,pins = < + MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL 0x400001c2 + MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA 0x400001c2 + MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x40000010 + MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x40000010 + >; + }; + pinctrl_i2c2: i2c2grp { fsl,pins = < MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2 diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts index 7e1b58dbe23a..d0fc5977258f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts @@ -59,6 +59,18 @@ pwms = <&pwm4 0 83 0>; }; + hdmi-connector { + compatible = "hdmi-connector"; + label = "J17"; + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi_tx_out>; + }; + }; + }; + panel: panel { /* Compatible string is filled in by panel board DT Overlay. */ backlight = <&backlight>; @@ -311,6 +323,33 @@ "", "SPI3_CS#", "", "", "", "", "", ""; }; +&hdmi_pvi { + status = "okay"; +}; + +&hdmi_tx { + ddc-i2c-bus = <&i2c5>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hdmi>; + status = "okay"; + + ports { + port@1 { + hdmi_tx_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; +}; + +&hdmi_tx_phy { + status = "okay"; +}; + +&lcdif3 { + status = "okay"; +}; + &i2c1 { clock-frequency = <100000>; pinctrl-names = "default", "gpio"; @@ -499,7 +538,6 @@ }; &sai3 { - #clock-cells = <0>; #sound-dai-cells = <0>; assigned-clocks = <&clk IMX8MP_CLK_SAI3>; assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; @@ -682,6 +720,13 @@ >; }; + pinctrl_hdmi: hdmi-grp { + fsl,pins = < + MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x154 + MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x154 + >; + }; + pinctrl_hog_feature: hog-feature-grp { fsl,pins = < /* GPIO5_IO03 */ diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts index 938347704136..d26930f1a9e9 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts @@ -56,6 +56,18 @@ <0x1 0x00000000 0 0xc0000000>; }; + native-hdmi-connector { + compatible = "hdmi-connector"; + label = "HDMI OUT"; + type = "a"; + + port { + hdmi_in: endpoint { + remote-endpoint = <&hdmi_tx_out>; + }; + }; + }; + pcie0_refclk: pcie0-refclk { compatible = "fixed-clock"; #clock-cells = <0>; @@ -408,6 +420,28 @@ status = "disabled";/* can2 pin conflict with pdm */ }; +&hdmi_pvi { + status = "okay"; +}; + +&hdmi_tx { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hdmi>; + status = "okay"; + + ports { + port@1 { + hdmi_tx_out: endpoint { + remote-endpoint = <&hdmi_in>; + }; + }; + }; +}; + +&hdmi_tx_phy { + status = "okay"; +}; + &i2c1 { clock-frequency = <400000>; pinctrl-names = "default"; @@ -604,6 +638,10 @@ status = "okay"; }; +&lcdif3 { + status = "okay"; +}; + &micfil { #sound-dai-cells = <0>; pinctrl-names = "default"; @@ -858,6 +896,14 @@ >; }; + pinctrl_hdmi: hdmigrp { + fsl,pins = < + MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL 0x1c2 + MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA 0x1c2 + MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC 0x10 + >; + }; + pinctrl_hog: hoggrp { fsl,pins = < MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD 0x40000010 diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts index 00a240484c25..9c102acb8052 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts @@ -6,6 +6,7 @@ /dts-v1/; +#include <dt-bindings/phy/phy-imx8-pcie.h> #include <dt-bindings/leds/leds-pca9532.h> #include <dt-bindings/pwm/pwm.h> #include "imx8mp-phycore-som.dtsi" @@ -43,6 +44,15 @@ }; }; + reg_vcc_5v_sw: regulator-vcc-5v-sw { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "VCC_5V_SW"; + }; + reg_can1_stby: regulator-can1-stby { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -103,6 +113,22 @@ }; }; +/* TPM */ +&ecspi1 { + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + tpm: tpm@0 { + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <38000000>; + }; +}; + &eqos { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_eqos>; @@ -155,6 +181,7 @@ compatible = "atmel,24c02"; reg = <0x51>; pagesize = <16>; + vcc-supply = <®_vcc_3v3_sw>; }; leds@62 { @@ -191,10 +218,39 @@ }; }; +&media_blk_ctrl { + /* + * The LVDS panel on this device uses 72.4 MHz pixel clock, + * set IMX8MP_VIDEO_PLL1 to 72.4 * 7 = 506.8 MHz so the LDB + * serializer and LCDIFv3 scanout engine can reach accurate + * pixel clock of exactly 72.4 MHz. + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, + <506800000>; +}; + &snvs_pwrkey { status = "okay"; }; +&pcie_phy { + clocks = <&hsio_blk_ctrl>; + clock-names = "ref"; + fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>; + fsl,clkreq-unsupported; + status = "okay"; +}; + +/* Mini PCIe */ +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie0>; + reset-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>; + vpcie-supply = <®_vcc_3v3_sw>; + status = "okay"; +}; + &pwm3 { status = "okay"; pinctrl-names = "default"; @@ -206,6 +262,7 @@ pinctrl-0 = <&pinctrl_rtc>; interrupt-parent = <&gpio4>; interrupts = <19 IRQ_TYPE_LEVEL_LOW>; + aux-voltage-chargeable = <1>; wakeup-source; trickle-resistor-ohms = <3000>; }; @@ -234,6 +291,7 @@ /* USB2 4-port USB3.0 HUB */ &usb3_phy1 { + vbus-supply = <®_vcc_5v_sw>; status = "okay"; }; @@ -267,7 +325,9 @@ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_pins>; pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_pins>; cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + disable-wp; vmmc-supply = <®_usdhc2_vmmc>; + vqmmc-supply = <&ldo5>; bus-width = <4>; status = "okay"; }; @@ -300,6 +360,15 @@ }; &iomuxc { + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX8MP_IOMUXC_ECSPI1_MISO__ECSPI1_MISO 0x80 + MX8MP_IOMUXC_ECSPI1_MOSI__ECSPI1_MOSI 0x80 + MX8MP_IOMUXC_ECSPI1_SCLK__ECSPI1_SCLK 0x80 + MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09 0x00 + >; + }; + pinctrl_eqos: eqosgrp { fsl,pins = < MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x2 @@ -366,6 +435,15 @@ >; }; + pinctrl_pcie0: pcie0grp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO08__GPIO1_IO08 0x40 + MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x60 + MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11 0x60 /* open drain, pull up */ + MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x40 + >; + }; + pinctrl_pwm3: pwm3grp { fsl,pins = < MX8MP_IOMUXC_SPDIF_TX__PWM3_OUT 0x12 diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phycore-no-eth.dtso b/arch/arm64/boot/dts/freescale/imx8mp-phycore-no-eth.dtso new file mode 100644 index 000000000000..5f0278bf61ee --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-phycore-no-eth.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 PHYTEC Messtechnik GmbH + * Author: Cem Tenruh <c.tenruh@phytec.de> + */ + +/dts-v1/; +/plugin/; + +ðphy1 { + status = "disabled"; +}; + +&fec { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi index e6ffa6a6b68b..a5ecdca8bc0e 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi @@ -20,6 +20,15 @@ device_type = "memory"; reg = <0x0 0x40000000 0 0x80000000>; }; + + reg_vdd_io: regulator-vdd-io { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "VDD_IO"; + }; }; &A53_0 { @@ -170,6 +179,7 @@ compatible = "atmel,24c32"; reg = <0x51>; pagesize = <32>; + vcc-supply = <®_vdd_io>; }; rv3028: rtc@52 { diff --git a/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts b/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts index 3c2efdc59bfa..30962922b361 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-skov-revb-mi1010ait-1cp1.dts @@ -71,6 +71,7 @@ assigned-clock-rates = <500000000>, <200000000>, <0>, /* IMX8MP_CLK_MEDIA_DISP2_PIX = pixelclk of lvds panel */ <68900000>, + <500000000>, /* IMX8MP_VIDEO_PLL1 = IMX8MP_CLK_MEDIA_LDB * 2 */ <964600000>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-var-som-symphony.dts b/arch/arm64/boot/dts/freescale/imx8mp-var-som-symphony.dts new file mode 100644 index 000000000000..36d3eb865202 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-var-som-symphony.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024 Variscite Ltd. + */ + +#include "imx8mp-var-som.dtsi" + +/ { + model = "Variscite VAR-SOM-MX8M-PLUS on Symphony-Board"; + compatible = "variscite,var-som-mx8mp-symphony", "variscite,var-som-mx8mp", "fsl,imx8mp"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-var-som.dtsi new file mode 100644 index 000000000000..b2ac2583a592 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-var-som.dtsi @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024 Variscite Ltd. + * + * Author: Tarang Raval <tarang.raval@siliconsignals.io> + */ + +/dts-v1/; + +#include <dt-bindings/phy/phy-imx8-pcie.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/usb/pd.h> +#include "imx8mp.dtsi" + +/ { + model = "Variscite VAR-SOM-MX8M Plus module"; + + chosen { + stdout-path = &uart2; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led-0 { + function = LED_FUNCTION_POWER; + gpios = <&pca9534 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0 0xc0000000>, + <0x1 0x00000000 0 0xc0000000>; + }; + + + reg_usdhc2_vmmc: regulator-usdhc2-vmmc { + compatible = "regulator-fixed"; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <100>; + off-on-delay-us = <12000>; + }; +}; + +&A53_0 { + cpu-supply = <&buck2>; +}; + +&A53_1 { + cpu-supply = <&buck2>; +}; + +&A53_2 { + cpu-supply = <&buck2>; +}; + +&A53_3 { + cpu-supply = <&buck2>; +}; + +&i2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic@25 { + compatible = "nxp,pca9450c"; + reg = <0x25>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pmic>; + interrupt-parent = <&gpio5>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + + regulators { + buck1: BUCK1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <2187500>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + buck2: BUCK2 { + regulator-name = "BUCK2"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <2187500>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + nxp,dvs-run-voltage = <950000>; + nxp,dvs-standby-voltage = <850000>; + }; + + buck4: BUCK4 { + regulator-name = "BUCK4"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + buck5: BUCK5 { + regulator-name = "BUCK5"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + buck6: BUCK6 { + regulator-name = "BUCK6"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2: LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3: LDO3 { + regulator-name = "LDO3"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4: LDO4 { + regulator-name = "LDO4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo5: LDO5 { + regulator-name = "LDO5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; + + /* GPIO expander */ + pca9534: gpio@20 { + compatible = "nxp,pca9534"; + reg = <0x20>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pca9534>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio1>; + interrupts = <15 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + + usb3-sata-sel-hog { + gpio-hog; + gpios = <4 0>; + output-low; + line-name = "usb3_sata_sel"; + }; + }; +}; + +/* Console */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +/* SD-card */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + status = "okay"; +}; + +/* eMMC */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_DATA4__I2C1_SCL 0x400001c2 + MX8MP_IOMUXC_SD1_DATA5__I2C1_SDA 0x400001c2 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2 + MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2 + >; + }; + + pinctrl_pca9534: pca9534grp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15 0xc0 + >; + }; + + pinctrl_pmic: pmicgrp { + fsl,pins = < + MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 0x1c0 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x40 + MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x40 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2-gpiogrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x1c4 + MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x10 + MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12 0xc0 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d0 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d0 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d0 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d0 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d0 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x194 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d4 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d4 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d4 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d4 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d4 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x196 + MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d6 + MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0 0x1d6 + MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1 0x1d6 + MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2 0x1d6 + MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3 0x1d6 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190 + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp { + fsl,pins = < + MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196 + MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6 + MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6 + MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6 + MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6 + MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6 + MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6 + MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6 + MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6 + MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6 + MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0xc6 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso index edf22ff549a4..7d9fcdee58a7 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx-imx219.dtso @@ -11,7 +11,19 @@ /plugin/; &{/} { - compatible = "gw,imx8mp-gw74xx", "fsl,imx8mp"; + reg_vana: regulator-2p8v { + compatible = "regulator-fixed"; + regulator-name = "2P8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + reg_vddl: regulator-1p2v { + compatible = "regulator-fixed"; + regulator-name = "1P2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; reg_cam: regulator-cam { pinctrl-names = "default"; @@ -41,6 +53,8 @@ reg = <0x10>; clocks = <&cam24m>; VDIG-supply = <®_cam>; + VANA-supply = <®_vana>; + VDDL-supply = <®_vddl>; port { /* MIPI CSI-2 bus endpoint */ diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905-2x.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx-2x.dts index 4a1bbbbe19e6..7ca68df9e516 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905-2x.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx-2x.dts @@ -7,11 +7,11 @@ #include "imx8mp.dtsi" #include "imx8mp-venice-gw702x.dtsi" -#include "imx8mp-venice-gw7905.dtsi" +#include "imx8mp-venice-gw75xx.dtsi" / { - model = "Gateworks Venice GW7905-2x i.MX8MP Development Kit"; - compatible = "gateworks,imx8mp-gw7905-2x", "fsl,imx8mp"; + model = "Gateworks Venice GW75xx-2x i.MX8MP Development Kit"; + compatible = "gateworks,imx8mp-gw75xx-2x", "fsl,imx8mp"; chosen { stdout-path = &uart2; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi index 0d40cb0f05f6..0d40cb0f05f6 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw7905.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw75xx.dtsi diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi index fbcd93e33aea..da8902c5f7e5 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi @@ -65,6 +65,11 @@ }; }; +/* Verdin HDMI_1 Audio */ +&aud2htx { + status = "okay"; +}; + &backlight { power-supply = <®_3p3v>; }; @@ -219,6 +224,11 @@ status = "okay"; }; +/* Verdin HDMI_1 Audio */ +&sound_hdmi { + status = "okay"; +}; + /* Verdin UART_1 */ &uart1 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi index 09733fea036d..a38e7c947a42 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi @@ -64,6 +64,11 @@ }; }; +/* Verdin HDMI_1 Audio */ +&aud2htx { + status = "okay"; +}; + &backlight { power-supply = <®_3p3v>; }; @@ -215,6 +220,11 @@ status = "okay"; }; +/* Verdin HDMI_1 Audio */ +&sound_hdmi { + status = "okay"; +}; + /* Verdin UART_1, connector X50 through RS485 transceiver */ &uart1 { linux,rs485-enabled-at-boot-time; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi index 3a40338cf2d8..11cf3bdc95c4 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-mallow.dtsi @@ -62,6 +62,11 @@ }; }; +/* Verdin HDMI_1 Audio */ +&aud2htx { + status = "okay"; +}; + &backlight { power-supply = <®_3p3v>; }; @@ -182,6 +187,11 @@ vin-supply = <®_3p3v>; }; +/* Verdin HDMI_1 Audio */ +&sound_hdmi { + status = "okay"; +}; + /* Verdin UART_1 */ &uart1 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi index efcab00c0142..cae06cb67cd3 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi @@ -75,7 +75,6 @@ &usdhc1 { bus-width = <4>; keep-power-in-suspend; - max-frequency = <100000000>; non-removable; pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_wifi_ctrl>; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi index 533b7fe218ce..cc389cda2af2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi @@ -85,6 +85,11 @@ }; }; +/* Verdin HDMI_1 Audio */ +&aud2htx { + status = "okay"; +}; + &backlight { power-supply = <®_3p3v>; }; @@ -192,6 +197,11 @@ vin-supply = <®_3p3v>; }; +/* Verdin HDMI_1 Audio */ +&sound_hdmi { + status = "okay"; +}; + /* Verdin UART_1 */ &uart1 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi index d23a3942174d..a19ad5ee7f79 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi @@ -77,6 +77,14 @@ }; }; + sound_hdmi: sound-hdmi { + compatible = "fsl,imx-audio-hdmi"; + model = "audio-hdmi"; + audio-cpu = <&aud2htx>; + hdmi-out; + status = "disabled"; + }; + /* Carrier Board Supplies */ reg_1p8v: regulator-1p8v { compatible = "regulator-fixed"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 603dfe80216f..40e847bc0b7f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -1261,7 +1261,7 @@ compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b40000 0x10000>; interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_DUMMY>, + clocks = <&clk IMX8MP_CLK_IPG_ROOT>, <&clk IMX8MP_CLK_NAND_USDHC_BUS>, <&clk IMX8MP_CLK_USDHC1_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -1275,7 +1275,7 @@ compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b50000 0x10000>; interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_DUMMY>, + clocks = <&clk IMX8MP_CLK_IPG_ROOT>, <&clk IMX8MP_CLK_NAND_USDHC_BUS>, <&clk IMX8MP_CLK_USDHC2_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -1289,7 +1289,7 @@ compatible = "fsl,imx8mp-usdhc", "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b60000 0x10000>; interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX8MP_CLK_DUMMY>, + clocks = <&clk IMX8MP_CLK_IPG_ROOT>, <&clk IMX8MP_CLK_NAND_USDHC_BUS>, <&clk IMX8MP_CLK_USDHC3_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -1673,6 +1673,50 @@ }; }; + isp_0: isp@32e10000 { + compatible = "fsl,imx8mp-isp"; + reg = <0x32e10000 0x10000>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>; + clock-names = "isp", "aclk", "hclk"; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_ISP>; + fsl,blk-ctrl = <&media_blk_ctrl 0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + }; + }; + }; + + isp_1: isp@32e20000 { + compatible = "fsl,imx8mp-isp"; + reg = <0x32e20000 0x10000>; + interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>, + <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>, + <&clk IMX8MP_CLK_MEDIA_APB_ROOT>; + clock-names = "isp", "aclk", "hclk"; + power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_ISP>; + fsl,blk-ctrl = <&media_blk_ctrl 1>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + }; + }; + }; + dewarp: dwe@32e30000 { compatible = "nxp,imx8mp-dw100"; reg = <0x32e30000 0x10000>; @@ -1687,7 +1731,7 @@ compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2"; reg = <0x32e40000 0x10000>; interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <266000000>; + clock-frequency = <250000000>; clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, <&clk IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT>, <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>, @@ -1695,9 +1739,8 @@ clock-names = "pclk", "wrap", "phy", "axi"; assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>, <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>; - assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_250M>, <&clk IMX8MP_CLK_24M>; - assigned-clock-rates = <266000000>; power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_1>; status = "disabled"; @@ -1723,7 +1766,7 @@ compatible = "fsl,imx8mp-mipi-csi2", "fsl,imx8mm-mipi-csi2"; reg = <0x32e50000 0x10000>; interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <266000000>; + clock-frequency = <250000000>; clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, <&clk IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT>, <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>, @@ -1731,9 +1774,8 @@ clock-names = "pclk", "wrap", "phy", "axi"; assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>, <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>; - assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_250M>, <&clk IMX8MP_CLK_24M>; - assigned-clock-rates = <266000000>; power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_MIPI_CSI2_2>; status = "disabled"; @@ -1871,17 +1913,26 @@ clock-names = "apb", "axi", "cam1", "cam2", "disp1", "disp2", "isp", "phy"; + /* + * The ISP maximum frequency is 400MHz in normal mode + * and 500MHz in overdrive mode. The 400MHz operating + * point hasn't been successfully tested yet, so set + * IMX8MP_CLK_MEDIA_ISP to 500MHz for the time being. + */ assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>, <&clk IMX8MP_CLK_MEDIA_APB>, <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>, <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>, + <&clk IMX8MP_CLK_MEDIA_ISP>, <&clk IMX8MP_VIDEO_PLL1>; assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, <&clk IMX8MP_SYS_PLL1_800M>, <&clk IMX8MP_VIDEO_PLL1_OUT>, - <&clk IMX8MP_VIDEO_PLL1_OUT>; + <&clk IMX8MP_VIDEO_PLL1_OUT>, + <&clk IMX8MP_SYS_PLL2_500M>; assigned-clock-rates = <500000000>, <200000000>, - <0>, <0>, <1039500000>; + <0>, <0>, <500000000>, + <1039500000>; #power-domain-cells = <1>; lvds_bridge: bridge@5c { diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts index 7507548cdb16..a87d0692c3bb 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts @@ -125,19 +125,33 @@ }; }; + spdif_out: spdif-out { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + }; + + spdif_in: spdif-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; + }; + + hdmi_arc_in: hdmi-arc-in { + compatible = "linux,spdif-dir"; + #sound-dai-cells = <0>; }; sound-hdmi-arc { compatible = "fsl,imx-audio-spdif"; model = "imx-hdmi-arc"; - spdif-controller = <&spdif2>; - spdif-in; + audio-cpu = <&spdif2>; + audio-codec = <&hdmi_arc_in>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts index 778741dbbb33..62203eed6a6c 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts @@ -6,6 +6,7 @@ /dts-v1/; +#include <dt-bindings/usb/pd.h> #include "imx8qm.dtsi" / { @@ -31,6 +32,99 @@ reg = <0x00000000 0x80000000 0 0x40000000>; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + vdev0vring0: memory@90000000 { + reg = <0 0x90000000 0 0x8000>; + no-map; + }; + + vdev0vring1: memory@90008000 { + reg = <0 0x90008000 0 0x8000>; + no-map; + }; + + vdev1vring0: memory@90010000 { + reg = <0 0x90010000 0 0x8000>; + no-map; + }; + + vdev1vring1: memory@90018000 { + reg = <0 0x90018000 0 0x8000>; + no-map; + }; + + rsc_table0: memory@900ff000 { + reg = <0 0x900ff000 0 0x1000>; + no-map; + }; + + vdev2vring0: memory@90100000 { + reg = <0 0x90100000 0 0x8000>; + no-map; + }; + + vdev2vring1: memory@90108000 { + reg = <0 0x90108000 0 0x8000>; + no-map; + }; + + vdev3vring0: memory@90110000 { + reg = <0 0x90110000 0 0x8000>; + no-map; + }; + + vdev3vring1: memory@90118000 { + reg = <0 0x90118000 0 0x8000>; + no-map; + }; + + rsc_table1: memory@901ff000 { + reg = <0 0x901ff000 0 0x1000>; + no-map; + }; + + vdevbuffer: memory@90400000 { + compatible = "shared-dma-pool"; + reg = <0 0x90400000 0 0x100000>; + no-map; + }; + }; + + lvds_backlight0: backlight-lvds0 { + compatible = "pwm-backlight"; + pwms = <&qm_pwm_lvds0 0 100000 0>; + brightness-levels = <0 100>; + num-interpolated-steps = <100>; + default-brightness-level = <80>; + }; + + lvds_backlight1: backlight-lvds1 { + compatible = "pwm-backlight"; + pwms = <&pwm_lvds1 0 100000 0>; + brightness-levels = <0 100>; + num-interpolated-steps = <100>; + default-brightness-level = <80>; + }; + + mux-controller { + compatible = "nxp,cbdtu02043", "gpio-sbu-mux"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_typec_mux>; + select-gpios = <&lsio_gpio4 6 GPIO_ACTIVE_LOW>; + enable-gpios = <&lsio_gpio4 19 GPIO_ACTIVE_HIGH>; + orientation-switch; + + port { + usb3_data_ss: endpoint { + remote-endpoint = <&typec_con_ss>; + }; + }; + }; + reg_usdhc2_vmmc: usdhc2-vmmc { compatible = "regulator-fixed"; regulator-name = "SD1_SPWR"; @@ -133,6 +227,37 @@ "LINPUT1", "Mic Jack", "Mic Jack", "MICB"; }; + + imx8qm-cm4-0 { + compatible = "fsl,imx8qm-cm4"; + clocks = <&clk_dummy>; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&lsio_mu5 0 1 + &lsio_mu5 1 1 + &lsio_mu5 3 1>; + memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table0>; + power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>; + + fsl,resource-id = <IMX_SC_R_M4_0_PID0>; + fsl,entry-address = <0x34fe0000>; + }; + + imx8qm-cm4-1 { + compatible = "fsl,imx8qm-cm4"; + clocks = <&clk_dummy>; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&lsio_mu6 0 1 + &lsio_mu6 1 1 + &lsio_mu6 3 1>; + memory-region = <&vdevbuffer>, <&vdev2vring0>, <&vdev2vring1>, + <&vdev3vring0>, <&vdev3vring1>, <&rsc_table1>; + power-domains = <&pd IMX_SC_R_M4_1_PID0>, <&pd IMX_SC_R_M4_1_MU_1A>; + + fsl,resource-id = <IMX_SC_R_M4_1_PID0>; + fsl,entry-address = <0x38fe0000>; + }; + }; &adc0 { @@ -212,6 +337,44 @@ compatible = "st,l3g4200d-gyro"; reg = <0x69>; }; + + ptn5110: tcpc@51 { + compatible = "nxp,ptn5110", "tcpci"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_typec>; + reg = <0x51>; + interrupt-parent = <&lsio_gpio4>; + interrupts = <26 IRQ_TYPE_LEVEL_LOW>; + status = "okay"; + + usb_con1: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "source"; + data-role = "dual"; + source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + typec_dr_sw: endpoint { + remote-endpoint = <&usb3_drd_sw>; + }; + }; + + port@1 { + reg = <1>; + typec_con_ss: endpoint { + remote-endpoint = <&usb3_data_ss>; + }; + }; + }; + }; + }; }; &i2c1 { @@ -241,6 +404,34 @@ }; }; +&i2c1_lvds0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lvds0_lpi2c1>; + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c1_lvds1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lvds1_lpi2c1>; + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c0_mipi0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mipi0_lpi2c0>; + clock-frequency = <100000>; + status = "okay"; +}; + +&i2c0_mipi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mipi1_lpi2c0>; + clock-frequency = <100000>; + status = "okay"; +}; + &flexcan1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flexcan1>; @@ -287,12 +478,6 @@ pinctrl-0 = <&pinctrl_lpspi2 &pinctrl_lpspi2_cs>; cs-gpios = <&lsio_gpio3 10 GPIO_ACTIVE_LOW>; status = "okay"; - - spidev0: spi@0 { - reg = <0>; - compatible = "rohm,dh2228fv"; - spi-max-frequency = <30000000>; - }; }; &lsio_mu5 { @@ -356,6 +541,18 @@ status = "okay"; }; +&qm_pwm_lvds0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm_lvds0>; + status = "okay"; +}; + +&pwm_lvds1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm_lvds1>; + status = "okay"; +}; + &usdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc1>; @@ -376,6 +573,26 @@ status = "okay"; }; +&usb3_phy { + status = "okay"; +}; + +&usbotg3 { + status = "okay"; +}; + +&usbotg3_cdns3 { + dr_mode = "otg"; + usb-role-switch; + status = "okay"; + + port { + usb3_drd_sw: endpoint { + remote-endpoint = <&typec_dr_sw>; + }; + }; +}; + &sai0 { #sound-dai-cells = <0>; assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>, @@ -501,6 +718,22 @@ >; }; + pinctrl_mipi0_lpi2c0: mipi0_lpi2c0grp { + fsl,pins = < + IMX8QM_MIPI_DSI0_I2C0_SCL_MIPI_DSI0_I2C0_SCL 0xc6000020 + IMX8QM_MIPI_DSI0_I2C0_SDA_MIPI_DSI0_I2C0_SDA 0xc6000020 + IMX8QM_MIPI_DSI0_GPIO0_01_LSIO_GPIO1_IO19 0x00000020 + >; + }; + + pinctrl_mipi1_lpi2c0: mipi1_lpi2c0grp { + fsl,pins = < + IMX8QM_MIPI_DSI1_I2C0_SCL_MIPI_DSI1_I2C0_SCL 0xc6000020 + IMX8QM_MIPI_DSI1_I2C0_SDA_MIPI_DSI1_I2C0_SDA 0xc6000020 + IMX8QM_MIPI_DSI1_GPIO0_01_LSIO_GPIO1_IO23 0x00000020 + >; + }; + pinctrl_flexspi0: flexspi0grp { fsl,pins = < IMX8QM_QSPI0A_DATA0_LSIO_QSPI0A_DATA0 0x06000021 @@ -582,6 +815,32 @@ >; }; + pinctrl_lvds0_lpi2c1: lvds0lpi2c1grp { + fsl,pins = < + IMX8QM_LVDS0_I2C1_SCL_LVDS0_I2C1_SCL 0xc600004c + IMX8QM_LVDS0_I2C1_SDA_LVDS0_I2C1_SDA 0xc600004c + >; + }; + + pinctrl_lvds1_lpi2c1: lvds1lpi2c1grp { + fsl,pins = < + IMX8QM_LVDS1_I2C1_SCL_LVDS1_I2C1_SCL 0xc600004c + IMX8QM_LVDS1_I2C1_SDA_LVDS1_I2C1_SDA 0xc600004c + >; + }; + + pinctrl_pwm_lvds0: pwmlvds0grp { + fsl,pins = < + IMX8QM_LVDS0_GPIO00_LVDS0_PWM0_OUT 0x00000020 + >; + }; + + pinctrl_pwm_lvds1: pwmlvds1grp { + fsl,pins = < + IMX8QM_LVDS1_GPIO00_LVDS1_PWM0_OUT 0x00000020 + >; + }; + pinctrl_sai0: sai0grp { fsl,pins = < IMX8QM_SPI0_CS1_AUD_SAI0_TXC 0x0600004c @@ -600,6 +859,19 @@ >; }; + pinctrl_typec: typecgrp { + fsl,pins = < + IMX8QM_QSPI1A_DATA0_LSIO_GPIO4_IO26 0x00000021 + >; + }; + + pinctrl_typec_mux: typecmuxgrp { + fsl,pins = < + IMX8QM_QSPI1A_SS0_B_LSIO_GPIO4_IO19 0x60 + IMX8QM_USB_SS3_TC3_LSIO_GPIO4_IO06 0x60 + >; + }; + pinctrl_usdhc1: usdhc1grp { fsl,pins = < IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041 diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-lvds.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-lvds.dtsi new file mode 100644 index 000000000000..0514d8b2af75 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-lvds.dtsi @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2024 NXP + */ + +&qm_lvds0_lis_lpcg { + clocks = <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_4>; +}; + +&qm_lvds0_pwm_lpcg { + clocks = <&clk IMX_SC_R_LVDS_0_PWM_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; +}; + +&qm_lvds0_i2c0_lpcg { + clocks = <&clk IMX_SC_R_LVDS_0_I2C_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; +}; + +&qm_pwm_lvds0 { + clocks = <&qm_lvds0_pwm_lpcg IMX_LPCG_CLK_4>, + <&qm_lvds0_pwm_lpcg IMX_LPCG_CLK_0>; +}; + +&qm_i2c0_lvds0 { + clocks = <&qm_lvds0_i2c0_lpcg IMX_LPCG_CLK_0>, + <&qm_lvds0_i2c0_lpcg IMX_LPCG_CLK_4>; +}; + +&lvds0_subsys { + interrupt-parent = <&irqsteer_lvds0>; + + irqsteer_lvds0: interrupt-controller@56240000 { + compatible = "fsl,imx8qm-irqsteer", "fsl,imx-irqsteer"; + reg = <0x56240000 0x1000>; + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <1>; + clocks = <&qm_lvds0_lis_lpcg IMX_LPCG_CLK_4>; + clock-names = "ipg"; + power-domains = <&pd IMX_SC_R_LVDS_0>; + + fsl,channel = <0>; + fsl,num-irqs = <32>; + }; + + lvds0_i2c1_lpcg: clock-controller@56243014 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x56243014 0x4>; + #clock-cells = <1>; + clocks = <&clk IMX_SC_R_LVDS_0_I2C_0 IMX_SC_PM_CLK_PER>, + <&lvds_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "lvds0_i2c1_lpcg_clk", + "lvds0_i2c1_lpcg_ipg_clk"; + power-domains = <&pd IMX_SC_R_LVDS_0_I2C_0>; + }; + + i2c1_lvds0: i2c@56247000 { + compatible = "fsl,imx8qm-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x56247000 0x1000>; + interrupts = <9>; + clocks = <&lvds0_i2c1_lpcg IMX_LPCG_CLK_0>, + <&lvds0_i2c1_lpcg IMX_LPCG_CLK_4>; + clock-names = "per", "ipg"; + assigned-clocks = <&clk IMX_SC_R_LVDS_0_I2C_0 IMX_SC_PM_CLK_PER>; + assigned-clock-rates = <24000000>; + power-domains = <&pd IMX_SC_R_LVDS_0_I2C_0>; + status = "disabled"; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-mipi.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-mipi.dtsi new file mode 100644 index 000000000000..f4c393fe7204 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-mipi.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * Copyright 2024 NXP + */ + +&mipi0_lis_lpcg { + clocks = <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>; + clock-output-names = "mipi0_lis_lpcg_ipg_clk"; +}; + +&mipi0_pwm_lpcg { + clocks = <&clk IMX_SC_R_MIPI_0_PWM_0 IMX_SC_PM_CLK_PER>, + <&dsi_ipg_clk>; + clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>; + clock-output-names = "mipi0_pwm_lpcg_clk", + "mipi0_pwm_lpcg_ipg_clk"; +};
\ No newline at end of file diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi index 61986e0639e5..3ee6e2869e3c 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi @@ -560,11 +560,36 @@ clock-output-names = "spdif1_rx"; }; + lvds_ipg_clk: clock-controller-lvds-ipg { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "lvds0_ipg_clk"; + }; + + dsi_ipg_clk: clock-controller-dsi-ipg { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <120000000>; + clock-output-names = "dsi_ipg_clk"; + }; + + mipi_pll_div2_clk: clock-controller-mipi-div2-pll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <432000000>; + clock-output-names = "mipi_pll_div2_clk"; + }; + /* sorted in register address */ #include "imx8-ss-cm41.dtsi" #include "imx8-ss-audio.dtsi" #include "imx8-ss-vpu.dtsi" #include "imx8-ss-gpu0.dtsi" + #include "imx8-ss-mipi0.dtsi" + #include "imx8-ss-lvds0.dtsi" + #include "imx8-ss-mipi1.dtsi" + #include "imx8-ss-lvds1.dtsi" #include "imx8-ss-img.dtsi" #include "imx8-ss-dma.dtsi" #include "imx8-ss-conn.dtsi" @@ -576,3 +601,5 @@ #include "imx8qm-ss-conn.dtsi" #include "imx8qm-ss-lsio.dtsi" #include "imx8qm-ss-audio.dtsi" +#include "imx8qm-ss-lvds.dtsi" +#include "imx8qm-ss-mipi.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi index 7894a3ab26d6..f81937b5fb72 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-vpu.dtsi @@ -5,6 +5,14 @@ * Author: Alexander Stein */ +&mu_m0 { + interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>; +}; + +&mu1_m0 { + interrupts = <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>; +}; + &vpu_core0 { reg = <0x2d040000 0x10000>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi index e32d5afcf4a9..43f543768444 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi @@ -384,7 +384,7 @@ }; flexspi2: spi@29810000 { - compatible = "nxp,imx8mm-fspi"; + compatible = "nxp,imx8ulp-fspi"; reg = <0x29810000 0x10000>, <0x60000000 0x10000000>; reg-names = "fspi_base", "fspi_mmap"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-aster.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-aster.dtsi index bc659066e19a..f7bbb2153ae0 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri-aster.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-aster.dtsi @@ -3,10 +3,24 @@ * Copyright 2018-2021 Toradex */ +/* Colibri Analogue Inputs */ +&adc0 { + status = "okay"; +}; + +/* Colibri PWM_A */ +&adma_pwm { + status = "okay"; +}; + &colibri_gpio_keys { status = "okay"; }; +&extcon_usbc_det { + status = "okay"; +}; + /* Colibri Ethernet */ &fec1 { status = "okay"; @@ -38,6 +52,28 @@ status = "okay"; }; +/* USB PHY for usbotg3 */ +&usb3_phy { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usbotg3 { + status = "okay"; +}; + +&usbotg3_cdns3 { + status = "okay"; +}; + +/* USB PHY for usbotg1 */ +&usbphy1 { + status = "okay"; +}; + /* Colibri SDCard */ &usdhc2 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi index 9af769ab8ceb..f75499765d85 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi @@ -19,10 +19,24 @@ }; }; +/* Colibri Analogue Inputs */ +&adc0 { + status = "okay"; +}; + +/* Colibri PWM_A */ +&adma_pwm { + status = "okay"; +}; + &colibri_gpio_keys { status = "okay"; }; +&extcon_usbc_det { + status = "okay"; +}; + &i2c1 { status = "okay"; @@ -90,6 +104,28 @@ status = "okay"; }; +/* USB PHY for usbotg3 */ +&usb3_phy { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usbotg3 { + status = "okay"; +}; + +&usbotg3_cdns3 { + status = "okay"; +}; + +/* USB PHY for usbotg1 */ +&usbphy1 { + status = "okay"; +}; + /* Colibri SD/MMC Card */ &usdhc2 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi index 8d06925a8ebd..54393a0c5cbf 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi @@ -17,10 +17,24 @@ }; }; +/* Colibri Analogue Inputs */ +&adc0 { + status = "okay"; +}; + +/* Colibri PWM_A */ +&adma_pwm { + status = "okay"; +}; + &colibri_gpio_keys { status = "okay"; }; +&extcon_usbc_det { + status = "okay"; +}; + /* Colibri FastEthernet */ &fec1 { status = "okay"; @@ -108,6 +122,28 @@ status = "okay"; }; +/* USB PHY for usbotg3 */ +&usb3_phy { + status = "okay"; +}; + +&usbotg1 { + status = "okay"; +}; + +&usbotg3 { + status = "okay"; +}; + +&usbotg3_cdns3 { + status = "okay"; +}; + +/* USB PHY for usbotg1 */ +&usbphy1 { + status = "okay"; +}; + /* Colibri SD/MMC Card */ &usdhc2 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi index 49d105eb4769..edba5b582414 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi @@ -23,17 +23,76 @@ }; }; + extcon_usbc_det: usbc-det { + compatible = "linux,extcon-usb-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbc_det>; + id-gpios = <&lsio_gpio5 9 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + reg_module_3v3: regulator-module-3v3 { compatible = "regulator-fixed"; regulator-name = "+V3.3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + reg_module_3v3_avdd: regulator-module-3v3-avdd { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_AVDD_AUDIO"; + }; + + reg_module_vref_1v8: regulator-module-vref-1v8 { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vref-1v8"; + }; + + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1_reg>; + gpio = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>; + regulator-always-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usbh_vbus"; + }; + + sound-card { + compatible = "simple-audio-card"; + simple-audio-card,bitclock-master = <&dailink_master>; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&dailink_master>; + simple-audio-card,name = "colibri-imx8x"; + + dailink_master: simple-audio-card,codec { + clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>; + sound-dai = <&sgtl5000_a>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai0>; + }; + }; }; -/* TODO Analogue Inputs */ +/* Colibri Analogue Inputs */ +&adc0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc0>; + vref-supply = <®_module_vref_1v8>; +}; -/* TODO Cooling maps for DX */ +/* Colibri PWM_A */ +&adma_pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm_a>; +}; &cpu_alert0 { hysteresis = <2000>; @@ -47,9 +106,20 @@ type = "critical"; }; -/* TODO flexcan1 - 3 */ - -/* TODO GPU */ +&enet0_lpcg { + clocks = <&clk IMX_SC_R_ENET_0 IMX_SC_PM_CLK_PER>, + <&clk IMX_SC_R_ENET_0 IMX_SC_PM_CLK_PER>, + <&conn_axi_clk>, + <&clk IMX_SC_R_ENET_0 IMX_SC_C_DISABLE_50>, + <&conn_ipg_clk>, + <&conn_ipg_clk>; + clock-output-names = "enet0_lpcg_timer_clk", + "enet0_lpcg_txc_sampling_clk", + "enet0_lpcg_ahb_clk", + "enet0_lpcg_ref_50mhz_clk", + "enet0_lpcg_ipg_clk", + "enet0_lpcg_ipg_s_clk"; +}; /* On-module I2C */ &i2c0 { @@ -60,6 +130,41 @@ pinctrl-0 = <&pinctrl_i2c0>, <&pinctrl_sgtl5000_usb_clk>; status = "okay"; + /* USB HUB USB3803 */ + usb-hub@8 { + compatible = "smsc,usb3803"; + reg = <0x8>; + assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>, + <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>, + <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>, + <&mclkout0_lpcg IMX_LPCG_CLK_0>; + assigned-clock-rates = <786432000>, <49152000>, <12000000>, <12000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb3503a>; + bypass-gpios = <&gpio_expander_43 5 GPIO_ACTIVE_LOW>; + clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>; + clock-names = "refclk"; + disabled-ports = <2>; + initial-mode = <1>; + intn-gpios = <&lsio_gpio3 4 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio_expander_43 4 GPIO_ACTIVE_LOW>; + }; + + sgtl5000_a: audio-codec@a { + compatible = "fsl,sgtl5000"; + reg = <0xa>; + #sound-dai-cells = <0>; + assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>, + <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>, + <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>, + <&mclkout0_lpcg IMX_LPCG_CLK_0>; + assigned-clock-rates = <786432000>, <49152000>, <12000000>, <12000000>; + clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>; + VDDA-supply = <®_module_3v3_avdd>; + VDDD-supply = <®_module_vref_1v8>; + VDDIO-supply = <®_module_3v3>; + }; + /* Touch controller */ touchscreen@2c { compatible = "adi,ad7879-1"; @@ -77,6 +182,21 @@ adi,conversion-interval = /bits/ 8 <255>; status = "disabled"; }; + + gpio_expander_43: gpio@43 { + compatible = "fcs,fxl6408"; + reg = <0x43>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "Wi-Fi_W_DISABLE", + "Wi-Fi_WKUP_WLAN", + "PWR_EN_+V3.3_WiFi_N", + "PCIe_REF_CLK_EN", + "USB_RESET_N", + "USB_BYPASS_N", + "Wi-Fi_PDn", + "Wi-Fi_WKUP_BT"; + }; }; /* TODO i2c lvds0 accessible on FFC (X2) */ @@ -321,13 +441,74 @@ pinctrl-names = "default"; }; +/* VPU Mailboxes */ +&mu_m0 { + status="okay"; +}; + +&mu1_m0 { + status="okay"; +}; + /* TODO MIPI CSI */ /* TODO MIPI DSI with DSI-to-HDMI bridge lt8912 */ /* TODO on-module PCIe for Wi-Fi */ -/* TODO On-module i2s / Audio */ +/* On-module I2S */ +&sai0 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai0>; + status = "okay"; +}; + +&thermal_zones { + pmic-thermal { + polling-delay-passive = <250>; + polling-delay = <2000>; + thermal-sensors = <&tsens IMX_SC_R_PMIC_0>; + + trips { + pmic_alert0: trip0 { + temperature = <110000>; + hysteresis = <2000>; + type = "passive"; + }; + + pmic_crit0: trip1 { + temperature = <125000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + pmic_cooling_map0: map0 { + trip = <&pmic_alert0>; + cooling-device = <&A35_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&A35_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; +}; + +&usbotg1 { + adp-disable; + disable-over-current; + extcon = <&extcon_usbc_det &extcon_usbc_det>; + hnp-disable; + power-active-high; + srp-disable; + vbus-supply = <®_usbh_vbus>; +}; + +&usbotg3_cdns3 { + dr_mode = "host"; +}; /* On-module eMMC */ &usdhc1 { @@ -356,11 +537,24 @@ no-1-8-v; }; -/* TODO USB Client/Host */ +&vpu { + compatible = "nxp,imx8qxp-vpu"; + status = "okay"; +}; -/* TODO USB Host */ +/* VPU Decoder */ +&vpu_core0 { + reg = <0x2d040000 0x10000>; + memory-region = <&decoder_boot>, <&decoder_rpc>; + status = "okay"; +}; -/* TODO VPU Encoder/Decoder */ +/* VPU Encoder */ +&vpu_core1 { + reg = <0x2d050000 0x10000>; + memory-region = <&encoder_boot>, <&encoder_rpc>; + status = "okay"; +}; &iomuxc { /* On-module touch pen-down interrupt */ diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts index a15987f49e8d..8d036b3962e9 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts @@ -62,6 +62,15 @@ }; + reg_vdd_12v: regulator-vdd-12v { + compatible = "regulator-fixed"; + regulator-name = "VDD_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + gpio = <&pcal6524 14 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + reg_vref_1v8: regulator-adc-vref { compatible = "regulator-fixed"; regulator-name = "vref_1v8"; @@ -80,6 +89,68 @@ off-on-delay-us = <12000>; enable-active-high; }; + + backlight_lvds: backlight-lvds { + compatible = "pwm-backlight"; + pwms = <&adp5585 0 100000 0>; + brightness-levels = <0 100>; + num-interpolated-steps = <100>; + default-brightness-level = <100>; + power-supply = <®_vdd_12v>; + enable-gpios = <&adp5585 9 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + + bt_sco_codec: bt-sco-codec { + compatible = "linux,bt-sco"; + #sound-dai-cells = <1>; + }; + + sound-bt-sco { + compatible = "simple-audio-card"; + simple-audio-card,name = "bt-sco-audio"; + simple-audio-card,format = "dsp_a"; + simple-audio-card,bitclock-inversion; + simple-audio-card,frame-master = <&btcpu>; + simple-audio-card,bitclock-master = <&btcpu>; + + btcpu: simple-audio-card,cpu { + sound-dai = <&sai1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + + simple-audio-card,codec { + sound-dai = <&bt_sco_codec 1>; + }; + }; + + sound-micfil { + compatible = "fsl,imx-audio-card"; + model = "micfil-audio"; + + pri-dai-link { + link-name = "micfil hifi"; + format = "i2s"; + + cpu { + sound-dai = <&micfil>; + }; + }; + }; + + sound-xcvr { + compatible = "fsl,imx-audio-card"; + model = "imx-audio-xcvr"; + + pri-dai-link { + link-name = "XCVR PCM"; + + cpu { + sound-dai = <&xcvr>; + }; + }; + }; }; &adc1 { @@ -145,9 +216,19 @@ }; }; +&lpi2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c1>; + status = "okay"; + + inertial-meter@6a { + compatible = "st,lsm6dso"; + reg = <0x6a>; + }; +}; + &lpi2c2 { - #address-cells = <1>; - #size-cells = <0>; clock-frequency = <400000>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_lpi2c2>; @@ -241,11 +322,19 @@ }; }; }; + + adp5585: io-expander@34 { + compatible = "adi,adp5585-00", "adi,adp5585"; + reg = <0x34>; + vdd-supply = <&buck4>; + gpio-controller; + #gpio-cells = <2>; + gpio-reserved-ranges = <5 1>; + #pwm-cells = <3>; + }; }; &lpi2c3 { - #address-cells = <1>; - #size-cells = <0>; clock-frequency = <400000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lpi2c3>; @@ -337,6 +426,16 @@ status = "okay"; }; +&micfil { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_pdm>; + pinctrl-1 = <&pinctrl_pdm_sleep>; + assigned-clocks = <&clk IMX93_CLK_PDM>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <49152000>; + status = "okay"; +}; + &mu1 { status = "okay"; }; @@ -345,6 +444,17 @@ status = "okay"; }; +&sai1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_sai1>; + pinctrl-1 = <&pinctrl_sai1_sleep>; + assigned-clocks = <&clk IMX93_CLK_SAI1>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &usbotg1 { dr_mode = "otg"; hnp-disable; @@ -408,6 +518,18 @@ status = "okay"; }; +&xcvr { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_spdif>; + pinctrl-1 = <&pinctrl_spdif_sleep>; + assigned-clocks = <&clk IMX93_CLK_SPDIF>, + <&clk IMX93_CLK_AUDIO_XCVR>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>, + <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; + assigned-clock-rates = <12288000>, <200000000>; + status = "okay"; +}; + &iomuxc { pinctrl_eqos: eqosgrp { fsl,pins = < @@ -508,6 +630,13 @@ >; }; + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + pinctrl_lpi2c2: lpi2c2grp { fsl,pins = < MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e @@ -528,6 +657,40 @@ >; }; + pinctrl_pdm: pdmgrp { + fsl,pins = < + MX93_PAD_PDM_CLK__PDM_CLK 0x31e + MX93_PAD_PDM_BIT_STREAM0__PDM_BIT_STREAM00 0x31e + MX93_PAD_PDM_BIT_STREAM1__PDM_BIT_STREAM01 0x31e + >; + }; + + pinctrl_pdm_sleep: pdmsleepgrp { + fsl,pins = < + MX93_PAD_PDM_CLK__GPIO1_IO08 0x31e + MX93_PAD_PDM_BIT_STREAM0__GPIO1_IO09 0x31e + MX93_PAD_PDM_BIT_STREAM1__GPIO1_IO10 0x31e + >; + }; + + pinctrl_sai1: sai1grp { + fsl,pins = < + MX93_PAD_SAI1_TXC__SAI1_TX_BCLK 0x31e + MX93_PAD_SAI1_TXFS__SAI1_TX_SYNC 0x31e + MX93_PAD_SAI1_TXD0__SAI1_TX_DATA00 0x31e + MX93_PAD_SAI1_RXD0__SAI1_RX_DATA00 0x31e + >; + }; + + pinctrl_sai1_sleep: sai1sleepgrp { + fsl,pins = < + MX93_PAD_SAI1_TXC__GPIO1_IO12 0x51e + MX93_PAD_SAI1_TXFS__GPIO1_IO11 0x51e + MX93_PAD_SAI1_TXD0__GPIO1_IO13 0x51e + MX93_PAD_SAI1_RXD0__GPIO1_IO14 0x51e + >; + }; + /* need to config the SION for data and cmd pad, refer to ERR052021 */ pinctrl_usdhc1: usdhc1grp { fsl,pins = < @@ -585,6 +748,20 @@ >; }; + pinctrl_spdif: spdifgrp { + fsl,pins = < + MX93_PAD_GPIO_IO22__SPDIF_IN 0x31e + MX93_PAD_GPIO_IO23__SPDIF_OUT 0x31e + >; + }; + + pinctrl_spdif_sleep: spdifsleepgrp { + fsl,pins = < + MX93_PAD_GPIO_IO22__GPIO2_IO22 0x31e + MX93_PAD_GPIO_IO23__GPIO2_IO23 0x31e + >; + }; + pinctrl_usdhc2_gpio: usdhc2gpiogrp { fsl,pins = < MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e diff --git a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts new file mode 100644 index 000000000000..236a44c1782a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts @@ -0,0 +1,468 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024 NXP + */ + +/dts-v1/; + +#include <dt-bindings/usb/pd.h> +#include "imx93.dtsi" + +/ { + model = "NXP i.MX93 14X14 EVK board"; + compatible = "fsl,imx93-14x14-evk", "fsl,imx93"; + + chosen { + stdout-path = &lpuart1; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0 0x80000000 0 0x40000000>; + size = <0 0x10000000>; + linux,cma-default; + }; + + vdev0vring0: vdev0vring0@a4000000 { + reg = <0 0xa4000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@a4008000 { + reg = <0 0xa4008000 0 0x8000>; + no-map; + }; + + vdev1vring0: vdev1vring0@a4010000 { + reg = <0 0xa4010000 0 0x8000>; + no-map; + }; + + vdev1vring1: vdev1vring1@a4018000 { + reg = <0 0xa4018000 0 0x8000>; + no-map; + }; + + rsc_table: rsc-table@2021e000 { + reg = <0 0x2021e000 0 0x1000>; + no-map; + }; + + vdevbuffer: vdevbuffer@a4020000 { + compatible = "shared-dma-pool"; + reg = <0 0xa4020000 0 0x100000>; + no-map; + }; + }; + + reg_can1_stby: regulator-can1-stby { + compatible = "regulator-fixed"; + regulator-name = "can1-stby"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524_2 10 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_can1_en>; + }; + + reg_can1_en: regulator-can1-en { + compatible = "regulator-fixed"; + regulator-name = "can1-en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524_2 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_can2_stby: regulator-can2-stby { + compatible = "regulator-fixed"; + regulator-name = "can2-stby"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524_2 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_can2_en>; + }; + + reg_can2_en: regulator-can2-en { + compatible = "regulator-fixed"; + regulator-name = "can2-en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524_2 13 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + off-on-delay-us = <12000>; + }; + + reg_vdd_12v: regulator-vdd-12v { + compatible = "regulator-fixed"; + regulator-name = "reg_vdd_12v"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + gpio = <&pcal6524 14 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_vref_1v8: regulator-adc-vref { + compatible = "regulator-fixed"; + regulator-name = "vref_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&adc1 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&cm33 { + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu1 0 1>, + <&mu1 1 1>, + <&mu1 3 1>; + memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy2>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <5000000>; + + ethphy2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + eee-broken-1000t; + reset-gpios = <&pcal6524 16 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <80000>; + realtek,clkout-disable; + }; + }; +}; + +&flexcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <®_can1_stby>; + status = "okay"; +}; + +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <®_can2_stby>; + status = "okay"; +}; + +&lpi2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c1>; + status = "okay"; + + lsm6dsm@6a { + compatible = "st,lsm6dso"; + reg = <0x6a>; + }; +}; + +&lpi2c2 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c2>; + status = "okay"; + + pcal6524_2: gpio@20 { + compatible = "nxp,pcal6524"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; + + pcal6524: gpio@22 { + compatible = "nxp,pcal6524"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcal6524>; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&lpi2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c3>; + status = "okay"; +}; + +&lpuart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&mu1 { + status = "okay"; +}; + +&mu2 { + status = "okay"; +}; + +&usbotg1 { + dr_mode = "otg"; + hnp-disable; + srp-disable; + adp-disable; + disable-over-current; + samsung,picophy-pre-emp-curr-control = <3>; + samsung,picophy-dc-vol-level-adjust = <7>; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + samsung,picophy-pre-emp-curr-control = <3>; + samsung,picophy-dc-vol-level-adjust = <7>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + no-mmc; + status = "okay"; +}; + +&wdog3 { + status = "okay"; +}; + +&iomuxc { + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX93_PAD_PDM_CLK__CAN1_TX 0x139e + MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x139e + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX93_PAD_GPIO_IO25__CAN2_TX 0x139e + MX93_PAD_GPIO_IO27__CAN2_RX 0x139e + >; + }; + + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c2: lpi2c2grp { + fsl,pins = < + MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e + MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c3: lpi2c3grp { + fsl,pins = < + MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e + MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e + >; + }; + + pinctrl_pcal6524: pcal6524grp { + fsl,pins = < + MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e + >; + }; + + pinctrl_fec: fecgrp { + fsl,pins = < + MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e + MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e + MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e + MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e + MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x58e + MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e + MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e + MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e + MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e + MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e + MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x58e + MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e + MX93_PAD_DAP_TDI__LPUART5_RX 0x31e + MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e + MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 + MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e + MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe + MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 + MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe + MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts index 950dece83c24..f8a73612fa05 100644 --- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts +++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts @@ -178,8 +178,6 @@ }; &lpi2c2 { - #address-cells = <1>; - #size-cells = <0>; clock-frequency = <400000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lpi2c2>; diff --git a/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts b/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts new file mode 100644 index 000000000000..89e97c604bd3 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +/dts-v1/; + +#include "imx93-kontron-osm-s.dtsi" + +/ { + model = "Kontron BL i.MX93 OSM-S"; + compatible = "kontron,imx93-bl-osm-s", "kontron,imx93-osm-s", "fsl,imx93"; + + aliases { + ethernet0 = &fec; + ethernet1 = &eqos; + }; + + leds { + compatible = "gpio-leds"; + + led1 { + label = "led1"; + gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + pwm-beeper { + compatible = "pwm-beeper"; + pwms = <&tpm6 1 5000 0>; + }; + + reg_vcc_panel: regulator-vcc-panel { + compatible = "regulator-fixed"; + gpio = <&gpio4 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "VCC_PANEL"; + }; +}; + +&eqos { /* Second ethernet (OSM-S ETH_B) */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eqos_rgmii>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy1>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-id4f51.e91b"; + reg = <1>; + reset-assert-us = <10000>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&fec { /* First ethernet (OSM-S ETH_A) */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet_rgmii>; + phy-connection-type = "rgmii-id"; + phy-handle = <ðphy0>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@1 { + compatible = "ethernet-phy-id4f51.e91b"; + reg = <1>; + reset-assert-us = <10000>; + reset-gpios = <&gpio2 18 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&flexcan1 { + status = "okay"; +}; + +&lpi2c2 { + status = "okay"; + + gpio_expander_dio: gpio@20 { + compatible = "ti,tca6408"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "DIO1_OUT","DIO1_IN", "DIO2_OUT","DIO2_IN", + "DIO3_OUT","DIO3_IN", "DIO4_OUT","DIO4_IN"; + interrupt-parent = <&gpio4>; + interrupts = <28 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + }; +}; + +&lpspi8 { + assigned-clocks = <&clk IMX93_CLK_LPSPI8>; + assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>; + assigned-clock-rates = <100000000>; + status = "okay"; + + eeram@0 { + compatible = "microchip,48l640"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&lpuart1 { + status = "okay"; +}; + +&lpuart7 { + uart-has-rtscts; + status = "okay"; +}; + +&lpuart6 { + linux,rs485-enabled-at-boot-time; + uart-has-rtscts; + status = "okay"; +}; + +&tpm6 { + status = "okay"; +}; + +&usbotg1 { + #address-cells = <1>; + #size-cells = <0>; + disable-over-current; + dr_mode = "host"; + status = "okay"; + + usb1@1 { + compatible = "usb424,2514"; + reg = <1>; + }; +}; + +&usbotg2 { + adp-disable; + hnp-disable; + srp-disable; + disable-over-current; + dr_mode = "otg"; + usb-role-switch; + status = "okay"; +}; + +&usdhc2 { + vmmc-supply = <®_vdd_3v3>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi new file mode 100644 index 000000000000..47c1363a2f99 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi @@ -0,0 +1,628 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +#include <dt-bindings/interrupt-controller/irq.h> +#include "imx93.dtsi" + +/ { + model = "Kontron OSM-S i.MX93"; + compatible = "kontron,imx93-osm-s", "fsl,imx93"; + + aliases { + rtc0 = &rv3028; + rtc1 = &bbnsm_rtc; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0 0x80000000>; + }; + + chosen { + stdout-path = &lpuart1; + }; + + reg_usdhc2_vcc: regulator-usdhc2-vcc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vcc>; + gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "VCC_SDIO_A"; + }; + + reg_vdd_carrier: regulator-vdd-carrier { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_vdd_carrier>; + gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + regulator-name = "VDD_CARRIER"; + + regulator-state-standby { + regulator-on-in-suspend; + }; + + regulator-state-mem { + regulator-off-in-suspend; + }; + + regulator-state-disk { + regulator-off-in-suspend; + }; + }; +}; + +&flexcan1 { /* OSM-S CAN_A */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; +}; + +&flexcan2 { /* OSM-S CAN_B */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; +}; + +&gpio1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio1>; + gpio-line-names = "", "", "I2C_A_SCL", "I2C_A_SDA", + "UART_CON_RX", "UART_CON_TX", "UART_C_RX", "UART_C_TX", + "CAN_A_TX", "CAN_A_RX", "GPIO_A_0", "SPI_A_CS0", + "SPI_A_SDI", "SPI_A_SCK","SPI_A_SDO"; +}; + +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio2>; + gpio-line-names = "I2C_B_SDA", "I2C_B_SCL", "GPIO_B_1", "GPIO_A_2", + "UART_B_TX", "UART_B_RX", "UART_B_RTS", "UART_B_CTS", + "UART_A_TX", "UART_A_RX", "UART_A_RTS", "UART_A_CTS", + "SPI_B_CS0", "SPI_B_SDI", "SPI_B_SDO", "SPI_B_SCK", + "I2S_BITCLK", "I2S_MCLK", "GPIO_A_1", "I2S_A_DATA_OUT", + "I2S_A_DATA_IN", "PWM_2", "GPIO_A_3", "PWM_1", + "PWM_0", "CAN_B_TX", "I2S_LRCLK", "CAN_B_RX", "GPIO_A_4", + "GPIO_A_5"; +}; + +&gpio3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio3>; + gpio-line-names = "SDIO_A_CD", "SDIO_A_CLK", "SDIO_A_CMD", "SDIO_A_D0", + "SDIO_A_D1", "SDIO_A_D2", "SDIO_A_D3", "SDIO_A_PWR_EN", + "", "", "", "", + "", "", "", "", + "", "", "", "", + "SDIO_B_CLK", "SDIO_B_CMD", "SDIO_B_D0", "SDIO_B_D1", + "SDIO_B_D2", "SDIO_B_D3", "GPIO_A_6", "GPIO_A_7"; +}; + +&gpio4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio4>; + gpio-line-names = "ETH_B_MDC", "ETH_B_MDIO", "ETH_B_TXD4", "ETH_B_TXD3", + "ETH_B_TXD2", "ETH_B_TXD1", "ETH_B_TX_EN", "ETH_B_TX_CLK", + "ETH_B_RX_CTL", "ETH_B_RX_CLK", "ETH_B_RXD0", "ETH_B_RXD1", + "ETH_B_RXD2", "ETH_B_RXD3", "ETH_MDC", "ETH_MDIO", + "ETH_A_TXD3", "ETH_A_TXD2", "ETH_A_TXD1", "ETH_A_TXD0", + "ETH_A_TX_EN", "ETH_A_TX_CLK", "ETH_A_RX_CTL", "ETH_A_RX_CLK", + "ETH_A_RXD0", "ETH_A_RXD1", "ETH_A_RXD2", "ETH_A_RXD3", + "GPIO_B_0", "CARRIER_PWR_EN"; +}; + +&lpi2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c1>; + status = "okay"; + + pca9451: pmic@25 { + compatible = "nxp,pca9451a"; + reg = <0x25>; + nxp,i2c-lt-enable; + + regulators { + reg_vdd_soc: BUCK1 { /* dual phase with BUCK3 */ + regulator-name = "+0V8_VDD_SOC (BUCK1)"; + regulator-min-microvolt = <650000>; + regulator-max-microvolt = <950000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + reg_vddq_ddr: BUCK2 { + regulator-name = "+0V6_VDDQ_DDR (BUCK2)"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <600000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + reg_vdd_3v3: BUCK4 { + regulator-name = "+3V3 (BUCK4)"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_vdd_1v8: BUCK5 { + regulator-name = "+1V8 (BUCK5)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_nvcc_dram: BUCK6 { + regulator-name = "+1V1_NVCC_DRAM (BUCK6)"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_nvcc_snvs: LDO1 { + regulator-name = "+1V8_NVCC_SNVS (LDO1)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_vdd_ana: LDO4 { + regulator-name = "+0V8_VDD_ANA (LDO4)"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_nvcc_sd: LDO5 { + regulator-name = "NVCC_SD (LDO5)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + + eeprom@50 { + compatible = "onnn,n24s64b", "atmel,24c64"; + reg = <0x50>; + pagesize = <32>; + size = <8192>; + num-addresses = <1>; + }; + + rv3028: rtc@52 { + compatible = "microcrystal,rv3028"; + reg = <0x52>; + }; +}; + +&lpi2c2 { /* OSM-S I2C_A */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c2>; +}; + +&lpi2c3 { /* OSM-S I2C_B */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c3>; +}; + +&lpspi1 { /* OSM-S SPI_A */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpspi1>; + cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; +}; + +&lpspi8 { /* OSM-S SPI_B */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpspi8>; + cs-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; +}; + +&lpuart1 { /* OSM-S UART_CON */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart1>; +}; + +&lpuart2 { /* OSM-S UART_C */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart2>; +}; + +&lpuart6 { /* OSM-S UART_B */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart6>; +}; + +&lpuart7 { /* OSM-S UART_A */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpuart7>; +}; + +&tpm3 { /* OSM-S PWM_0 */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm3>; +}; + +&tpm4 { /* OSM-S PWM_2 */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm4>; +}; + +&tpm6 { /* OSM-S PWM_1 */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm6>; +}; + +&usdhc1 { /* eMMC */ + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + vmmc-supply = <®_vdd_3v3>; + vqmmc-supply = <®_vdd_1v8>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&usdhc2 { /* OSM-S SDIO_A */ + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + vmmc-supply = <®_usdhc2_vcc>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; +}; + +&usdhc3 { /* OSM-S SDIO_B */ + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + vqmmc-supply = <®_vdd_1v8>; +}; + +&wdog3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_enet_rgmii: enetrgmiigrp { + fsl,pins = < + MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e /* ETH_MDC */ + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e /* ETH_MDIO */ + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e /* ETH_A_(S)(R)(G)MII_RXD0 */ + MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e /* ETH_A_(S)(R)(G)MII_RXD1 */ + MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e /* ETH_A_(R)(G)MII_RXD2 */ + MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e /* ETH_A_(R)(G)MII_RXD3 */ + MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x5fe /* ETH_A_(R)(G)MII_RX_CLK */ + MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e /* ETH_A_(R)(G)MII_RX_DV(_ER) */ + MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e /* ETH_A_(S)(R)(G)MII_TXD0 */ + MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e /* ETH_A_(S)(R)(G)MII_TXD1 */ + MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e /* ETH_A_(S)(R)(G)MII_TXD2 */ + MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e /* ETH_A_(S)(R)(G)MII_TXD3 */ + MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x5fe /* ETH_A_(R)(G)MII_TX_CLK */ + MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e /* ETH_A_(R)(G)MII_TX_EN(_ER) */ + >; + }; + + pinctrl_eqos_rgmii: eqosrgmiigrp { + fsl,pins = < + MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e /* ETH_B_MDC */ + MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e /* ETH_B_MDIO */ + MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e /* ETH_B_(S)(R)(G)MII_RXD0 */ + MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e /* ETH_B_(S)(R)(G)MII_RXD1 */ + MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e /* ETH_B_(R)(G)MII_RXD2 */ + MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e /* ETH_B_(R)(G)MII_RXD3 */ + MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x57e /* ETH_B_(R)(G)MII_RX_CLK */ + MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e /* ETH_B_(R)(G)MII_RX_DV(_ER) */ + MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e /* ETH_B_(S)(R)(G)MII_TXD0 */ + MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e /* ETH_B_(S)(R)(G)MII_TXD1 */ + MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e /* ETH_B_(S)(R)(G)MII_TXD2 */ + MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e /* ETH_B_(S)(R)(G)MII_TXD3 */ + MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x57e /* ETH_B_(R)(G)MII_TX_CLK */ + MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e /* ETH_B_(R)(G)MII_TX_EN(_ER) */ + >; + }; + + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX93_PAD_PDM_CLK__CAN1_TX 0x139e /* CAN_A_TX */ + MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x139e /* CAN_A_RX */ + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX93_PAD_GPIO_IO25__CAN2_TX 0x139e /* CAN_B_TX */ + MX93_PAD_GPIO_IO27__CAN2_RX 0x139e /* CAN_B_RX */ + >; + }; + + pinctrl_gpio1: gpio1grp { + fsl,pins = < + MX93_PAD_PDM_BIT_STREAM1__GPIO1_IO10 0x31e /* GPIO_A_0 */ + >; + }; + + pinctrl_gpio2: gpio2grp { + fsl,pins = < + MX93_PAD_GPIO_IO18__GPIO2_IO18 0x31e /* GPIO_A_1 */ + MX93_PAD_GPIO_IO03__GPIO2_IO03 0x31e /* GPIO_A_2 */ + MX93_PAD_GPIO_IO22__GPIO2_IO22 0x31e /* GPIO_A_3 */ + MX93_PAD_GPIO_IO28__GPIO2_IO28 0x31e /* GPIO_A_4 */ + MX93_PAD_GPIO_IO29__GPIO2_IO29 0x31e /* GPIO_A_5 */ + MX93_PAD_GPIO_IO02__GPIO2_IO02 0x31e /* GPIO_B_1 */ + >; + }; + + pinctrl_gpio3: gpio3grp { + fsl,pins = < + MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x31e /* GPIO_A_6 */ + MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e /* GPIO_A_7 */ + >; + }; + + pinctrl_gpio4: gpio4grp { + fsl,pins = < + MX93_PAD_CCM_CLKO3__GPIO4_IO28 0x31e /* GPIO_B_0 */ + >; + }; + + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c2: lpi2c2grp { + fsl,pins = < + MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e /* I2C_A_SCL */ + MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e /* I2C_A_SDA */ + >; + }; + + pinctrl_lpi2c3: lpi2c3grp { + fsl,pins = < + MX93_PAD_GPIO_IO01__LPI2C3_SCL 0x40000b9e /* I2C_B_SCL */ + MX93_PAD_GPIO_IO00__LPI2C3_SDA 0x40000b9e /* I2C_B_SDA */ + >; + }; + + pinctrl_lpspi1: lpspi1grp { + fsl,pins = < + MX93_PAD_SAI1_TXC__LPSPI1_SIN 0x3fe /* SPI_A_SDI_(IO0) */ + MX93_PAD_SAI1_RXD0__LPSPI1_SOUT 0x3fe /* SPI_A_SDO_(IO1) */ + MX93_PAD_SAI1_TXD0__LPSPI1_SCK 0x3fe /* SPI_A_SCK */ + MX93_PAD_SAI1_TXFS__GPIO1_IO11 0x3fe /* SPI_A_CS0# */ + >; + }; + + pinctrl_lpspi8: lpspi8grp { + fsl,pins = < + MX93_PAD_GPIO_IO13__LPSPI8_SIN 0x3fe /* SPI_B_SDI */ + MX93_PAD_GPIO_IO14__LPSPI8_SOUT 0x3fe /* SPI_B_SDO */ + MX93_PAD_GPIO_IO15__LPSPI8_SCK 0x3fe /* SPI_B_SCK */ + MX93_PAD_GPIO_IO12__GPIO2_IO12 0x3fe /* SPI_B_CS0# */ + >; + }; + + pinctrl_lpuart1: lpuart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e /* UART_CON_RX */ + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e /* UART_CON_TX */ + >; + }; + + pinctrl_lpuart2: lpuart2grp { + fsl,pins = < + MX93_PAD_UART2_RXD__LPUART2_RX 0x31e /* UART_C_RX */ + MX93_PAD_UART2_TXD__LPUART2_TX 0x31e /* UART_C_TX */ + >; + }; + + pinctrl_lpuart6: lpuart6grp { + fsl,pins = < + MX93_PAD_GPIO_IO05__LPUART6_RX 0x31e /* UART_B_RX */ + MX93_PAD_GPIO_IO04__LPUART6_TX 0x31e /* UART_B_TX */ + MX93_PAD_GPIO_IO07__LPUART6_RTS_B 0x31e /* UART_B_CTS */ + MX93_PAD_GPIO_IO06__LPUART6_CTS_B 0x31e /* UART_B_RTS */ + >; + }; + + pinctrl_lpuart7: lpuart7grp { + fsl,pins = < + MX93_PAD_GPIO_IO09__LPUART7_RX 0x31e /* UART_A_RX */ + MX93_PAD_GPIO_IO08__LPUART7_TX 0x31e /* UART_A_TX */ + MX93_PAD_GPIO_IO11__LPUART7_RTS_B 0x31e /* UART_A_CTS */ + MX93_PAD_GPIO_IO10__LPUART7_CTS_B 0x31e /* UART_A_RTS */ + >; + }; + + pinctrl_reg_usdhc2_vcc: regusdhc2vccgrp { + fsl,pins = < + MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e /* SDIO_A_PWR_EN */ + >; + }; + + pinctrl_reg_vdd_carrier: regvddcarriergrp { + fsl,pins = < + MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x31e /* CARRIER_PWR_EN */ + >; + }; + + pinctrl_sai3: sai3grp { + fsl,pins = < + MX93_PAD_GPIO_IO20__SAI3_RX_DATA00 0x31e /* I2S_A_DATA_IN */ + MX93_PAD_GPIO_IO19__SAI3_TX_DATA00 0x31e /* I2S_A_DATA_OUT */ + MX93_PAD_GPIO_IO17__SAI3_MCLK 0x31e /* I2S_MCLK */ + MX93_PAD_GPIO_IO26__SAI3_TX_SYNC 0x31e /* I2S_LRCLK */ + MX93_PAD_GPIO_IO16__SAI3_TX_BCLK 0x31e /* I2S_BITCLK */ + >; + }; + + pinctrl_tpm3: tpm3grp { + fsl,pins = < + MX93_PAD_GPIO_IO24__TPM3_CH3 0x57e /* PWM_0 */ + >; + }; + + pinctrl_tpm4: tpm4grp { + fsl,pins = < + MX93_PAD_GPIO_IO21__TPM4_CH1 0x57e /* PWM_2 */ + >; + }; + + pinctrl_tpm6: tpm6grp { + fsl,pins = < + MX93_PAD_GPIO_IO23__TPM6_CH1 0x57e /* PWM_1 */ + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 + MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e + MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe + MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 /* SDIO_A_CLK */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 /* SDIO_A_CMD */ + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 /* SDIO_A_D0 */ + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 /* SDIO_A_D1 */ + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 /* SDIO_A_D2 */ + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 /* SDIO_A_D3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x1d0 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e /* SDIO_A_CLK */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e /* SDIO_A_CMD */ + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e /* SDIO_A_D0 */ + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e /* SDIO_A_D1 */ + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e /* SDIO_A_D2 */ + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e /* SDIO_A_D3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x1d0 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe /* SDIO_A_CLK */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe /* SDIO_A_CMD */ + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe /* SDIO_A_D0 */ + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe /* SDIO_A_D1 */ + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe /* SDIO_A_D2 */ + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe /* SDIO_A_D3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x1d0 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e /* SDIO_A_CD# */ + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX93_PAD_SD3_CLK__USDHC3_CLK 0x1582 /* SDIO_B_CLK */ + MX93_PAD_SD3_CMD__USDHC3_CMD 0x40001382 /* SDIO_B_CMD */ + MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x40001382 /* SDIO_B_D0 */ + MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x40001382 /* SDIO_B_D1 */ + MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x40001382 /* SDIO_B_D2 */ + MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x40001382 /* SDIO_B_D3 */ + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp { + fsl,pins = < + MX93_PAD_SD3_CLK__USDHC3_CLK 0x158e /* SDIO_B_CLK */ + MX93_PAD_SD3_CMD__USDHC3_CMD 0x4000138e /* SDIO_B_CMD */ + MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x4000138e /* SDIO_B_D0 */ + MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x4000138e /* SDIO_B_D1 */ + MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x4000138e /* SDIO_B_D2 */ + MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x4000138e /* SDIO_B_D3 */ + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp { + fsl,pins = < + MX93_PAD_SD3_CLK__USDHC3_CLK 0x15fe /* SDIO_B_CLK */ + MX93_PAD_SD3_CMD__USDHC3_CMD 0x400013fe /* SDIO_B_CMD */ + MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x400013fe /* SDIO_B_D0 */ + MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x400013fe /* SDIO_B_D1 */ + MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x400013fe /* SDIO_B_D2 */ + MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x400013fe /* SDIO_B_D3 */ + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX93_PAD_WDOG_ANY__WDOG1_WDOG_ANY 0xc6 + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts index 852dd3d2eac7..599df32976e2 100644 --- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxca.dts @@ -26,6 +26,8 @@ aliases { eeprom0 = &eeprom0; + ethernet0 = &fec; + ethernet1 = &eqos; rtc0 = &pcf85063; rtc1 = &bbnsm_rtc; }; @@ -274,6 +276,16 @@ }; &gpio1 { + gpio-line-names = + /* 00 */ "", "", "USB_C_ALERT#", "PMIC_IRQ#", + /* 04 */ "", "", "", "", + /* 08 */ "", "", "", "BM2_TEMP_EVENT_MOD#", + /* 12 */ "PEX_INT#", "", "RTC_EVENT#", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "", "", ""; + expander-irq-hog { gpio-hog; gpios = <12 GPIO_ACTIVE_LOW>; @@ -289,6 +301,45 @@ }; }; +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio2>; + + gpio-line-names = + /* 00 */ "SPI6_PCS0#", "", "", "", + /* 04 */ "", "", "", "", + /* 08 */ "", "FAN_RPM", "MIPI_CSI_TRIGGER", "MIPI_CSI_SYNC", + /* 12 */ "", "", "", "", + /* 16 */ "X1_11", "X1_21", "X1_17", "X1_13", + /* 20 */ "X1_15", "X1_9", "", "", + /* 24 */ "", "", "X1_7", "", + /* 28 */ "", "", "", ""; +}; + +&gpio3 { + gpio-line-names = + /* 00 */ "SD2_CD#", "", "", "", + /* 04 */ "", "", "", "SD2_RST#", + /* 08 */ "", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "ENET1_INT#", "ENET2_INT#", + /* 28 */ "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + /* 00 */ "", "", "", "", + /* 04 */ "", "", "", "", + /* 08 */ "", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "DP_INT", "", ""; +}; + &lpi2c3 { #address-cells = <1>; #size-cells = <0>; @@ -495,6 +546,22 @@ status = "okay"; }; +&pcf85063 { + /* RTC_EVENT# from SoM is connected on mainboard */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcf85063>; + interrupt-parent = <&gpio1>; + interrupts = <14 IRQ_TYPE_EDGE_FALLING>; +}; + +&se97_som { + /* TEMP_EVENT# from SoM is connected on mainboard */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_temp_sensor_som>; + interrupt-parent = <&gpio1>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; +}; + &tpm5 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_tpm5>; @@ -533,7 +600,7 @@ samsung,picophy-dc-vol-level-adjust = <7>; status = "okay"; - hub_2_0: hub@1 { + hub_2_0: usb-hub@1 { compatible = "usb424,2517"; reg = <1>; reset-gpios = <&expander1 2 GPIO_ACTIVE_LOW>; @@ -559,22 +626,23 @@ pinctrl_eqos: eqosgrp { fsl,pins = < /* PD | FSEL_2 | DSE X4 */ - MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x51e - MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x4000051e - /* PD | FSEL_2 | DSE X6 */ - MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e - MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e - MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e - MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e - /* PD | FSEL_3 | DSE X6 */ - MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x5fe - MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e + MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x51e + /* SION | HYS | FSEL_2 | DSE X4 */ + MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x4000111e + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x1000 + MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x1000 + MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x1000 + MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x1000 + MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x1000 + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x1400 /* PD | FSEL_2 | DSE X4 */ - MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x51e - MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x51e - MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x51e - MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x51e - MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x51e + MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x51e + MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x51e + MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x51e + MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x51e + MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x51e /* PD | FSEL_3 | DSE X3 */ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e >; @@ -582,7 +650,8 @@ pinctrl_eqos_phy: eqosphygrp { fsl,pins = < - MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x1306 + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x1000 >; }; @@ -590,15 +659,16 @@ fsl,pins = < /* PD | FSEL_2 | DSE X4 */ MX93_PAD_ENET2_MDC__ENET1_MDC 0x51e - MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x4000051e - /* PD | FSEL_2 | DSE X6 */ - MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e - MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e - MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e - MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e - /* PD | FSEL_3 | DSE X6 */ - MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x5fe - MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e + /* SION | HYS | FSEL_2 | DSE X4 */ + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x4000111e + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x1000 + MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x1000 + MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x1000 + MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x1000 + MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x1000 + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x1400 /* PD | FSEL_2 | DSE X4 */ MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x51e MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x51e @@ -612,147 +682,224 @@ pinctrl_fec_phy: fecphygrp { fsl,pins = < - MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x1306 + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x1000 >; }; pinctrl_flexcan1: flexcan1grp { fsl,pins = < - MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x139e - MX93_PAD_PDM_CLK__CAN1_TX 0x139e + /* HYS | PU | FSEL_0 | DSE no drive */ + MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x1200 + /* PU | FSEL_3 | DSE X4 */ + MX93_PAD_PDM_CLK__CAN1_TX 0x039e >; }; pinctrl_flexcan2: flexcan2grp { fsl,pins = < - MX93_PAD_GPIO_IO25__CAN2_TX 0x139e - MX93_PAD_GPIO_IO27__CAN2_RX 0x139e + /* HYS | PU | FSEL_0 | DSE no drive */ + MX93_PAD_GPIO_IO27__CAN2_RX 0x1200 + /* PU | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO25__CAN2_TX 0x039e + >; + }; + + pinctrl_gpio2: gpio2grp { + fsl,pins = < + /* HYS | PD | FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO16__GPIO2_IO16 0x151e + MX93_PAD_GPIO_IO17__GPIO2_IO17 0x151e + MX93_PAD_GPIO_IO18__GPIO2_IO18 0x151e + MX93_PAD_GPIO_IO19__GPIO2_IO19 0x151e + MX93_PAD_GPIO_IO20__GPIO2_IO20 0x151e + MX93_PAD_GPIO_IO21__GPIO2_IO21 0x151e + MX93_PAD_GPIO_IO26__GPIO2_IO26 0x151e + >; + }; + + pinctrl_jtag: jtaggrp { + fsl,pins = < + MX93_PAD_DAP_TCLK_SWCLK__JTAG_MUX_TCK 0x051e + MX93_PAD_DAP_TDI__JTAG_MUX_TDI 0x1200 + MX93_PAD_DAP_TDO_TRACESWO__JTAG_MUX_TDO 0x031e + MX93_PAD_DAP_TMS_SWDIO__JTAG_MUX_TMS 0x1200 >; }; pinctrl_lpi2c3: lpi2c3grp { fsl,pins = < - MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e - MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e + /* SION | HYS | OD | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x4000199e + MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x4000199e >; }; pinctrl_lpi2c5: lpi2c5grp { fsl,pins = < - MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x40000b9e - MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x40000b9e + /* SION | HYS | OD | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x4000199e + MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x4000199e >; }; pinctrl_lpspi6: lpspi6grp { fsl,pins = < - MX93_PAD_GPIO_IO00__LPSPI6_PCS0 0x3fe - MX93_PAD_GPIO_IO01__LPSPI6_SIN 0x3fe - MX93_PAD_GPIO_IO02__LPSPI6_SOUT 0x3fe - MX93_PAD_GPIO_IO03__LPSPI6_SCK 0x3fe + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO00__LPSPI6_PCS0 0x011e + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_GPIO_IO01__LPSPI6_SIN 0x1400 + /* PD | FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO02__LPSPI6_SOUT 0x051e + MX93_PAD_GPIO_IO03__LPSPI6_SCK 0x051e + >; + }; + + pinctrl_pcf85063: pcf85063grp { + fsl,pins = < + MX93_PAD_SAI1_RXD0__GPIO1_IO14 0x1000 + >; + }; + + pinctrl_mipi_csi: mipicsigrp { + fsl,pins = < + MX93_PAD_CCM_CLKO3__CCMSRCGPCMIX_CLKO3 0x051e /* MCLK */ + MX93_PAD_GPIO_IO10__GPIO2_IO10 0x051e /* TRIGGER */ + MX93_PAD_GPIO_IO11__GPIO2_IO11 0x1400 /* SYNC */ >; }; pinctrl_pexp_irq: pexpirqgrp { fsl,pins = < - MX93_PAD_SAI1_TXC__GPIO1_IO12 0x1306 + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_SAI1_TXC__GPIO1_IO12 0x1000 >; }; pinctrl_pwmfan: pwmfangrp { fsl,pins = < - MX93_PAD_GPIO_IO09__GPIO2_IO09 0x1306 + /* HYS | PU | FSEL_0 | no DSE */ + MX93_PAD_GPIO_IO09__GPIO2_IO09 0x1200 + >; + }; + + pinctrl_temp_sensor_som: tempsensorsomgrp { + fsl,pins = < + /* HYS | FSEL_0 | no DSE */ + MX93_PAD_SAI1_TXFS__GPIO1_IO11 0x1000 + >; + }; + + pinctrl_tc9595: tc9595-grp { + fsl,pins = < + /* HYS | PD | FSEL_0 | no DSE */ + MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x1400 >; }; pinctrl_tpm5: tpm5grp { fsl,pins = < - MX93_PAD_GPIO_IO06__TPM5_CH0 0x57e + MX93_PAD_GPIO_IO06__TPM5_CH0 0x57e >; }; pinctrl_tpm6: tpm6grp { fsl,pins = < - MX93_PAD_GPIO_IO08__TPM6_CH0 0x57e + MX93_PAD_GPIO_IO08__TPM6_CH0 0x57e >; }; pinctrl_typec: typecgrp { fsl,pins = < - MX93_PAD_I2C2_SCL__GPIO1_IO02 0x1306 + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_I2C2_SCL__GPIO1_IO02 0x1000 >; }; pinctrl_uart1: uart1grp { fsl,pins = < - MX93_PAD_UART1_RXD__LPUART1_RX 0x31e - MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_UART1_RXD__LPUART1_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_UART1_TXD__LPUART1_TX 0x011e >; }; pinctrl_uart2: uart2grp { fsl,pins = < - MX93_PAD_UART2_TXD__LPUART2_TX 0x31e - MX93_PAD_UART2_RXD__LPUART2_RX 0x31e - MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x51e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_UART2_RXD__LPUART2_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_UART2_TXD__LPUART2_TX 0x011e + /* FSEL_2 | DSE X4 */ + MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x011e >; }; pinctrl_uart3: uart3grp { fsl,pins = < - MX93_PAD_GPIO_IO14__LPUART3_TX 0x31e - MX93_PAD_GPIO_IO15__LPUART3_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO15__LPUART3_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO14__LPUART3_TX 0x011e >; }; pinctrl_uart6: uart6grp { fsl,pins = < - MX93_PAD_GPIO_IO04__LPUART6_TX 0x31e - MX93_PAD_GPIO_IO05__LPUART6_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO05__LPUART6_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO04__LPUART6_TX 0x011e >; }; pinctrl_uart8: uart8grp { fsl,pins = < - MX93_PAD_GPIO_IO12__LPUART8_TX 0x31e - MX93_PAD_GPIO_IO13__LPUART8_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO13__LPUART8_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO12__LPUART8_TX 0x011e >; }; pinctrl_usdhc2_gpio: usdhc2gpiogrp { fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x1000 >; }; + /* enable SION for data and cmd pad due to ERR052021 */ pinctrl_usdhc2_hs: usdhc2hsgrp { fsl,pins = < - /* HYS | PD | PU | FSEL_3 | DSE X5 */ - MX93_PAD_SD2_CLK__USDHC2_CLK 0x17be - /* HYS | PD | PU | FSEL_3 | DSE X4 */ - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - /* HYS | PD | PU | FSEL_3 | DSE X3 */ - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x138e - /* PD | PU | FSEL_2 | DSE X3 */ - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x50e + /* PD | FSEL_3 | DSE X5 */ + MX93_PAD_SD2_CLK__USDHC2_CLK 0x05be + /* HYS | PU | FSEL_3 | DSE X4 */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000139e + /* HYS | PU | FSEL_3 | DSE X3 */ + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e + /* FSEL_2 | DSE X3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x010e >; }; + /* enable SION for data and cmd pad due to ERR052021 */ pinctrl_usdhc2_uhs: usdhc2uhsgrp { fsl,pins = < - /* HYS | PD | PU | FSEL_3 | DSE X6 */ - MX93_PAD_SD2_CLK__USDHC2_CLK 0x17fe - /* HYS | PD | PU | FSEL_3 | DSE X4 */ - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x139e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x139e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x139e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x139e - /* PD | PU | FSEL_2 | DSE X3 */ - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x50e + /* PD | FSEL_3 | DSE X6 */ + MX93_PAD_SD2_CLK__USDHC2_CLK 0x05fe + /* HYS | PU | FSEL_3 | DSE X4 */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000139e + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000139e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000139e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000139e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000139e + /* FSEL_2 | DSE X3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x010e >; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts index da8f19a646a9..0b4b3bb866d0 100644 --- a/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352-mba93xxla.dts @@ -26,6 +26,8 @@ aliases { eeprom0 = &eeprom0; + ethernet0 = &fec; + ethernet1 = &eqos; rtc0 = &pcf85063; rtc1 = &bbnsm_rtc; }; @@ -207,6 +209,16 @@ }; &gpio1 { + gpio-line-names = + /* 00 */ "", "", "USB_C_ALERT#", "PMIC_IRQ#", + /* 04 */ "", "", "", "", + /* 08 */ "", "", "", "BM2_TEMP_EVENT_MOD#", + /* 12 */ "PEX_INT#", "", "RTC_EVENT#", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "", "", ""; + expander-irq-hog { gpio-hog; gpios = <12 GPIO_ACTIVE_LOW>; @@ -222,19 +234,63 @@ }; }; +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio2>; + + gpio-line-names = + /* 00 */ "", "", "", "", + /* 04 */ "", "", "", "AFE_RESET#", + /* 08 */ "AFE_SYNC", "AFE_DRDY", "MIPI_CSI_TRIGGER", "MIPI_CSI_SYNC", + /* 12 */ "", "", "", "", + /* 16 */ "X1_19", "X1_29", "X1_25", "X1_21", + /* 20 */ "X1_23", "X1_17", "", "", + /* 24 */ "AFE_INT#", "", "X1_15", "", + /* 28 */ "", "", "", ""; +}; + &gpio3 { + gpio-line-names = + /* 00 */ "SD2_CD#", "", "", "", + /* 04 */ "", "", "", "SD2_RST#", + /* 08 */ "", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "ENET1_INT#", "ENET2_INT#", + /* 28 */ "", "", "", ""; + ethphy-eqos-irq-hog { gpio-hog; gpios = <26 GPIO_ACTIVE_LOW>; input; - line-name = "ENET0_IRQ#"; + line-name = "ENET1_INT#"; }; ethphy-fec-irq-hog { gpio-hog; gpios = <27 GPIO_ACTIVE_LOW>; input; - line-name = "ENET1_IRQ#"; + line-name = "ENET2_INT#"; + }; +}; + +&gpio4 { + gpio-line-names = + /* 00 */ "", "", "", "", + /* 04 */ "", "", "", "", + /* 08 */ "", "", "", "", + /* 12 */ "", "", "", "", + /* 16 */ "", "", "", "", + /* 20 */ "", "", "", "", + /* 24 */ "", "", "", "", + /* 28 */ "", "DP_INT", "", ""; + + dp-int-hog { + gpio-hog; + gpios = <29 GPIO_ACTIVE_LOW>; + input; + line-name = "DP_INT"; }; }; @@ -371,7 +427,7 @@ #gpio-cells = <2>; vcc-supply = <®_3v3>; gpio-line-names = "LCD_RESET#", "LCD_PWR_EN", - "LCD_BL_EN", "DP_EN", + "LCD_BLT_EN", "DP_EN", "MIPI_CSI_EN", "MIPI_CSI_RST#", "USER_LED1", "USER_LED2"; }; @@ -414,6 +470,13 @@ }; }; +&lpspi6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpspi6>, <&pinctrl_lpspi6_cs>; + cs-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + &lpuart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; @@ -447,13 +510,21 @@ }; &pcf85063 { - /* RTC_EVENT# is connected on MBa93xxLA */ + /* RTC_EVENT# from SoM is connected on mainboard */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcf85063>; interrupt-parent = <&gpio1>; interrupts = <14 IRQ_TYPE_EDGE_FALLING>; }; +&se97_som { + /* TEMP_EVENT# from SoM is connected on mainboard */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_temp_sensor_som>; + interrupt-parent = <&gpio1>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; +}; + &tpm5 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_tpm5>; @@ -486,7 +557,7 @@ samsung,picophy-dc-vol-level-adjust = <7>; status = "okay"; - hub_2_0: hub@1 { + hub_2_0: usb-hub@1 { compatible = "usb424,2517"; reg = <1>; reset-gpios = <&expander1 2 GPIO_ACTIVE_LOW>; @@ -499,7 +570,7 @@ pinctrl-0 = <&pinctrl_usdhc2_hs>, <&pinctrl_usdhc2_gpio>; pinctrl-1 = <&pinctrl_usdhc2_uhs>, <&pinctrl_usdhc2_gpio>; pinctrl-2 = <&pinctrl_usdhc2_uhs>, <&pinctrl_usdhc2_gpio>; - cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; vmmc-supply = <®_usdhc2_vmmc>; bus-width = <4>; no-sdio; @@ -509,25 +580,39 @@ }; &iomuxc { + pinctrl_afe: afegrp { + fsl,pins = < + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO07__GPIO2_IO07 0x011e + /* PD | FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO08__GPIO2_IO08 0x051e + /* HYS | PD */ + MX93_PAD_GPIO_IO09__GPIO2_IO09 0x1400 + /* HYS */ + MX93_PAD_GPIO_IO24__GPIO2_IO24 0x1000 + >; + }; + pinctrl_eqos: eqosgrp { fsl,pins = < /* PD | FSEL_2 | DSE X4 */ - MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x51e - MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x4000051e - /* PD | FSEL_2 | DSE X6 */ - MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e - MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e - MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e - MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e - /* PD | FSEL_3 | DSE X6 */ - MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x5fe - MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e + MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x51e + /* SION | HYS | FSEL_2 | DSE X4 */ + MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x4000111e + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x1000 + MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x1000 + MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x1000 + MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x1000 + MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x1000 + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x1400 /* PD | FSEL_2 | DSE X4 */ - MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x51e - MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x51e - MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x51e - MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x51e - MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x51e + MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x51e + MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x51e + MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x51e + MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x51e + MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x51e /* PD | FSEL_3 | DSE X3 */ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e >; @@ -535,7 +620,8 @@ pinctrl_eqos_phy: eqosphygrp { fsl,pins = < - MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x1306 + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x1000 >; }; @@ -543,15 +629,16 @@ fsl,pins = < /* PD | FSEL_2 | DSE X4 */ MX93_PAD_ENET2_MDC__ENET1_MDC 0x51e - MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x4000051e - /* PD | FSEL_2 | DSE X6 */ - MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e - MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e - MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e - MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e - /* PD | FSEL_3 | DSE X6 */ - MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x5fe - MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e + /* SION | HYS | FSEL_2 | DSE X4 */ + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x4000111e + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x1000 + MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x1000 + MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x1000 + MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x1000 + MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x1000 + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x1400 /* PD | FSEL_2 | DSE X4 */ MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x51e MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x51e @@ -565,139 +652,216 @@ pinctrl_fec_phy: fecphygrp { fsl,pins = < - MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x1306 + /* HYS | FSEL_0 | DSE no drive */ + MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x1000 >; }; pinctrl_flexcan1: flexcan1grp { fsl,pins = < - MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x139e - MX93_PAD_PDM_CLK__CAN1_TX 0x139e + /* HYS | PU | FSEL_0 | DSE no drive */ + MX93_PAD_PDM_BIT_STREAM0__CAN1_RX 0x1200 + /* PU | FSEL_3 | DSE X4 */ + MX93_PAD_PDM_CLK__CAN1_TX 0x039e >; }; pinctrl_flexcan2: flexcan2grp { fsl,pins = < - MX93_PAD_GPIO_IO25__CAN2_TX 0x139e - MX93_PAD_GPIO_IO27__CAN2_RX 0x139e + /* HYS | PU | FSEL_0 | DSE no drive */ + MX93_PAD_GPIO_IO27__CAN2_RX 0x1200 + /* PU | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO25__CAN2_TX 0x039e + >; + }; + + pinctrl_gpio2: gpio2grp { + fsl,pins = < + /* HYS | PD | FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO16__GPIO2_IO16 0x151e + MX93_PAD_GPIO_IO17__GPIO2_IO17 0x151e + MX93_PAD_GPIO_IO18__GPIO2_IO18 0x151e + MX93_PAD_GPIO_IO19__GPIO2_IO19 0x151e + MX93_PAD_GPIO_IO20__GPIO2_IO20 0x151e + MX93_PAD_GPIO_IO21__GPIO2_IO21 0x151e + MX93_PAD_GPIO_IO26__GPIO2_IO26 0x151e + >; + }; + + pinctrl_jtag: jtaggrp { + fsl,pins = < + MX93_PAD_DAP_TCLK_SWCLK__JTAG_MUX_TCK 0x051e + MX93_PAD_DAP_TDI__JTAG_MUX_TDI 0x1200 + MX93_PAD_DAP_TDO_TRACESWO__JTAG_MUX_TDO 0x031e + MX93_PAD_DAP_TMS_SWDIO__JTAG_MUX_TMS 0x1200 >; }; pinctrl_lpi2c3: lpi2c3grp { fsl,pins = < - MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e - MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e + /* SION | HYS | OD | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x4000199e + MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x4000199e >; }; pinctrl_lpi2c5: lpi2c5grp { fsl,pins = < - MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x40000b9e - MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x40000b9e + /* SION | HYS | OD | FSEL_3 | DSE X4 */ + MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x4000199e + MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x4000199e + >; + }; + + pinctrl_lpspi6: lpspi6grp { + fsl,pins = < + /* HYS | PD | FSEL_0 | DSE no drive */ + MX93_PAD_GPIO_IO01__LPSPI6_SIN 0x1400 + /* PD | FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO02__LPSPI6_SOUT 0x051e + MX93_PAD_GPIO_IO03__LPSPI6_SCK 0x051e + >; + }; + + pinctrl_lpspi6_cs: lpspi6csgrp { + fsl,pins = < + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO00__GPIO2_IO00 0x011e + >; + }; + + pinctrl_mipi_csi: mipicsigrp { + fsl,pins = < + MX93_PAD_CCM_CLKO3__CCMSRCGPCMIX_CLKO3 0x051e /* MCLK */ + MX93_PAD_GPIO_IO10__GPIO2_IO10 0x051e /* TRIGGER */ + MX93_PAD_GPIO_IO11__GPIO2_IO11 0x1400 /* SYNC */ >; }; pinctrl_pcf85063: pcf85063grp { fsl,pins = < - MX93_PAD_SAI1_RXD0__GPIO1_IO14 0x1306 + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_SAI1_RXD0__GPIO1_IO14 0x1000 >; }; pinctrl_pexp_irq: pexpirqgrp { fsl,pins = < - MX93_PAD_SAI1_TXC__GPIO1_IO12 0x1306 + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_SAI1_TXC__GPIO1_IO12 0x1000 >; }; pinctrl_tc9595: tc9595-grp { fsl,pins = < - /* DP_IRQ */ - MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x1306 + /* HYS | PD | FSEL_0 | no DSE */ + MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x1400 + >; + }; + + pinctrl_temp_sensor_som: tempsensorsomgrp { + fsl,pins = < + /* HYS | FSEL_0 | no DSE */ + MX93_PAD_SAI1_TXFS__GPIO1_IO11 0x1000 >; }; pinctrl_tpm5: tpm5grp { fsl,pins = < - MX93_PAD_GPIO_IO06__TPM5_CH0 0x57e + MX93_PAD_GPIO_IO06__TPM5_CH0 0x57e >; }; pinctrl_typec: typecgrp { fsl,pins = < - MX93_PAD_I2C2_SCL__GPIO1_IO02 0x1306 + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_I2C2_SCL__GPIO1_IO02 0x1000 >; }; pinctrl_uart1: uart1grp { fsl,pins = < - MX93_PAD_UART1_RXD__LPUART1_RX 0x31e - MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_UART1_RXD__LPUART1_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_UART1_TXD__LPUART1_TX 0x011e >; }; pinctrl_uart2: uart2grp { fsl,pins = < - MX93_PAD_UART2_TXD__LPUART2_TX 0x31e - MX93_PAD_UART2_RXD__LPUART2_RX 0x31e - MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x51e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_UART2_RXD__LPUART2_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_UART2_TXD__LPUART2_TX 0x011e + MX93_PAD_SAI1_TXD0__LPUART2_RTS_B 0x011e >; }; pinctrl_uart3: uart3grp { fsl,pins = < - MX93_PAD_GPIO_IO14__LPUART3_TX 0x31e - MX93_PAD_GPIO_IO15__LPUART3_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO15__LPUART3_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO14__LPUART3_TX 0x011e >; }; pinctrl_uart6: uart6grp { fsl,pins = < - MX93_PAD_GPIO_IO04__LPUART6_TX 0x31e - MX93_PAD_GPIO_IO05__LPUART6_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO05__LPUART6_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO04__LPUART6_TX 0x011e >; }; pinctrl_uart8: uart8grp { fsl,pins = < - MX93_PAD_GPIO_IO12__LPUART8_TX 0x31e - MX93_PAD_GPIO_IO13__LPUART8_RX 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_GPIO_IO13__LPUART8_RX 0x1000 + /* FSEL_2 | DSE X4 */ + MX93_PAD_GPIO_IO12__LPUART8_TX 0x011e >; }; pinctrl_usdhc2_gpio: usdhc2gpiogrp { fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e + /* HYS | FSEL_0 | No DSE */ + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x1000 >; }; + /* enable SION for data and cmd pad due to ERR052021 */ pinctrl_usdhc2_hs: usdhc2hsgrp { fsl,pins = < - /* HYS | PD | PU | FSEL_3 | DSE X5 */ - MX93_PAD_SD2_CLK__USDHC2_CLK 0x17be - /* HYS | PD | PU | FSEL_3 | DSE X4 */ - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - /* HYS | PD | PU | FSEL_3 | DSE X3 */ - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x138e - /* PD | PU | FSEL_2 | DSE X3 */ - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x50e + /* PD | FSEL_3 | DSE X5 */ + MX93_PAD_SD2_CLK__USDHC2_CLK 0x05be + /* HYS | PU | FSEL_3 | DSE X4 */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000139e + /* HYS | PU | FSEL_3 | DSE X3 */ + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e + /* FSEL_2 | DSE X3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x010e >; }; + /* enable SION for data and cmd pad due to ERR052021 */ pinctrl_usdhc2_uhs: usdhc2uhsgrp { fsl,pins = < - /* HYS | PD | PU | FSEL_3 | DSE X6 */ - MX93_PAD_SD2_CLK__USDHC2_CLK 0x17fe - /* HYS | PD | PU | FSEL_3 | DSE X4 */ - MX93_PAD_SD2_CMD__USDHC2_CMD 0x139e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x139e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x139e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x139e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x139e - /* PD | PU | FSEL_2 | DSE X3 */ - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x50e + /* PD | FSEL_3 | DSE X6 */ + MX93_PAD_SD2_CLK__USDHC2_CLK 0x05fe + /* HYS | PU | FSEL_3 | DSE X4 */ + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000139e + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000139e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000139e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000139e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000139e + /* FSEL_2 | DSE X3 */ + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x010e >; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi index edbd8cad35bc..2cabdae24227 100644 --- a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi @@ -19,26 +19,12 @@ linux,cma { compatible = "shared-dma-pool"; reusable; - alloc-ranges = <0 0x60000000 0 0x40000000>; + alloc-ranges = <0 0x80000000 0 0x40000000>; size = <0 0x10000000>; linux,cma-default; }; }; - reg_v1v8: regulator-v1v8 { - compatible = "regulator-fixed"; - regulator-name = "V_1V8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - reg_v3v3: regulator-v3v3 { - compatible = "regulator-fixed"; - regulator-name = "V_3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - /* SD2 RST# via PMIC SW_EN */ reg_usdhc2_vmmc: regulator-usdhc2 { compatible = "regulator-fixed"; @@ -47,14 +33,14 @@ regulator-name = "VSD_3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - vin-supply = <®_v3v3>; + vin-supply = <&buck4>; gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; &adc1 { - vref-supply = <®_v1v8>; + vref-supply = <&buck5>; }; &flexspi1 { @@ -105,6 +91,91 @@ reg = <0x1b>; }; + pca9451a: pmic@25 { + compatible = "nxp,pca9451a"; + reg = <0x25>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pca9451>; + interrupt-parent = <&gpio1>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW>; + + regulators { + /* V_0V8_SOC - hw developer guide: 0.75 .. 0.9 */ + buck1: BUCK1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + /* V_DDRQ - 1.1 LPDDR4 or 0.6 LPDDR4X */ + buck2: BUCK2 { + regulator-name = "BUCK2"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + /* V_3V3 - EEPROM, RTC, ... */ + buck4: BUCK4 { + regulator-name = "BUCK4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + /* V_1V8 - SPI NOR, eMMC, RAM VDD1... */ + buck5: BUCK5 { + regulator-name = "BUCK5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* V_1V1 - RAM VDD2*/ + buck6: BUCK6 { + regulator-name = "BUCK6"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + /* V_1V8_BBSM, fix 1.8 */ + ldo1: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* V_0V8_ANA */ + ldo4: LDO4 { + regulator-name = "LDO4"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + regulator-boot-on; + regulator-always-on; + }; + + /* V_SD2 - 3.3/1.8V USDHC2 io Voltage */ + ldo5: LDO5 { + regulator-name = "LDO5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + pcf85063: rtc@51 { compatible = "nxp,pcf85063a"; reg = <0x51>; @@ -116,28 +187,28 @@ reg = <0x53>; pagesize = <16>; read-only; - vcc-supply = <®_v3v3>; + vcc-supply = <&buck4>; }; eeprom1: eeprom@57 { compatible = "atmel,24c64"; reg = <0x57>; pagesize = <32>; - vcc-supply = <®_v3v3>; + vcc-supply = <&buck4>; }; /* protectable identification memory (part of M24C64-D @57) */ eeprom@5f { compatible = "atmel,24c64d-wl"; reg = <0x5f>; - vcc-supply = <®_v3v3>; + vcc-supply = <&buck4>; }; imu@6a { compatible = "st,ism330dhcx"; reg = <0x6a>; - vdd-supply = <®_v3v3>; - vddio-supply = <®_v3v3>; + vdd-supply = <&buck4>; + vddio-supply = <&buck4>; }; }; @@ -146,6 +217,8 @@ pinctrl-0 = <&pinctrl_usdhc1>; pinctrl-1 = <&pinctrl_usdhc1>; pinctrl-2 = <&pinctrl_usdhc1>; + vmmc-supply = <&buck4>; + vqmmc-supply = <&buck5>; bus-width = <8>; non-removable; no-sdio; @@ -156,61 +229,71 @@ &wdog3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; status = "okay"; }; &iomuxc { pinctrl_flexspi1: flexspi1grp { fsl,pins = < - MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x3fe - MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x3fe - MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x3fe - MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x3fe - MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x3fe - MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x3fe + /* FSEL 3 | DSE X6 */ + MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x01fe + MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x01fe + /* HYS | PU | FSEL 3 | DSE X6 */ + MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x13fe + MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x13fe + /* HYS | FSEL 3 | DSE X6 (external PU) */ + MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x11fe + MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x11fe >; }; pinctrl_lpi2c1: lpi2c1grp { fsl,pins = < - MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e - MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + /* SION | OD | FSEL 3 | DSE X4 */ + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x4000199e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x4000199e >; }; pinctrl_pca9451: pca9451grp { fsl,pins = < - MX93_PAD_I2C2_SDA__GPIO1_IO03 0x1306 + /* HYS | PU */ + MX93_PAD_I2C2_SDA__GPIO1_IO03 0x1200 >; }; pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { fsl,pins = < - MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x1306 + /* FSEL 2 | DSE X2 */ + MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x106 >; }; + /* enable SION for data and cmd pad due to ERR052021 */ pinctrl_usdhc1: usdhc1grp { fsl,pins = < - /* HYS | PU | PD | FSEL_3 | X5 */ - MX93_PAD_SD1_CLK__USDHC1_CLK 0x17be - MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x17be - /* HYS | PU | FSEL_3 | X5 */ - MX93_PAD_SD1_CMD__USDHC1_CMD 0x13be - /* HYS | PU | FSEL_3 | X4 */ - MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x139e - MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x139e - MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x139e - MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x139e - MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x139e - MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x139e - MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x139e - MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x139e + /* PD | FSEL 3 | DSE X5 */ + MX93_PAD_SD1_CLK__USDHC1_CLK 0x5be + /* HYS | FSEL 0 | no drive */ + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1000 + /* HYS | FSEL 3 | X5 */ + MX93_PAD_SD1_CMD__USDHC1_CMD 0x400011be + /* HYS | FSEL 3 | X4 */ + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000119e + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000119e + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000119e + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000119e + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000119e + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000119e + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000119e + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000119e >; }; pinctrl_wdog: wdoggrp { fsl,pins = < + /* PU | FSEL 1 | DSE X4 */ MX93_PAD_WDOG_ANY__WDOG1_WDOG_ANY 0x31e >; }; diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi index 4a3f42355cb8..04b9b3d31f4f 100644 --- a/arch/arm64/boot/dts/freescale/imx93.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93.dtsi @@ -69,6 +69,13 @@ enable-method = "psci"; #cooling-cells = <2>; cpu-idle-states = <&cpu_pd_wait>; + i-cache-size = <32768>; + i-cache-line-size = <64>; + i-cache-sets = <128>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l0>; }; A55_1: cpu@100 { @@ -78,8 +85,43 @@ enable-method = "psci"; #cooling-cells = <2>; cpu-idle-states = <&cpu_pd_wait>; + i-cache-size = <32768>; + i-cache-line-size = <64>; + i-cache-sets = <128>; + d-cache-size = <32768>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l1>; }; + l2_cache_l0: l2-cache-l0 { + compatible = "cache"; + cache-size = <65536>; + cache-line-size = <64>; + cache-sets = <256>; + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + + l2_cache_l1: l2-cache-l1 { + compatible = "cache"; + cache-size = <65536>; + cache-line-size = <64>; + cache-sets = <256>; + cache-level = <2>; + cache-unified; + next-level-cache = <&l3_cache>; + }; + + l3_cache: l3-cache { + compatible = "cache"; + cache-size = <262144>; + cache-line-size = <64>; + cache-sets = <256>; + cache-level = <3>; + cache-unified; + }; }; osc_32k: clock-osc-32k { @@ -425,6 +467,7 @@ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; dmas = <&edma1 22 0 FSL_EDMA_RX>, <&edma1 21 0 0>; dma-names = "rx", "tx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -524,6 +567,7 @@ clock-names = "ipg_clk", "ipg_clk_app", "pll8k"; dmas = <&edma1 29 0 5>; dma-names = "rx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -846,6 +890,7 @@ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; dmas = <&edma2 59 0 FSL_EDMA_RX>, <&edma2 58 0 0>; dma-names = "rx", "tx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -859,6 +904,7 @@ clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; dmas = <&edma2 61 0 FSL_EDMA_RX>, <&edma2 60 0 0>; dma-names = "rx", "tx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -878,6 +924,7 @@ clock-names = "ipg", "phy", "spba", "pll_ipg"; dmas = <&edma2 65 0 FSL_EDMA_RX>, <&edma2 66 0 0>; dma-names = "rx", "tx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -1105,7 +1152,7 @@ <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>; assigned-clock-rates = <100000000>, <250000000>; intf_mode = <&wakeupmix_gpr 0x28>; - snps,clk-csr = <0>; + snps,clk-csr = <6>; nvmem-cells = <ð_mac2>; nvmem-cell-names = "mac-address"; status = "disabled"; diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts index d14a54ab4fd4..37a1d4ca1b20 100644 --- a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts @@ -5,6 +5,7 @@ /dts-v1/; +#include <dt-bindings/pwm/pwm.h> #include "imx95.dtsi" / { @@ -17,6 +18,11 @@ serial0 = &lpuart1; }; + bt_sco_codec: audio-codec-bt-sco { + #sound-dai-cells = <1>; + compatible = "linux,bt-sco"; + }; + chosen { stdout-path = &lpuart1; }; @@ -26,6 +32,13 @@ reg = <0x0 0x80000000 0 0x80000000>; }; + fan0: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&tpm6 2 4000000 PWM_POLARITY_INVERTED>; + cooling-levels = <64 128 192 255>; + }; + reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -40,6 +53,34 @@ }; }; + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SW"; + }; + + reg_audio_pwr: regulator-audio-pwr { + compatible = "regulator-fixed"; + regulator-name = "audio-pwr"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&i2c4_gpio_expander_21 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + reg_audio_slot: regulator-audio-slot { + compatible = "regulator-fixed"; + regulator-name = "audio-wm8962"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&i2c4_gpio_expander_21 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + status = "disabled"; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-name = "M.2-power"; @@ -79,6 +120,116 @@ enable-active-high; off-on-delay-us = <12000>; }; + + sound-bt-sco { + compatible = "simple-audio-card"; + simple-audio-card,name = "bt-sco-audio"; + simple-audio-card,format = "dsp_a"; + simple-audio-card,bitclock-inversion; + simple-audio-card,frame-master = <&btcpu>; + simple-audio-card,bitclock-master = <&btcpu>; + + btcpu: simple-audio-card,cpu { + sound-dai = <&sai1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + + simple-audio-card,codec { + sound-dai = <&bt_sco_codec 1>; + }; + }; + + sound-micfil { + compatible = "fsl,imx-audio-card"; + model = "micfil-audio"; + + pri-dai-link { + link-name = "micfil hifi"; + format = "i2s"; + cpu { + sound-dai = <&micfil>; + }; + }; + }; + + sound-wm8962 { + compatible = "fsl,imx-audio-wm8962"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hp>; + model = "wm8962-audio"; + audio-cpu = <&sai3>; + audio-codec = <&wm8962>; + hp-det-gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>; + audio-routing = "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "Ext Spk", "SPKOUTL", + "Ext Spk", "SPKOUTR", + "AMIC", "MICBIAS", + "IN3R", "AMIC", + "IN1R", "AMIC"; + }; +}; + +&flexspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexspi1>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexspi1_reset>; + reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <200000000>; + spi-tx-bus-width = <8>; + spi-rx-bus-width = <8>; + }; +}; + +&lpi2c4 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c4>; + status = "okay"; + + wm8962: audio-codec@1a { + compatible = "wlf,wm8962"; + reg = <0x1a>; + clocks = <&scmi_clk IMX95_CLK_SAI3>; + DCVDD-supply = <®_audio_pwr>; + DBVDD-supply = <®_audio_pwr>; + AVDD-supply = <®_audio_pwr>; + CPVDD-supply = <®_audio_pwr>; + MICVDD-supply = <®_audio_pwr>; + PLLVDD-supply = <®_audio_pwr>; + SPKVDD1-supply = <®_audio_pwr>; + SPKVDD2-supply = <®_audio_pwr>; + gpio-cfg = < 0x0000 /* 0:Default */ + 0x0000 /* 1:Default */ + 0x0000 /* 2:FN_DMICCLK */ + 0x0000 /* 3:Default */ + 0x0000 /* 4:FN_DMICCDAT */ + 0x0000 /* 5:Default */ + >; + }; + + i2c4_gpio_expander_21: gpio@21 { + compatible = "nxp,pcal6408"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio2>; + interrupts = <18 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c4_pcal6408>; + vcc-supply = <®_3p3v>; + }; }; &lpi2c7 { @@ -108,6 +259,23 @@ status = "okay"; }; +&micfil { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pdm>; + assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>, + <&scmi_clk IMX95_CLK_AUDIOPLL2>, + <&scmi_clk IMX95_CLK_PDM>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, + <3612672000>, <393216000>, + <361267200>, <49152000>; + status = "okay"; +}; + &mu7 { status = "okay"; }; @@ -128,6 +296,42 @@ status = "okay"; }; +&sai1 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai1>; + assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>, + <&scmi_clk IMX95_CLK_AUDIOPLL2>, + <&scmi_clk IMX95_CLK_SAI1>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, + <3612672000>, <393216000>, + <361267200>, <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + +&sai3 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>, + <&scmi_clk IMX95_CLK_AUDIOPLL2>, + <&scmi_clk IMX95_CLK_SAI3>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, + <3612672000>, <393216000>, + <361267200>, <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + &usdhc1 { pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; pinctrl-0 = <&pinctrl_usdhc1>; @@ -159,12 +363,53 @@ }; &scmi_iomuxc { + pinctrl_flexspi1: flexspi1grp { + fsl,pins = < + IMX95_PAD_XSPI1_SS0_B__FLEXSPI1_A_SS0_B 0x3fe + IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK 0x3fe + IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS 0x3fe + IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0 0x3fe + IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1 0x3fe + IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2 0x3fe + IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3 0x3fe + IMX95_PAD_XSPI1_DATA4__FLEXSPI1_A_DATA_BIT4 0x3fe + IMX95_PAD_XSPI1_DATA5__FLEXSPI1_A_DATA_BIT5 0x3fe + IMX95_PAD_XSPI1_DATA6__FLEXSPI1_A_DATA_BIT6 0x3fe + IMX95_PAD_XSPI1_DATA7__FLEXSPI1_A_DATA_BIT7 0x3fe + >; + }; + + pinctrl_flexspi1_reset: flexspi1-reset-grp { + fsl,pins = < + IMX95_PAD_XSPI1_SS1_B__GPIO5_IO_BIT11 0x3fe + >; + }; + + pinctrl_hp: hpgrp { + fsl,pins = < + IMX95_PAD_GPIO_IO11__GPIO2_IO_BIT11 0x31e + >; + }; + + pinctrl_i2c4_pcal6408: i2c4pcal6498grp { + fsl,pins = < + IMX95_PAD_GPIO_IO18__GPIO2_IO_BIT18 0x31e + >; + }; + pinctrl_i2c7_pcal6524: i2c7pcal6524grp { fsl,pins = < IMX95_PAD_GPIO_IO36__GPIO5_IO_BIT16 0x31e >; }; + pinctrl_lpi2c4: lpi2c4grp { + fsl,pins = < + IMX95_PAD_GPIO_IO30__LPI2C4_SDA 0x40000b9e + IMX95_PAD_GPIO_IO31__LPI2C4_SCL 0x40000b9e + >; + }; + pinctrl_lpi2c7: lpi2c7grp { fsl,pins = < IMX95_PAD_GPIO_IO08__LPI2C7_SDA 0x40000b9e @@ -184,6 +429,54 @@ >; }; + pinctrl_pdm: pdmgrp { + fsl,pins = < + IMX95_PAD_PDM_CLK__AONMIX_TOP_PDM_CLK 0x31e + IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_PDM_BIT_STREAM_BIT0 0x31e + >; + }; + + pinctrl_sai1: sai1grp { + fsl,pins = < + IMX95_PAD_SAI1_RXD0__AONMIX_TOP_SAI1_RX_DATA_BIT0 0x31e + IMX95_PAD_SAI1_TXC__AONMIX_TOP_SAI1_TX_BCLK 0x31e + IMX95_PAD_SAI1_TXFS__AONMIX_TOP_SAI1_TX_SYNC 0x31e + IMX95_PAD_SAI1_TXD0__AONMIX_TOP_SAI1_TX_DATA_BIT0 0x31e + >; + }; + + pinctrl_sai2: sai2grp { + fsl,pins = < + IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_SAI2_RX_BCLK 0x31e + IMX95_PAD_ENET2_MDC__NETCMIX_TOP_SAI2_RX_SYNC 0x31e + IMX95_PAD_ENET2_TD3__NETCMIX_TOP_SAI2_RX_DATA_BIT0 0x31e + IMX95_PAD_ENET2_TD2__NETCMIX_TOP_SAI2_RX_DATA_BIT1 0x31e + IMX95_PAD_ENET2_TXC__NETCMIX_TOP_SAI2_TX_BCLK 0x31e + IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_SAI2_TX_SYNC 0x31e + IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_SAI2_TX_DATA_BIT0 0x31e + IMX95_PAD_ENET2_RXC__NETCMIX_TOP_SAI2_TX_DATA_BIT1 0x31e + IMX95_PAD_ENET2_RD0__NETCMIX_TOP_SAI2_TX_DATA_BIT2 0x31e + IMX95_PAD_ENET2_RD1__NETCMIX_TOP_SAI2_TX_DATA_BIT3 0x31e + IMX95_PAD_ENET2_RD2__NETCMIX_TOP_SAI2_MCLK 0x31e + >; + }; + + pinctrl_sai3: sai3grp { + fsl,pins = < + IMX95_PAD_GPIO_IO17__SAI3_MCLK 0x31e + IMX95_PAD_GPIO_IO16__SAI3_TX_BCLK 0x31e + IMX95_PAD_GPIO_IO26__SAI3_TX_SYNC 0x31e + IMX95_PAD_GPIO_IO20__SAI3_RX_DATA_BIT0 0x31e + IMX95_PAD_GPIO_IO21__SAI3_TX_DATA_BIT0 0x31e + >; + }; + + pinctrl_tpm6: tpm6grp { + fsl,pins = < + IMX95_PAD_GPIO_IO19__TPM6_CH2 0x51e + >; + }; + pinctrl_uart1: uart1grp { fsl,pins = < IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x31e @@ -287,3 +580,50 @@ >; }; }; + +&thermal_zones { + a55-thermal { + trips { + atrip2: trip2 { + temperature = <55000>; + hysteresis = <2000>; + type = "active"; + }; + + atrip3: trip3 { + temperature = <65000>; + hysteresis = <2000>; + type = "active"; + }; + + atrip4: trip4 { + temperature = <75000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + map1 { + trip = <&atrip2>; + cooling-device = <&fan0 0 1>; + }; + + map2 { + trip = <&atrip3>; + cooling-device = <&fan0 1 2>; + }; + + map3 { + trip = <&atrip4>; + cooling-device = <&fan0 2 3>; + }; + }; + }; +}; + +&tpm6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm6>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi index 1bbf9a0468f6..03661e76550f 100644 --- a/arch/arm64/boot/dts/freescale/imx95.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi @@ -3,6 +3,7 @@ * Copyright 2024 NXP */ +#include <dt-bindings/dma/fsl-edma.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -27,7 +28,7 @@ reg = <0x0>; enable-method = "psci"; #cooling-cells = <2>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; i-cache-size = <32768>; i-cache-line-size = <64>; @@ -44,7 +45,7 @@ reg = <0x100>; enable-method = "psci"; #cooling-cells = <2>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; i-cache-size = <32768>; i-cache-line-size = <64>; @@ -61,7 +62,7 @@ reg = <0x200>; enable-method = "psci"; #cooling-cells = <2>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; i-cache-size = <32768>; i-cache-line-size = <64>; @@ -78,7 +79,7 @@ reg = <0x300>; enable-method = "psci"; #cooling-cells = <2>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; i-cache-size = <32768>; i-cache-line-size = <64>; @@ -93,7 +94,7 @@ device_type = "cpu"; compatible = "arm,cortex-a55"; reg = <0x400>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; enable-method = "psci"; #cooling-cells = <2>; @@ -110,7 +111,7 @@ device_type = "cpu"; compatible = "arm,cortex-a55"; reg = <0x500>; - power-domains = <&scmi_devpd IMX95_PERF_A55>; + power-domains = <&scmi_perf IMX95_PERF_A55>; power-domain-names = "perf"; enable-method = "psci"; #cooling-cells = <2>; @@ -187,7 +188,7 @@ compatible = "cache"; cache-size = <524288>; cache-line-size = <64>; - cache-sets = <1024>; + cache-sets = <512>; cache-level = <3>; cache-unified; }; @@ -221,6 +222,13 @@ }; }; + dummy: clock-dummy { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + clock-output-names = "dummy"; + }; + clk_ext1: clock-ext1 { compatible = "fixed-clock"; #clock-cells = <0>; @@ -281,7 +289,7 @@ firmware { scmi { compatible = "arm,scmi"; - mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>; + mboxes = <&mu2 5 0>, <&mu2 3 0>, <&mu2 3 1>, <&mu2 5 1>; shmem = <&scmi_buf0>, <&scmi_buf1>; #address-cells = <1>; #size-cells = <0>; @@ -318,7 +326,7 @@ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>; }; - thermal-zones { + thermal_zones: thermal-zones { a55-thermal { polling-delay-passive = <250>; polling-delay = <2000>; @@ -405,6 +413,152 @@ #address-cells = <1>; #size-cells = <1>; + edma2: dma-controller@42000000 { + compatible = "fsl,imx95-edma5"; + reg = <0x42000000 0x210000>; + #dma-cells = <3>; + dma-channels = <64>; + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>; + clock-names = "dma"; + }; + + edma3: dma-controller@42210000 { + compatible = "fsl,imx95-edma5"; + reg = <0x42210000 0x210000>; + #dma-cells = <3>; + dma-channels = <64>; + interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>; + clock-names = "dma"; + }; + mu7: mailbox@42430000 { compatible = "fsl,imx95-mu"; reg = <0x42430000 0x10000>; @@ -464,6 +618,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 8 0 0>, <&edma2 9 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -476,6 +632,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 10 0 0>, <&edma2 11 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -488,6 +646,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI3>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 12 0 0>, <&edma2 13 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -500,6 +660,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI4>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 14 0 0>, <&edma2 15 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -510,6 +672,8 @@ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART3>; clock-names = "ipg"; + dmas = <&edma2 18 0 FSL_EDMA_RX>, <&edma2 17 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -520,6 +684,8 @@ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART4>; clock-names = "ipg"; + dmas = <&edma2 20 0 FSL_EDMA_RX>, <&edma2 19 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -530,6 +696,8 @@ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART5>; clock-names = "ipg"; + dmas = <&edma2 22 0 FSL_EDMA_RX>, <&edma2 21 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -540,6 +708,110 @@ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART6>; clock-names = "ipg"; + dmas = <&edma2 24 0 FSL_EDMA_RX>, <&edma2 23 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + flexcan2: can@425b0000 { + compatible = "fsl,imx95-flexcan"; + reg = <0x425b0000 0x10000>; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, + <&scmi_clk IMX95_CLK_CAN2>; + clock-names = "ipg", "per"; + assigned-clocks = <&scmi_clk IMX95_CLK_CAN2>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + status = "disabled"; + }; + + flexcan3: can@42600000 { + compatible = "fsl,imx95-flexcan"; + reg = <0x42600000 0x10000>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, + <&scmi_clk IMX95_CLK_CAN3>; + clock-names = "ipg", "per"; + assigned-clocks = <&scmi_clk IMX95_CLK_CAN3>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + status = "disabled"; + }; + + flexspi1: spi@425e0000 { + compatible = "nxp,imx8mm-fspi"; + reg = <0x425e0000 0x10000>, <0x28000000 0x8000000>; + reg-names = "fspi_base", "fspi_mmap"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_FLEXSPI1>, + <&scmi_clk IMX95_CLK_FLEXSPI1>; + clock-names = "fspi_en", "fspi"; + assigned-clocks = <&scmi_clk IMX95_CLK_FLEXSPI1>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1>; + assigned-clock-rates = <200000000>; + status = "disabled"; + }; + + sai3: sai@42650000 { + compatible = "fsl,imx95-sai"; + reg = <0x42650000 0x10000>; + interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI3>, <&dummy>, + <&dummy>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&edma2 61 0 FSL_EDMA_RX>, <&edma2 60 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + sai4: sai@42660000 { + compatible = "fsl,imx95-sai"; + reg = <0x42660000 0x10000>; + interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI4>, <&dummy>, + <&dummy>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&edma2 68 0 FSL_EDMA_RX>, <&edma2 67 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + sai5: sai@42670000 { + compatible = "fsl,imx95-sai"; + reg = <0x42670000 0x10000>; + interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI5>, <&dummy>, + <&dummy>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&edma2 70 0 FSL_EDMA_RX>, <&edma2 69 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + xcvr: xcvr@42680000 { + compatible = "fsl,imx95-xcvr"; + reg = <0x42680000 0x800>, <0x42680800 0x400>, + <0x42680c00 0x080>, <0x42680e00 0x080>; + reg-names = "ram", "regs", "rxfifo", "txfifo"; + interrupts = /* XCVR IRQ 0 */ + <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>, + /* XCVR IRQ 1 */ + <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, + <&scmi_clk IMX95_CLK_SPDIF>, + <&dummy>, + <&scmi_clk IMX95_CLK_AUDIOXCVR>; + clock-names = "ipg", "phy", "spba", "pll_ipg"; + dmas = <&edma2 65 0 1>, <&edma2 66 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -550,6 +822,8 @@ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART7>; clock-names = "ipg"; + dmas = <&edma2 26 0 FSL_EDMA_RX>, <&edma2 25 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -560,6 +834,8 @@ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART8>; clock-names = "ipg"; + dmas = <&edma2 28 0 FSL_EDMA_RX>, <&edma2 27 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -572,6 +848,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 71 0 0>, <&edma2 72 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -584,6 +862,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 73 0 0>, <&edma2 74 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -596,6 +876,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 75 0 0>, <&edma2 76 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -608,6 +890,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma2 77 0 0>, <&edma2 78 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -620,6 +904,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI5>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 79 0 0>, <&edma2 80 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -632,6 +918,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI6>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 81 0 0>, <&edma2 82 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -644,6 +932,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI7>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 83 0 0>, <&edma2 84 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -656,6 +946,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI8>, <&scmi_clk IMX95_CLK_BUSWAKEUP>; clock-names = "per", "ipg"; + dmas = <&edma2 85 0 0>, <&edma2 86 0 FSL_EDMA_RX>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -667,6 +959,34 @@ #mbox-cells = <2>; status = "disabled"; }; + + flexcan4: can@427c0000 { + compatible = "fsl,imx95-flexcan"; + reg = <0x427c0000 0x10000>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, + <&scmi_clk IMX95_CLK_CAN4>; + clock-names = "ipg", "per"; + assigned-clocks = <&scmi_clk IMX95_CLK_CAN4>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + status = "disabled"; + }; + + flexcan5: can@427d0000 { + compatible = "fsl,imx95-flexcan"; + reg = <0x427d0000 0x10000>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSWAKEUP>, + <&scmi_clk IMX95_CLK_CAN5>; + clock-names = "ipg", "per"; + assigned-clocks = <&scmi_clk IMX95_CLK_CAN5>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + status = "disabled"; + }; }; aips3: bus@42800000 { @@ -796,6 +1116,46 @@ #address-cells = <1>; #size-cells = <1>; + edma1: dma-controller@44000000 { + compatible = "fsl,imx93-edma3"; + reg = <0x44000000 0x200000>; + #dma-cells = <3>; + dma-channels = <31>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSAON>; + clock-names = "dma"; + }; + mu1: mailbox@44220000 { compatible = "fsl,imx95-mu"; reg = <0x44220000 0x10000>; @@ -830,6 +1190,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX> ; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -842,6 +1204,8 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; + dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX> ; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -854,6 +1218,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI1>, <&scmi_clk IMX95_CLK_BUSAON>; clock-names = "per", "ipg"; + dmas = <&edma1 16 0 FSL_EDMA_RX>, <&edma1 17 0 0> ; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -866,6 +1232,8 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI2>, <&scmi_clk IMX95_CLK_BUSAON>; clock-names = "per", "ipg"; + dmas = <&edma1 18 0 FSL_EDMA_RX>, <&edma1 19 0 0> ; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -876,6 +1244,8 @@ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART1>; clock-names = "ipg"; + dmas = <&edma1 21 0 FSL_EDMA_RX>, <&edma1 20 0 0>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -886,6 +1256,54 @@ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; clocks = <&scmi_clk IMX95_CLK_LPUART2>; clock-names = "ipg"; + dmas = <&edma1 23 0 FSL_EDMA_RX>, <&edma1 22 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + flexcan1: can@443a0000 { + compatible = "fsl,imx95-flexcan"; + reg = <0x443a0000 0x10000>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSAON>, + <&scmi_clk IMX95_CLK_CAN1>; + clock-names = "ipg", "per"; + assigned-clocks = <&scmi_clk IMX95_CLK_CAN1>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <40000000>; + fsl,clk-source = /bits/ 8 <0>; + status = "disabled"; + }; + + sai1: sai@443b0000 { + compatible = "fsl,imx95-sai"; + reg = <0x443b0000 0x10000>; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSAON>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI1>, <&dummy>, + <&dummy>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + dmas = <&edma1 25 0 FSL_EDMA_RX>, <&edma1 24 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + micfil: micfil@44520000 { + compatible = "fsl,imx95-micfil", "fsl,imx93-micfil"; + reg = <0x44520000 0x10000>; + interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSAON>, + <&scmi_clk IMX95_CLK_PDM>, + <&scmi_clk IMX95_CLK_AUDIOPLL1>, + <&scmi_clk IMX95_CLK_AUDIOPLL2>, + <&dummy>; + clock-names = "ipg_clk", "ipg_clk_app", + "pll8k", "pll11k", "clkext3"; + dmas = <&edma1 6 0 5>; + dma-names = "rx"; status = "disabled"; }; @@ -1188,5 +1606,37 @@ power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>; status = "disabled"; }; + + netcmix_blk_ctrl: syscon@4c810000 { + compatible = "nxp,imx95-netcmix-blk-ctrl", "syscon"; + reg = <0x0 0x4c810000 0x0 0x10000>; + #clock-cells = <1>; + clocks = <&scmi_clk IMX95_CLK_BUSNETCMIX>; + assigned-clocks = <&scmi_clk IMX95_CLK_BUSNETCMIX>; + assigned-clock-parents = <&scmi_clk IMX95_CLK_SYSPLL1_PFD1_DIV2>; + assigned-clock-rates = <133333333>; + power-domains = <&scmi_devpd IMX95_PD_NETC>; + status = "disabled"; + }; + + sai2: sai@4c880000 { + compatible = "fsl,imx95-sai"; + reg = <0x0 0x4c880000 0x0 0x10000>; + interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&scmi_clk IMX95_CLK_BUSNETCMIX>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI2>, <&dummy>, + <&dummy>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; + power-domains = <&scmi_devpd IMX95_PD_NETC>; + dmas = <&edma2 59 0 FSL_EDMA_RX>, <&edma2 58 0 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + ddr-pmu@4e090dc0 { + compatible = "fsl,imx95-ddr-pmu", "fsl,imx93-ddr-pmu"; + reg = <0x0 0x4e090dc0 0x0 0x200>; + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; + }; }; }; diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/freescale/mba8mx.dtsi index 815241526a0d..c60c7a9e54af 100644 --- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi +++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi @@ -185,6 +185,8 @@ reset-gpios = <&expander2 7 GPIO_ACTIVE_LOW>; reset-assert-us = <500000>; reset-deassert-us = <500>; + interrupt-parent = <&expander2>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; }; }; }; @@ -237,7 +239,6 @@ }; &i2c2 { - clock-frequency = <100000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; pinctrl-1 = <&pinctrl_i2c2_gpio>; @@ -258,6 +259,11 @@ reg = <0x1f>; }; + /* + * TUSB8041 is at 0x41, but not connected by default + * Note: TUSB8041 only supports 100 kHz! + */ + eeprom3: eeprom@57 { compatible = "nxp,se97b", "atmel,24c02"; reg = <0x57>; @@ -274,7 +280,6 @@ }; &i2c3 { - clock-frequency = <100000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c3>; pinctrl-1 = <&pinctrl_i2c3_gpio>; diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi index 65f7b5a50eb5..1b2b20c6126d 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi @@ -27,6 +27,7 @@ fman@1a00000 { reg = <0xf0000 0x1000>; fsl,fman-ports = <&fman0_rx_0x10 &fman0_tx_0x30>; pcsphy-handle = <&pcsphy6>; + pcs-handle = <&pcsphy6>; }; mdio@f1000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi index 3f70482c98c3..55d78f6f7c6c 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi @@ -27,6 +27,7 @@ fman@1a00000 { reg = <0xf2000 0x1000>; fsl,fman-ports = <&fman0_rx_0x11 &fman0_tx_0x31>; pcsphy-handle = <&pcsphy7>; + pcs-handle = <&pcsphy7>; }; mdio@f3000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi index 78841c1f3252..18916a860c2e 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi @@ -26,6 +26,7 @@ fman@1a00000 { fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>; ptp-timer = <&ptp_timer0>; pcsphy-handle = <&pcsphy0>; + pcs-handle = <&pcsphy0>; }; mdio@e1000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi index 1f43fa666222..e90af445a293 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi @@ -26,6 +26,7 @@ fman@1a00000 { fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>; ptp-timer = <&ptp_timer0>; pcsphy-handle = <&pcsphy1>; + pcs-handle = <&pcsphy1>; }; mdio@e3000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi index de0aa017701d..fec93905bc81 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi @@ -26,6 +26,7 @@ fman@1a00000 { fsl,fman-ports = <&fman0_rx_0x0a &fman0_tx_0x2a>; ptp-timer = <&ptp_timer0>; pcsphy-handle = <&pcsphy2>; + pcs-handle = <&pcsphy2>; }; mdio@e5000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi index 6904aa5d8e54..2aa953faa62b 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi @@ -26,6 +26,7 @@ fman@1a00000 { fsl,fman-ports = <&fman0_rx_0x0b &fman0_tx_0x2b>; ptp-timer = <&ptp_timer0>; pcsphy-handle = <&pcsphy3>; + pcs-handle = <&pcsphy3>; }; mdio@e7000 { diff --git a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi index a3d29d470297..948e39411415 100644 --- a/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi +++ b/arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi @@ -26,6 +26,7 @@ fman@1a00000 { fsl,fman-ports = <&fman0_rx_0x0c &fman0_tx_0x2c>; ptp-timer = <&ptp_timer0>; pcsphy-handle = <&pcsphy4>; + pcs-handle = <&pcsphy4>; }; mdio@e9000 { diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi index fc19ae2e8d3b..fa054bfe7d5c 100644 --- a/arch/arm64/boot/dts/freescale/s32g2.dtsi +++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi @@ -114,6 +114,56 @@ #size-cells = <1>; ranges = <0 0 0 0x80000000>; + pinctrl: pinctrl@4009c240 { + compatible = "nxp,s32g2-siul2-pinctrl"; + /* MSCR0-MSCR101 registers on siul2_0 */ + reg = <0x4009c240 0x198>, + /* MSCR112-MSCR122 registers on siul2_1 */ + <0x44010400 0x2c>, + /* MSCR144-MSCR190 registers on siul2_1 */ + <0x44010480 0xbc>, + /* IMCR0-IMCR83 registers on siul2_0 */ + <0x4009ca40 0x150>, + /* IMCR119-IMCR397 registers on siul2_1 */ + <0x44010c1c 0x45c>, + /* IMCR430-IMCR495 registers on siul2_1 */ + <0x440110f8 0x108>; + + jtag_pins: jtag-pins { + jtag-grp0 { + pinmux = <0x0>; + input-enable; + bias-pull-up; + slew-rate = <166>; + }; + + jtag-grp1 { + pinmux = <0x11>; + slew-rate = <166>; + }; + + jtag-grp2 { + pinmux = <0x40>; + input-enable; + bias-pull-down; + slew-rate = <166>; + }; + + jtag-grp3 { + pinmux = <0x23c0>, + <0x23d0>, + <0x2320>; + }; + + jtag-grp4 { + pinmux = <0x51>; + input-enable; + bias-pull-up; + slew-rate = <166>; + }; + }; + }; + uart0: serial@401c8000 { compatible = "nxp,s32g2-linflexuart", "fsl,s32v234-linflexuart"; diff --git a/arch/arm64/boot/dts/freescale/s32g274a-evb.dts b/arch/arm64/boot/dts/freescale/s32g274a-evb.dts index 00070c949e2a..dbe498798bd9 100644 --- a/arch/arm64/boot/dts/freescale/s32g274a-evb.dts +++ b/arch/arm64/boot/dts/freescale/s32g274a-evb.dts @@ -34,5 +34,6 @@ }; &usdhc0 { + disable-wp; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts b/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts index b3fc12899cae..ab1e5caaeae7 100644 --- a/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts +++ b/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dts @@ -40,5 +40,6 @@ }; &usdhc0 { + disable-wp; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi index c1b08992754b..b4226a9143c8 100644 --- a/arch/arm64/boot/dts/freescale/s32g3.dtsi +++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright 2021-2023 NXP + * Copyright 2021-2024 NXP * * Authors: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com> * Ciprian Costea <ciprianmarian.costea@nxp.com> @@ -171,6 +171,56 @@ #size-cells = <1>; ranges = <0 0 0 0x80000000>; + pinctrl: pinctrl@4009c240 { + compatible = "nxp,s32g2-siul2-pinctrl"; + /* MSCR0-MSCR101 registers on siul2_0 */ + reg = <0x4009c240 0x198>, + /* MSCR112-MSCR122 registers on siul2_1 */ + <0x44010400 0x2c>, + /* MSCR144-MSCR190 registers on siul2_1 */ + <0x44010480 0xbc>, + /* IMCR0-IMCR83 registers on siul2_0 */ + <0x4009ca40 0x150>, + /* IMCR119-IMCR397 registers on siul2_1 */ + <0x44010c1c 0x45c>, + /* IMCR430-IMCR495 registers on siul2_1 */ + <0x440110f8 0x108>; + + jtag_pins: jtag-pins { + jtag-grp0 { + pinmux = <0x0>; + input-enable; + bias-pull-up; + slew-rate = <166>; + }; + + jtag-grp1 { + pinmux = <0x11>; + slew-rate = <166>; + }; + + jtag-grp2 { + pinmux = <0x40>; + input-enable; + bias-pull-down; + slew-rate = <166>; + }; + + jtag-grp3 { + pinmux = <0x23c0>, + <0x23d0>, + <0x2320>; + }; + + jtag-grp4 { + pinmux = <0x51>; + input-enable; + bias-pull-up; + slew-rate = <166>; + }; + }; + }; + uart0: serial@401c8000 { compatible = "nxp,s32g3-linflexuart", "fsl,s32v234-linflexuart"; diff --git a/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts b/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts index 9d674819876e..176e5af191c8 100644 --- a/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts +++ b/arch/arm64/boot/dts/freescale/s32g399a-rdb3.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright 2021-2023 NXP + * Copyright 2021-2024 NXP * * NXP S32G3 Reference Design Board 3 (S32G-VNP-RDB3) */ @@ -41,5 +41,6 @@ &usdhc0 { bus-width = <8>; + disable-wp; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/s32v234.dtsi b/arch/arm64/boot/dts/freescale/s32v234.dtsi index 42409ec56792..bf608ded5dda 100644 --- a/arch/arm64/boot/dts/freescale/s32v234.dtsi +++ b/arch/arm64/boot/dts/freescale/s32v234.dtsi @@ -89,7 +89,7 @@ }; gic: interrupt-controller@7d001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + compatible = "arm,cortex-a15-gic"; #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; diff --git a/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi b/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi index 4676e3488f54..cb8d54895a77 100644 --- a/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi +++ b/arch/arm64/boot/dts/marvell/cn9130-sr-som.dtsi @@ -136,7 +136,7 @@ }; cp0_mdio_pins: cp0-mdio-pins { - marvell,pins = "mpp40", "mpp41"; + marvell,pins = "mpp0", "mpp1"; marvell,function = "ge"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt6357.dtsi b/arch/arm64/boot/dts/mediatek/mt6357.dtsi index 3330a03c2f74..5fafa842d312 100644 --- a/arch/arm64/boot/dts/mediatek/mt6357.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6357.dtsi @@ -10,6 +10,11 @@ mt6357_pmic: pmic { compatible = "mediatek,mt6357"; + pmic_adc: adc { + compatible = "mediatek,mt6357-auxadc"; + #io-channel-cells = <1>; + }; + regulators { mt6357_vproc_reg: buck-vproc { regulator-name = "vproc"; diff --git a/arch/arm64/boot/dts/mediatek/mt6358.dtsi b/arch/arm64/boot/dts/mediatek/mt6358.dtsi index a1b96013f814..641d452fbc08 100644 --- a/arch/arm64/boot/dts/mediatek/mt6358.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6358.dtsi @@ -10,6 +10,11 @@ interrupt-controller; #interrupt-cells = <2>; + pmic_adc: adc { + compatible = "mediatek,mt6358-auxadc"; + #io-channel-cells = <1>; + }; + mt6358codec: mt6358codec { compatible = "mediatek,mt6358-sound"; mediatek,dmic-mode = <0>; /* two-wires */ diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi index df3e822232d3..8e1b8c85c6ed 100644 --- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi @@ -9,6 +9,11 @@ interrupt-controller; #interrupt-cells = <2>; + pmic_adc: adc { + compatible = "mediatek,mt6359-auxadc"; + #io-channel-cells = <1>; + }; + mt6359codec: mt6359codec { }; diff --git a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi index 64aeeb24efac..5cbea9cd411f 100644 --- a/arch/arm64/boot/dts/mediatek/mt7981b.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7981b.dtsi @@ -94,6 +94,39 @@ #pwm-cells = <2>; }; + serial@11002000 { + compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x100>; + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "uart", "wakeup"; + clocks = <&infracfg CLK_INFRA_UART0_SEL>, + <&infracfg CLK_INFRA_UART0_CK>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + serial@11003000 { + compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart"; + reg = <0 0x11003000 0 0x100>; + interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "uart", "wakeup"; + clocks = <&infracfg CLK_INFRA_UART1_SEL>, + <&infracfg CLK_INFRA_UART1_CK>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + + serial@11004000 { + compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x100>; + interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "uart", "wakeup"; + clocks = <&infracfg CLK_INFRA_UART2_SEL>, + <&infracfg CLK_INFRA_UART2_CK>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + i2c@11007000 { compatible = "mediatek,mt7981-i2c"; reg = <0 0x11007000 0 0x1000>, @@ -109,6 +142,48 @@ status = "disabled"; }; + spi@11009000 { + compatible = "mediatek,mt7981-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x11009000 0 0x1000>; + interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI2_CK>, + <&infracfg CLK_INFRA_SPI2_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi@1100a000 { + compatible = "mediatek,mt7981-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100a000 0 0x1000>; + interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI0_CK>, + <&infracfg CLK_INFRA_SPI0_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi@1100b000 { + compatible = "mediatek,mt7981-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100b000 0 0x1000>; + interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&topckgen CLK_TOP_CB_M_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI1_CK>, + <&infracfg CLK_INFRA_SPI1_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + pio: pinctrl@11d00000 { compatible = "mediatek,mt7981-pinctrl"; reg = <0 0x11d00000 0 0x1000>, diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi index fa4ab4d2899f..783c333107bc 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi @@ -91,16 +91,11 @@ &dsi0 { status = "okay"; - /delete-property/#size-cells; - /delete-property/#address-cells; /delete-node/panel@0; - ports { - port { - dsi_out: endpoint { - remote-endpoint = <&anx7625_in>; - }; - }; - }; +}; + +&dsi_out { + remote-endpoint = <&anx7625_in>; }; &i2c0 { diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi index 6345e969efae..22924f61ec9e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi @@ -24,7 +24,7 @@ backlight_lcd0: backlight_lcd0 { compatible = "pwm-backlight"; pwms = <&pwm0 0 500000>; - power-supply = <&bl_pp5000>; + power-supply = <®_vsys>; enable-gpios = <&pio 176 0>; brightness-levels = <0 1023>; num-interpolated-steps = <1023>; @@ -47,10 +47,9 @@ it6505_pp18_reg: regulator0 { compatible = "regulator-fixed"; regulator-name = "it6505_pp18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; gpio = <&pio 178 0>; enable-active-high; + vin-supply = <&pp1800_alw>; }; lcd_pp3300: regulator1 { @@ -62,27 +61,16 @@ regulator-boot-on; }; - bl_pp5000: regulator2 { - compatible = "regulator-fixed"; - regulator-name = "bl_pp5000"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; - }; - mmc1_fixed_power: regulator3 { compatible = "regulator-fixed"; regulator-name = "mmc1_power"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; + vin-supply = <&pp3300_alw>; }; mmc1_fixed_io: regulator4 { compatible = "regulator-fixed"; regulator-name = "mmc1_io"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; + vin-supply = <&pp1800_alw>; }; pp1800_alw: regulator5 { @@ -92,6 +80,7 @@ regulator-boot-on; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + vin-supply = <®_vsys>; }; pp3300_alw: regulator6 { @@ -101,6 +90,7 @@ regulator-boot-on; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + vin-supply = <®_vsys>; }; /* system wide semi-regulated power rail from charger */ @@ -868,10 +858,6 @@ domain-supply = <&mt6358_vgpu_reg>; }; -&soc_data { - status = "okay"; -}; - &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins>; diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index fbf145639b8c..266441e999f2 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -872,8 +872,6 @@ mfg_async: power-domain@MT8183_POWER_DOMAIN_MFG_ASYNC { reg = <MT8183_POWER_DOMAIN_MFG_ASYNC>; - clocks = <&topckgen CLK_TOP_MUX_MFG>; - clock-names = "mfg"; #address-cells = <1>; #size-cells = <0>; #power-domain-cells = <1>; @@ -1838,6 +1836,17 @@ phy-names = "dphy"; }; + dpi0: dpi@14015000 { + compatible = "mediatek,mt8183-dpi"; + reg = <0 0x14015000 0 0x1000>; + interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>; + power-domains = <&spm MT8183_POWER_DOMAIN_DISP>; + clocks = <&mmsys CLK_MM_DPI_IF>, + <&mmsys CLK_MM_DPI_MM>, + <&apmixedsys CLK_APMIXED_TVDPLL>; + clock-names = "pixel", "engine", "pll"; + }; + mutex: mutex@14016000 { compatible = "mediatek,mt8183-disp-mutex"; reg = <0 0x14016000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi index afdab5724eaa..682c6ad2574d 100644 --- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi @@ -169,7 +169,7 @@ adsp_mem: memory@60000000 { compatible = "shared-dma-pool"; - reg = <0 0x60000000 0 0xA00000>; + reg = <0 0x60000000 0 0x1000000>; no-map; }; @@ -353,7 +353,8 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&dpi_pins_default>; pinctrl-1 = <&dpi_pins_sleep>; - status = "okay"; + /* TODO Re-enable after DP to Type-C port muxing can be described */ + status = "disabled"; }; &dpi_out { diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi index 4763ed5dc86c..148c332018b0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi @@ -13,6 +13,8 @@ #include <dt-bindings/power/mt8186-power.h> #include <dt-bindings/phy/phy.h> #include <dt-bindings/reset/mt8186-resets.h> +#include <dt-bindings/thermal/thermal.h> +#include <dt-bindings/thermal/mediatek,lvts-thermal.h> / { compatible = "mediatek,mt8186"; @@ -731,7 +733,7 @@ opp-900000000-3 { opp-hz = /bits/ 64 <900000000>; opp-microvolt = <850000>; - opp-supported-hw = <0x8>; + opp-supported-hw = <0xcf>; }; opp-900000000-4 { @@ -743,13 +745,13 @@ opp-900000000-5 { opp-hz = /bits/ 64 <900000000>; opp-microvolt = <825000>; - opp-supported-hw = <0x30>; + opp-supported-hw = <0x20>; }; opp-950000000-3 { opp-hz = /bits/ 64 <950000000>; opp-microvolt = <900000>; - opp-supported-hw = <0x8>; + opp-supported-hw = <0xcf>; }; opp-950000000-4 { @@ -761,13 +763,13 @@ opp-950000000-5 { opp-hz = /bits/ 64 <950000000>; opp-microvolt = <850000>; - opp-supported-hw = <0x30>; + opp-supported-hw = <0x20>; }; opp-1000000000-3 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <950000>; - opp-supported-hw = <0x8>; + opp-supported-hw = <0xcf>; }; opp-1000000000-4 { @@ -779,7 +781,7 @@ opp-1000000000-5 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <875000>; - opp-supported-hw = <0x30>; + opp-supported-hw = <0x20>; }; }; @@ -1361,6 +1363,29 @@ status = "disabled"; }; + lvts: thermal-sensor@1100b000 { + compatible = "mediatek,mt8186-lvts"; + reg = <0 0x1100b000 0 0x1000>; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; + resets = <&infracfg_ao MT8186_INFRA_THERMAL_CTRL_RST>; + nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>; + nvmem-cell-names = "lvts-calib-data-1", "lvts-calib-data-2"; + #thermal-sensor-cells = <1>; + }; + + svs: svs@1100bc00 { + compatible = "mediatek,mt8186-svs"; + reg = <0 0x1100bc00 0 0x400>; + interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; + clock-names = "main"; + nvmem-cells = <&svs_calibration>, <&lvts_efuse_data1>; + nvmem-cell-names = "svs-calibration-data", "t-calibration-data"; + resets = <&infracfg_ao MT8186_INFRA_PTP_CTRL_RST>; + reset-names = "svs_rst"; + }; + pwm0: pwm@1100e000 { compatible = "mediatek,mt8186-disp-pwm", "mediatek,mt8183-disp-pwm"; reg = <0 0x1100e000 0 0x1000>; @@ -1676,6 +1701,18 @@ #address-cells = <1>; #size-cells = <1>; + lvts_efuse_data1: lvts1-calib@1cc { + reg = <0x1cc 0x14>; + }; + + lvts_efuse_data2: lvts2-calib@2f8 { + reg = <0x2f8 0x14>; + }; + + svs_calibration: calib@550 { + reg = <0x550 0x50>; + }; + gpu_speedbin: gpu-speedbin@59c { reg = <0x59c 0x4>; bits = <0 3>; @@ -1824,6 +1861,7 @@ assigned-clocks = <&topckgen CLK_TOP_DPI>; assigned-clock-parents = <&topckgen CLK_TOP_TVDPLL_D2>; interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_LOW 0>; + power-domains = <&spm MT8186_POWER_DOMAIN_DIS>; status = "disabled"; port { @@ -2178,4 +2216,299 @@ power-domains = <&spm MT8186_POWER_DOMAIN_IPE>; }; }; + + thermal_zones: thermal-zones { + cpu-little0-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts MT8186_LITTLE_CPU0>; + + trips { + cpu_little0_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little0_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little0_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little0_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-little1-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts MT8186_LITTLE_CPU1>; + + trips { + cpu_little1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little1_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-little2-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts MT8186_LITTLE_CPU2>; + + trips { + cpu_little2_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little2_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little2_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little2_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cam-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts MT8186_CAM>; + + trips { + cam_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cam_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cam_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nna-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts MT8186_NNA>; + + trips { + nna_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + nna_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + nna_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + adsp-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts MT8186_ADSP>; + + trips { + adsp_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + adsp_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + adsp_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts MT8186_GPU>; + + trips { + gpu_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + gpu_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-big0-thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + thermal-sensors = <&lvts MT8186_BIG_CPU0>; + + trips { + cpu_big0_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_big0_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_big0_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_big0_alert0>; + cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-big1-thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + thermal-sensors = <&lvts MT8186_BIG_CPU1>; + + trips { + cpu_big1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_big1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_big1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_big1_alert0>; + cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8188.dtsi b/arch/arm64/boot/dts/mediatek/mt8188.dtsi index 29d012d28edb..cd27966d2e3c 100644 --- a/arch/arm64/boot/dts/mediatek/mt8188.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8188.dtsi @@ -12,6 +12,9 @@ #include <dt-bindings/phy/phy.h> #include <dt-bindings/pinctrl/mediatek,mt8188-pinfunc.h> #include <dt-bindings/power/mediatek,mt8188-power.h> +#include <dt-bindings/reset/mt8188-resets.h> +#include <dt-bindings/thermal/thermal.h> +#include <dt-bindings/thermal/mediatek,lvts-thermal.h> / { compatible = "mediatek,mt8188"; @@ -417,6 +420,450 @@ method = "smc"; }; + thermal_zones: thermal-zones { + cpu-little0-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts_mcu MT8188_MCU_LITTLE_CPU0>; + + trips { + cpu_little0_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little0_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little0_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little0_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-little1-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts_mcu MT8188_MCU_LITTLE_CPU1>; + + trips { + cpu_little1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little1_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-little2-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts_mcu MT8188_MCU_LITTLE_CPU2>; + + trips { + cpu_little2_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little2_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little2_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little2_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-little3-thermal { + polling-delay = <1000>; + polling-delay-passive = <150>; + thermal-sensors = <&lvts_mcu MT8188_MCU_LITTLE_CPU3>; + + trips { + cpu_little3_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_little3_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_little3_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_little3_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-big0-thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + thermal-sensors = <&lvts_mcu MT8188_MCU_BIG_CPU0>; + + trips { + cpu_big0_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_big0_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_big0_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_big0_alert0>; + cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + cpu-big1-thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + thermal-sensors = <&lvts_mcu MT8188_MCU_BIG_CPU1>; + + trips { + cpu_big1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_big1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_big1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_big1_alert0>; + cooling-device = <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + apu-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_APU>; + + trips { + apu_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + apu_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + apu_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_GPU0>; + + trips { + gpu_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + gpu_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu1-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_GPU1>; + + trips { + gpu1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + gpu1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + gpu1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu1_alert0>; + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + adsp-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_ADSP>; + + trips { + soc_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + soc_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + soc_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + vdo-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_VDO>; + + trips { + soc1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + soc1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + soc1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + infra-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_INFRA>; + + trips { + soc2_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + soc2_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + soc2_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cam1-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_CAM1>; + + trips { + cam1_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cam1_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cam1_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cam2-thermal { + polling-delay = <1000>; + polling-delay-passive = <250>; + thermal-sensors = <&lvts_ap MT8188_AP_CAM2>; + + trips { + cam2_alert0: trip-alert0 { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + cam2_alert1: trip-alert1 { + temperature = <95000>; + hysteresis = <2000>; + type = "hot"; + }; + + cam2_crit: trip-crit { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; + timer: timer { compatible = "arm,armv8-timer"; interrupt-parent = <&gic>; @@ -464,6 +911,7 @@ compatible = "mediatek,mt8188-infracfg-ao", "syscon"; reg = <0 0x10001000 0 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; }; pericfg: syscon@10003000 { @@ -937,6 +1385,17 @@ status = "disabled"; }; + lvts_ap: thermal-sensor@1100b000 { + compatible = "mediatek,mt8188-lvts-ap"; + reg = <0 0x1100b000 0 0xc00>; + interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; + resets = <&infracfg_ao MT8188_INFRA_RST1_THERMAL_CTRL_RST>; + nvmem-cells = <&lvts_efuse_data1>; + nvmem-cell-names = "lvts-calib-data-1"; + #thermal-sensor-cells = <1>; + }; + spi1: spi@11010000 { compatible = "mediatek,mt8188-spi-ipm", "mediatek,spi-ipm"; #address-cells = <1>; @@ -1050,6 +1509,17 @@ status = "disabled"; }; + lvts_mcu: thermal-sensor@11278000 { + compatible = "mediatek,mt8188-lvts-mcu"; + reg = <0 0x11278000 0 0x1000>; + interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&infracfg_ao CLK_INFRA_AO_THERM>; + resets = <&infracfg_ao MT8188_INFRA_RST1_THERMAL_MCU_RST>; + nvmem-cells = <&lvts_efuse_data1>; + nvmem-cell-names = "lvts-calib-data-1"; + #thermal-sensor-cells = <1>; + }; + i2c0: i2c@11280000 { compatible = "mediatek,mt8188-i2c"; reg = <0 0x11280000 0 0x1000>, @@ -1273,6 +1743,17 @@ #clock-cells = <1>; }; + efuse: efuse@11f20000 { + compatible = "mediatek,mt8188-efuse", "mediatek,efuse"; + reg = <0 0x11f20000 0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + lvts_efuse_data1: lvts1-calib@1ac { + reg = <0x1ac 0x40>; + }; + }; + gpu: gpu@13000000 { compatible = "mediatek,mt8188-mali", "arm,mali-valhall-jm"; reg = <0 0x13000000 0 0x4000>; @@ -1287,6 +1768,7 @@ <&spm MT8188_POWER_DOMAIN_MFG3>, <&spm MT8188_POWER_DOMAIN_MFG4>; power-domain-names = "core0", "core1", "core2"; + #cooling-cells = <2>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts index 88123842c818..49664de99b88 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-dojo-r1.dts @@ -82,12 +82,17 @@ pins-low-power-hdmi-disable { pinmux = <PINMUX_GPIO31__FUNC_GPIO31>, <PINMUX_GPIO32__FUNC_GPIO32>, - <PINMUX_GPIO33__FUNC_GPIO33>, - <PINMUX_GPIO34__FUNC_GPIO34>, - <PINMUX_GPIO35__FUNC_GPIO35>; + <PINMUX_GPIO33__FUNC_GPIO33>; input-enable; bias-pull-down; }; + + pins-low-power-hdmi-rsel-disable { + pinmux = <PINMUX_GPIO34__FUNC_GPIO34>, + <PINMUX_GPIO35__FUNC_GPIO35>; + input-enable; + bias-pull-down = <75000>; + }; }; &sound { diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts index 2fe20e0dad83..2d6522c144b7 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts @@ -19,13 +19,18 @@ pins-low-power-hdmi-disable { pinmux = <PINMUX_GPIO31__FUNC_GPIO31>, <PINMUX_GPIO32__FUNC_GPIO32>, - <PINMUX_GPIO33__FUNC_GPIO33>, - <PINMUX_GPIO34__FUNC_GPIO34>, - <PINMUX_GPIO35__FUNC_GPIO35>; + <PINMUX_GPIO33__FUNC_GPIO33>; input-enable; bias-pull-down; }; + pins-low-power-hdmi-rsel-disable { + pinmux = <PINMUX_GPIO34__FUNC_GPIO34>, + <PINMUX_GPIO35__FUNC_GPIO35>; + input-enable; + bias-pull-down = <75000>; + }; + pins-low-power-pcie0-disable { pinmux = <PINMUX_GPIO19__FUNC_GPIO19>, <PINMUX_GPIO20__FUNC_GPIO20>, diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts index dd294ca98194..9049d362a5e0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts @@ -20,13 +20,18 @@ pins-low-power-hdmi-disable { pinmux = <PINMUX_GPIO31__FUNC_GPIO31>, <PINMUX_GPIO32__FUNC_GPIO32>, - <PINMUX_GPIO33__FUNC_GPIO33>, - <PINMUX_GPIO34__FUNC_GPIO34>, - <PINMUX_GPIO35__FUNC_GPIO35>; + <PINMUX_GPIO33__FUNC_GPIO33>; input-enable; bias-pull-down; }; + pins-low-power-hdmi-rsel-disable { + pinmux = <PINMUX_GPIO34__FUNC_GPIO34>, + <PINMUX_GPIO35__FUNC_GPIO35>; + input-enable; + bias-pull-down = <75000>; + }; + pins-low-power-pcie0-disable { pinmux = <PINMUX_GPIO19__FUNC_GPIO19>, <PINMUX_GPIO20__FUNC_GPIO20>, diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi index fe5400e17b0f..75d56b2d5a3d 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi @@ -1228,10 +1228,6 @@ spi-max-frequency = <3000000>; wakeup-source; - keyboard-backlight { - compatible = "google,cros-kbd-led-backlight"; - }; - i2c_tunnel: i2c-tunnel { compatible = "google,cros-ec-i2c-tunnel"; google,remote-bus = <0>; @@ -1401,9 +1397,11 @@ &xhci1 { status = "okay"; + phys = <&u2port1 PHY_TYPE_USB2>; rx-fifo-depth = <3072>; vusb33-supply = <&mt6359_vusb_ldo_reg>; vbus-supply = <&usb_vbus>; + mediatek,u3p-dis-msk = <1>; }; &xhci2 { diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi index 2ee45752583c..e89ba384c4aa 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi @@ -1444,7 +1444,7 @@ <0 0x11293e00 0 0x0100>; reg-names = "mac", "ippc"; interrupts = <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH 0>; - phys = <&u2port1 PHY_TYPE_USB2>; + phys = <&u2port1 PHY_TYPE_USB2>, <&u3port1 PHY_TYPE_USB3>; assigned-clocks = <&topckgen CLK_TOP_USB_TOP_1P>, <&topckgen CLK_TOP_SSUSB_XHCI_1P>; assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D5_D4>, @@ -2037,6 +2037,7 @@ mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0x1000 0x1000>; mediatek,gce-events = <CMDQ_EVENT_VPP0_MDP_RDMA_SOF>, <CMDQ_EVENT_VPP0_MDP_RDMA_FRAME_DONE>; + mediatek,scp = <&scp>; power-domains = <&spm MT8195_POWER_DOMAIN_VPPSYS0>; iommus = <&iommu_vpp M4U_PORT_L4_MDP_RDMA>; clocks = <&vppsys0 CLK_VPP0_MDP_RDMA>; @@ -3251,10 +3252,10 @@ compatible = "mediatek,mt8195-dp-intf"; reg = <0 0x1c015000 0 0x1000>; interrupts = <GIC_SPI 657 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&vdosys0 CLK_VDO0_DP_INTF0>, - <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>, + clocks = <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>, + <&vdosys0 CLK_VDO0_DP_INTF0>, <&apmixedsys CLK_APMIXED_TVDPLL1>; - clock-names = "engine", "pixel", "pll"; + clock-names = "pixel", "engine", "pll"; status = "disabled"; }; @@ -3521,10 +3522,10 @@ reg = <0 0x1c113000 0 0x1000>; interrupts = <GIC_SPI 513 IRQ_TYPE_LEVEL_HIGH 0>; power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; - clocks = <&vdosys1 CLK_VDO1_DP_INTF0_MM>, - <&vdosys1 CLK_VDO1_DPINTF>, + clocks = <&vdosys1 CLK_VDO1_DPINTF>, + <&vdosys1 CLK_VDO1_DP_INTF0_MM>, <&apmixedsys CLK_APMIXED_TVDPLL2>; - clock-names = "engine", "pixel", "pll"; + clock-names = "pixel", "engine", "pll"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts index 4211a992dd9d..7d90112a7e27 100644 --- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts +++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts @@ -4,6 +4,7 @@ * Authors: * Fabien Parent <fparent@baylibre.com> * Bernhard Rosenkränzer <bero@baylibre.com> + * Alexandre Mergnat <amergnat@baylibre.com> */ /dts-v1/; @@ -86,6 +87,28 @@ reg = <0 0x43200000 0 0x00c00000>; }; }; + + sound: sound { + compatible = "mediatek,mt8365-mt6357"; + pinctrl-names = "default", + "dmic", + "miso_off", + "miso_on", + "mosi_off", + "mosi_on"; + pinctrl-0 = <&aud_default_pins>; + pinctrl-1 = <&aud_dmic_pins>; + pinctrl-2 = <&aud_miso_off_pins>; + pinctrl-3 = <&aud_miso_on_pins>; + pinctrl-4 = <&aud_mosi_off_pins>; + pinctrl-5 = <&aud_mosi_on_pins>; + mediatek,platform = <&afe>; + }; +}; + +&afe { + mediatek,dmic-mode = <1>; + status = "okay"; }; &cpu0 { @@ -178,9 +201,72 @@ interrupts-extended = <&pio 145 IRQ_TYPE_LEVEL_HIGH>; interrupt-controller; #interrupt-cells = <2>; + mediatek,micbias0-microvolt = <1900000>; + mediatek,micbias1-microvolt = <1700000>; }; &pio { + aud_default_pins: audiodefault-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_72_CMDAT4__FUNC_I2S3_BCK>, + <MT8365_PIN_73_CMDAT5__FUNC_I2S3_LRCK>, + <MT8365_PIN_74_CMDAT6__FUNC_I2S3_MCK>, + <MT8365_PIN_75_CMDAT7__FUNC_I2S3_DO>; + }; + }; + + aud_dmic_pins: audiodmic-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_117_DMIC0_CLK__FUNC_DMIC0_CLK>, + <MT8365_PIN_118_DMIC0_DAT0__FUNC_DMIC0_DAT0>, + <MT8365_PIN_119_DMIC0_DAT1__FUNC_DMIC0_DAT1>; + }; + }; + + aud_miso_off_pins: misooff-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_53_AUD_CLK_MISO__FUNC_GPIO53>, + <MT8365_PIN_54_AUD_SYNC_MISO__FUNC_GPIO54>, + <MT8365_PIN_55_AUD_DAT_MISO0__FUNC_GPIO55>, + <MT8365_PIN_56_AUD_DAT_MISO1__FUNC_GPIO56>; + input-enable; + bias-pull-down; + drive-strength = <2>; + }; + }; + + aud_miso_on_pins: misoon-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_53_AUD_CLK_MISO__FUNC_AUD_CLK_MISO>, + <MT8365_PIN_54_AUD_SYNC_MISO__FUNC_AUD_SYNC_MISO>, + <MT8365_PIN_55_AUD_DAT_MISO0__FUNC_AUD_DAT_MISO0>, + <MT8365_PIN_56_AUD_DAT_MISO1__FUNC_AUD_DAT_MISO1>; + drive-strength = <6>; + }; + }; + + aud_mosi_off_pins: mosioff-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_49_AUD_CLK_MOSI__FUNC_GPIO49>, + <MT8365_PIN_50_AUD_SYNC_MOSI__FUNC_GPIO50>, + <MT8365_PIN_51_AUD_DAT_MOSI0__FUNC_GPIO51>, + <MT8365_PIN_52_AUD_DAT_MOSI1__FUNC_GPIO52>; + input-enable; + bias-pull-down; + drive-strength = <2>; + }; + }; + + aud_mosi_on_pins: mosion-pins { + clk-dat-pins { + pinmux = <MT8365_PIN_49_AUD_CLK_MOSI__FUNC_AUD_CLK_MOSI>, + <MT8365_PIN_50_AUD_SYNC_MOSI__FUNC_AUD_SYNC_MOSI>, + <MT8365_PIN_51_AUD_DAT_MOSI0__FUNC_AUD_DAT_MOSI0>, + <MT8365_PIN_52_AUD_DAT_MOSI1__FUNC_AUD_DAT_MOSI1>; + drive-strength = <6>; + }; + }; + ethernet_pins: ethernet-pins { phy_reset_pins { pinmux = <MT8365_PIN_133_TDM_TX_DATA1__FUNC_GPIO133>; diff --git a/arch/arm64/boot/dts/mediatek/mt8365.dtsi b/arch/arm64/boot/dts/mediatek/mt8365.dtsi index eb449bfa8803..9c91fe8ea0f9 100644 --- a/arch/arm64/boot/dts/mediatek/mt8365.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8365.dtsi @@ -2,9 +2,11 @@ /* * (C) 2018 MediaTek Inc. * Copyright (C) 2022 BayLibre SAS - * Fabien Parent <fparent@baylibre.com> - * Bernhard Rosenkränzer <bero@baylibre.com> + * Authors: Fabien Parent <fparent@baylibre.com> + * Bernhard Rosenkränzer <bero@baylibre.com> + * Alexandre Mergnat <amergnat@baylibre.com> */ + #include <dt-bindings/clock/mediatek,mt8365-clk.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/irq.h> @@ -812,6 +814,43 @@ reg = <0 0x19020000 0 0x1000>; #clock-cells = <1>; }; + + afe: audio-controller@11220000 { + compatible = "mediatek,mt8365-afe-pcm"; + reg = <0 0x11220000 0 0x1000>; + #sound-dai-cells = <0>; + clocks = <&clk26m>, + <&topckgen CLK_TOP_AUDIO_SEL>, + <&topckgen CLK_TOP_AUD_I2S0_M>, + <&topckgen CLK_TOP_AUD_I2S1_M>, + <&topckgen CLK_TOP_AUD_I2S2_M>, + <&topckgen CLK_TOP_AUD_I2S3_M>, + <&topckgen CLK_TOP_AUD_ENGEN1_SEL>, + <&topckgen CLK_TOP_AUD_ENGEN2_SEL>, + <&topckgen CLK_TOP_AUD_1_SEL>, + <&topckgen CLK_TOP_AUD_2_SEL>, + <&topckgen CLK_TOP_APLL_I2S0_SEL>, + <&topckgen CLK_TOP_APLL_I2S1_SEL>, + <&topckgen CLK_TOP_APLL_I2S2_SEL>, + <&topckgen CLK_TOP_APLL_I2S3_SEL>; + clock-names = "top_clk26m_clk", + "top_audio_sel", + "audio_i2s0_m", + "audio_i2s1_m", + "audio_i2s2_m", + "audio_i2s3_m", + "engen1", + "engen2", + "aud1", + "aud2", + "i2s0_m_sel", + "i2s1_m_sel", + "i2s2_m_sel", + "i2s3_m_sel"; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>; + power-domains = <&spm MT8365_POWER_DOMAIN_AUDIO>; + status = "disabled"; + }; }; timer { diff --git a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts index a06610fff8ad..1ef6262b65c9 100644 --- a/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts +++ b/arch/arm64/boot/dts/mediatek/mt8395-genio-1200-evk.dts @@ -904,8 +904,6 @@ }; &xhci1 { - phys = <&u2port1 PHY_TYPE_USB2>, - <&u3port1 PHY_TYPE_USB3>; vusb33-supply = <&mt6359_vusb_ldo_reg>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts b/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts index e4b2af9489a8..e2e75b8ff918 100644 --- a/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts +++ b/arch/arm64/boot/dts/mediatek/mt8395-kontron-3-5-sbc-i1200.dts @@ -1111,6 +1111,7 @@ /* USB2.0 M.2 Key-B */ &xhci1 { + phys = <&u2port1 PHY_TYPE_USB2>; vusb33-supply = <&mt6359_vusb_ldo_reg>; mediatek,u3p-dis-msk = <0x01>; status = "okay"; diff --git a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts index 4b5f6cf16f70..14ec970c4e49 100644 --- a/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts +++ b/arch/arm64/boot/dts/mediatek/mt8395-radxa-nio-12l.dts @@ -894,10 +894,12 @@ }; &xhci1 { + phys = <&u2port1 PHY_TYPE_USB2>; /* MT7921's USB Bluetooth has issues with USB2 LPM */ usb2-lpm-disable; vusb33-supply = <&mt6359_vusb_ldo_reg>; vbus-supply = <&vsys>; + mediatek,u3p-dis-msk = <1>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts index b89e2be6abae..9482bec1aa57 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-iot-512m.dts @@ -14,6 +14,10 @@ aliases { serial0 = &uart0; + serial10 = &uart10; + serial12 = &uart12; + serial13 = &uart13; + serial14 = &uart14; }; chosen { @@ -33,10 +37,6 @@ }; }; -&uart0 { - status = "okay"; -}; - &clk { assigned-clocks = <&clk CAPLL>, <&clk DDRPLL>, @@ -54,3 +54,75 @@ "integer", "integer"; }; + +&pinctrl { + uart-grp { + pinctrl_uart0: uart0-pins { + nuvoton,pins = <4 14 1>, + <4 15 1>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart10: uart10-pins { + nuvoton,pins = <7 4 2>, + <7 5 2>, + <7 6 2>, + <7 7 2>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart12: uart12-pins { + nuvoton,pins = <2 13 2>, + <2 14 2>, + <2 15 2>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart13: uart13-pins { + nuvoton,pins = <7 12 3>, + <7 13 3>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart14: uart14-pins { + nuvoton,pins = <7 14 2>, + <7 15 2>; + bias-disable; + power-source = <1>; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "okay"; +}; + +&uart10 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart10>; + status = "okay"; +}; + +&uart12 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart12>; + status = "okay"; +}; + +&uart13 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart13>; + status = "okay"; +}; + +&uart14 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart14>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts index a1ebddecb7f8..f6f20a17e501 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts +++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts @@ -14,6 +14,10 @@ aliases { serial0 = &uart0; + serial11 = &uart11; + serial12 = &uart12; + serial14 = &uart14; + serial16 = &uart16; }; chosen { @@ -33,10 +37,6 @@ }; }; -&uart0 { - status = "okay"; -}; - &clk { assigned-clocks = <&clk CAPLL>, <&clk DDRPLL>, @@ -54,3 +54,78 @@ "integer", "integer"; }; + +&pinctrl { + uart-grp { + pinctrl_uart0: uart0-pins { + nuvoton,pins = <4 14 1>, + <4 15 1>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart11: uart11-pins { + nuvoton,pins = <11 0 2>, + <11 1 2>, + <11 2 2>, + <11 3 2>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart12: uart12-pins { + nuvoton,pins = <8 1 2>, + <8 2 2>, + <8 3 2>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart14: uart14-pins { + nuvoton,pins = <8 5 2>, + <8 6 2>, + <8 7 2>; + bias-disable; + power-source = <1>; + }; + + pinctrl_uart16: uart16-pins { + nuvoton,pins = <10 0 2>, + <10 1 2>, + <10 2 2>, + <10 3 2>; + bias-disable; + power-source = <1>; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "okay"; +}; + +&uart11 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart11>; + status = "okay"; +}; + +&uart12 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart12>; + status = "okay"; +}; + +&uart14 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart14>; + status = "okay"; +}; + +&uart16 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart16>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi index 781cdae566a0..e51b98f5bdce 100644 --- a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi +++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi @@ -83,7 +83,7 @@ ranges; sys: system-management@40460000 { - compatible = "nuvoton,ma35d1-reset"; + compatible = "nuvoton,ma35d1-reset", "syscon"; reg = <0x0 0x40460000 0x0 0x200>; #reset-cells = <1>; }; @@ -95,6 +95,155 @@ clocks = <&clk_hxt>; }; + pinctrl: pinctrl@40040000 { + compatible = "nuvoton,ma35d1-pinctrl"; + reg = <0x0 0x40040000 0x0 0xc00>; + #address-cells = <1>; + #size-cells = <1>; + nuvoton,sys = <&sys>; + ranges = <0x0 0x0 0x40040000 0x400>; + + gpioa: gpio@0 { + reg = <0x0 0x40>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPA_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiob: gpio@40 { + reg = <0x40 0x40>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPB_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpioc: gpio@80 { + reg = <0x80 0x40>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPC_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiod: gpio@c0 { + reg = <0xc0 0x40>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPD_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpioe: gpio@100 { + reg = <0x100 0x40>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPE_GATE>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiof: gpio@140 { + reg = <0x140 0x40>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPF_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiog: gpio@180 { + reg = <0x180 0x40>; + interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPG_GATE>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpioh: gpio@1c0 { + reg = <0x1c0 0x40>; + interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPH_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpioi: gpio@200 { + reg = <0x200 0x40>; + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPI_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpioj: gpio@240 { + reg = <0x240 0x40>; + interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPJ_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiok: gpio@280 { + reg = <0x280 0x40>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPK_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiol: gpio@2c0 { + reg = <0x2c0 0x40>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPL_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpiom: gpio@300 { + reg = <0x300 0x40>; + interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPM_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpion: gpio@340 { + reg = <0x340 0x40>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk GPN_GATE>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + uart0: serial@40700000 { compatible = "nuvoton,ma35d1-uart"; reg = <0x0 0x40700000 0x0 0x100>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi index 0ae5a44f7d07..c00db75e3910 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi @@ -33,6 +33,51 @@ status = "okay"; }; + serial@70006300 { + /delete-property/ reg-shift; + status = "okay"; + compatible = "nvidia,tegra30-hsuart"; + reset-names = "serial"; + + bluetooth { + compatible = "brcm,bcm43540-bt"; + device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(H, 5) IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "host-wakeup"; + }; + }; + + i2c@7000c400 { + status = "okay"; + + power-sensor@40 { + compatible = "ti,ina3221"; + reg = <0x40>; + #address-cells = <1>; + #size-cells = <0>; + + input@0 { + reg = <0x0>; + label = "VDD_IN"; + shunt-resistor-micro-ohms = <20000>; + }; + + input@1 { + reg = <0x1>; + label = "VDD_GPU"; + shunt-resistor-micro-ohms = <10000>; + }; + + input@2 { + reg = <0x2>; + label = "VDD_CPU"; + shunt-resistor-micro-ohms = <10000>; + }; + }; + }; + i2c@7000c500 { status = "okay"; @@ -295,6 +340,25 @@ nvidia,sys-clock-req-active-high; }; + mmc@700b0200 { + status = "okay"; + bus-width = <4>; + non-removable; + power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>; + vqmmc-supply = <&vdd_1v8>; + vmmc-supply = <&vdd_3v3_sys>; + #address-cells = <1>; + #size-cells = <0>; + + wifi@1 { + compatible = "brcm,bcm4354-fmac"; + reg = <1>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wake"; + }; + }; + /* eMMC */ mmc@700b0600 { status = "okay"; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi index b4a1108c2dd7..63b94a04308e 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -1319,6 +1319,56 @@ status = "okay"; clock-frequency = <100000>; + power-sensor@42 { + compatible = "ti,ina3221"; + reg = <0x42>; + #address-cells = <1>; + #size-cells = <0>; + + input@0 { + reg = <0x0>; + label = "VDD_MUX"; + shunt-resistor-micro-ohms = <20000>; + }; + + input@1 { + reg = <0x1>; + label = "VDD_5V_IO_SYS"; + shunt-resistor-micro-ohms = <5000>; + }; + + input@2 { + reg = <0x2>; + label = "VDD_3V3_SYS"; + shunt-resistor-micro-ohms = <10000>; + }; + }; + + power-sensor@43 { + compatible = "ti,ina3221"; + reg = <0x43>; + #address-cells = <1>; + #size-cells = <0>; + + input@0 { + reg = <0x0>; + label = "VDD_3V3_IO"; + shunt-resistor-micro-ohms = <10000>; + }; + + input@1 { + reg = <0x1>; + label = "VDD_1V8_IO"; + shunt-resistor-micro-ohms = <10000>; + }; + + input@2 { + reg = <0x2>; + label = "VDD_M2_IN"; + shunt-resistor-micro-ohms = <10000>; + }; + }; + exp1: gpio@74 { compatible = "ti,tca9539"; reg = <0x74>; @@ -1517,6 +1567,7 @@ bus-width = <4>; cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; vqmmc-supply = <&vddio_sdmmc>; vmmc-supply = <&vdd_3v3_sd>; @@ -1603,7 +1654,7 @@ regulator-name = "VDD_3V3_SD"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>; + gpio = <&gpio TEGRA_GPIO(Z, 3) GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_3v3_sys>; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi index cb792041fc62..d977f4901c09 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi @@ -1,146 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 -#include "tegra234.dtsi" #include "tegra234-p3701.dtsi" / { model = "NVIDIA Jetson AGX Orin"; compatible = "nvidia,p3701-0000", "nvidia,tegra234"; - bus@0 { - i2c@3160000 { - status = "okay"; - - eeprom@50 { - compatible = "atmel,24c02"; - reg = <0x50>; - - label = "module"; - vcc-supply = <&vdd_1v8_hs>; - address-width = <8>; - pagesize = <8>; - size = <256>; - read-only; - }; - }; - - spi@3270000 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <102000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - }; - }; - - mmc@3400000 { - status = "okay"; - bus-width = <4>; - cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>; - disable-wp; - }; - - mmc@3460000 { - status = "okay"; - bus-width = <8>; - non-removable; - }; - - padctl@3520000 { - vclamp-usb-supply = <&vdd_1v8_ao>; - avdd-usb-supply = <&vdd_3v3_ao>; - - ports { - usb2-0 { - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-1 { - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-2 { - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-3 { - vbus-supply = <&vdd_5v0_sys>; - }; - }; - }; - - rtc@c2a0000 { - status = "okay"; - }; - - pmc@c360000 { - nvidia,invert-interrupt; - }; - }; - - vdd_5v0_sys: regulator-vdd-5v0-sys { - compatible = "regulator-fixed"; - regulator-name = "VIN_SYS_5V0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; - }; - - vdd_1v8_ls: regulator-vdd-1v8-ls { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_LS"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_1v8_hs: regulator-vdd-1v8-hs { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_HS"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_1v8_ao: regulator-vdd-1v8-ao { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_AO"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_3v3_ao: regulator-vdd-3v3-ao { - compatible = "regulator-fixed"; - regulator-name = "VDD_3V3_AO"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vdd_3v3_pcie: regulator-vdd-3v3-pcie { - compatible = "regulator-fixed"; - regulator-name = "VDD_3V3_PCIE"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH>; - regulator-boot-on; - enable-active-high; - }; - - vdd_12v_pcie: regulator-vdd-12v-pcie { - compatible = "regulator-fixed"; - regulator-name = "VDD_12V_PCIE"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>; - regulator-boot-on; - }; - thermal-zones { tj-thermal { polling-delay = <1000>; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi index 553fa4ba1cd4..0809634e5732 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0008.dtsi @@ -1,145 +1,29 @@ // SPDX-License-Identifier: GPL-2.0 -#include "tegra234.dtsi" #include "tegra234-p3701.dtsi" / { compatible = "nvidia,p3701-0008", "nvidia,tegra234"; - bus@0 { - i2c@3160000 { + thermal-zones { + tj-thermal { + polling-delay = <1000>; + polling-delay-passive = <1000>; status = "okay"; - eeprom@50 { - compatible = "atmel,24c02"; - reg = <0x50>; - label = "module"; - vcc-supply = <&vdd_1v8_hs>; - address-width = <8>; - pagesize = <8>; - size = <256>; - read-only; - }; - }; - - spi@3270000 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <102000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - }; - }; - - mmc@3460000 { - status = "okay"; - bus-width = <8>; - non-removable; - }; - - i2c@c240000 { - status = "okay"; - }; - - i2c@c250000 { - power-sensor@41 { - compatible = "ti,ina3221"; - reg = <0x41>; - #address-cells = <1>; - #size-cells = <0>; - - input@0 { - reg = <0x0>; - label = "CVB_ATX_12V"; - shunt-resistor-micro-ohms = <2000>; - }; - - input@1 { - reg = <0x1>; - label = "CVB_ATX_3V3"; - shunt-resistor-micro-ohms = <2000>; + trips { + tj_trip_active0: active-0 { + temperature = <85000>; + hysteresis = <4000>; + type = "active"; }; - input@2 { - reg = <0x2>; - label = "CVB_ATX_5V"; - shunt-resistor-micro-ohms = <2000>; + tj_trip_active1: active-1 { + temperature = <105000>; + hysteresis = <4000>; + type = "active"; }; }; - - power-sensor@44 { - compatible = "ti,ina219"; - reg = <0x44>; - shunt-resistor = <2000>; - }; - }; - - rtc@c2a0000 { - status = "okay"; }; - - pmc@c360000 { - nvidia,invert-interrupt; - }; - }; - - bpmp { - i2c { - status = "okay"; - - thermal-sensor@4c { - status = "okay"; - reg = <0x4c>; - vcc-supply = <&vdd_1v8_ao>; - }; - }; - - thermal { - status = "okay"; - }; - }; - - vdd_1v8_ao: regulator-vdd-1v8-ao { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_AO"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_1v8_hs: regulator-vdd-1v8-hs { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_HS"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_1v8_ls: regulator-vdd-1v8-ls { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_LS"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vdd_3v3_ao: regulator-vdd-3v3-ao { - compatible = "regulator-fixed"; - regulator-name = "vdd-AO-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vdd_5v0_sys: regulator-vdd-5v0-sys { - compatible = "regulator-fixed"; - regulator-name = "VIN_SYS_5V0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi index 320c8e9b06b4..9086a0d010e5 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701.dtsi @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 +#include "tegra234.dtsi" + / { compatible = "nvidia,p3701", "nvidia,tegra234"; @@ -45,6 +47,63 @@ }; }; + i2c@3160000 { + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + + label = "module"; + vcc-supply = <&vdd_1v8_hs>; + address-width = <8>; + pagesize = <8>; + size = <256>; + read-only; + }; + }; + + spi@3270000 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <102000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + }; + + mmc@3460000 { + status = "okay"; + bus-width = <8>; + non-removable; + }; + + padctl@3520000 { + vclamp-usb-supply = <&vdd_1v8_ao>; + avdd-usb-supply = <&vdd_3v3_ao>; + + ports { + usb2-0 { + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-1 { + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-2 { + vbus-supply = <&vdd_5v0_sys>; + }; + + usb2-3 { + vbus-supply = <&vdd_5v0_sys>; + }; + }; + }; + i2c@c240000 { status = "okay"; @@ -97,5 +156,71 @@ }; }; }; + + rtc@c2a0000 { + status = "okay"; + }; + + pmc@c360000 { + nvidia,invert-interrupt; + }; + }; + + bpmp { + i2c { + status = "okay"; + + thermal-sensor@4c { + compatible = "ti,tmp451"; + status = "okay"; + reg = <0x4c>; + vcc-supply = <&vdd_1v8_ao>; + }; + }; + + thermal { + status = "okay"; + }; + }; + + vdd_1v8_ao: regulator-vdd-1v8-ao { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_AO"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_1v8_hs: regulator-vdd-1v8-hs { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_HS"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_1v8_ls: regulator-vdd-1v8-ls { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_LS"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_3v3_ao: regulator-vdd-3v3-ao { + compatible = "regulator-fixed"; + regulator-name = "VDD_3V3_AO"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_5v0_sys: regulator-vdd-5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "VIN_SYS_5V0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts index 69db584253da..90f12277aede 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts @@ -3,9 +3,9 @@ #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/input/gpio-keys.h> +#include <dt-bindings/sound/rt5640.h> #include "tegra234-p3701-0000.dtsi" -#include "tegra234-p3737-0000.dtsi" / { model = "NVIDIA Jetson AGX Orin Developer Kit"; @@ -22,23 +22,97 @@ }; bus@0 { + aconnect@2900000 { + ahub@2900800 { + i2s@2901000 { + ports { + port@1 { + endpoint { + dai-format = "i2s"; + remote-endpoint = <&rt5640_ep>; + }; + }; + }; + }; + }; + }; + serial@3100000 { compatible = "nvidia,tegra194-hsuart"; reset-names = "serial"; status = "okay"; }; + i2c@3160000 { + status = "okay"; + + eeprom@56 { + compatible = "atmel,24c02"; + reg = <0x56>; + + label = "system"; + vcc-supply = <&vdd_1v8_sys>; + address-width = <8>; + pagesize = <8>; + size = <256>; + read-only; + }; + }; + serial@31d0000 { current-speed = <115200>; status = "okay"; }; + i2c@31e0000 { + status = "okay"; + + audio-codec@1c { + compatible = "realtek,rt5640"; + reg = <0x1c>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA234_MAIN_GPIO(AC, 5) GPIO_ACTIVE_HIGH>; + clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>; + clock-names = "mclk"; + realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>; + realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>; + realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>; + sound-name-prefix = "CVB-RT"; + + port { + rt5640_ep: endpoint { + remote-endpoint = <&i2s1_dap>; + mclk-fs = <256>; + }; + }; + }; + }; + + pwm@3280000 { + status = "okay"; + }; + pwm@32a0000 { assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>; assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>; status = "okay"; }; + pwm@32c0000 { + status = "okay"; + }; + + pwm@32f0000 { + status = "okay"; + }; + + mmc@3400000 { + status = "okay"; + bus-width = <4>; + cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>; + disable-wp; + }; + hda@3510000 { nvidia,model = "NVIDIA Jetson AGX Orin HDA"; status = "okay"; @@ -341,8 +415,11 @@ }; }; - pwm-fan { + fan: pwm-fan { + compatible = "pwm-fan"; cooling-levels = <66 215 255>; + pwms = <&pwm3 0 45334>; + #cooling-cells = <2>; }; serial { @@ -444,4 +521,31 @@ }; }; }; + + vdd_1v8_sys: regulator-vdd-1v8-sys { + compatible = "regulator-fixed"; + regulator-name = "VDD_1V8_SYS"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vdd_3v3_pcie: regulator-vdd-3v3-pcie { + compatible = "regulator-fixed"; + regulator-name = "VDD_3V3_PCIE"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio TEGRA234_MAIN_GPIO(H, 4) GPIO_ACTIVE_HIGH>; + regulator-boot-on; + enable-active-high; + }; + + vdd_12v_pcie: regulator-vdd-12v-pcie { + compatible = "regulator-fixed"; + regulator-name = "VDD_12V_PCIE"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi deleted file mode 100644 index eb79e80a9852..000000000000 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include <dt-bindings/sound/rt5640.h> - -/ { - compatible = "nvidia,p3737-0000"; - - bus@0 { - aconnect@2900000 { - ahub@2900800 { - i2s@2901000 { - ports { - port@1 { - endpoint { - dai-format = "i2s"; - remote-endpoint = <&rt5640_ep>; - }; - }; - }; - }; - }; - }; - - i2c@3160000 { - status = "okay"; - - eeprom@56 { - compatible = "atmel,24c02"; - reg = <0x56>; - - label = "system"; - vcc-supply = <&vdd_1v8_sys>; - address-width = <8>; - pagesize = <8>; - size = <256>; - read-only; - }; - }; - - i2c@31e0000 { - status = "okay"; - - audio-codec@1c { - compatible = "realtek,rt5640"; - reg = <0x1c>; - interrupt-parent = <&gpio>; - interrupts = <TEGRA234_MAIN_GPIO(AC, 5) GPIO_ACTIVE_HIGH>; - clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>; - clock-names = "mclk"; - realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>; - realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>; - realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>; - sound-name-prefix = "CVB-RT"; - - port { - rt5640_ep: endpoint { - remote-endpoint = <&i2s1_dap>; - mclk-fs = <256>; - }; - }; - }; - }; - - pwm@3280000 { - status = "okay"; - }; - - pwm@32c0000 { - status = "okay"; - }; - - pwm@32f0000 { - status = "okay"; - }; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - pwms = <&pwm3 0 45334>; - #cooling-cells = <2>; - }; - - vdd_1v8_sys: regulator-vdd-1v8-sys { - compatible = "regulator-fixed"; - regulator-name = "VDD_1V8_SYS"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; -}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts index bac611d735c5..36e888053746 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts @@ -3,8 +3,8 @@ #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/input/gpio-keys.h> +#include <dt-bindings/sound/rt5640.h> #include "tegra234-p3701-0008.dtsi" -#include "tegra234-p3740-0002.dtsi" / { model = "NVIDIA IGX Orin Development Kit"; @@ -20,6 +20,32 @@ }; bus@0 { + aconnect@2900000 { + ahub@2900800 { + i2s@2901300 { + ports { + port@1 { + endpoint { + dai-format = "i2s"; + remote-endpoint = <&rt5640_ep>; + }; + }; + }; + }; + + i2s@2901500 { + ports { + port@1 { + endpoint { + bitclock-master; + frame-master; + }; + }; + }; + }; + }; + }; + serial@3100000 { compatible = "nvidia,tegra194-hsuart"; reset-names = "serial"; @@ -45,6 +71,40 @@ i2c@31c0000 { status = "okay"; + rt5640: audio-codec@1c { + compatible = "realtek,rt5640"; + reg = <0x1c>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA234_MAIN_GPIO(F, 3) GPIO_ACTIVE_HIGH>; + clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>; + clock-names = "mclk"; + + realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>; + realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>; + realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>; + + sound-name-prefix = "CVB-RT"; + + port { + rt5640_ep: endpoint { + remote-endpoint = <&i2s4_dap>; + mclk-fs = <256>; + }; + }; + }; + + /* carrier board ID EEPROM */ + eeprom@55 { + compatible = "atmel,24c02"; + reg = <0x55>; + + label = "system"; + vcc-supply = <&vdd_1v8_ls>; + address-width = <8>; + pagesize = <8>; + size = <256>; + read-only; + }; }; i2c@31e0000 { @@ -60,6 +120,115 @@ status = "okay"; }; + padctl@3520000 { + status = "okay"; + + pads { + usb2 { + lanes { + usb2-0 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-1 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-2 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-3 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; + }; + + usb3 { + lanes { + usb3-0 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb3-1 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb3-2 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; + }; + }; + + ports { + usb2-0 { + mode = "otg"; + usb-role-switch; + status = "okay"; + }; + + usb2-1 { + mode = "host"; + status = "okay"; + }; + + usb2-2 { + mode = "host"; + status = "okay"; + }; + + usb2-3 { + mode = "host"; + status = "okay"; + }; + + usb3-0 { + nvidia,usb2-companion = <2>; + status = "okay"; + }; + + usb3-1 { + nvidia,usb2-companion = <0>; + status = "okay"; + }; + + usb3-2 { + nvidia,usb2-companion = <1>; + status = "okay"; + }; + }; + }; + + usb@3550000 { + status = "okay"; + + phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>; + phy-names = "usb2-0", "usb3-0"; + }; + + usb@3610000 { + status = "okay"; + + phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-1}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-2}>, + <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-3}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-0}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>, + <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>; + phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", + "usb3-0", "usb3-1", "usb3-2"; + }; + fuse@3810000 { status = "okay"; }; @@ -70,6 +239,37 @@ i2c@c250000 { status = "okay"; + + power-sensor@41 { + compatible = "ti,ina3221"; + reg = <0x41>; + #address-cells = <1>; + #size-cells = <0>; + + input@0 { + reg = <0x0>; + label = "CVB_ATX_12V"; + shunt-resistor-micro-ohms = <2000>; + }; + + input@1 { + reg = <0x1>; + label = "CVB_ATX_3V3"; + shunt-resistor-micro-ohms = <2000>; + }; + + input@2 { + reg = <0x2>; + label = "CVB_ATX_5V"; + shunt-resistor-micro-ohms = <2000>; + }; + }; + + power-sensor@44 { + compatible = "ti,ina219"; + reg = <0x44>; + shunt-resistor = <2000>; + }; }; host1x@13e00000 { @@ -235,4 +435,32 @@ "CVB-RT DMIC1", "CVB-RT MIC", "CVB-RT DMIC2", "CVB-RT MIC"; }; + + vdd_3v3_dp: regulator-vdd-3v3-dp { + compatible = "regulator-fixed"; + regulator-name = "VDD_3V3_DP"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vdd_3v3_sys>; + gpio = <&gpio TEGRA234_MAIN_GPIO(H, 6) 0>; + enable-active-high; + regulator-always-on; + }; + + vdd_3v3_sys: regulator-vdd-3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "VDD_3V3_SYS"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_3v3_wifi: regulator-vdd-3v3-wifi { + compatible = "regulator-fixed"; + regulator-name = "VDD_3V3_WIFI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio TEGRA234_MAIN_GPIO(G, 3) GPIO_ACTIVE_HIGH>; + regulator-boot-on; + enable-active-high; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi deleted file mode 100644 index 527f2f3aee3a..000000000000 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002.dtsi +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include <dt-bindings/sound/rt5640.h> - -/ { - compatible = "nvidia,p3740-0002"; - - bus@0 { - aconnect@2900000 { - ahub@2900800 { - i2s@2901300 { - ports { - port@1 { - endpoint { - dai-format = "i2s"; - remote-endpoint = <&rt5640_ep>; - }; - }; - }; - }; - - i2s@2901500 { - ports { - port@1 { - endpoint { - bitclock-master; - frame-master; - }; - }; - }; - }; - }; - }; - - i2c@31c0000 { - rt5640: audio-codec@1c { - compatible = "realtek,rt5640"; - reg = <0x1c>; - interrupt-parent = <&gpio>; - interrupts = <TEGRA234_MAIN_GPIO(F, 3) GPIO_ACTIVE_HIGH>; - clocks = <&bpmp TEGRA234_CLK_AUD_MCLK>; - clock-names = "mclk"; - - realtek,dmic1-data-pin = <RT5640_DMIC1_DATA_PIN_NONE>; - realtek,dmic2-data-pin = <RT5640_DMIC2_DATA_PIN_NONE>; - realtek,jack-detect-source = <RT5640_JD_SRC_HDA_HEADER>; - - sound-name-prefix = "CVB-RT"; - - port { - rt5640_ep: endpoint { - remote-endpoint = <&i2s4_dap>; - mclk-fs = <256>; - }; - }; - }; - - /* carrier board ID EEPROM */ - eeprom@55 { - compatible = "atmel,24c02"; - reg = <0x55>; - - label = "system"; - vcc-supply = <&vdd_1v8_ls>; - address-width = <8>; - pagesize = <8>; - size = <256>; - read-only; - }; - }; - - padctl@3520000 { - vclamp-usb-supply = <&vdd_1v8_ao>; - avdd-usb-supply = <&vdd_3v3_ao>; - status = "okay"; - - pads { - usb2 { - lanes { - usb2-0 { - nvidia,function = "xusb"; - status = "okay"; - }; - - usb2-1 { - nvidia,function = "xusb"; - status = "okay"; - }; - - usb2-2 { - nvidia,function = "xusb"; - status = "okay"; - }; - - usb2-3 { - nvidia,function = "xusb"; - status = "okay"; - }; - }; - }; - - usb3 { - lanes { - usb3-0 { - nvidia,function = "xusb"; - status = "okay"; - }; - - usb3-1 { - nvidia,function = "xusb"; - status = "okay"; - }; - - usb3-2 { - nvidia,function = "xusb"; - status = "okay"; - }; - }; - }; - }; - - ports { - usb2-0 { - mode = "otg"; - usb-role-switch; - status = "okay"; - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-1 { - mode = "host"; - status = "okay"; - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-2 { - mode = "host"; - status = "okay"; - vbus-supply = <&vdd_5v0_sys>; - }; - - usb2-3 { - mode = "host"; - status = "okay"; - vbus-supply = <&vdd_5v0_sys>; - }; - - usb3-0 { - nvidia,usb2-companion = <2>; - status = "okay"; - }; - - usb3-1 { - nvidia,usb2-companion = <0>; - status = "okay"; - }; - - usb3-2 { - nvidia,usb2-companion = <1>; - status = "okay"; - }; - }; - }; - - usb@3550000 { - status = "okay"; - - phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, - <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>; - phy-names = "usb2-0", "usb3-0"; - }; - - usb@3610000 { - status = "okay"; - - phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>, - <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-1}>, - <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-2}>, - <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-3}>, - <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-0}>, - <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-1}>, - <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>; - phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", - "usb3-0", "usb3-1", "usb3-2"; - }; - }; - - vdd_3v3_dp: regulator-vdd-3v3-dp { - compatible = "regulator-fixed"; - regulator-name = "VDD_3V3_DP"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vdd_3v3_sys>; - gpio = <&gpio TEGRA234_MAIN_GPIO(H, 6) 0>; - enable-active-high; - regulator-always-on; - }; - - vdd_3v3_sys: regulator-vdd-3v3-sys { - compatible = "regulator-fixed"; - regulator-name = "VDD_3V3_SYS"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - vdd_3v3_wifi: regulator-vdd-3v3-wifi { - compatible = "regulator-fixed"; - regulator-name = "VDD_3V3_WIFI"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio TEGRA234_MAIN_GPIO(G, 3) GPIO_ACTIVE_HIGH>; - regulator-boot-on; - enable-active-high; - }; -}; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts index 82a59e33c46c..5dc974bb360c 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767-0000.dts @@ -7,24 +7,7 @@ compatible = "nvidia,p3768-0000+p3767-0000", "nvidia,p3767-0000", "nvidia,tegra234"; model = "NVIDIA Jetson Orin NX Engineering Reference Developer Kit"; - aliases { - serial1 = &uarta; - serial2 = &uarte; - }; - bus@0 { - serial@3100000 { - compatible = "nvidia,tegra194-hsuart"; - reset-names = "serial"; - status = "okay"; - }; - - serial@3140000 { - compatible = "nvidia,tegra194-hsuart"; - reset-names = "serial"; - status = "okay"; - }; - hda@3510000 { nvidia,model = "NVIDIA Jetson Orin NX HDA"; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi index 6d64a24fa251..19340d13f789 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi @@ -9,6 +9,8 @@ aliases { serial0 = &tcu; + serial1 = &uarta; + serial2 = &uarte; }; chosen { @@ -16,6 +18,18 @@ }; bus@0 { + serial@3100000 { + compatible = "nvidia,tegra194-hsuart"; + reset-names = "serial"; + status = "okay"; + }; + + serial@3140000 { + compatible = "nvidia,tegra194-hsuart"; + reset-names = "serial"; + status = "okay"; + }; + i2c@3160000 { status = "okay"; @@ -172,6 +186,18 @@ phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3"; }; + pcie-ep@14160000 {/* C4 - End Point */ + phys = <&p2u_hsio_4>, <&p2u_hsio_5>, <&p2u_hsio_6>, + <&p2u_hsio_7>; + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3"; + reset-gpios = <&gpio + TEGRA234_MAIN_GPIO(L, 1) + GPIO_ACTIVE_LOW>; + nvidia,refclk-select-gpios = <&gpio_aon + TEGRA234_AON_GPIO(AA, 4) + GPIO_ACTIVE_HIGH>; + }; + /* C7 - M.2 Key-M */ pcie@141e0000 { status = "okay"; diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi index f2e2d8d6845b..984c85eab41a 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi @@ -2763,6 +2763,8 @@ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; clocks = <&bpmp TEGRA234_CLK_UARTA>; resets = <&bpmp TEGRA234_RESET_UARTA>; + dmas = <&gpcdma 8>, <&gpcdma 8>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -4840,6 +4842,37 @@ status = "disabled"; }; + pcie-ep@14160000 { + compatible = "nvidia,tegra234-pcie-ep"; + power-domains = <&bpmp TEGRA234_POWER_DOMAIN_PCIEX4BB>; + reg = <0x00 0x14160000 0x0 0x00020000 /* appl registers (128K) */ + 0x00 0x36040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */ + 0x00 0x36080000 0x0 0x00040000 /* DBI space (256K) */ + 0x21 0x40000000 0x3 0x00000000>; /* Address Space (12G) */ + reg-names = "appl", "atu_dma", "dbi", "addr_space"; + num-lanes = <4>; + clocks = <&bpmp TEGRA234_CLK_PEX0_C4_CORE>; + clock-names = "core"; + resets = <&bpmp TEGRA234_RESET_PEX0_CORE_4_APB>, + <&bpmp TEGRA234_RESET_PEX0_CORE_4>; + reset-names = "apb", "core"; + + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */ + interrupt-names = "intr"; + nvidia,bpmp = <&bpmp 4>; + nvidia,enable-ext-refclk; + nvidia,aspm-cmrt-us = <60>; + nvidia,aspm-pwr-on-t-us = <20>; + nvidia,aspm-l0s-entrance-latency-us = <3>; + + interconnects = <&mc TEGRA234_MEMORY_CLIENT_PCIE4R &emc>, + <&mc TEGRA234_MEMORY_CLIENT_PCIE4W &emc>; + interconnect-names = "dma-mem", "write"; + iommus = <&smmu_niso0 TEGRA234_SID_PCIE4>; + dma-coherent; + status = "disabled"; + }; + pcie@14180000 { compatible = "nvidia,tegra234-pcie"; power-domains = <&bpmp TEGRA234_POWER_DOMAIN_PCIEX4BA>; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 0e5c810304fb..ae002c7cf126 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -48,18 +48,24 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-grandmax.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-grandprimelte.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-gt510.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-gt58.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j3ltetw.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j5.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j5x.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-rossa.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-serranove.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-uf896.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-thwc-ufi001c.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt86518.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt86528.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt88047.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-yiming-uz801v3.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8929-wingtech-wt82918hd.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8939-huawei-kiwi.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8939-longcheer-l9100.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8939-samsung-a7.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8939-sony-xperia-kanuti-tulip.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8939-wingtech-wt82918.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8939-wingtech-wt82918hd.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-motorola-potter.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-xiaomi-daisy.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8953-xiaomi-mido.dtb @@ -69,6 +75,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8956-sony-xperia-loire-kugo.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8956-sony-xperia-loire-suzu.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-lg-bullhead-rev-10.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-lg-bullhead-rev-101.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8992-lg-h815.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-msft-lumia-octagon-talkman.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-xiaomi-libra.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-huawei-angler-rev-101.dtb @@ -261,7 +268,10 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1e78100-lenovo-thinkpad-t14s.dtb dtb-$(CONFIG_ARCH_QCOM) += x1e80100-asus-vivobook-s15.dtb dtb-$(CONFIG_ARCH_QCOM) += x1e80100-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += x1e80100-lenovo-yoga-slim7x.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1e80100-microsoft-romulus13.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1e80100-microsoft-romulus15.dtb dtb-$(CONFIG_ARCH_QCOM) += x1e80100-qcp.dtb diff --git a/arch/arm64/boot/dts/qcom/ipq5332.dtsi b/arch/arm64/boot/dts/qcom/ipq5332.dtsi index 573656587c0d..71328b223531 100644 --- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi @@ -7,6 +7,7 @@ #include <dt-bindings/clock/qcom,apss-ipq.h> #include <dt-bindings/clock/qcom,ipq5332-gcc.h> +#include <dt-bindings/interconnect/qcom,ipq5332.h> #include <dt-bindings/interrupt-controller/arm-gic.h> / { @@ -208,6 +209,7 @@ reg = <0x01800000 0x80000>; #clock-cells = <1>; #reset-cells = <1>; + #interconnect-cells = <1>; clocks = <&xo_board>, <&sleep_clk>, <0>, @@ -320,18 +322,16 @@ reg = <0x08af8800 0x400>; interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 53 IRQ_TYPE_EDGE_BOTH>, - <GIC_SPI 52 IRQ_TYPE_EDGE_BOTH>; + <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "pwr_event", "dp_hs_phy_irq", "dm_hs_phy_irq"; clocks = <&gcc GCC_USB0_MASTER_CLK>, - <&gcc GCC_SNOC_USB_CLK>, <&gcc GCC_USB0_SLEEP_CLK>, <&gcc GCC_USB0_MOCK_UTMI_CLK>; clock-names = "core", - "iface", "sleep", "mock_utmi"; @@ -342,6 +342,9 @@ #address-cells = <1>; #size-cells = <1>; ranges; + interconnects = <&gcc MASTER_SNOC_USB &gcc SLAVE_SNOC_USB>, + <&gcc MASTER_SNOC_USB &gcc SLAVE_SNOC_USB>; + interconnect-names = "usb-ddr", "apps-usb"; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi index e1e45da7f787..8edd535a188f 100644 --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi @@ -168,7 +168,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-ipq6018"; + compatible = "qcom,rpm-ipq6018", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; regulators { diff --git a/arch/arm64/boot/dts/qcom/ipq9574.dtsi b/arch/arm64/boot/dts/qcom/ipq9574.dtsi index 48dfafea46a7..08a82a5cf667 100644 --- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi @@ -181,7 +181,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-ipq9574"; + compatible = "qcom,rpm-ipq9574", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts index 3b7fdb6797a9..2cc54eaf7202 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts @@ -125,6 +125,26 @@ }; }; }; + + flash-led-controller@53 { + compatible = "silergy,sy7802"; + reg = <0x53>; + + enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&camera_rear_flash_default>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_FLASH; + color = <LED_COLOR_ID_WHITE>; + led-sources = <0>, <1>; + }; + }; }; &blsp_i2c3 { @@ -278,6 +298,13 @@ bias-disable; }; + camera_rear_flash_default: camera-rear-flash-default-state { + pins = "gpio9", "gpio16", "gpio117"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + gpio_keys_default: gpio-keys-default-state { pins = "gpio107"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi index 81b3e0760154..7a7e99b015d9 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-fortuna-common.dtsi @@ -262,6 +262,8 @@ pinctrl-0 = <&tsp_int_default>; pinctrl-names = "default"; + + linux,keycodes = <KEY_APPSELECT KEY_BACK>; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts index 135df1739dbd..5ddb69bf8e78 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts @@ -47,12 +47,34 @@ constant-charge-voltage-max-microvolt = <4400000>; }; +&blsp_i2c5 { + status = "okay"; + + touchscreen@50 { + compatible = "imagis,ist3038"; + reg = <0x50>; + + interrupts-extended = <&tlmm 13 IRQ_TYPE_EDGE_FALLING>; + + touchscreen-size-x = <720>; + touchscreen-size-y = <1280>; + + vdd-supply = <®_vdd_tsp_a>; + vddio-supply = <&pm8916_l6>; + + pinctrl-0 = <&ts_int_default>; + pinctrl-names = "default"; + + linux,keycodes = <KEY_APPSELECT KEY_BACK>; + }; +}; + ®_motor_vdd { gpio = <&tlmm 72 GPIO_ACTIVE_HIGH>; }; ®_touch_key { - status = "disabled"; + status = "disabled"; /* Using Imagis touch key */ }; &sound { diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts index 579312ed53ce..3d6d9dd3b8a8 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-gt58.dts @@ -75,6 +75,7 @@ touchscreen-size-x = <768>; touchscreen-size-y = <1024>; + linux,keycodes = <KEY_APPSELECT KEY_BACK>; vcca-supply = <®_vdd_tsp>; vdd-supply = <&pm8916_l6>; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j3-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-j3-common.dtsi new file mode 100644 index 000000000000..1d74cccc438a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j3-common.dtsi @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "msm8916-samsung-j5-common.dtsi" + +/ { + reserved-memory { + /delete-node/ tz-apps@85500000; + + /* Additional memory used by Samsung firmware modifications */ + tz-apps@85800000 { + reg = <0x0 0x85800000 0x0 0x800000>; + no-map; + }; + }; + + reg_vdd_tsp_a: regulator-vdd-tsp-a { + compatible = "regulator-fixed"; + regulator-name = "vdd_tsp_a"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + gpio = <&tlmm 16 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&tsp_ldo_en_default>; + pinctrl-names = "default"; + }; +}; + +&accelerometer { + vdd-supply = <&pm8916_l5>; + vddio-supply = <&pm8916_l5>; + + mount-matrix = "0", "-1", "0", + "1", "0", "0", + "0", "0", "-1"; +}; + +&gpio_hall_sensor { + status = "disabled"; +}; + +&i2c_muic { + /* GPIO pins vary depending on model variant */ +}; + +&i2c_sensors { + /* GPIO pins vary depending on model variant */ +}; + +&touchscreen { + vdd-supply = <®_vdd_tsp_a>; +}; + +&tlmm { + tsp_ldo_en_default: tsp-ldo-en-default-state { + pins = "gpio16"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j3ltetw.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-j3ltetw.dts new file mode 100644 index 000000000000..a26d2fd13c94 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j3ltetw.dts @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-samsung-j3-common.dtsi" + +/ { + model = "Samsung Galaxy J3 (2016) (SM-J320YZ)"; + compatible = "samsung,j3ltetw", "qcom,msm8916"; + chassis-type = "handset"; +}; + +&i2c_muic { + sda-gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; +}; + +&i2c_sensors { + /* I2C2 */ + sda-gpios = <&tlmm 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; +}; + +&muic_i2c_default { + pins = "gpio0", "gpio1"; +}; + +&sensors_i2c_default { + /* I2C2 */ + pins = "gpio6", "gpio7"; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts index 1981bb71f6a9..3413b0970c4a 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-rossa.dts @@ -16,6 +16,26 @@ constant-charge-voltage-max-microvolt = <4400000>; }; +&blsp_i2c5 { + touchscreen@50 { + compatible = "imagis,ist3038"; + reg = <0x50>; + + interrupts-extended = <&tlmm 13 IRQ_TYPE_EDGE_FALLING>; + + touchscreen-size-x = <480>; + touchscreen-size-y = <800>; + + vdd-supply = <®_vdd_tsp_a>; + vddio-supply = <&pm8916_l6>; + + pinctrl-0 = <&tsp_int_default>; + pinctrl-names = "default"; + + linux,keycodes = <KEY_APPSELECT KEY_BACK>; + }; +}; + &mpss_mem { /* Firmware for rossa needs more space */ reg = <0x0 0x86800000 0x0 0x5800000>; diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts new file mode 100644 index 000000000000..3cfa80e38a9e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86518.dts @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-wingtech-wt865x8.dtsi" + +/ { + model = "Lenovo A6000 (Wingtech WT86518)"; + compatible = "wingtech,wt86518", "qcom,msm8916"; + chassis-type = "handset"; + + speaker_amp: audio-amplifier { + compatible = "awinic,aw8738"; + + pinctrl-0 = <&spk_ext_pa_default>; + pinctrl-names = "default"; + + mode-gpios = <&tlmm 119 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Speaker Amp"; + awinic,mode = <1>; + }; +}; + +&blsp_i2c2 { + accelerometer@e { + compatible = "kionix,kxcj91008"; + reg = <0xe>; + + vdd-supply = <&pm8916_l6>; + vddio-supply = <&pm8916_l6>; + + mount-matrix = "0", "-1", "0", + "-1", "0", "0", + "0", "0", "1"; + }; +}; + +&headphones_switch { + VCC-supply = <&pm8916_l17>; +}; + +&pm8916_bms { + power-supplies = <&pm8916_charger>; +}; + +&pm8916_charger { + qcom,fast-charge-safe-current = <900000>; + qcom,fast-charge-safe-voltage = <4300000>; + + monitored-battery = <&battery>; + + status = "okay"; +}; + +&sound { + model = "wt88047"; + widgets = "Speaker", "Speaker", + "Headphone", "Headphones"; + pin-switches = "Speaker", "Headphones"; + audio-routing = "Speaker", "Speaker Amp OUT", + "Speaker Amp IN", "HPH_R", + "Headphones", "Headphones Switch OUTL", + "Headphones", "Headphones Switch OUTR", + "Headphones Switch INL", "HPH_L", + "Headphones Switch INR", "HPH_R", + "AMIC1", "MIC BIAS Internal1", + "AMIC2", "MIC BIAS Internal2"; + aux-devs = <&speaker_amp>, <&headphones_switch>; +}; + +&usb { + dr_mode = "peripheral"; + extcon = <&pm8916_charger>; +}; + +&usb_hs_phy { + extcon = <&pm8916_charger>; +}; + +&tlmm { + spk_ext_pa_default: spk-ext-pa-default-state { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86528.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86528.dts new file mode 100644 index 000000000000..ec2c4dcd3ead --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt86528.dts @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8916-wingtech-wt865x8.dtsi" + +/ { + model = "Lenovo A6010 (Wingtech WT86528)"; + compatible = "wingtech,wt86528", "qcom,msm8916"; + chassis-type = "handset"; + + /* left AW8736 */ + speaker_amp_left: audio-amplifier-left { + compatible = "awinic,aw8738"; + + pinctrl-0 = <&spk_ext_pa_left_default>; + pinctrl-names = "default"; + + mode-gpios = <&tlmm 119 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Speaker Amp L"; + awinic,mode = <3>; + }; + + /* right AW8736 */ + speaker_amp_right: audio-amplifier-right { + compatible = "awinic,aw8738"; + + pinctrl-0 = <&spk_ext_pa_right_default>; + pinctrl-names = "default"; + + mode-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Speaker Amp R"; + awinic,mode = <3>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + pinctrl-0 = <&gpio_leds_default>; + pinctrl-names = "default"; + + led-0 { + gpios = <&tlmm 16 GPIO_ACTIVE_LOW>; + label = "red"; + default-state = "off"; + retain-state-suspended; + }; + + led-1 { + gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; + label = "green"; + default-state = "off"; + retain-state-suspended; + }; + }; + + usb_id: usb-id { + compatible = "linux,extcon-usb-gpio"; + id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb_id_default>; + pinctrl-names = "default"; + }; +}; + +&blsp_i2c2 { + magnetometer@c { + compatible = "asahi-kasei,ak09911"; + reg = <0x0c>; + + vdd-supply = <&pm8916_l17>; + vid-supply = <&pm8916_l6>; + }; + + imu@68 { + compatible = "invensense,mpu6880"; + reg = <0x68>; + + interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_RISING>; + + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + + pinctrl-0 = <&imu_default>; + pinctrl-names = "default"; + + mount-matrix = "1", "0", "0", + "0", "-1", "0", + "0", "0", "1"; + }; +}; + +&pm8916_codec { + qcom,micbias1-ext-cap; +}; + +&sound { + model = "wt86528"; + widgets = "Speaker", "Speaker", + "Headphone", "Headphones"; + pin-switches = "Speaker", "Headphones"; + audio-routing = "Speaker", "Speaker Amp L OUT", + "Speaker", "Speaker Amp R OUT", + "Speaker Amp L IN", "HPH_L", + "Speaker Amp R IN", "HPH_R", + "Headphones", "Headphones Switch OUTL", + "Headphones", "Headphones Switch OUTR", + "Headphones Switch INL", "HPH_L", + "Headphones Switch INR", "HPH_R", + "AMIC1", "MIC BIAS External1", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External1"; + aux-devs = <&speaker_amp_left>, <&speaker_amp_right>, <&headphones_switch>; +}; + +&usb { + extcon = <&usb_id>, <&usb_id>; +}; + +&usb_hs_phy { + extcon = <&usb_id>; +}; + +&tlmm { + gpio_leds_default: gpio-leds-default-state { + pins = "gpio16", "gpio17"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + imu_default: imu-default-state { + pins = "gpio115"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + spk_ext_pa_left_default: spk-ext-pa-left-default-state { + pins = "gpio119"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + spk_ext_pa_right_default: spk-ext-pa-right-default-state { + pins = "gpio121"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + usb_id_default: usb-id-default-state { + pins = "gpio110"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt865x8.dtsi b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt865x8.dtsi new file mode 100644 index 000000000000..1a7c347dc3f0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt865x8.dtsi @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "msm8916-pm8916.dtsi" +#include "msm8916-modem-qdsp6.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/qcom,pmic-mpp.h> + +/ { + aliases { + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + headphones_switch: audio-switch { + compatible = "simple-audio-amplifier"; + + pinctrl-0 = <&headphones_switch_default>; + pinctrl-names = "default"; + + enable-gpios = <&tlmm 120 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "Headphones Switch"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pm8916_pwm 0 100000>; + + brightness-levels = <0 255>; + num-interpolated-steps = <255>; + default-brightness-level = <255>; + }; + + battery: battery { + compatible = "simple-battery"; + voltage-min-design-microvolt = <3400000>; + voltage-max-design-microvolt = <4350000>; + energy-full-design-microwatt-hours = <8740000>; + charge-full-design-microamp-hours = <2300000>; + + ocv-capacity-celsius = <25>; + ocv-capacity-table-0 = <4328000 100>, <4266000 95>, <4208000 90>, + <4154000 85>, <4102000 80>, <4062000 75>, <3992000 70>, + <3960000 65>, <3914000 60>, <3870000 55>, <3840000 50>, + <3818000 45>, <3800000 40>, <3784000 35>, <3770000 30>, + <3756000 25>, <3736000 20>, <3714000 16>, <3696000 13>, + <3690000 11>, <3689000 10>, <3688000 9>, <3686000 8>, + <3682000 7>, <3670000 6>, <3639000 5>, <3592000 4>, + <3530000 3>, <3448000 2>, <3320000 1>, <3000000 0>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&gpio_keys_default>; + pinctrl-names = "default"; + + label = "GPIO Buttons"; + + volume-up-button { + label = "Volume Up"; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEUP>; + }; + }; +}; + +&blsp_i2c5 { + status = "okay"; + + touchscreen@38 { + compatible = "edt,edt-ft5306"; + reg = <0x38>; + + interrupts-extended = <&tlmm 13 IRQ_TYPE_EDGE_FALLING>; + + vcc-supply = <&pm8916_l17>; + iovcc-supply = <&pm8916_l6>; + + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <720>; + touchscreen-size-y = <1280>; + + pinctrl-0 = <&touchscreen_default>; + pinctrl-names = "default"; + }; +}; + +&blsp_uart2 { + status = "okay"; +}; + +&mpss_mem { + reg = <0x0 0x86800000 0x0 0x5500000>; +}; + +&pm8916_bms { + monitored-battery = <&battery>; + status = "okay"; +}; + +&pm8916_codec { + qcom,micbias-lvl = <2800>; + qcom,mbhc-vthreshold-low = <75 150 237 450 500>; + qcom,mbhc-vthreshold-high = <75 150 237 450 500>; + qcom,hphl-jack-type-normally-open; +}; + +&pm8916_pwm { + pinctrl-0 = <&pwm_out>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pm8916_resin { + linux,code = <KEY_VOLUMEDOWN>; + status = "okay"; +}; + +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + +&pm8916_vib { + status = "okay"; +}; + +&sdhc_1 { + status = "okay"; +}; + +&sdhc_2 { + pinctrl-0 = <&sdc2_default>; + pinctrl-1 = <&sdc2_sleep>; + pinctrl-names = "default", "sleep"; + + non-removable; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&venus { + status = "okay"; +}; + +&venus_mem { + status = "okay"; +}; + +&wcnss { + status = "okay"; +}; + +&wcnss_iris { + compatible = "qcom,wcn3620"; +}; + +&wcnss_mem { + status = "okay"; +}; + +&tlmm { + gpio_keys_default: gpio-keys-default-state { + pins = "gpio107"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + headphones_switch_default: headphones-switch-default-state { + pins = "gpio120"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + touchscreen_default: touchscreen-default-state { + touchscreen-pins { + pins = "gpio13"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + reset-pins { + pins = "gpio12"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; +}; + +&pm8916_mpps { + pwm_out: mpp4-state { + pins = "mpp4"; + function = "digital"; + power-source = <PM8916_MPP_VPH>; + output-low; + qcom,dtest = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 7383bcc603ab..0ee44706b70b 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -312,7 +312,7 @@ qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8916"; + compatible = "qcom,rpm-msm8916", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/msm8929-pm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8929-pm8916.dtsi new file mode 100644 index 000000000000..c2bf25997e9b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8929-pm8916.dtsi @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * msm8929-pm8916.dtsi describes common properties (e.g. regulator connections) + * that apply to most devices that make use of the MSM8929 SoC and PM8916 PMIC. + * Many regulators have a fixed purpose in the original reference design and + * were rarely re-used for different purposes. Devices that deviate from the + * typical reference design should not make use of this include and instead add + * the necessary properties in the board-specific device tree. + */ + +#include "msm8929.dtsi" +#include "pm8916.dtsi" + +&mdss_dsi0 { + vdda-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi0_phy { + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi1 { + vdda-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; +}; + +&mdss_dsi1_phy { + vddio-supply = <&pm8916_l6>; +}; + +&mpss { + pll-supply = <&pm8916_l7>; +}; + +&pm8916_codec { + vdd-cdc-io-supply = <&pm8916_l5>; + vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; + vdd-micbias-supply = <&pm8916_l13>; +}; + +&rpm_requests { + pm8916_rpm_regulators: regulators { + compatible = "qcom,rpm-pm8916-regulators"; + vdd_l1_l2_l3-supply = <&pm8916_s3>; + vdd_l4_l5_l6-supply = <&pm8916_s4>; + vdd_l7-supply = <&pm8916_s4>; + + /* pm8916_s1 is managed by rpmpd (MSM8939_VDDMDCX) */ + /* pm8916_s2 is managed by rpmpd (MSM8939_VDDCX) */ + pm8916_s3: s3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; /* Needed for L2 */ + }; + pm8916_s4: s4 { + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <2150000>; + regulator-always-on; /* Needed for L5/L7 */ + }; + + /* + * Some of the regulators are unused or managed by another + * processor (e.g. the modem). We should still define nodes for + * them to ensure the vote from the application processor can be + * dropped in case the regulators are already on during boot. + * + * The labels for these nodes are omitted on purpose because + * boards should configure a proper voltage before using them. + */ + l1 {}; + + pm8916_l2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; /* Needed for LPDDR RAM */ + }; + + /* pm8916_l3 is managed by rpmpd (MSM8939_VDDMX) */ + + l4 {}; + + pm8916_l5: l5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for most digital I/O */ + }; + + pm8916_l6: l6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + pm8916_l7: l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; /* Needed for CPU PLL */ + }; + + pm8916_l8: l8 { + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + pm8916_l9: l9 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + l10 {}; + + pm8916_l11: l11 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-allow-set-load; + regulator-system-load = <200000>; + }; + + pm8916_l12: l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + }; + + pm8916_l13: l13 { + regulator-min-microvolt = <3075000>; + regulator-max-microvolt = <3075000>; + }; + + l14 {}; + l15 {}; + l16 {}; + l17 {}; + l18 {}; + }; +}; + +&sdhc_1 { + vmmc-supply = <&pm8916_l8>; + vqmmc-supply = <&pm8916_l5>; +}; + +&sdhc_2 { + vmmc-supply = <&pm8916_l11>; + vqmmc-supply = <&pm8916_l12>; +}; + +&usb_hs_phy { + v1p8-supply = <&pm8916_l7>; + v3p3-supply = <&pm8916_l13>; +}; + +&wcnss { + vddpx-supply = <&pm8916_l7>; +}; + +&wcnss_iris { + vddxo-supply = <&pm8916_l7>; + vddrfa-supply = <&pm8916_s3>; + vddpa-supply = <&pm8916_l9>; + vdddig-supply = <&pm8916_l5>; +}; + diff --git a/arch/arm64/boot/dts/qcom/msm8929-wingtech-wt82918hd.dts b/arch/arm64/boot/dts/qcom/msm8929-wingtech-wt82918hd.dts new file mode 100644 index 000000000000..8feecffb16bf --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8929-wingtech-wt82918hd.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8929-pm8916.dtsi" +#include "msm8939-wingtech-wt82918.dtsi" + +/ { + model = "Lenovo Vibe K5 (HD) (Wingtech WT82918)"; + compatible = "wingtech,wt82918hd", "qcom,msm8929"; + chassis-type = "handset"; +}; + +&touchscreen { + touchscreen-size-x = <720>; + touchscreen-size-y = <1280>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8929.dtsi b/arch/arm64/boot/dts/qcom/msm8929.dtsi new file mode 100644 index 000000000000..ef7bb1ced954 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8929.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "msm8939.dtsi" + +&opp_table { + /delete-node/ opp-550000000; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts b/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts index e3404c4455cf..b845da4fa23e 100644 --- a/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts +++ b/arch/arm64/boot/dts/qcom/msm8939-longcheer-l9100.dts @@ -159,6 +159,26 @@ }; }; }; + + flash-led-controller@53 { + compatible = "silergy,sy7802"; + reg = <0x53>; + + enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&camera_rear_flash_default>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_FLASH; + color = <LED_COLOR_ID_WHITE>; + led-sources = <0>, <1>; + }; + }; }; &blsp_i2c3 { @@ -318,6 +338,13 @@ bias-disable; }; + camera_rear_flash_default: camera-rear-flash-default-state { + pins = "gpio9", "gpio16", "gpio51"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + gpio_hall_sensor_default: gpio-hall-sensor-default-state { pins = "gpio20"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts index 91acdb160227..ceba6e73b211 100644 --- a/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts +++ b/arch/arm64/boot/dts/qcom/msm8939-samsung-a7.dts @@ -198,7 +198,7 @@ }; }; - pwm_vibrator: pwm-vibrator { + pwm_vibrator: pwm { compatible = "clk-pwm"; #pwm-cells = <2>; diff --git a/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dts b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dts new file mode 100644 index 000000000000..aa6b699aa2a1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8939-pm8916.dtsi" +#include "msm8939-wingtech-wt82918.dtsi" + +/ { + model = "Lenovo Vibe K5 (Wingtech WT82918)"; + compatible = "wingtech,wt82918", "qcom,msm8939"; + chassis-type = "handset"; +}; + +&touchscreen { + touchscreen-size-x = <1080>; + touchscreen-size-y = <1920>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dtsi b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dtsi new file mode 100644 index 000000000000..800e0747a2f7 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918.dtsi @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "msm8916-modem-qdsp6.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pinctrl/qcom,pmic-mpp.h> + +/ { + aliases { + mmc0 = &sdhc_1; /* eMMC */ + mmc1 = &sdhc_2; /* SD card */ + serial0 = &blsp_uart2; + }; + + chosen { + stdout-path = "serial0"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pm8916_pwm 0 100000>; + brightness-levels = <0 255>; + num-interpolated-steps = <255>; + default-brightness-level = <128>; + }; + + flash-led-controller { + compatible = "sgmicro,sgm3140"; + enable-gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + flash-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&camera_front_flash_default>; + pinctrl-names = "default"; + + flash_led: led { + function = LED_FUNCTION_FLASH; + color = <LED_COLOR_ID_WHITE>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&gpio_keys_default>; + pinctrl-names = "default"; + + label = "GPIO Buttons"; + + button-volume-up { + label = "Volume Up"; + gpios = <&tlmm 107 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEUP>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + pinctrl-0 = <&gpio_leds_default>; + pinctrl-names = "default"; + + led-0 { + gpios = <&tlmm 69 GPIO_ACTIVE_LOW>; + function = LED_FUNCTION_CHARGING; + color = <LED_COLOR_ID_RED>; + default-state = "off"; + retain-state-suspended; + }; + + led-1 { + gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_STATUS; + color = <LED_COLOR_ID_GREEN>; + default-state = "off"; + retain-state-suspended; + }; + }; + + usb_id: usb-id { + compatible = "linux,extcon-usb-gpio"; + id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb_id_default>; + pinctrl-names = "default"; + }; +}; + +&blsp_i2c2 { + status = "okay"; + + accelerometer@68 { + compatible = "invensense,icm20608"; + reg = <0x68>; + + interrupts-extended = <&tlmm 115 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&accelerometer_default>; + pinctrl-names = "default"; + + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l6>; + + mount-matrix = "-1", "0", "0", + "0", "1", "0", + "0", "0", "1"; + }; +}; + +&blsp_i2c5 { + status = "okay"; + + touchscreen: touchscreen@38 { + compatible = "edt,edt-ft5306"; + reg = <0x38>; + + interrupts-extended = <&tlmm 13 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&touchscreen_default>; + pinctrl-names = "default"; + + vcc-supply = <&pm8916_l17>; + iovcc-supply = <&pm8916_l6>; + + reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + }; +}; + +&blsp_uart2 { + status = "okay"; +}; + +&mpss_mem { + reg = <0x0 0x86800000 0x0 0x5500000>; +}; + +&pm8916_pwm { + pinctrl-0 = <&pwm_out>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pm8916_resin { + linux,code = <KEY_VOLUMEDOWN>; + status = "okay"; +}; + +&pm8916_rpm_regulators { + pm8916_l17: l17 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; +}; + +&pm8916_vib { + status = "okay"; +}; + +&sdhc_1 { + status = "okay"; +}; + +&sdhc_2 { + pinctrl-0 = <&sdc2_default>; + pinctrl-1 = <&sdc2_sleep>; + pinctrl-names = "default", "sleep"; + non-removable; + status = "okay"; +}; + +&usb { + extcon = <&usb_id>, <&usb_id>; + status = "okay"; +}; + +&usb_hs_phy { + extcon = <&usb_id>; +}; + +&wcnss { + status = "okay"; +}; + +&wcnss_iris { + compatible = "qcom,wcn3620"; +}; + +&wcnss_mem { + status = "okay"; +}; + +&tlmm { + accelerometer_default: accelerometer-default-state { + pins = "gpio115"; + function = "gpio"; + drive-strength = <6>; + bias-pull-up; + }; + + camera_front_flash_default: camera-front-flash-default-state { + pins = "gpio31", "gpio32"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + gpio_keys_default: gpio-keys-default-state { + pins = "gpio107"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + gpio_leds_default: gpio-leds-default-state { + pins = "gpio36", "gpio69"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + touchscreen_default: touchscreen-default-state { + reset-pins { + pins = "gpio12"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + touchscreen-pins { + pins = "gpio13"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + usb_id_default: usb-id-default-state { + pins = "gpio110"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; +}; + +&pm8916_mpps { + pwm_out: mpp4-state { + pins = "mpp4"; + function = "digital"; + power-source = <PM8916_MPP_VPH>; + output-low; + qcom,dtest = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918hd.dts b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918hd.dts new file mode 100644 index 000000000000..59414db42508 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8939-wingtech-wt82918hd.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +#include "msm8939-pm8916.dtsi" +#include "msm8939-wingtech-wt82918.dtsi" + +/ { + model = "Lenovo Vibe K5 (HD) (Wingtech WT82918)"; + compatible = "wingtech,wt82918hdhw39", "qcom,msm8939"; + chassis-type = "handset"; +}; + +&touchscreen { + touchscreen-size-x = <720>; + touchscreen-size-y = <1280>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8939.dtsi b/arch/arm64/boot/dts/qcom/msm8939.dtsi index 46d9480cd464..7af210789879 100644 --- a/arch/arm64/boot/dts/qcom/msm8939.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8939.dtsi @@ -248,11 +248,11 @@ smd-edge { interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; - mboxes = <&apcs1_mbox 0>; + qcom,ipc = <&apcs1_mbox 8 0>; qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8936"; + compatible = "qcom,rpm-msm8936", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi index a4bfb624fb8a..d20fd3d7c46e 100644 --- a/arch/arm64/boot/dts/qcom/msm8953.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi @@ -199,7 +199,7 @@ qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8953"; + compatible = "qcom,rpm-msm8953", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi index d62dcb76fa48..06af6e5ec578 100644 --- a/arch/arm64/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi @@ -247,7 +247,7 @@ qcom,smd-edge = <15>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8976"; + compatible = "qcom,rpm-msm8976", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { @@ -663,6 +663,11 @@ #thermal-sensor-cells = <1>; }; + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x004ab000 0x4>; + }; + tlmm: pinctrl@1000000 { compatible = "qcom,msm8976-pinctrl"; reg = <0x01000000 0x300000>; diff --git a/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts b/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts new file mode 100644 index 000000000000..38b305816d2f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8992-lg-h815.dts @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * MSM8992 LG G4 (h815) device tree. + * + * Copyright (c) 2024, Alexander Reimelt <alexander.reimelt@posteo.de> + */ + +/dts-v1/; + +#include "msm8992.dtsi" +#include "pm8994.dtsi" +#include "pmi8994.dtsi" +#include <dt-bindings/leds/common.h> + +/* different mapping */ +/delete-node/ &cont_splash_mem; + +/* disabled downstream */ +/delete-node/ &dfps_data_mem; + +/ { + model = "LG G4 (H815)"; + compatible = "lg,h815", "qcom,msm8992"; + chassis-type = "handset"; + + qcom,msm-id = <0xfb 0x0>; + qcom,pmic-id = <0x10009 0x1000a 0x0 0x0>; + qcom,board-id = <0xb64 0x0>; + + /* psci is broken */ + /delete-node/ psci; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + spin-table@6000000 { + reg = <0x0 0x06000000 0x0 0x00001000>; + no-map; + }; + + ramoops@ff00000 { + compatible = "ramoops"; + reg = <0x0 0x0ff00000 0x0 0x00100000>; + console-size = <0x20000>; + pmsg-size = <0x20000>; + record-size = <0x10000>; + ecc-size = <0x10>; + }; + + cont_splash_mem: fb@3400000 { + reg = <0x0 0x03400000 0x0 0x00c00000>; + no-map; + }; + + crash_fb_mem: crash-fb@4000000 { + reg = <0x0 0x04000000 0x0 0x00c00000>; + no-map; + }; + }; + + gpio-hall-sensor { + compatible = "gpio-keys"; + + pinctrl-0 = <&hall_sensor_default>; + pinctrl-names = "default"; + + label = "Hall Effect Sensor"; + + event-hall-sensor { + gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + label = "hall effect sensor"; + linux,input-type = <EV_SW>; + linux,code = <SW_LID>; + linux,can-disable; + wakeup-source; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-vol-up { + label = "volume up"; + gpios = <&pm8994_gpios 3 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEUP>; + wakeup-source; + debounce-interval = <15>; + }; + }; +}; + +&CPU0 { + enable-method = "spin-table"; +}; + +&CPU1 { + enable-method = "spin-table"; +}; + +&CPU2 { + enable-method = "spin-table"; +}; + +&CPU3 { + enable-method = "spin-table"; +}; + +&CPU4 { + enable-method = "spin-table"; +}; + +&CPU5 { + enable-method = "spin-table"; +}; + +&pm8994_resin { + linux,code = <KEY_VOLUMEDOWN>; + status = "okay"; +}; + +&rpm_requests { + regulators-0 { + compatible = "qcom,rpm-pm8994-regulators"; + + vdd_s3-supply = <&vph_pwr>; + vdd_s4-supply = <&vph_pwr>; + vdd_s5-supply = <&vph_pwr>; + vdd_s7-supply = <&vph_pwr>; + vdd_l1-supply = <&pmi8994_s1>; + vdd_l2_26_28-supply = <&pm8994_s3>; + vdd_l3_11-supply = <&pm8994_s3>; + vdd_l4_27_31-supply = <&pm8994_s3>; + vdd_l5_7-supply = <&pm8994_s5>; + vdd_l6_12_32-supply = <&pm8994_s5>; + vdd_l8_16_30-supply = <&vph_pwr>; + vdd_l9_10_18_22-supply = <&pmi8994_bby>; + vdd_l13_19_23_24-supply = <&pmi8994_bby>; + vdd_l14_15-supply = <&pm8994_s5>; + vdd_l17_29-supply = <&pmi8994_bby>; + vdd_l20_21-supply = <&pmi8994_bby>; + vdd_l25-supply = <&pm8994_s5>; + vdd_lvs1_2-supply = <&pm8994_s4>; + + pm8994_s3: s3 { + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + }; + + /* sdhc1 vqmmc and bcm */ + pm8994_s4: s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-system-load = <325000>; + regulator-allow-set-load; + }; + + pm8994_s5: s5 { + regulator-min-microvolt = <2150000>; + regulator-max-microvolt = <2150000>; + }; + + /* sdhc2 vqmmc */ + pm8994_l13: l13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + regulator-system-load = <22000>; + regulator-allow-set-load; + }; + + /* sdhc1 vmmc */ + pm8994_l20: l20 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-system-load = <570000>; + regulator-allow-set-load; + }; + + /* sdhc2 vmmc */ + pm8994_l21: l21 { + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + regulator-system-load = <800000>; + regulator-allow-set-load; + }; + }; + + regulators-1 { + compatible = "qcom,rpm-pmi8994-regulators"; + + vdd_s1-supply = <&vph_pwr>; + vdd_bst_byp-supply = <&vph_pwr>; + + pmi8994_s1: s1 { + regulator-min-microvolt = <1025000>; + regulator-max-microvolt = <1025000>; + }; + + /* S2 & S3 - VDD_GFX */ + + pmi8994_bby: boost-bypass { + regulator-min-microvolt = <3150000>; + regulator-max-microvolt = <3600000>; + }; + }; +}; + +&sdhc1 { + mmc-hs400-1_8v; + vmmc-supply = <&pm8994_l20>; + vqmmc-supply = <&pm8994_s4>; + non-removable; + status = "okay"; +}; + +&sdhc2 { + vmmc-supply = <&pm8994_l21>; + vqmmc-supply = <&pm8994_l13>; + cd-gpios = <&pm8994_gpios 8 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&tlmm { + hall_sensor_default: hall-sensor-default-state { + pins = "gpio75"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi index 917fa246857d..fc2a7f13f690 100644 --- a/arch/arm64/boot/dts/qcom/msm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi @@ -188,7 +188,7 @@ qcom,remote-pid = <6>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8994"; + compatible = "qcom,rpm-msm8994", "qcom,smd-rpm"; qcom,smd-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 0fd2b1b944a5..e5966724f37c 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -472,7 +472,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8996"; + compatible = "qcom,rpm-msm8996", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi index 7f44807b1b97..9aa9c5cee355 100644 --- a/arch/arm64/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -352,7 +352,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-msm8998"; + compatible = "qcom,rpm-msm8998", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { @@ -1586,6 +1586,33 @@ "gpll0"; }; + lpass_q6_smmu: iommu@5100000 { + compatible = "qcom,msm8998-smmu-v2", "qcom,smmu-v2"; + reg = <0x05100000 0x40000>; + clocks = <&gcc HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>; + clock-names = "bus"; + + #global-interrupts = <0>; + #iommu-cells = <1>; + interrupts = + <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>; + + power-domains = <&gcc LPASS_ADSP_GDSC>; + status = "disabled"; + }; + remoteproc_slpi: remoteproc@5800000 { compatible = "qcom,msm8998-slpi-pas"; reg = <0x05800000 0x4040>; diff --git a/arch/arm64/boot/dts/qcom/pm8950.dtsi b/arch/arm64/boot/dts/qcom/pm8950.dtsi index f03095779de0..ed72c6101813 100644 --- a/arch/arm64/boot/dts/qcom/pm8950.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8950.dtsi @@ -18,7 +18,7 @@ #address-cells = <1>; #size-cells = <0>; - pon@800 { + pm8950_pon: pon@800 { compatible = "qcom,pm8916-pon"; reg = <0x0800>; mode-bootloader = <0x2>; @@ -31,6 +31,14 @@ bias-pull-up; linux,code = <KEY_POWER>; }; + + pm8950_resin: resin { + compatible = "qcom,pm8941-resin"; + interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + status = "disabled"; + }; }; pm8950_temp: temp-alarm@2400 { diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi index b4822cb17a37..4aff437263a2 100644 --- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi +++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi @@ -84,9 +84,8 @@ #address-cells = <1>; #size-cells = <0>; - pmi8950_pwm: pwm@b000 { + pmi8950_pwm: pwm { compatible = "qcom,pmi8950-pwm"; - reg = <0xb000 0x100>; #pwm-cells = <2>; status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi index 36d6a1fb553a..9ee59e6d2cdb 100644 --- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi +++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi @@ -57,8 +57,11 @@ interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>, <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>; interrupt-names = "ovp", "short"; + label = "backlight"; + qcom,cabc; qcom,external-pfet; + status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 8f3be4c75db3..79bc42ffb6a1 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -215,7 +215,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-qcm2290"; + compatible = "qcom,rpm-qcm2290", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index a0668f767e4b..84c45419cb8d 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -641,6 +641,21 @@ status = "okay"; }; +&sdc2_clk { + bias-disable; + drive-strength = <16>; +}; + +&sdc2_cmd { + bias-pull-up; + drive-strength = <10>; +}; + +&sdc2_data { + bias-pull-up; + drive-strength = <10>; +}; + &sdhc_1 { non-removable; no-sd; @@ -652,9 +667,27 @@ status = "okay"; }; +&sdhc_2 { + status = "okay"; + + pinctrl-0 = <&sdc2_clk>, <&sdc2_cmd>, <&sdc2_data>, <&sd_cd>; + pinctrl-1 = <&sdc2_clk_sleep>, <&sdc2_cmd_sleep>, <&sdc2_data_sleep>, <&sd_cd>; + + vmmc-supply = <&vreg_l9c_2p96>; + vqmmc-supply = <&vreg_l6c_2p96>; + + cd-gpios = <&tlmm 91 GPIO_ACTIVE_LOW>; +}; + &tlmm { gpio-reserved-ranges = <32 2>, /* ADSP */ <48 4>; /* NFC */ + + sd_cd: sd-cd-state { + pins = "gpio91"; + function = "gpio"; + bias-pull-up; + }; }; &uart5 { diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi index c291bbed6073..cddc16bac0ce 100644 --- a/arch/arm64/boot/dts/qcom/qcs404.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi @@ -177,7 +177,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-qcs404"; + compatible = "qcom,rpm-qcs404", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/sa8155p.dtsi b/arch/arm64/boot/dts/qcom/sa8155p.dtsi index 9e70effc72e1..d678ed822378 100644 --- a/arch/arm64/boot/dts/qcom/sa8155p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155p.dtsi @@ -9,6 +9,10 @@ #include "sm8150.dtsi" +&camcc { + power-domains = <&rpmhpd SA8155P_CX>; +}; + &dispcc { power-domains = <&rpmhpd SA8155P_CX>; }; diff --git a/arch/arm64/boot/dts/qcom/sa8295p-adp.dts b/arch/arm64/boot/dts/qcom/sa8295p-adp.dts index 78e933c42c31..2fd1dafe63ce 100644 --- a/arch/arm64/boot/dts/qcom/sa8295p-adp.dts +++ b/arch/arm64/boot/dts/qcom/sa8295p-adp.dts @@ -9,6 +9,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/regulator/qcom,rpmh-regulator.h> #include <dt-bindings/spmi/spmi.h> +#include <dt-bindings/pinctrl/qcom,pmic-gpio.h> #include "sa8540p.dtsi" #include "sa8540p-pmics.dtsi" @@ -109,6 +110,46 @@ }; }; + regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB2_VBUS"; + gpio = <&pmm8540c_gpios 9 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb2_en>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + }; + + regulator-usb3-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB3_VBUS"; + gpio = <&pmm8540e_gpios 5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb3_en>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + }; + + regulator-usb4-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB4_VBUS"; + gpio = <&pmm8540g_gpios 5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb4_en>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + }; + + regulator-usb5-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB5_VBUS"; + gpio = <&pmm8540g_gpios 9 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb5_en>; + pinctrl-names = "default"; + enable-active-high; + regulator-always-on; + }; + reserved-memory { gpu_mem: gpu-mem@8bf00000 { reg = <0 0x8bf00000 0 0x2000>; @@ -637,6 +678,10 @@ status = "okay"; }; +&usb_2 { + status = "okay"; +}; + &usb_2_hsphy0 { vdda-pll-supply = <&vreg_l5a>; vdda18-supply = <&vreg_l7g>; @@ -697,6 +742,44 @@ }; }; +&pmm8540c_gpios { + usb2_en: usb2-en-state { + pins = "gpio9"; + function = "normal"; + qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>; + output-enable; + power-source = <0>; + }; +}; + +&pmm8540e_gpios { + usb3_en: usb3-en-state { + pins = "gpio5"; + function = "normal"; + qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>; + output-enable; + power-source = <0>; + }; +}; + +&pmm8540g_gpios { + usb4_en: usb4-en-state { + pins = "gpio5"; + function = "normal"; + qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>; + output-enable; + power-source = <0>; + }; + + usb5_en: usb5-en-state { + pins = "gpio9"; + function = "normal"; + qcom,drive-strength = <PMIC_GPIO_STRENGTH_HIGH>; + output-enable; + power-source = <0>; + }; +}; + &tlmm { pcie2a_default: pcie2a-default-state { clkreq-n-pins { diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi index 2a6170623ea9..0c1b21def4b6 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi @@ -702,6 +702,31 @@ status = "okay"; }; +&remoteproc_adsp { + firmware-name = "qcom/sa8775p/adsp.mbn"; + status = "okay"; +}; + +&remoteproc_cdsp0 { + firmware-name = "qcom/sa8775p/cdsp0.mbn"; + status = "okay"; +}; + +&remoteproc_cdsp1 { + firmware-name = "qcom/sa8775p/cdsp1.mbn"; + status = "okay"; +}; + +&remoteproc_gpdsp0 { + firmware-name = "qcom/sa8775p/gpdsp0.mbn"; + status = "okay"; +}; + +&remoteproc_gpdsp1 { + firmware-name = "qcom/sa8775p/gpdsp1.mbn"; + status = "okay"; +}; + &uart10 { compatible = "qcom,geni-debug-uart"; pinctrl-0 = <&qup_uart10_default>; diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi index 23f1b2e5e624..e8dbc8d820a6 100644 --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi @@ -10,6 +10,8 @@ #include <dt-bindings/clock/qcom,sa8775p-gpucc.h> #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> #include <dt-bindings/mailbox/qcom-ipcc.h> +#include <dt-bindings/firmware/qcom,scm.h> +#include <dt-bindings/power/qcom,rpmhpd.h> #include <dt-bindings/power/qcom-rpmpd.h> #include <dt-bindings/soc/qcom,rpmh-rsc.h> @@ -42,6 +44,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; next-level-cache = <&L2_0>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_0: l2-cache { compatible = "cache"; cache-level = <2>; @@ -62,6 +66,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; next-level-cache = <&L2_1>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_1: l2-cache { compatible = "cache"; cache-level = <2>; @@ -77,6 +83,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; next-level-cache = <&L2_2>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_2: l2-cache { compatible = "cache"; cache-level = <2>; @@ -92,6 +100,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 0>; next-level-cache = <&L2_3>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_3: l2-cache { compatible = "cache"; cache-level = <2>; @@ -107,6 +117,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; next-level-cache = <&L2_4>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_4: l2-cache { compatible = "cache"; cache-level = <2>; @@ -128,6 +140,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; next-level-cache = <&L2_5>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_5: l2-cache { compatible = "cache"; cache-level = <2>; @@ -143,6 +157,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; next-level-cache = <&L2_6>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_6: l2-cache { compatible = "cache"; cache-level = <2>; @@ -158,6 +174,8 @@ enable-method = "psci"; qcom,freq-domain = <&cpufreq_hw 1>; next-level-cache = <&L2_7>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <100>; L2_7: l2-cache { compatible = "cache"; cache-level = <2>; @@ -203,6 +221,48 @@ }; }; }; + + idle-states { + entry-method = "psci"; + + GOLD_CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + idle-state-name = "gold-power-collapse"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <549>; + exit-latency-us = <901>; + min-residency-us = <1774>; + local-timer-stop; + }; + + GOLD_RAIL_CPU_SLEEP_0: cpu-sleep-1 { + compatible = "arm,idle-state"; + idle-state-name = "gold-rail-power-collapse"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <702>; + exit-latency-us = <1061>; + min-residency-us = <4488>; + local-timer-stop; + }; + }; + + domain-idle-states { + CLUSTER_SLEEP_GOLD: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <2752>; + exit-latency-us = <3048>; + min-residency-us = <6118>; + }; + + CLUSTER_SLEEP_APSS_RSC_PC: cluster-sleep-1 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x42000144>; + entry-latency-us = <3263>; + exit-latency-us = <6562>; + min-residency-us = <9987>; + }; + }; }; dummy-sink { @@ -332,6 +392,79 @@ psci { compatible = "arm,psci-1.0"; method = "smc"; + + CPU_PD0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_0_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD4: power-domain-cpu4 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD5: power-domain-cpu5 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD6: power-domain-cpu6 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CPU_PD7: power-domain-cpu7 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_1_PD>; + domain-idle-states = <&GOLD_CPU_SLEEP_0>, + <&GOLD_RAIL_CPU_SLEEP_0>; + }; + + CLUSTER_0_PD: power-domain-cluster0 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_2_PD>; + domain-idle-states = <&CLUSTER_SLEEP_GOLD>; + }; + + CLUSTER_1_PD: power-domain-cluster1 { + #power-domain-cells = <0>; + power-domains = <&CLUSTER_2_PD>; + domain-idle-states = <&CLUSTER_SLEEP_GOLD>; + }; + + CLUSTER_2_PD: power-domain-cluster2 { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_SLEEP_APSS_RSC_PC>; + }; }; reserved-memory { @@ -564,6 +697,121 @@ }; }; + smp2p-adsp { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_LPASS IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + smp2p_adsp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_adsp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp0 { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + interrupts-extended = <&ipcc IPCC_CLIENT_CDSP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_CDSP IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + smp2p_cdsp0_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp0_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp1 { + compatible = "qcom,smp2p"; + qcom,smem = <617>, <616>; + interrupts-extended = <&ipcc IPCC_CLIENT_NSP1 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_NSP1 IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,local-pid = <0>; + qcom,remote-pid = <12>; + + smp2p_cdsp1_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp1_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-gpdsp0 { + compatible = "qcom,smp2p"; + qcom,smem = <617>, <616>; + interrupts-extended = <&ipcc IPCC_CLIENT_GPDSP0 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_GPDSP0 IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,local-pid = <0>; + qcom,remote-pid = <17>; + + smp2p_gpdsp0_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_gpdsp0_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-gpdsp1 { + compatible = "qcom,smp2p"; + qcom,smem = <617>, <616>; + interrupts-extended = <&ipcc IPCC_CLIENT_GPDSP1 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_GPDSP1 IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,local-pid = <0>; + qcom,remote-pid = <18>; + + smp2p_gpdsp1_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_gpdsp1_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; #address-cells = <2>; @@ -2892,6 +3140,101 @@ status = "disabled"; }; + pmu@9091000 { + compatible = "qcom,sa8775p-llcc-bwmon", "qcom,sc7280-llcc-bwmon"; + reg = <0x0 0x9091000 0x0 0x1000>; + interrupts = <GIC_SPI 620 IRQ_TYPE_LEVEL_HIGH>; + interconnects = <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>; + + operating-points-v2 = <&llcc_bwmon_opp_table>; + + llcc_bwmon_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <762000>; + }; + + opp-1 { + opp-peak-kBps = <1720000>; + }; + + opp-2 { + opp-peak-kBps = <2086000>; + }; + + opp-3 { + opp-peak-kBps = <2601000>; + }; + + opp-4 { + opp-peak-kBps = <2929000>; + }; + + opp-5 { + opp-peak-kBps = <5931000>; + }; + + opp-6 { + opp-peak-kBps = <6515000>; + }; + + opp-7 { + opp-peak-kBps = <7984000>; + }; + + opp-8 { + opp-peak-kBps = <10437000>; + }; + + opp-9 { + opp-peak-kBps = <12195000>; + }; + }; + }; + + pmu@90b5400 { + compatible = "qcom,sa8775p-cpu-bwmon", "qcom,sdm845-bwmon"; + reg = <0x0 0x90b5400 0x0 0x600>; + interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>; + + operating-points-v2 = <&cpu_bwmon_opp_table>; + + cpu_bwmon_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <9155000>; + }; + + opp-1 { + opp-peak-kBps = <12298000>; + }; + + opp-2 { + opp-peak-kBps = <14236000>; + }; + + opp-3 { + opp-peak-kBps = <16265000>; + }; + }; + + }; + + pmu@90b6400 { + compatible = "qcom,sa8775p-cpu-bwmon", "qcom,sdm845-bwmon"; + reg = <0x0 0x90b6400 0x0 0x600>; + interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &gem_noc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>; + + operating-points-v2 = <&cpu_bwmon_opp_table>; + }; + llcc: system-cache-controller@9200000 { compatible = "qcom,sa8775p-llcc"; reg = <0x0 0x09200000 0x0 0x80000>, @@ -3070,6 +3413,7 @@ reg = <0x0 0x15000000 0x0 0x100000>; #iommu-cells = <2>; #global-interrupts = <2>; + dma-coherent; interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, @@ -3208,6 +3552,7 @@ reg = <0x0 0x15200000 0x0 0x80000>; #iommu-cells = <2>; #global-interrupts = <2>; + dma-coherent; interrupts = <GIC_SPI 920 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 921 IRQ_TYPE_LEVEL_HIGH>, @@ -3445,6 +3790,92 @@ #freq-domain-cells = <1>; }; + remoteproc_gpdsp0: remoteproc@20c00000 { + compatible = "qcom,sa8775p-gpdsp0-pas"; + reg = <0x0 0x20c00000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 768 IRQ_TYPE_EDGE_RISING>, + <&smp2p_gpdsp0_in 0 0>, + <&smp2p_gpdsp0_in 2 0>, + <&smp2p_gpdsp0_in 1 0>, + <&smp2p_gpdsp0_in 3 0>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "cx", "mxc"; + + interconnects = <&gpdsp_anoc MASTER_DSP0 0 + &config_noc SLAVE_CLK_CTL 0>; + + memory-region = <&pil_gdsp0_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_gpdsp0_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_GPDSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_GPDSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "gpdsp0"; + qcom,remote-pid = <17>; + }; + }; + + remoteproc_gpdsp1: remoteproc@21c00000 { + compatible = "qcom,sa8775p-gpdsp1-pas"; + reg = <0x0 0x21c00000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 624 IRQ_TYPE_EDGE_RISING>, + <&smp2p_gpdsp1_in 0 0>, + <&smp2p_gpdsp1_in 2 0>, + <&smp2p_gpdsp1_in 1 0>, + <&smp2p_gpdsp1_in 3 0>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "cx", "mxc"; + + interconnects = <&gpdsp_anoc MASTER_DSP1 0 + &config_noc SLAVE_CLK_CTL 0>; + + memory-region = <&pil_gdsp1_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_gpdsp1_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_GPDSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_GPDSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "gpdsp1"; + qcom,remote-pid = <18>; + }; + }; + ethernet1: ethernet@23000000 { compatible = "qcom,sa8775p-ethqos"; reg = <0x0 0x23000000 0x0 0x10000>, @@ -3464,6 +3895,12 @@ "ptp_ref", "phyaux"; + interconnects = <&aggre1_noc MASTER_EMAC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC1_CFG QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "mac-mem", "cpu-mac"; + power-domains = <&gcc EMAC1_GDSC>; phys = <&serdes1>; @@ -3499,6 +3936,12 @@ "ptp_ref", "phyaux"; + interconnects = <&aggre1_noc MASTER_EMAC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC_CFG QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "mac-mem", "cpu-mac"; + power-domains = <&gcc EMAC0_GDSC>; phys = <&serdes0>; @@ -3514,6 +3957,569 @@ status = "disabled"; }; + + remoteproc_cdsp0: remoteproc@26300000 { + compatible = "qcom,sa8775p-cdsp0-pas"; + reg = <0x0 0x26300000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_NSP0>; + power-domain-names = "cx", "mxc", "nsp"; + + interconnects = <&nspa_noc MASTER_CDSP_PROC 0 + &mc_virt SLAVE_EBI1 0>; + + memory-region = <&pil_cdsp0_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp0_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_CDSP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_CDSP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "cdsp"; + qcom,remote-pid = <5>; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x2141 0x04a0>, + <&apps_smmu 0x2161 0x04a0>, + <&apps_smmu 0x2181 0x0400>, + <&apps_smmu 0x21c1 0x04a0>, + <&apps_smmu 0x21e1 0x04a0>, + <&apps_smmu 0x2541 0x04a0>, + <&apps_smmu 0x2561 0x04a0>, + <&apps_smmu 0x2581 0x0400>, + <&apps_smmu 0x25c1 0x04a0>, + <&apps_smmu 0x25e1 0x04a0>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x2142 0x04a0>, + <&apps_smmu 0x2162 0x04a0>, + <&apps_smmu 0x2182 0x0400>, + <&apps_smmu 0x21c2 0x04a0>, + <&apps_smmu 0x21e2 0x04a0>, + <&apps_smmu 0x2542 0x04a0>, + <&apps_smmu 0x2562 0x04a0>, + <&apps_smmu 0x2582 0x0400>, + <&apps_smmu 0x25c2 0x04a0>, + <&apps_smmu 0x25e2 0x04a0>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x2143 0x04a0>, + <&apps_smmu 0x2163 0x04a0>, + <&apps_smmu 0x2183 0x0400>, + <&apps_smmu 0x21c3 0x04a0>, + <&apps_smmu 0x21e3 0x04a0>, + <&apps_smmu 0x2543 0x04a0>, + <&apps_smmu 0x2563 0x04a0>, + <&apps_smmu 0x2583 0x0400>, + <&apps_smmu 0x25c3 0x04a0>, + <&apps_smmu 0x25e3 0x04a0>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x2144 0x04a0>, + <&apps_smmu 0x2164 0x04a0>, + <&apps_smmu 0x2184 0x0400>, + <&apps_smmu 0x21c4 0x04a0>, + <&apps_smmu 0x21e4 0x04a0>, + <&apps_smmu 0x2544 0x04a0>, + <&apps_smmu 0x2564 0x04a0>, + <&apps_smmu 0x2584 0x0400>, + <&apps_smmu 0x25c4 0x04a0>, + <&apps_smmu 0x25e4 0x04a0>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x2145 0x04a0>, + <&apps_smmu 0x2165 0x04a0>, + <&apps_smmu 0x2185 0x0400>, + <&apps_smmu 0x21c5 0x04a0>, + <&apps_smmu 0x21e5 0x04a0>, + <&apps_smmu 0x2545 0x04a0>, + <&apps_smmu 0x2565 0x04a0>, + <&apps_smmu 0x2585 0x0400>, + <&apps_smmu 0x25c5 0x04a0>, + <&apps_smmu 0x25e5 0x04a0>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x2146 0x04a0>, + <&apps_smmu 0x2166 0x04a0>, + <&apps_smmu 0x2186 0x0400>, + <&apps_smmu 0x21c6 0x04a0>, + <&apps_smmu 0x21e6 0x04a0>, + <&apps_smmu 0x2546 0x04a0>, + <&apps_smmu 0x2566 0x04a0>, + <&apps_smmu 0x2586 0x0400>, + <&apps_smmu 0x25c6 0x04a0>, + <&apps_smmu 0x25e6 0x04a0>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x2147 0x04a0>, + <&apps_smmu 0x2167 0x04a0>, + <&apps_smmu 0x2187 0x0400>, + <&apps_smmu 0x21c7 0x04a0>, + <&apps_smmu 0x21e7 0x04a0>, + <&apps_smmu 0x2547 0x04a0>, + <&apps_smmu 0x2567 0x04a0>, + <&apps_smmu 0x2587 0x0400>, + <&apps_smmu 0x25c7 0x04a0>, + <&apps_smmu 0x25e7 0x04a0>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu 0x2148 0x04a0>, + <&apps_smmu 0x2168 0x04a0>, + <&apps_smmu 0x2188 0x0400>, + <&apps_smmu 0x21c8 0x04a0>, + <&apps_smmu 0x21e8 0x04a0>, + <&apps_smmu 0x2548 0x04a0>, + <&apps_smmu 0x2568 0x04a0>, + <&apps_smmu 0x2588 0x0400>, + <&apps_smmu 0x25c8 0x04a0>, + <&apps_smmu 0x25e8 0x04a0>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu 0x2149 0x04a0>, + <&apps_smmu 0x2169 0x04a0>, + <&apps_smmu 0x2189 0x0400>, + <&apps_smmu 0x21c9 0x04a0>, + <&apps_smmu 0x21e9 0x04a0>, + <&apps_smmu 0x2549 0x04a0>, + <&apps_smmu 0x2569 0x04a0>, + <&apps_smmu 0x2589 0x0400>, + <&apps_smmu 0x25c9 0x04a0>, + <&apps_smmu 0x25e9 0x04a0>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu 0x214a 0x04a0>, + <&apps_smmu 0x216a 0x04a0>, + <&apps_smmu 0x218a 0x0400>, + <&apps_smmu 0x21ca 0x04a0>, + <&apps_smmu 0x21ea 0x04a0>, + <&apps_smmu 0x254a 0x04a0>, + <&apps_smmu 0x256a 0x04a0>, + <&apps_smmu 0x258a 0x0400>, + <&apps_smmu 0x25ca 0x04a0>, + <&apps_smmu 0x25ea 0x04a0>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu 0x214b 0x04a0>, + <&apps_smmu 0x216b 0x04a0>, + <&apps_smmu 0x218b 0x0400>, + <&apps_smmu 0x21cb 0x04a0>, + <&apps_smmu 0x21eb 0x04a0>, + <&apps_smmu 0x254b 0x04a0>, + <&apps_smmu 0x256b 0x04a0>, + <&apps_smmu 0x258b 0x0400>, + <&apps_smmu 0x25cb 0x04a0>, + <&apps_smmu 0x25eb 0x04a0>; + dma-coherent; + }; + }; + }; + }; + + remoteproc_cdsp1: remoteproc@2a300000 { + compatible = "qcom,sa8775p-cdsp1-pas"; + reg = <0x0 0x2A300000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 798 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_NSP1>; + power-domain-names = "cx", "mxc", "nsp"; + + interconnects = <&nspb_noc MASTER_CDSP_PROC_B 0 + &mc_virt SLAVE_EBI1 0>; + + memory-region = <&pil_cdsp1_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp1_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_NSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_NSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "cdsp"; + qcom,remote-pid = <12>; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp1"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x2941 0x04a0>, + <&apps_smmu 0x2961 0x04a0>, + <&apps_smmu 0x2981 0x0400>, + <&apps_smmu 0x29c1 0x04a0>, + <&apps_smmu 0x29e1 0x04a0>, + <&apps_smmu 0x2d41 0x04a0>, + <&apps_smmu 0x2d61 0x04a0>, + <&apps_smmu 0x2d81 0x0400>, + <&apps_smmu 0x2dc1 0x04a0>, + <&apps_smmu 0x2de1 0x04a0>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x2942 0x04a0>, + <&apps_smmu 0x2962 0x04a0>, + <&apps_smmu 0x2982 0x0400>, + <&apps_smmu 0x29c2 0x04a0>, + <&apps_smmu 0x29e2 0x04a0>, + <&apps_smmu 0x2d42 0x04a0>, + <&apps_smmu 0x2d62 0x04a0>, + <&apps_smmu 0x2d82 0x0400>, + <&apps_smmu 0x2dc2 0x04a0>, + <&apps_smmu 0x2de2 0x04a0>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x2943 0x04a0>, + <&apps_smmu 0x2963 0x04a0>, + <&apps_smmu 0x2983 0x0400>, + <&apps_smmu 0x29c3 0x04a0>, + <&apps_smmu 0x29e3 0x04a0>, + <&apps_smmu 0x2d43 0x04a0>, + <&apps_smmu 0x2d63 0x04a0>, + <&apps_smmu 0x2d83 0x0400>, + <&apps_smmu 0x2dc3 0x04a0>, + <&apps_smmu 0x2de3 0x04a0>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x2944 0x04a0>, + <&apps_smmu 0x2964 0x04a0>, + <&apps_smmu 0x2984 0x0400>, + <&apps_smmu 0x29c4 0x04a0>, + <&apps_smmu 0x29e4 0x04a0>, + <&apps_smmu 0x2d44 0x04a0>, + <&apps_smmu 0x2d64 0x04a0>, + <&apps_smmu 0x2d84 0x0400>, + <&apps_smmu 0x2dc4 0x04a0>, + <&apps_smmu 0x2de4 0x04a0>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x2945 0x04a0>, + <&apps_smmu 0x2965 0x04a0>, + <&apps_smmu 0x2985 0x0400>, + <&apps_smmu 0x29c5 0x04a0>, + <&apps_smmu 0x29e5 0x04a0>, + <&apps_smmu 0x2d45 0x04a0>, + <&apps_smmu 0x2d65 0x04a0>, + <&apps_smmu 0x2d85 0x0400>, + <&apps_smmu 0x2dc5 0x04a0>, + <&apps_smmu 0x2de5 0x04a0>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x2946 0x04a0>, + <&apps_smmu 0x2966 0x04a0>, + <&apps_smmu 0x2986 0x0400>, + <&apps_smmu 0x29c6 0x04a0>, + <&apps_smmu 0x29e6 0x04a0>, + <&apps_smmu 0x2d46 0x04a0>, + <&apps_smmu 0x2d66 0x04a0>, + <&apps_smmu 0x2d86 0x0400>, + <&apps_smmu 0x2dc6 0x04a0>, + <&apps_smmu 0x2de6 0x04a0>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x2947 0x04a0>, + <&apps_smmu 0x2967 0x04a0>, + <&apps_smmu 0x2987 0x0400>, + <&apps_smmu 0x29c7 0x04a0>, + <&apps_smmu 0x29e7 0x04a0>, + <&apps_smmu 0x2d47 0x04a0>, + <&apps_smmu 0x2d67 0x04a0>, + <&apps_smmu 0x2d87 0x0400>, + <&apps_smmu 0x2dc7 0x04a0>, + <&apps_smmu 0x2de7 0x04a0>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu 0x2948 0x04a0>, + <&apps_smmu 0x2968 0x04a0>, + <&apps_smmu 0x2988 0x0400>, + <&apps_smmu 0x29c8 0x04a0>, + <&apps_smmu 0x29e8 0x04a0>, + <&apps_smmu 0x2d48 0x04a0>, + <&apps_smmu 0x2d68 0x04a0>, + <&apps_smmu 0x2d88 0x0400>, + <&apps_smmu 0x2dc8 0x04a0>, + <&apps_smmu 0x2de8 0x04a0>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu 0x2949 0x04a0>, + <&apps_smmu 0x2969 0x04a0>, + <&apps_smmu 0x2989 0x0400>, + <&apps_smmu 0x29c9 0x04a0>, + <&apps_smmu 0x29e9 0x04a0>, + <&apps_smmu 0x2d49 0x04a0>, + <&apps_smmu 0x2d69 0x04a0>, + <&apps_smmu 0x2d89 0x0400>, + <&apps_smmu 0x2dc9 0x04a0>, + <&apps_smmu 0x2de9 0x04a0>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu 0x294a 0x04a0>, + <&apps_smmu 0x296a 0x04a0>, + <&apps_smmu 0x298a 0x0400>, + <&apps_smmu 0x29ca 0x04a0>, + <&apps_smmu 0x29ea 0x04a0>, + <&apps_smmu 0x2d4a 0x04a0>, + <&apps_smmu 0x2d6a 0x04a0>, + <&apps_smmu 0x2d8a 0x0400>, + <&apps_smmu 0x2dca 0x04a0>, + <&apps_smmu 0x2dea 0x04a0>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu 0x294b 0x04a0>, + <&apps_smmu 0x296b 0x04a0>, + <&apps_smmu 0x298b 0x0400>, + <&apps_smmu 0x29cb 0x04a0>, + <&apps_smmu 0x29eb 0x04a0>, + <&apps_smmu 0x2d4b 0x04a0>, + <&apps_smmu 0x2d6b 0x04a0>, + <&apps_smmu 0x2d8b 0x0400>, + <&apps_smmu 0x2dcb 0x04a0>, + <&apps_smmu 0x2deb 0x04a0>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu 0x294c 0x04a0>, + <&apps_smmu 0x296c 0x04a0>, + <&apps_smmu 0x298c 0x0400>, + <&apps_smmu 0x29cc 0x04a0>, + <&apps_smmu 0x29ec 0x04a0>, + <&apps_smmu 0x2d4c 0x04a0>, + <&apps_smmu 0x2d6c 0x04a0>, + <&apps_smmu 0x2d8c 0x0400>, + <&apps_smmu 0x2dcc 0x04a0>, + <&apps_smmu 0x2dec 0x04a0>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu 0x294d 0x04a0>, + <&apps_smmu 0x296d 0x04a0>, + <&apps_smmu 0x298d 0x0400>, + <&apps_smmu 0x29Cd 0x04a0>, + <&apps_smmu 0x29ed 0x04a0>, + <&apps_smmu 0x2d4d 0x04a0>, + <&apps_smmu 0x2d6d 0x04a0>, + <&apps_smmu 0x2d8d 0x0400>, + <&apps_smmu 0x2dcd 0x04a0>, + <&apps_smmu 0x2ded 0x04a0>; + dma-coherent; + }; + }; + }; + }; + + remoteproc_adsp: remoteproc@30000000 { + compatible = "qcom,sa8775p-adsp-pas"; + reg = <0x0 0x30000000 0x0 0x100>; + + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", "fatal", "ready", "handover", + "stop-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_LCX>, + <&rpmhpd RPMHPD_LMX>; + power-domain-names = "lcx", "lmx"; + + interconnects = <&lpass_ag_noc MASTER_LPASS_PROC 0 &mc_virt SLAVE_EBI1 0>; + + memory-region = <&pil_adsp_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_adsp_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + remoteproc_adsp_glink: glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "lpass"; + qcom,remote-pid = <2>; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + memory-region = <&adsp_rpc_remote_heap_mem>; + qcom,vmids = <QCOM_SCM_VMID_LPASS + QCOM_SCM_VMID_ADSP_HEAP>; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x3003 0x0>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x3004 0x0>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x3005 0x0>; + qcom,nsessions = <5>; + dma-coherent; + }; + }; + }; + }; }; thermal-zones { diff --git a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts index 5b226577f9d8..62de4774c556 100644 --- a/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts +++ b/arch/arm64/boot/dts/qcom/sc8180x-lenovo-flex-5g.dts @@ -484,6 +484,10 @@ status = "okay"; }; +&pmc8180_pwrkey { + status = "okay"; +}; + &pmc8180c_lpg { status = "okay"; }; @@ -557,6 +561,40 @@ status = "okay"; }; +&usb_mp { + status = "okay"; +}; + +&usb_mp_hsphy0 { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_mp_hsphy1 { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_mp_qmpphy0 { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_mp_qmpphy1 { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + &usb_prim_hsphy { vdda-pll-supply = <&vreg_l5e_0p88>; vdda18-supply = <&vreg_l12a_1p8>; diff --git a/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi index 1c6f12fafe1d..451c9b984f1f 100644 --- a/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/sc8180x-pmics.dtsi @@ -75,7 +75,7 @@ pon: pon@800 { compatible = "qcom,pm8916-pon"; reg = <0x0800>; - pwrkey { + pmc8180_pwrkey: pwrkey { compatible = "qcom,pm8941-pwrkey"; interrupts = <0x0 0x8 0x0 IRQ_TYPE_EDGE_BOTH>; debounce = <15625>; @@ -139,11 +139,11 @@ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>; }; - pmc8180_gpios: gpio@c000 { + pmc8180_1_gpios: gpio@c000 { compatible = "qcom,pmc8180-gpio", "qcom,spmi-gpio"; reg = <0xc000>; gpio-controller; - gpio-ranges = <&pmc8180_gpios 0 0 10>; + gpio-ranges = <&pmc8180_1_gpios 0 0 10>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; @@ -198,11 +198,21 @@ #size-cells = <0>; }; - pmic@8 { + pmc8180_2: pmic@8 { compatible = "qcom,pm8150", "qcom,spmi-pmic"; reg = <0x8 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + pmc8180_2_gpios: gpio@c000 { + compatible = "qcom,pmc8180-gpio", "qcom,spmi-gpio"; + reg = <0xc000>; + gpio-controller; + gpio-ranges = <&pmc8180_2_gpios 0 0 10>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; }; pmic@a { diff --git a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts index 65d923497a05..79b4d293ea1e 100644 --- a/arch/arm64/boot/dts/qcom/sc8180x-primus.dts +++ b/arch/arm64/boot/dts/qcom/sc8180x-primus.dts @@ -223,6 +223,32 @@ vin-supply = <&vph_pwr>; }; + vreg_usb2_host_en: regulator-usb2-host-en { + compatible = "regulator-fixed"; + regulator-name = "usb2_host_en"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&pmc8180_1_gpios 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + + regulator-always-on; + }; + + vreg_usb3_host_en: regulator-usb3-host-en { + compatible = "regulator-fixed"; + regulator-name = "usb3_host_en"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&pmc8180_2_gpios 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + + regulator-always-on; + }; + usbprim-sbu-mux { compatible = "pericom,pi3usb102", "gpio-sbu-mux"; @@ -552,6 +578,10 @@ status = "okay"; }; +&pmc8180_pwrkey { + status = "okay"; +}; + &pmc8180c_lpg { status = "okay"; }; @@ -623,6 +653,40 @@ status = "okay"; }; +&usb_mp { + status = "okay"; +}; + +&usb_mp_hsphy0 { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_mp_hsphy1 { + vdda-pll-supply = <&vreg_l5e_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; + vdda33-supply = <&vreg_l16e_3p0>; + + status = "okay"; +}; + +&usb_mp_qmpphy0 { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + +&usb_mp_qmpphy1 { + vdda-phy-supply = <&vreg_l3c_1p2>; + vdda-pll-supply = <&vreg_l5e_0p88>; + + status = "okay"; +}; + &usb_prim_hsphy { vdda-pll-supply = <&vreg_l5e_0p88>; vdda18-supply = <&vreg_l12a_1p8>; diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi index 6e707d993aeb..0e9429684dd9 100644 --- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi +++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi @@ -2507,6 +2507,34 @@ status = "disabled"; }; + usb_mp_hsphy0: phy@88e4000 { + compatible = "qcom,sc8180x-usb-hs-phy", + "qcom,usb-snps-hs-7nm-phy"; + reg = <0 0x088e4000 0 0x400>; + #phy-cells = <0>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_MP0_BCR>; + + status = "disabled"; + }; + + usb_mp_hsphy1: phy@88e5000 { + compatible = "qcom,sc8180x-usb-hs-phy", + "qcom,usb-snps-hs-7nm-phy"; + reg = <0 0x088e5000 0 0x400>; + #phy-cells = <0>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_MP1_BCR>; + + status = "disabled"; + }; + usb_prim_qmpphy: phy@88e8000 { compatible = "qcom,sc8180x-qmp-usb3-dp-phy"; reg = <0 0x088e8000 0 0x3000>; @@ -2555,6 +2583,60 @@ }; }; + usb_mp_qmpphy0: phy@88eb000 { + compatible = "qcom,sc8180x-qmp-usb3-uni-phy"; + reg = <0 0x088eb000 0 0x1000>; + + clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_UNIPHY_MP0_BCR>, + <&gcc GCC_USB3UNIPHY_PHY_MP0_BCR>; + reset-names = "phy", "phy_phy"; + + power-domains = <&gcc USB30_MP_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb2_phy0_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_mp_qmpphy1: phy@88ec000 { + compatible = "qcom,sc8180x-qmp-usb3-uni-phy"; + reg = <0 0x088ec000 0 0x1000>; + + clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_UNIPHY_MP1_BCR>, + <&gcc GCC_USB3UNIPHY_PHY_MP1_BCR>; + reset-names = "phy", "phy_phy"; + + power-domains = <&gcc USB30_MP_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb2_phy1_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + usb_sec_qmpphy: phy@88ee000 { compatible = "qcom,sc8180x-qmp-usb3-dp-phy"; reg = <0 0x088ed000 0 0x3000>; @@ -2622,17 +2704,89 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + usb_mp: usb@a4f8800 { + compatible = "qcom,sc8180x-dwc3-mp", "qcom,dwc3"; + reg = <0 0x0a4f8800 0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + dma-ranges; + + clocks = <&gcc GCC_CFG_NOC_USB3_MP_AXI_CLK>, + <&gcc GCC_USB30_MP_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_MP_AXI_CLK>, + <&gcc GCC_USB30_MP_SLEEP_CLK>, + <&gcc GCC_USB30_MP_MOCK_UTMI_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + interconnects = <&aggre1_noc MASTER_USB3_2 0 &mc_virt SLAVE_EBI_CH0 0>, + <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3_2 0>; + interconnect-names = "usb-ddr", "apps-usb"; + + assigned-clocks = <&gcc GCC_USB30_MP_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_MP_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_SPI 656 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 655 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 658 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 657 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 59 IRQ_TYPE_EDGE_BOTH>, + <&pdc 46 IRQ_TYPE_EDGE_BOTH>, + <&pdc 71 IRQ_TYPE_EDGE_BOTH>, + <&pdc 68 IRQ_TYPE_EDGE_BOTH>, + <&pdc 7 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 30 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event_1", "pwr_event_2", + "hs_phy_1", "hs_phy_2", + "dp_hs_phy_1", "dm_hs_phy_1", + "dp_hs_phy_2", "dm_hs_phy_2", + "ss_phy_1", "ss_phy_2"; + + power-domains = <&gcc USB30_MP_GDSC>; + + resets = <&gcc GCC_USB30_MP_BCR>; + + status = "disabled"; + + usb_mp_dwc3: usb@a400000 { + compatible = "snps,dwc3"; + reg = <0 0x0a400000 0 0xcd00>; + interrupts = <GIC_SPI 654 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&apps_smmu 0x60 0>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + phys = <&usb_mp_hsphy0>, + <&usb_mp_qmpphy0>, + <&usb_mp_hsphy1>, + <&usb_mp_qmpphy1>; + phy-names = "usb2-0", + "usb3-0", + "usb2-1", + "usb3-1"; + dr_mode = "host"; + }; + }; + usb_prim: usb@a6f8800 { compatible = "qcom,sc8180x-dwc3", "qcom,dwc3"; reg = <0 0x0a6f8800 0 0x400>; - interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, - <&pdc 6 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 9 IRQ_TYPE_EDGE_BOTH>, <&pdc 8 IRQ_TYPE_EDGE_BOTH>, - <&pdc 9 IRQ_TYPE_EDGE_BOTH>; - interrupt-names = "hs_phy_irq", - "ss_phy_irq", + <&pdc 6 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", "dm_hs_phy_irq", - "dp_hs_phy_irq"; + "ss_phy_irq"; clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, <&gcc GCC_USB30_PRIM_MASTER_CLK>, @@ -2714,12 +2868,17 @@ "xo"; resets = <&gcc GCC_USB30_SEC_BCR>; power-domains = <&gcc USB30_SEC_GDSC>; - interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, - <&pdc 40 IRQ_TYPE_LEVEL_HIGH>, + + interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 11 IRQ_TYPE_EDGE_BOTH>, <&pdc 10 IRQ_TYPE_EDGE_BOTH>, - <&pdc 11 IRQ_TYPE_EDGE_BOTH>; - interrupt-names = "hs_phy_irq", "ss_phy_irq", - "dm_hs_phy_irq", "dp_hs_phy_irq"; + <&pdc 40 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, <&gcc GCC_USB30_SEC_MASTER_CLK>; diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts index b98b2f7752b5..6020582b0a59 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts +++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts @@ -848,15 +848,15 @@ pins = "gpio143"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { - pins = "gpio145"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; + pins = "gpio145"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; pcie3a_default: pcie3a-default-state { @@ -871,7 +871,7 @@ pins = "gpio151"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { @@ -894,7 +894,7 @@ pins = "gpio141"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts index b27143f81867..6a28cab97189 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts +++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts @@ -592,6 +592,57 @@ }; }; +&camss { + vdda-phy-supply = <&vreg_l6d>; + vdda-pll-supply = <&vreg_l4d>; + + status = "okay"; + + ports { + port@0 { + csiphy0_lanes01_ep: endpoint@0 { + reg = <0>; + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov5675_ep>; + }; + }; + }; +}; + +&cci2 { + status = "okay"; +}; + +&cci2_i2c1 { + camera@10 { + compatible = "ovti,ov5675"; + reg = <0x10>; + + reset-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAMCC_MCLK3_CLK>; + + orientation = <0>; /* Front facing */ + + avdd-supply = <&vreg_l6q>; + dvdd-supply = <&vreg_l2q>; + dovdd-supply = <&vreg_l7q>; + + port { + ov5675_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <450000000>; + remote-endpoint = <&csiphy0_lanes01_ep>; + }; + }; + + }; +}; + &dispcc0 { status = "okay"; }; @@ -1436,6 +1487,22 @@ bias-disable; }; + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio17"; + function = "cam_mclk"; + drive-strength = <16>; + bias-disable; + }; + + sc-rgb-xshut-n-pins { + pins = "gpio15"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio25"; function = "gpio"; @@ -1509,15 +1576,15 @@ pins = "gpio143"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { - pins = "gpio145"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; + pins = "gpio145"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; pcie3a_default: pcie3a-default-state { @@ -1532,7 +1599,7 @@ pins = "gpio151"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { @@ -1555,7 +1622,7 @@ pins = "gpio141"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi index c7e3764a8cf3..c8da5cb8d04e 100644 --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi @@ -372,7 +372,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-sdm660"; + compatible = "qcom,rpm-sdm660", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/sdx75-idp.dts b/arch/arm64/boot/dts/qcom/sdx75-idp.dts index fde16308c7e2..f1bbe7ab01ab 100644 --- a/arch/arm64/boot/dts/qcom/sdx75-idp.dts +++ b/arch/arm64/boot/dts/qcom/sdx75-idp.dts @@ -282,6 +282,12 @@ status = "okay"; }; +&remoteproc_mpss { + firmware-name = "qcom/sdx75/modem.mbn", + "qcom/sdx75/modem_dtb.mbn"; + status = "okay"; +}; + &sdhc { cd-gpios = <&tlmm 103 GPIO_ACTIVE_LOW>; vmmc-supply = <®_2v95_vdd>; diff --git a/arch/arm64/boot/dts/qcom/sdx75.dtsi b/arch/arm64/boot/dts/qcom/sdx75.dtsi index 9b93f6501d55..7cf3fcb469a8 100644 --- a/arch/arm64/boot/dts/qcom/sdx75.dtsi +++ b/arch/arm64/boot/dts/qcom/sdx75.dtsi @@ -366,7 +366,12 @@ no-map; }; - qdss_mem: qdss@88800000 { + qdss_mem: qdss@88500000 { + reg = <0x0 0x88500000 0x0 0x300000>; + no-map; + }; + + qlink_logging_mem: qlink-logging@88800000 { reg = <0x0 0x88800000 0x0 0x300000>; no-map; }; @@ -377,8 +382,13 @@ no-map; }; - mpss_dsmharq_mem: mpss-dsmharq@88f00000 { - reg = <0x0 0x88f00000 0x0 0x5080000>; + mpss_dsm_mem_2: mpss-dsm-2@88f00000 { + reg = <0x0 0x88f00000 0x0 0x2500000>; + no-map; + }; + + mpss_dsm_mem: mpss-dsm@8b400000 { + reg = <0x0 0x8b400000 0x0 0x2b80000>; no-map; }; @@ -388,7 +398,7 @@ }; mpssadsp_mem: mpssadsp@8e000000 { - reg = <0x0 0x8e000000 0x0 0xf400000>; + reg = <0x0 0x8e000000 0x0 0xf100000>; no-map; }; @@ -881,6 +891,53 @@ reg = <0x0 0x01fc0000 0x0 0x30000>; }; + remoteproc_mpss: remoteproc@4080000 { + compatible = "qcom,sdx75-mpss-pas"; + reg = <0 0x04080000 0 0x4040>; + + interrupts-extended = <&intc GIC_SPI 250 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MSS>; + power-domain-names = "cx", + "mss"; + + memory-region = <&mpssadsp_mem>, <&q6_mpss_dtb_mem>, + <&mpss_dsm_mem>, <&mpss_dsm_mem_2>, + <&qlink_logging_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_modem_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_CLIENT_MPSS + IPCC_MPROC_SIGNAL_PING + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_CLIENT_MPSS + IPCC_MPROC_SIGNAL_PING>; + label = "mpss"; + qcom,remote-pid = <1>; + }; + }; + sdhc: mmc@8804000 { compatible = "qcom,sdx75-sdhci", "qcom,sdhci-msm-v5"; reg = <0x0 0x08804000 0x0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/sm4450.dtsi b/arch/arm64/boot/dts/qcom/sm4450.dtsi index 9c9919e78fbd..1e05cd00b635 100644 --- a/arch/arm64/boot/dts/qcom/sm4450.dtsi +++ b/arch/arm64/boot/dts/qcom/sm4450.dtsi @@ -4,7 +4,10 @@ */ #include <dt-bindings/clock/qcom,rpmh.h> +#include <dt-bindings/clock/qcom,sm4450-camcc.h> +#include <dt-bindings/clock/qcom,sm4450-dispcc.h> #include <dt-bindings/clock/qcom,sm4450-gcc.h> +#include <dt-bindings/clock/qcom,sm4450-gpucc.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/soc/qcom,rpmh-rsc.h> @@ -422,6 +425,41 @@ #hwlock-cells = <1>; }; + gpucc: clock-controller@3d90000 { + compatible = "qcom,sm4450-gpucc"; + reg = <0x0 0x03d90000 0x0 0xa000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + camcc: clock-controller@ade0000 { + compatible = "qcom,sm4450-camcc"; + reg = <0x0 0x0ade0000 0x0 0x20000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_CAMERA_AHB_CLK>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + dispcc: clock-controller@af00000 { + compatible = "qcom,sm4450-dispcc"; + reg = <0x0 0x0af00000 0x0 0x20000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&gcc GCC_DISP_AHB_CLK>, + <&sleep_clk>, + <0>, + <0>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,sm4450-pdc", "qcom,pdc"; reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>; diff --git a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts index 4a30024aa48f..f60d36c03b9b 100644 --- a/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts +++ b/arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts @@ -1,13 +1,16 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright (c) 2023, Dang Huynh <danct12@riseup.net> + * Copyright (c) 2023 - 2024, Dang Huynh <danct12@riseup.net> */ /dts-v1/; #include "sm6115.dtsi" #include "pm6125.dtsi" +#include "pmi632.dtsi" #include <dt-bindings/arm/qcom,ids.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/usb/pd.h> / { model = "F(x)tec Pro1X (QX1050)"; @@ -32,12 +35,48 @@ }; }; + disp_elvdd_supply: disp-elvdd-supply { + compatible = "regulator-fixed"; + regulator-name = "disp_elvdd_supply"; + }; + + disp_elvss_supply: disp-elvss-supply { + compatible = "regulator-fixed"; + regulator-name = "disp_elvss_supply"; + }; + + disp_vcc_supply: disp-vcc-supply { + compatible = "regulator-fixed"; + regulator-name = "disp_vcc_supply"; + }; + + disp_vci_supply: disp-vci-supply { + compatible = "regulator-fixed"; + regulator-name = "disp_vci_supply"; + }; + gpio-keys { compatible = "gpio-keys"; - pinctrl-0 = <&vol_up_n>; + pinctrl-0 = <&hall_sensor_n>, <&key_camera_n>, <&vol_up_n>; pinctrl-names = "default"; + hall-switch { + label = "Hall Switch"; + linux,input-type = <EV_SW>; + linux,code = <SW_KEYPAD_SLIDE>; + gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>; + debounce-interval = <90>; + wakeup-source; + }; + + key-camera { + label = "Camera Button"; + linux,code = <KEY_CAMERA>; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + }; + key-volume-up { label = "Volume Up"; linux,code = <KEY_VOLUMEUP>; @@ -47,11 +86,119 @@ wakeup-source; }; }; + + gpio-leds { + compatible = "gpio-leds"; + + capslock-led { + label = "green:capslock"; + function = LED_FUNCTION_CAPSLOCK; + color = <LED_COLOR_ID_GREEN>; + gpios = <&pca9534 1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "kbd-capslock"; + default-state = "off"; + }; + }; + + ts_vdd_supply: ts-vdd-supply { + compatible = "regulator-fixed"; + regulator-name = "ts_vdd_supply"; + gpio = <&pca9534 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + ts_vddio_supply: ts-vddio-supply { + compatible = "regulator-fixed"; + regulator-name = "ts_vddio_supply"; + gpio = <&pca9534 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; }; -&dispcc { - /* HACK: disable until a panel driver is ready to retain simplefb */ - status = "disabled"; +&gpi_dma0 { + status = "okay"; +}; + +&gpu { + status = "okay"; + + zap-shader { + firmware-name = "qcom/sm6115/Fxtec/QX1050/a610_zap.mbn"; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + + status = "okay"; + + pca9534: gpio@21 { + compatible = "nxp,pca9534"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&i2c2 { + status = "okay"; + /* Clock frequency was not specified downstream, let's park it to 100 KHz */ + clock-frequency = <100000>; + + touchscreen@14 { + compatible = "goodix,gt9286"; + reg = <0x14>; + + interrupts-extended = <&tlmm 80 IRQ_TYPE_LEVEL_LOW>; + + irq-gpios = <&tlmm 80 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&tlmm 71 GPIO_ACTIVE_HIGH>; + AVDD28-supply = <&ts_vdd_supply>; + VDDIO-supply = <&ts_vddio_supply>; + + pinctrl-0 = <&ts_int_n>, <&ts_rst_n>; + pinctrl-names = "default"; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm6125_l18a>; + status = "okay"; + + panel: panel@0 { + compatible = "boe,bf060y8m-aj0"; + reg = <0>; + + reset-gpios = <&tlmm 82 GPIO_ACTIVE_LOW>; + + elvdd-supply = <&disp_elvdd_supply>; + elvss-supply = <&disp_elvss_supply>; + vcc-supply = <&disp_vcc_supply>; + vci-supply = <&disp_vci_supply>; + vddio-supply = <&pm6125_l9a>; + + pinctrl-0 = <&mdss_dsi_n &panel_en_n>; + pinctrl-names = "default"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + data-lanes = <0 1 2 3>; + remote-endpoint = <&panel_in>; +}; + +&mdss_dsi0_phy { + status = "okay"; }; &pm6125_gpios { @@ -64,6 +211,73 @@ }; }; +&pmi632_lpg { + status = "okay"; + + multi-led { + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_STATUS; + + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = <LED_COLOR_ID_RED>; + }; + + led@2 { + reg = <2>; + color = <LED_COLOR_ID_GREEN>; + }; + + led@3 { + reg = <3>; + color = <LED_COLOR_ID_BLUE>; + }; + }; +}; + +&pmi632_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + pmi632_hs_in: endpoint { + remote-endpoint = <&usb_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + pmi632_ss_in: endpoint { + remote-endpoint = <&usb_qmpphy_out>; + }; + }; + }; + }; +}; + +&pmi632_vbus { + regulator-min-microamp = <500000>; + regulator-max-microamp = <1000000>; + status = "okay"; +}; + &pon_pwrkey { status = "okay"; }; @@ -73,6 +287,25 @@ status = "okay"; }; +&qupv3_id_0 { + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/sm6115/Fxtec/QX1050/adsp.mbn"; + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/sm6115/Fxtec/QX1050/cdsp.mbn"; + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/sm6115/Fxtec/QX1050/modem.mbn"; + status = "okay"; +}; + &rpm_requests { regulators-0 { compatible = "qcom,rpm-pm6125-regulators"; @@ -105,6 +338,7 @@ pm6125_l5a: l5 { regulator-min-microvolt = <1648000>; regulator-max-microvolt = <3056000>; + regulator-allow-set-load; }; pm6125_l6a: l6 { @@ -206,12 +440,84 @@ }; }; +&sdc2_state_off { + cd-pins { + pins = "gpio88"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + +&sdc2_state_on { + cd-pins { + pins = "gpio88"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; +}; + +&sdhc_2 { + pinctrl-0 = <&sdc2_state_on>; + pinctrl-1 = <&sdc2_state_off>; + pinctrl-names = "default", "sleep"; + + cd-gpios = <&tlmm 88 GPIO_ACTIVE_LOW>; + + vmmc-supply = <&pm6125_l22a>; + vqmmc-supply = <&pm6125_l5a>; + + status = "okay"; +}; + &sleep_clk { clock-frequency = <32764>; }; &tlmm { gpio-reserved-ranges = <0 4>, <14 4>; + + key_camera_n: key-camera-n-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + panel_en_n: panel-en-n-state { + pins = "gpio65"; + function = "gpio"; + bias-disable; + }; + + ts_rst_n: ts-rst-n-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + ts_int_n: ts-int-n-state { + pins = "gpio80"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + mdss_dsi_n: mdss-dsi-n-state { + pins = "gpio82"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + hall_sensor_n: hall-sensor-n-state { + pins = "gpio96"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; &ufs_mem_hc { @@ -233,10 +539,8 @@ status = "okay"; }; -&usb_dwc3 { - /delete-property/ usb-role-switch; - maximum-speed = "high-speed"; - dr_mode = "peripheral"; +&usb_dwc3_hs { + remote-endpoint = <&pmi632_hs_in>; }; &usb_hsphy { @@ -246,6 +550,27 @@ status = "okay"; }; +&usb_qmpphy { + vdda-phy-supply = <&pm6125_l4a>; + vdda-pll-supply = <&pm6125_l12a>; + status = "okay"; +}; + +&usb_qmpphy_out { + remote-endpoint = <&pmi632_ss_in>; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm6125_l8a>; + vdd-1.8-xo-supply = <&pm6125_l16a>; + vdd-1.3-rfa-supply = <&pm6125_l17a>; + vdd-3.3-ch0-supply = <&pm6125_l23a>; + + qcom,ath10k-calibration-variant = "Fxtec_QX1050"; + + status = "okay"; +}; + &xo_board { clock-frequency = <19200000>; }; diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi index e374733f3b85..41216cc319d6 100644 --- a/arch/arm64/boot/dts/qcom/sm6115.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi @@ -376,7 +376,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-sm6115"; + compatible = "qcom,rpm-sm6115", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi index 777c380c2fa0..133610d14fc4 100644 --- a/arch/arm64/boot/dts/qcom/sm6125.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi @@ -192,7 +192,7 @@ mboxes = <&apcs_glb 0>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-sm6125"; + compatible = "qcom,rpm-sm6125", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi index ddea681b536d..4d519dd6e7ef 100644 --- a/arch/arm64/boot/dts/qcom/sm6375.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi @@ -653,7 +653,7 @@ mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>; rpm_requests: rpm-requests { - compatible = "qcom,rpm-sm6375"; + compatible = "qcom,rpm-sm6375", "qcom,glink-smd-rpm"; qcom,glink-channels = "rpm_requests"; rpmcc: clock-controller { diff --git a/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi index 29289fa41b13..b9cff60efe6f 100644 --- a/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sm7125-xiaomi-common.dtsi @@ -411,6 +411,8 @@ }; &ufs_mem_hc { + reset-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l19a_3p0>; vcc-max-microamp = <600000>; vccq2-supply = <&vreg_l12a_1p8>; diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts index 286350ac7751..256a1ba94945 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts @@ -355,11 +355,6 @@ }; &gpu { - /* - * NOTE: "amd,imageon" makes Adreno start in headless mode, remove it - * after display support is added on this board. - */ - compatible = "qcom,adreno-640.1", "qcom,adreno", "amd,imageon"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi index 3e236adb9397..27f87835bc55 100644 --- a/arch/arm64/boot/dts/qcom/sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi @@ -17,6 +17,7 @@ #include <dt-bindings/clock/qcom,videocc-sm8150.h> #include <dt-bindings/interconnect/qcom,osm-l3.h> #include <dt-bindings/interconnect/qcom,sm8150.h> +#include <dt-bindings/clock/qcom,sm8150-camcc.h> #include <dt-bindings/thermal/thermal.h> / { @@ -3759,6 +3760,18 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + camcc: clock-controller@ad00000 { + compatible = "qcom,sm8150-camcc"; + reg = <0 0x0ad00000 0 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_CAMERA_AHB_CLK>; + power-domains = <&rpmhpd SM8150_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,sm8150-mdss"; reg = <0 0x0ae00000 0 0x1000>; diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi index 9d6c97d1fd9d..630f4eff20bf 100644 --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -8,8 +8,6 @@ #include <dt-bindings/clock/qcom,gcc-sm8250.h> #include <dt-bindings/clock/qcom,gpucc-sm8250.h> #include <dt-bindings/clock/qcom,rpmh.h> -#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h> -#include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h> #include <dt-bindings/dma/qcom-gpi.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interconnect/qcom,osm-l3.h> @@ -2633,14 +2631,13 @@ wsamacro: codec@3240000 { compatible = "qcom,sm8250-lpass-wsa-macro"; reg = <0 0x03240000 0 0x1000>; - clocks = <&audiocc LPASS_CDC_WSA_MCLK>, - <&audiocc LPASS_CDC_WSA_NPL>, + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&aoncc LPASS_CDC_VA_MCLK>, <&vamacro>; - clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen"; + clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; #clock-cells = <0>; clock-output-names = "mclk"; @@ -2674,20 +2671,10 @@ status = "disabled"; }; - audiocc: clock-controller@3300000 { - compatible = "qcom,sm8250-lpass-audiocc"; - reg = <0 0x03300000 0 0x30000>; - #clock-cells = <1>; - clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; - clock-names = "core", "audio", "bus"; - }; - vamacro: codec@3370000 { compatible = "qcom,sm8250-lpass-va-macro"; reg = <0 0x03370000 0 0x1000>; - clocks = <&aoncc LPASS_CDC_VA_MCLK>, + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; @@ -2792,16 +2779,6 @@ #size-cells = <0>; }; - aoncc: clock-controller@3380000 { - compatible = "qcom,sm8250-lpass-aoncc"; - reg = <0 0x03380000 0 0x40000>; - #clock-cells = <1>; - clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, - <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>; - clock-names = "core", "audio", "bus"; - }; - lpass_tlmm: pinctrl@33c0000 { compatible = "qcom,sm8250-lpass-lpi-pinctrl"; reg = <0 0x033c0000 0x0 0x20000>, diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi index 38ee0850c335..37a2aba0d4ca 100644 --- a/arch/arm64/boot/dts/qcom/sm8350.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi @@ -2251,6 +2251,12 @@ resets = <&gcc GCC_QUSB2PHY_SEC_BCR>; }; + refgen: regulator@88e7000 { + compatible = "qcom,sm8350-refgen-regulator", + "qcom,sm8250-refgen-regulator"; + reg = <0x0 0x088e7000 0x0 0x84>; + }; + usb_1_qmpphy: phy@88e8000 { compatible = "qcom,sm8350-qmp-usb3-dp-phy"; reg = <0 0x088e8000 0 0x3000>; @@ -2490,8 +2496,12 @@ reg-names = "mdss"; interconnects = <&mmss_noc MASTER_MDP0 0 &mc_virt SLAVE_EBI1 0>, - <&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>; - interconnect-names = "mdp0-mem", "mdp1-mem"; + <&mmss_noc MASTER_MDP1 0 &mc_virt SLAVE_EBI1 0>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", + "mdp1-mem", + "cpu-cfg"; power-domains = <&dispcc MDSS_GDSC>; resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; @@ -2706,6 +2716,7 @@ operating-points-v2 = <&dsi0_opp_table>; power-domains = <&rpmhpd RPMHPD_MMCX>; + refgen-supply = <&refgen>; phys = <&mdss_dsi0_phy>; @@ -2804,6 +2815,7 @@ operating-points-v2 = <&dsi1_opp_table>; power-domains = <&rpmhpd RPMHPD_MMCX>; + refgen-supply = <&refgen>; phys = <&mdss_dsi1_phy>; diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi index 9bafb3b350ff..38cb524cc568 100644 --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi @@ -1973,7 +1973,7 @@ clocks = <&gcc GCC_PCIE_1_PIPE_CLK>, <&gcc GCC_PCIE_1_PIPE_CLK_SRC>, - <&pcie1_phy>, + <&pcie1_phy QMP_PCIE_PIPE_CLK>, <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_PCIE_1_AUX_CLK>, <&gcc GCC_PCIE_1_CFG_AHB_CLK>, diff --git a/arch/arm64/boot/dts/qcom/sm8550-hdk.dts b/arch/arm64/boot/dts/qcom/sm8550-hdk.dts index 2e12219006c9..01c921602605 100644 --- a/arch/arm64/boot/dts/qcom/sm8550-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8550-hdk.dts @@ -279,6 +279,65 @@ }; }; }; + + wcn7850-pmu { + compatible = "qcom,wcn7850-pmu"; + + pinctrl-names = "default"; + pinctrl-0 = <&wlan_en>, <&bt_default>, <&pmk8550_sleep_clk>; + + wlan-enable-gpios = <&tlmm 80 GPIO_ACTIVE_HIGH>; + bt-enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; + + vdd-supply = <&vreg_s5g_0p85>; + vddio-supply = <&vreg_l15b_1p8>; + vddaon-supply = <&vreg_s2g_0p85>; + vdddig-supply = <&vreg_s4e_0p95>; + vddrfa1p2-supply = <&vreg_s4g_1p25>; + vddrfa1p8-supply = <&vreg_s6g_1p86>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 { + regulator-name = "vreg_pmu_rfa_cmn"; + }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + }; + + vreg_pmu_wlcx_0p8: ldo2 { + regulator-name = "vreg_pmu_wlcx_0p8"; + }; + + vreg_pmu_wlmx_0p85: ldo3 { + regulator-name = "vreg_pmu_wlmx_0p85"; + }; + + vreg_pmu_btcmx_0p85: ldo4 { + regulator-name = "vreg_pmu_btcmx_0p85"; + }; + + vreg_pmu_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -953,6 +1012,23 @@ status = "okay"; }; +&pcieport0 { + wifi@0 { + compatible = "pci17cb,1107"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; + }; +}; + &pcie0_phy { vdda-phy-supply = <&vreg_l1e_0p88>; vdda-pll-supply = <&vreg_l3e_1p2>; @@ -1041,6 +1117,17 @@ status = "okay"; }; +&pmk8550_gpios { + pmk8550_sleep_clk: sleep-clk-state { + pins = "gpio3"; + function = "func1"; + input-disable; + output-enable; + bias-disable; + power-source = <0>; + }; +}; + &qupv3_id_0 { status = "okay"; }; @@ -1203,6 +1290,13 @@ bias-disable; output-low; }; + + wlan_en: wlan-en-state { + pins = "gpio80"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + }; }; &uart7 { @@ -1215,20 +1309,15 @@ bluetooth { compatible = "qcom,wcn7850-bt"; - vddio-supply = <&vreg_l15b_1p8>; - vddaon-supply = <&vreg_s4e_0p95>; - vdddig-supply = <&vreg_s4e_0p95>; - vddrfa0p8-supply = <&vreg_s4e_0p95>; - vddrfa1p2-supply = <&vreg_s4g_1p25>; - vddrfa1p9-supply = <&vreg_s6g_1p86>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; max-speed = <3200000>; - - enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; - swctrl-gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&bt_default>; - pinctrl-names = "default"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts index 774bdfcffec3..6052dd922ec5 100644 --- a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts @@ -219,13 +219,10 @@ compatible = "qcom,wcn7850-pmu"; pinctrl-names = "default"; - pinctrl-0 = <&wlan_en>, <&pmk8550_sleep_clk>; + pinctrl-0 = <&wlan_en>, <&bt_default>, <&pmk8550_sleep_clk>; wlan-enable-gpios = <&tlmm 80 GPIO_ACTIVE_HIGH>; - /* - * TODO Add bt-enable-gpios once the Bluetooth driver is - * converted to using the power sequencer. - */ + bt-enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; vdd-supply = <&vreg_s5g_0p85>; vddio-supply = <&vreg_l15b_1p8>; @@ -1175,20 +1172,15 @@ bluetooth { compatible = "qcom,wcn7850-bt"; - vddio-supply = <&vreg_l15b_1p8>; - vddaon-supply = <&vreg_s4e_0p95>; - vdddig-supply = <&vreg_s4e_0p95>; - vddrfa0p8-supply = <&vreg_s4e_0p95>; - vddrfa1p2-supply = <&vreg_s4g_1p25>; - vddrfa1p9-supply = <&vreg_s6g_1p86>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; max-speed = <3200000>; - - enable-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>; - swctrl-gpios = <&tlmm 82 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&bt_default>; - pinctrl-names = "default"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi index 4c9820adcf52..9dc0ee3eb98f 100644 --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi @@ -2747,6 +2747,98 @@ #power-domain-cells = <1>; }; + cci0: cci@ac15000 { + compatible = "qcom,sm8550-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; + interrupts = <GIC_SPI 426 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,sm8550-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; + interrupts = <GIC_SPI 427 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci1_0_default>; + pinctrl-1 = <&cci1_0_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@ac17000 { + compatible = "qcom,sm8550-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac17000 0 0x1000>; + interrupts = <GIC_SPI 428 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,sm8550-camcc"; reg = <0 0x0ade0000 0 0x20000>; @@ -3393,6 +3485,166 @@ gpio-ranges = <&tlmm 0 0 211>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio110"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio111"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio110"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio111"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio113"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio113"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio114"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio115"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio114"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio115"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio74"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio75"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio74"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio75"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio0"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio1"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio0"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio1"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio16", "gpio17"; diff --git a/arch/arm64/boot/dts/qcom/sm8650-hdk.dts b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts index 591e6ab9bf5b..127c7aacd4fc 100644 --- a/arch/arm64/boot/dts/qcom/sm8650-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8650-hdk.dts @@ -271,13 +271,10 @@ compatible = "qcom,wcn7850-pmu"; pinctrl-names = "default"; - pinctrl-0 = <&wlan_en>; + pinctrl-0 = <&wlan_en>, <&bt_default>; wlan-enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>; - /* - * TODO Add bt-enable-gpios once the Bluetooth driver is - * converted to using the power sequencer. - */ + bt-enable-gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; vdd-supply = <&vreg_s4i_0p85>; vddio-supply = <&vreg_l15b_1p8>; @@ -1272,20 +1269,15 @@ bluetooth { compatible = "qcom,wcn7850-bt"; - vddio-supply = <&vreg_l3c_1p2>; - vddaon-supply = <&vreg_l15b_1p8>; - vdddig-supply = <&vreg_s3c_0p9>; - vddrfa0p8-supply = <&vreg_s3c_0p9>; - vddrfa1p2-supply = <&vreg_s1c_1p2>; - vddrfa1p9-supply = <&vreg_s6c_1p8>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; max-speed = <3200000>; - - enable-gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; - swctrl-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&bt_default>; - pinctrl-names = "default"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts index b0d7927b708f..8ca0d28eba9b 100644 --- a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts @@ -208,13 +208,10 @@ compatible = "qcom,wcn7850-pmu"; pinctrl-names = "default"; - pinctrl-0 = <&wlan_en>; + pinctrl-0 = <&wlan_en>, <&bt_default>; wlan-enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>; - /* - * TODO Add bt-enable-gpios once the Bluetooth driver is - * converted to using the power sequencer. - */ + bt-enable-gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; vdd-supply = <&vreg_s4i_0p85>; vddio-supply = <&vreg_l15b_1p8>; @@ -1255,22 +1252,15 @@ bluetooth { compatible = "qcom,wcn7850-bt"; - clocks = <&rpmhcc RPMH_RF_CLK1>; - - vddio-supply = <&vreg_l3c_1p2>; - vddaon-supply = <&vreg_l15b_1p8>; - vdddig-supply = <&vreg_s3c_0p9>; - vddrfa0p8-supply = <&vreg_s3c_0p9>; - vddrfa1p2-supply = <&vreg_s1c_1p2>; - vddrfa1p9-supply = <&vreg_s6c_1p8>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; max-speed = <3200000>; - - enable-gpios = <&tlmm 17 GPIO_ACTIVE_HIGH>; - swctrl-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&bt_default>; - pinctrl-names = "default"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi index 9d9bbb9aca64..01ac3769ffa6 100644 --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi @@ -3329,6 +3329,105 @@ #power-domain-cells = <1>; }; + cci0: cci@ac15000 { + compatible = "qcom,sm8650-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; + interrupts = <GIC_SPI 426 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,sm8650-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; + interrupts = <GIC_SPI 427 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@ac17000 { + compatible = "qcom,sm8650-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac17000 0 0x1000>; + interrupts = <GIC_SPI 428 IRQ_TYPE_EDGE_RISING>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,sm8650-camcc"; reg = <0 0x0ade0000 0 0x20000>; @@ -4029,6 +4128,198 @@ wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio12"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio13"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio12"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio13"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio64", "gpio65"; diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts new file mode 100644 index 000000000000..fdde988ae01e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts @@ -0,0 +1,809 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2024, Linaro Limited + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/gpio-keys.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/regulator/qcom,rpmh-regulator.h> + +#include "x1e80100.dtsi" +#include "x1e80100-pmics.dtsi" + +/ { + model = "Lenovo ThinkPad T14s Gen 6"; + compatible = "lenovo,thinkpad-t14s", "qcom,x1e78100", "qcom,x1e80100"; + chassis-type = "laptop"; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&hall_int_n_default>; + pinctrl-names = "default"; + + switch-lid { + gpios = <&tlmm 92 GPIO_ACTIVE_LOW>; + linux,input-type = <EV_SW>; + linux,code = <SW_LID>; + wakeup-source; + wakeup-event-action = <EV_ACT_DEASSERTED>; + }; + }; + + pmic-glink { + compatible = "qcom,x1e80100-pmic-glink", + "qcom,sm8550-pmic-glink", + "qcom,pmic-glink"; + orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>, + <&tlmm 123 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + /* Display-adjacent port */ + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss0_hs_in: endpoint { + remote-endpoint = <&usb_1_ss0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss0_ss_in: endpoint { + remote-endpoint = <&usb_1_ss0_qmpphy_out>; + }; + }; + }; + }; + + /* User-adjacent port */ + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss1_hs_in: endpoint { + remote-endpoint = <&usb_1_ss1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss1_ss_in: endpoint { + remote-endpoint = <&usb_1_ss1_qmpphy_out>; + }; + }; + }; + }; + }; + + reserved-memory { + linux,cma { + compatible = "shared-dma-pool"; + size = <0x0 0x8000000>; + reusable; + linux,cma-default; + }; + }; + + vreg_edp_3p3: regulator-edp-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_EDP_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&edp_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_nvme: regulator-nvme { + compatible = "regulator-fixed"; + + regulator-name = "VREG_NVME_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 18 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&nvme_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vph_pwr: regulator-vph-pwr { + compatible = "regulator-fixed"; + + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + + regulator-always-on; + regulator-boot-on; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pm8550-rpmh-regulators"; + qcom,pmic-id = "b"; + + vdd-bob1-supply = <&vph_pwr>; + vdd-bob2-supply = <&vph_pwr>; + vdd-l1-l4-l10-supply = <&vreg_s4c_1p8>; + vdd-l2-l13-l14-supply = <&vreg_bob1>; + vdd-l5-l16-supply = <&vreg_bob1>; + vdd-l6-l7-supply = <&vreg_bob2>; + vdd-l8-l9-supply = <&vreg_bob1>; + vdd-l12-supply = <&vreg_s5j_1p2>; + vdd-l15-supply = <&vreg_s4c_1p8>; + vdd-l17-supply = <&vreg_bob2>; + + vreg_bob1: bob1 { + regulator-name = "vreg_bob1"; + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_bob2: bob2 { + regulator-name = "vreg_bob2"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2b_3p0: ldo2 { + regulator-name = "vreg_l2b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l4b_1p8: ldo4 { + regulator-name = "vreg_l4b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l6b_1p8: ldo6 { + regulator-name = "vreg_l6b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l8b_3p0: ldo8 { + regulator-name = "vreg_l8b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l9b_2p9: ldo9 { + regulator-name = "vreg_l9b_2p9"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l10b_1p8: ldo10 { + regulator-name = "vreg_l10b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l12b_1p2: ldo12 { + regulator-name = "vreg_l12b_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l13b_3p0: ldo13 { + regulator-name = "vreg_l13b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l14b_3p0: ldo14 { + regulator-name = "vreg_l14b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l15b_1p8: ldo15 { + regulator-name = "vreg_l15b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l17b_2p5: ldo17 { + regulator-name = "vreg_l17b_2p5"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2504000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-1 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-l1-supply = <&vreg_s5j_1p2>; + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s4-supply = <&vph_pwr>; + + vreg_s4c_1p8: smps4 { + regulator-name = "vreg_s4c_1p8"; + regulator-min-microvolt = <1856000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1c_1p2: ldo1 { + regulator-name = "vreg_l1c_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2c_0p8: ldo2 { + regulator-name = "vreg_l2c_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3c_0p8: ldo3 { + regulator-name = "vreg_l3c_0p8"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-2 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "d"; + + vdd-l1-supply = <&vreg_s1f_0p7>; + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s4c_1p8>; + vdd-s1-supply = <&vph_pwr>; + + vreg_l1d_0p8: ldo1 { + regulator-name = "vreg_l1d_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2d_0p9: ldo2 { + regulator-name = "vreg_l2d_0p9"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3d_1p8: ldo3 { + regulator-name = "vreg_l3d_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-3 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "e"; + + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s5j_1p2>; + + vreg_l2e_0p8: ldo2 { + regulator-name = "vreg_l2e_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3e_1p2: ldo3 { + regulator-name = "vreg_l3e_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-4 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "f"; + + vdd-l1-supply = <&vreg_s5j_1p2>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s5j_1p2>; + vdd-s1-supply = <&vph_pwr>; + + vreg_s1f_0p7: smps1 { + regulator-name = "vreg_s1f_0p7"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-6 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "i"; + + vdd-l1-supply = <&vreg_s4c_1p8>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + + vreg_l1i_1p8: ldo1 { + regulator-name = "vreg_l1i_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2i_1p2: ldo2 { + regulator-name = "vreg_l2i_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3i_0p8: ldo3 { + regulator-name = "vreg_l3i_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-7 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "j"; + + vdd-l1-supply = <&vreg_s1f_0p7>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s5-supply = <&vph_pwr>; + + vreg_s5j_1p2: smps5 { + regulator-name = "vreg_s5j_1p2"; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1j_0p8: ldo1 { + regulator-name = "vreg_l1j_0p8"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2j_1p2: ldo2 { + regulator-name = "vreg_l2j_1p2"; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1256000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3j_0p8: ldo3 { + regulator-name = "vreg_l3j_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; +}; + +&gpu { + status = "okay"; + + zap-shader { + firmware-name = "qcom/x1e80100/LENOVO/21N1/qcdxkmsuc8380.mbn"; + }; +}; + +&i2c0 { + clock-frequency = <400000>; + + status = "okay"; + + /* ELAN06E2 or ELAN06E3 */ + touchpad@15 { + compatible = "hid-over-i2c"; + reg = <0x15>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&tpad_default>; + pinctrl-names = "default"; + + wakeup-source; + }; + + /* TODO: second-sourced SYNA8022 or SYNA8024 touchpad @ 0x2c */ + + /* ELAN06F1 or SYNA06F2 */ + keyboard@3a { + compatible = "hid-over-i2c"; + reg = <0x3a>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&kybd_default>; + pinctrl-names = "default"; + + wakeup-source; + }; +}; + +&i2c8 { + clock-frequency = <400000>; + + status = "okay"; + + /* ILIT2911 or GTCH1563 */ + touchscreen@10 { + compatible = "hid-over-i2c"; + reg = <0x10>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&ts0_default>; + pinctrl-names = "default"; + }; + + /* TODO: second-sourced touchscreen @ 0x41 */ +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp3 { + compatible = "qcom,x1e80100-dp"; + /delete-property/ #sound-dai-cells; + + status = "okay"; + + aux-bus { + panel { + compatible = "edp-panel"; + enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>; + power-supply = <&vreg_edp_3p3>; + + pinctrl-0 = <&edp_bl_en>; + pinctrl-names = "default"; + + port { + edp_panel_in: endpoint { + remote-endpoint = <&mdss_dp3_out>; + }; + }; + }; + }; + + ports { + port@1 { + reg = <1>; + + mdss_dp3_out: endpoint { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&edp_panel_in>; + }; + }; + }; +}; + +&mdss_dp3_phy { + vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-pll-supply = <&vreg_l2j_1p2>; + + status = "okay"; +}; + +&pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie4_phy { + vdda-phy-supply = <&vreg_l3i_0p8>; + vdda-pll-supply = <&vreg_l3e_1p2>; + + status = "okay"; +}; + +&pcie6a { + perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; + + vddpe-3v3-supply = <&vreg_nvme>; + + pinctrl-0 = <&pcie6a_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie6a_phy { + vdda-phy-supply = <&vreg_l1d_0p8>; + vdda-pll-supply = <&vreg_l2j_1p2>; + + status = "okay"; +}; + +&pmc8380_3_gpios { + edp_bl_en: edp-bl-en-state { + pins = "gpio4"; + function = "normal"; + power-source = <1>; + input-disable; + output-enable; + }; +}; + +&qupv3_0 { + status = "okay"; +}; + +&qupv3_1 { + status = "okay"; +}; + +&qupv3_2 { + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/x1e80100/LENOVO/21N1/qcadsp8380.mbn", + "qcom/x1e80100/LENOVO/21N1/adsp_dtbs.elf"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/x1e80100/LENOVO/21N1/qccdsp8380.mbn", + "qcom/x1e80100/LENOVO/21N1/cdsp_dtbs.elf"; + + status = "okay"; +}; + +&smb2360_0_eusb2_repeater { + vdd18-supply = <&vreg_l3d_1p8>; + vdd3-supply = <&vreg_l2b_3p0>; +}; + +&smb2360_1_eusb2_repeater { + vdd18-supply = <&vreg_l3d_1p8>; + vdd3-supply = <&vreg_l14b_3p0>; +}; + +&tlmm { + gpio-reserved-ranges = <34 2>, /* Unused */ + <44 4>, /* SPI (TPM) */ + <72 2>, /* Secure EC I2C connection (?) */ + <238 1>; /* UFS Reset */ + + tpad_default: tpad-default-state { + pins = "gpio3"; + function = "gpio"; + bias-pull-up; + }; + + nvme_reg_en: nvme-reg-en-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + ts0_default: ts0-default-state { + reset-n-pins { + pins = "gpio48"; + function = "gpio"; + output-high; + drive-strength = <16>; + }; + + int-n-pins { + pins = "gpio51"; + function = "gpio"; + bias-disable; + }; + }; + + kybd_default: kybd-default-state { + pins = "gpio67"; + function = "gpio"; + bias-disable; + }; + + edp_reg_en: edp-reg-en-state { + pins = "gpio70"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + hall_int_n_default: hall-int-n-state { + pins = "gpio92"; + function = "gpio"; + bias-disable; + }; + + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { + clkreq-n-pins { + pins = "gpio153"; + function = "pcie6a_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio152"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + wcd_default: wcd-reset-n-active-state { + pins = "gpio191"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; +}; + +&usb_1_ss0_hsphy { + vdd-supply = <&vreg_l3j_0p8>; + vdda12-supply = <&vreg_l2j_1p2>; + + phys = <&smb2360_0_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss0_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l1j_0p8>; + + status = "okay"; +}; + +&usb_1_ss0 { + status = "okay"; +}; + +&usb_1_ss0_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss0_dwc3_hs { + remote-endpoint = <&pmic_glink_ss0_hs_in>; +}; + +&usb_1_ss0_qmpphy_out { + remote-endpoint = <&pmic_glink_ss0_ss_in>; +}; + +&usb_1_ss1_hsphy { + vdd-supply = <&vreg_l3j_0p8>; + vdda12-supply = <&vreg_l2j_1p2>; + + phys = <&smb2360_1_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss1_qmpphy { + vdda-phy-supply = <&vreg_l3e_1p2>; + vdda-pll-supply = <&vreg_l2d_0p9>; + + status = "okay"; +}; + +&usb_1_ss1 { + status = "okay"; +}; + +&usb_1_ss1_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss1_dwc3_hs { + remote-endpoint = <&pmic_glink_ss1_hs_in>; +}; + +&usb_1_ss1_qmpphy_out { + remote-endpoint = <&pmic_glink_ss1_ss_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts index 7fb980fcb307..fb4a48a1e2a8 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-asus-vivobook-s15.dts @@ -134,6 +134,8 @@ pinctrl-0 = <&nvme_reg_en>; pinctrl-names = "default"; + + regulator-boot-on; }; }; @@ -278,6 +280,13 @@ vdd-l3-supply = <&vreg_s1f_0p7>; vdd-s1-supply = <&vph_pwr>; vdd-s2-supply = <&vph_pwr>; + + vreg_l3i_0p8: ldo3 { + regulator-name = "vreg_l3i_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; }; regulators-7 { @@ -423,11 +432,17 @@ }; &pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + status = "okay"; }; &pcie4_phy { - vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; status = "okay"; @@ -488,10 +503,6 @@ vdd3-supply = <&vreg_l14b_3p0>; }; -&smb2360_2 { - status = "disabled"; -}; - &tlmm { gpio-reserved-ranges = <34 2>, /* Unused */ <44 4>, /* SPI (TPM) */ @@ -517,7 +528,30 @@ bias-disable; }; - pcie6a_default: pcie2a-default-state { + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { clkreq-n-pins { pins = "gpio153"; function = "pcie6a_clk"; @@ -529,7 +563,7 @@ pins = "gpio152"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { diff --git a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts index 6152bcd0bc1f..c6e0356ed9a2 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-crd.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-crd.dts @@ -6,6 +6,8 @@ /dts-v1/; #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/gpio-keys.h> +#include <dt-bindings/input/input.h> #include <dt-bindings/regulator/qcom,rpmh-regulator.h> #include "x1e80100.dtsi" @@ -49,6 +51,21 @@ stdout-path = "serial0:115200n8"; }; + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&hall_int_n_default>; + pinctrl-names = "default"; + + switch-lid { + gpios = <&tlmm 92 GPIO_ACTIVE_LOW>; + linux,input-type = <EV_SW>; + linux,code = <SW_LID>; + wakeup-source; + wakeup-event-action = <EV_ACT_DEASSERTED>; + }; + }; + pmic-glink { compatible = "qcom,x1e80100-pmic-glink", "qcom,sm8550-pmic-glink", @@ -160,9 +177,9 @@ compatible = "qcom,x1e80100-sndcard"; model = "X1E80100-CRD"; audio-routing = "WooferLeft IN", "WSA WSA_SPK1 OUT", - "TwitterLeft IN", "WSA WSA_SPK2 OUT", + "TweeterLeft IN", "WSA WSA_SPK2 OUT", "WooferRight IN", "WSA2 WSA_SPK2 OUT", - "TwitterRight IN", "WSA2 WSA_SPK2 OUT", + "TweeterRight IN", "WSA2 WSA_SPK2 OUT", "IN1_HPHL", "HPHL_OUT", "IN2_HPHR", "HPHR_OUT", "AMIC2", "MIC BIAS2", @@ -268,7 +285,6 @@ pinctrl-0 = <&edp_reg_en>; pinctrl-names = "default"; - regulator-always-on; regulator-boot-on; }; @@ -284,6 +300,24 @@ pinctrl-names = "default"; pinctrl-0 = <&nvme_reg_en>; + + regulator-boot-on; + }; + + vreg_wwan: regulator-wwan { + compatible = "regulator-fixed"; + + regulator-name = "SDX_VPH_PWR"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 221 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wwan_sw_en>; + pinctrl-names = "default"; + + regulator-boot-on; }; }; @@ -637,6 +671,14 @@ }; }; +&gpu { + status = "okay"; + + zap-shader { + firmware-name = "qcom/x1e80100/gen70500_zap.mbn"; + }; +}; + &i2c0 { clock-frequency = <400000>; @@ -724,9 +766,13 @@ aux-bus { panel { - compatible = "edp-panel"; + compatible = "samsung,atna45af01", "samsung,atna33xc20"; + enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>; power-supply = <&vreg_edp_3p3>; + pinctrl-0 = <&edp_bl_en>; + pinctrl-names = "default"; + port { edp_panel_in: endpoint { remote-endpoint = <&mdss_dp3_out>; @@ -756,11 +802,36 @@ }; &pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + status = "okay"; }; &pcie4_phy { - vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-phy-supply = <&vreg_l3i_0p8>; + vdda-pll-supply = <&vreg_l3e_1p2>; + + status = "okay"; +}; + +&pcie5 { + perst-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + + vddpe-3v3-supply = <&vreg_wwan>; + + pinctrl-0 = <&pcie5_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie5_phy { + vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; status = "okay"; @@ -785,6 +856,16 @@ status = "okay"; }; +&pmc8380_3_gpios { + edp_bl_en: edp-bl-en-state { + pins = "gpio4"; + function = "normal"; + power-source = <1>; /* 1.8V */ + input-disable; + output-enable; + }; +}; + &qupv3_0 { status = "okay"; }; @@ -821,6 +902,10 @@ vdd3-supply = <&vreg_l14b_3p0>; }; +&smb2360_2 { + status = "okay"; +}; + &smb2360_2_eusb2_repeater { vdd18-supply = <&vreg_l3d_1p8>; vdd3-supply = <&vreg_l8b_3p0>; @@ -841,6 +926,7 @@ sound-name-prefix = "WooferLeft"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; }; /* WSA8845, Left Tweeter */ @@ -849,9 +935,10 @@ reg = <0 1>; reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>; #sound-dai-cells = <0>; - sound-name-prefix = "TwitterLeft"; + sound-name-prefix = "TweeterLeft"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; }; }; @@ -892,6 +979,7 @@ sound-name-prefix = "WooferRight"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; }; /* WSA8845, Right Tweeter */ @@ -900,9 +988,10 @@ reg = <0 1>; reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>; #sound-dai-cells = <0>; - sound-name-prefix = "TwitterRight"; + sound-name-prefix = "TweeterRight"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; }; }; @@ -918,6 +1007,12 @@ bias-disable; }; + hall_int_n_default: hall-int-n-state { + pins = "gpio92"; + function = "gpio"; + bias-disable; + }; + kybd_default: kybd-default-state { pins = "gpio67"; function = "gpio"; @@ -931,7 +1026,53 @@ bias-disable; }; - pcie6a_default: pcie2a-default-state { + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie5_default: pcie5-default-state { + clkreq-n-pins { + pins = "gpio150"; + function = "pcie5_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio149"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { clkreq-n-pins { pins = "gpio153"; function = "pcie6a_clk"; @@ -943,15 +1084,15 @@ pins = "gpio152"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { - pins = "gpio154"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; tpad_default: tpad-default-state { @@ -982,6 +1123,13 @@ bias-disable; output-low; }; + + wwan_sw_en: wwan-sw-en-state { + pins = "gpio221"; + function = "gpio"; + drive-strength = <4>; + bias-disable; + }; }; &uart21 { diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index fbff558f5b07..0cdaff9c8cf0 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -190,7 +190,6 @@ pinctrl-0 = <&edp_reg_en>; pinctrl-names = "default"; - regulator-always-on; regulator-boot-on; }; @@ -206,6 +205,8 @@ pinctrl-0 = <&nvme_reg_en>; pinctrl-names = "default"; + + regulator-boot-on; }; }; @@ -592,9 +593,13 @@ aux-bus { panel { - compatible = "edp-panel"; + compatible = "samsung,atna45dc02", "samsung,atna33xc20"; + enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>; power-supply = <&vreg_edp_3p3>; + pinctrl-0 = <&edp_bl_en>; + pinctrl-names = "default"; + port { edp_panel_in: endpoint { remote-endpoint = <&mdss_dp3_out>; @@ -625,16 +630,31 @@ }; &pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + status = "okay"; }; &pcie4_phy { - vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; status = "okay"; }; +&pcie4_port0 { + wifi@0 { + compatible = "pci17cb,1107"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + qcom,ath12k-calibration-variant = "LES790"; + }; +}; + &pcie6a { perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; @@ -654,6 +674,16 @@ status = "okay"; }; +&pmc8380_3_gpios { + edp_bl_en: edp-bl-en-state { + pins = "gpio4"; + function = "normal"; + power-source = <0>; + input-disable; + output-enable; + }; +}; + &qupv3_0 { status = "okay"; }; @@ -689,6 +719,10 @@ vdd3-supply = <&vreg_l14b_3p0>; }; +&smb2360_2 { + status = "okay"; +}; + &smb2360_2_eusb2_repeater { vdd18-supply = <&vreg_l3d_1p8>; vdd3-supply = <&vreg_l8b_3p0>; @@ -782,7 +816,30 @@ bias-disable; }; - pcie6a_default: pcie2a-default-state { + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { clkreq-n-pins { pins = "gpio153"; function = "pcie6a_clk"; @@ -794,15 +851,15 @@ pins = "gpio152"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { - pins = "gpio154"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; tpad_default: tpad-default-state { diff --git a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi new file mode 100644 index 000000000000..cdb401767c42 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus.dtsi @@ -0,0 +1,837 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/regulator/qcom,rpmh-regulator.h> + +#include "x1e80100.dtsi" +#include "x1e80100-pmics.dtsi" + +/ { + aliases { + serial0 = &uart2; + i2c0 = &i2c0; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c7 = &i2c7; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pmk8550_pwm 0 5000000>; + enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>; + /* TODO: power-supply? */ + + pinctrl-0 = <&edp_bl_en>, <&edp_bl_pwm>; + pinctrl-names = "default"; + }; + + leds { + compatible = "gpio-leds"; + + pinctrl-names = "default"; + pinctrl-0 = <&cam_indicator_en>; + + led-camera-indicator { + label = "white:camera-indicator"; + function = LED_FUNCTION_INDICATOR; + color = <LED_COLOR_ID_WHITE>; + gpios = <&tlmm 225 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + default-state = "off"; + /* Reuse as a panic indicator until we get a "camera on" trigger */ + panic-indicator; + }; + }; + + pmic-glink { + compatible = "qcom,x1e80100-pmic-glink", + "qcom,sm8550-pmic-glink", + "qcom,pmic-glink"; + #address-cells = <1>; + #size-cells = <0>; + orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>, + <&tlmm 123 GPIO_ACTIVE_HIGH>; + + /* Left-side rear port */ + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss0_hs_in: endpoint { + remote-endpoint = <&usb_1_ss0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss0_ss_in: endpoint { + remote-endpoint = <&usb_1_ss0_qmpphy_out>; + }; + }; + }; + }; + + /* Left-side front port */ + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss1_hs_in: endpoint { + remote-endpoint = <&usb_1_ss1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss1_ss_in: endpoint { + remote-endpoint = <&usb_1_ss1_qmpphy_out>; + }; + }; + }; + }; + }; + + reserved-memory { + linux,cma { + compatible = "shared-dma-pool"; + size = <0x0 0x8000000>; + reusable; + linux,cma-default; + }; + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + + regulator-always-on; + regulator-boot-on; + }; + + vreg_edp_3p3: regulator-edp-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_EDP_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&edp_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_nvme: regulator-nvme { + compatible = "regulator-fixed"; + + regulator-name = "VREG_NVME_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 18 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&nvme_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pm8550-rpmh-regulators"; + qcom,pmic-id = "b"; + + vdd-bob1-supply = <&vph_pwr>; + vdd-bob2-supply = <&vph_pwr>; + vdd-l1-l4-l10-supply = <&vreg_s4c>; + vdd-l2-l13-l14-supply = <&vreg_bob1>; + vdd-l5-l16-supply = <&vreg_bob1>; + vdd-l6-l7-supply = <&vreg_bob2>; + vdd-l8-l9-supply = <&vreg_bob1>; + vdd-l12-supply = <&vreg_s5j>; + vdd-l15-supply = <&vreg_s4c>; + vdd-l17-supply = <&vreg_bob2>; + + vreg_bob1: bob1 { + regulator-name = "vreg_bob1"; + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_bob2: bob2 { + regulator-name = "vreg_bob2"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1b: ldo1 { + regulator-name = "vreg_l1b"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2b: ldo2 { + regulator-name = "vreg_l2b"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l4b: ldo4 { + regulator-name = "vreg_l4b"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l5b: ldo5 { + regulator-name = "vreg_l5b"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l6b: ldo6 { + regulator-name = "vreg_l6b"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l7b: ldo7 { + regulator-name = "vreg_l7b"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l8b: ldo8 { + regulator-name = "vreg_l8b"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l9b: ldo9 { + regulator-name = "vreg_l9b"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l10b: ldo10 { + regulator-name = "vreg_l10b"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l12b: ldo12 { + regulator-name = "vreg_l12b"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l13b: ldo13 { + regulator-name = "vreg_l13b"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l14b: ldo14 { + regulator-name = "vreg_l14b"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l15b: ldo15 { + regulator-name = "vreg_l15b"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l16b: ldo16 { + regulator-name = "vreg_l16b"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l17b: ldo17 { + regulator-name = "vreg_l17b"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2504000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-1 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-l1-supply = <&vreg_s5j>; + vdd-l2-supply = <&vreg_s1f>; + vdd-l3-supply = <&vreg_s1f>; + vdd-s4-supply = <&vph_pwr>; + + vreg_s4c: smps4 { + regulator-name = "vreg_s4c"; + regulator-min-microvolt = <1856000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1c: ldo1 { + regulator-name = "vreg_l1c"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2c: ldo2 { + regulator-name = "vreg_l2c"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3c: ldo3 { + regulator-name = "vreg_l3c"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-2 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "d"; + + vdd-l1-supply = <&vreg_s1f>; + vdd-l2-supply = <&vreg_s1f>; + vdd-l3-supply = <&vreg_s4c>; + vdd-s1-supply = <&vph_pwr>; + + vreg_l1d: ldo1 { + regulator-name = "vreg_l1d"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2d: ldo2 { + regulator-name = "vreg_l2d"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3d: ldo3 { + regulator-name = "vreg_l3d"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-3 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "e"; + + vdd-l2-supply = <&vreg_s1f>; + vdd-l3-supply = <&vreg_s5j>; + + vreg_l2e: ldo2 { + regulator-name = "vreg_l2e"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3e: ldo3 { + regulator-name = "vreg_l3e"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-4 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "f"; + + vdd-l1-supply = <&vreg_s5j>; + vdd-l2-supply = <&vreg_s5j>; + vdd-l3-supply = <&vreg_s5j>; + vdd-s1-supply = <&vph_pwr>; + + vreg_s1f: smps1 { + regulator-name = "vreg_s1f"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1f: ldo1 { + regulator-name = "vreg_l1f"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2f: ldo2 { + regulator-name = "vreg_l2f"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3f: ldo3 { + regulator-name = "vreg_l3f"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-6 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "i"; + + vdd-l1-supply = <&vreg_s4c>; + vdd-l2-supply = <&vreg_s5j>; + vdd-l3-supply = <&vreg_s1f>; + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + + vreg_s1i: smps1 { + regulator-name = "vreg_s1i"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_s2i: smps2 { + regulator-name = "vreg_s2i"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1i: ldo1 { + regulator-name = "vreg_l1i"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2i: ldo2 { + regulator-name = "vreg_l2i"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3i: ldo3 { + regulator-name = "vreg_l3i"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-7 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "j"; + + vdd-l1-supply = <&vreg_s1f>; + vdd-l2-supply = <&vreg_s5j>; + vdd-l3-supply = <&vreg_s1f>; + vdd-s5-supply = <&vph_pwr>; + + vreg_s5j: smps5 { + regulator-name = "vreg_s5j"; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1j: ldo1 { + regulator-name = "vreg_l1j"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2j: ldo2 { + regulator-name = "vreg_l2j"; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1256000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3j: ldo3 { + regulator-name = "vreg_l3j"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; +}; + +&gpu { + status = "okay"; + + zap-shader { + memory-region = <&gpu_microcode_mem>; + firmware-name = "qcom/x1e80100/microsoft/qcdxkmsuc8380.mbn"; + }; +}; + +&i2c0 { + clock-frequency = <100000>; + + status = "okay"; + + /* Something @39, @3e, @44 */ +}; + +&i2c3 { + clock-frequency = <400000>; + + status = "okay"; + + /* PS8830 USB retimer @8 */ +}; + +&i2c4 { + clock-frequency = <400000>; + + status = "okay"; + + /* Something @18, @2c, @2e */ +}; + +&i2c5 { + clock-frequency = <400000>; + + status = "okay"; + + /* Something @4f */ +}; + +&i2c7 { + clock-frequency = <400000>; + + status = "okay"; + + /* PS8830 USB retimer @8 */ +}; + + +&mdss { + status = "okay"; +}; + +&mdss_dp3 { + compatible = "qcom,x1e80100-dp"; + /delete-property/ #sound-dai-cells; + + status = "okay"; + + aux-bus { + panel { + compatible = "edp-panel"; + + backlight = <&backlight>; + power-supply = <&vreg_edp_3p3>; + + port { + edp_panel_in: endpoint { + remote-endpoint = <&mdss_dp3_out>; + }; + }; + }; + }; + + ports { + port@1 { + reg = <1>; + + mdss_dp3_out: endpoint { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&edp_panel_in>; + }; + }; + }; +}; + +&mdss_dp3_phy { + vdda-phy-supply = <&vreg_l3j>; + vdda-pll-supply = <&vreg_l2j>; + + status = "okay"; +}; + +&pcie4 { + status = "okay"; +}; + +&pcie4_phy { + vdda-phy-supply = <&vreg_l3i>; + vdda-pll-supply = <&vreg_l3e>; + + status = "okay"; +}; + +&pcie6a { + perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; + + vddpe-3v3-supply = <&vreg_nvme>; + + pinctrl-0 = <&pcie6a_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie6a_phy { + vdda-phy-supply = <&vreg_l1d>; + vdda-pll-supply = <&vreg_l2j>; + + status = "okay"; +}; + +&pmc8380_3_gpios { + edp_bl_en: edp-bl-en-state { + pins = "gpio4"; + function = "normal"; + power-source = <1>; /* 1.8V */ + input-disable; + output-enable; + }; +}; + +&pmk8550_pwm { + status = "okay"; +}; + +&pmk8550_gpios { + edp_bl_pwm: edp-bl-pwm-state { + pins = "gpio5"; + function = "func3"; + }; +}; + +&qupv3_0 { + status = "okay"; +}; + +&qupv3_1 { + status = "okay"; +}; + +&qupv3_2 { + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/x1e80100/microsoft/Romulus/qcadsp8380.mbn", + "qcom/x1e80100/microsoft/Romulus/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/x1e80100/microsoft/Romulus/qccdsp8380.mbn", + "qcom/x1e80100/microsoft/Romulus/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&smb2360_0_eusb2_repeater { + vdd18-supply = <&vreg_l3d>; + vdd3-supply = <&vreg_l2b>; +}; + +&smb2360_1_eusb2_repeater { + vdd18-supply = <&vreg_l3d>; + vdd3-supply = <&vreg_l14b>; +}; + +&tlmm { + gpio-reserved-ranges = <44 4>, /* SPI (TPM) */ + <238 1>; /* UFS Reset */ + + nvme_reg_en: nvme-reg-en-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + edp_reg_en: edp-reg-en-state { + pins = "gpio70"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + ssam_state: ssam-state-state { + pins = "gpio91"; + function = "gpio"; + bias-disable; + }; + + pcie6a_default: pcie6a-default-state { + perst-n-pins { + pins = "gpio152"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + clkreq-n-pins { + pins = "gpio153"; + function = "pcie6a_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-n-pins { + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cam_indicator_en: cam-indicator-en-state { + pins = "gpio225"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + +&uart2 { + status = "okay"; + + embedded-controller { + compatible = "microsoft,surface-sam"; + + interrupts-extended = <&tlmm 91 IRQ_TYPE_EDGE_RISING>; + + current-speed = <4000000>; + + pinctrl-0 = <&ssam_state>; + pinctrl-names = "default"; + }; +}; + +&usb_1_ss0_hsphy { + vdd-supply = <&vreg_l3j>; + vdda12-supply = <&vreg_l2j>; + + phys = <&smb2360_0_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss0_qmpphy { + vdda-phy-supply = <&vreg_l3e>; + vdda-pll-supply = <&vreg_l1j>; + + status = "okay"; +}; + +&usb_1_ss0 { + status = "okay"; +}; + +&usb_1_ss0_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss0_dwc3_hs { + remote-endpoint = <&pmic_glink_ss0_hs_in>; +}; + +&usb_1_ss0_qmpphy_out { + remote-endpoint = <&pmic_glink_ss0_ss_in>; +}; + +&usb_1_ss1_hsphy { + vdd-supply = <&vreg_l3j>; + vdda12-supply = <&vreg_l2j>; + + phys = <&smb2360_1_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss1_qmpphy { + vdda-phy-supply = <&vreg_l3e>; + vdda-pll-supply = <&vreg_l2d>; + + status = "okay"; +}; + +&usb_1_ss1 { + status = "okay"; +}; + +&usb_1_ss1_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss1_dwc3_hs { + remote-endpoint = <&pmic_glink_ss1_hs_in>; +}; + +&usb_1_ss1_qmpphy_out { + remote-endpoint = <&pmic_glink_ss1_ss_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus13.dts b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus13.dts new file mode 100644 index 000000000000..eb7580dd9684 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus13.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "x1e80100-microsoft-romulus.dtsi" + +/ { + model = "Microsoft Surface Laptop 7 (13.8 inch)"; + compatible = "microsoft,romulus13", "qcom,x1e80100"; +}; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus15.dts b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus15.dts new file mode 100644 index 000000000000..4751ad9b510b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1e80100-microsoft-romulus15.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "x1e80100-microsoft-romulus.dtsi" + +/ { + model = "Microsoft Surface Laptop 7 (15 inch)"; + compatible = "microsoft,romulus15", "qcom,x1e80100"; +}; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi b/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi index e34e70922cd3..5b54ee79f048 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi @@ -249,6 +249,14 @@ interrupt-controller; #interrupt-cells = <2>; }; + + pmk8550_pwm: pwm { + compatible = "qcom,pmk8550-pwm"; + + #pwm-cells = <2>; + + status = "disabled"; + }; }; /* PMC8380C */ @@ -509,6 +517,8 @@ #address-cells = <1>; #size-cells = <0>; + status = "disabled"; + smb2360_2_eusb2_repeater: phy@fd00 { compatible = "qcom,smb2360-eusb2-repeater"; reg = <0xfd00>; diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts index 72a4f4138616..5ef030c60abe 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts @@ -253,6 +253,8 @@ pinctrl-names = "default"; pinctrl-0 = <&nvme_reg_en>; + + regulator-boot-on; }; }; @@ -606,6 +608,14 @@ }; }; +&gpu { + status = "okay"; + + zap-shader { + firmware-name = "qcom/x1e80100/gen70500_zap.mbn"; + }; +}; + &lpass_tlmm { spkr_01_sd_n_active: spkr-01-sd-n-active-state { pins = "gpio12"; @@ -660,11 +670,17 @@ }; &pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + status = "okay"; }; &pcie4_phy { - vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-phy-supply = <&vreg_l3i_0p8>; vdda-pll-supply = <&vreg_l3e_1p2>; status = "okay"; @@ -715,10 +731,6 @@ status = "okay"; }; -&smb2360_3 { - status = "okay"; -}; - &smb2360_0_eusb2_repeater { vdd18-supply = <&vreg_l3d_1p8>; vdd3-supply = <&vreg_l2b_3p0>; @@ -729,11 +741,19 @@ vdd3-supply = <&vreg_l14b_3p0>; }; +&smb2360_2 { + status = "okay"; +}; + &smb2360_2_eusb2_repeater { vdd18-supply = <&vreg_l3d_1p8>; vdd3-supply = <&vreg_l8b_3p0>; }; +&smb2360_3 { + status = "okay"; +}; + &swr0 { pinctrl-0 = <&wsa_swr_active>, <&spkr_01_sd_n_active>; pinctrl-names = "default"; @@ -749,6 +769,7 @@ sound-name-prefix = "SpkrLeft"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; }; /* WSA8845, Right Speaker */ @@ -760,6 +781,7 @@ sound-name-prefix = "SpkrRight"; vdd-1p8-supply = <&vreg_l15b_1p8>; vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; }; }; @@ -804,7 +826,30 @@ bias-disable; }; - pcie6a_default: pcie2a-default-state { + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { clkreq-n-pins { pins = "gpio153"; function = "pcie6a_clk"; @@ -816,15 +861,15 @@ pins = "gpio152"; function = "gpio"; drive-strength = <2>; - bias-pull-down; + bias-disable; }; wake-n-pins { - pins = "gpio154"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; wcd_default: wcd-reset-n-active-state { diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi index 7bca5fcd7d52..0510abc0edf0 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi @@ -4,6 +4,7 @@ */ #include <dt-bindings/clock/qcom,rpmh.h> +#include <dt-bindings/clock/qcom,sc8280xp-lpasscc.h> #include <dt-bindings/clock/qcom,x1e80100-dispcc.h> #include <dt-bindings/clock/qcom,x1e80100-gcc.h> #include <dt-bindings/clock/qcom,x1e80100-gpucc.h> @@ -745,7 +746,7 @@ <&sleep_clk>, <0>, <&pcie4_phy>, - <0>, + <&pcie5_phy>, <&pcie6a_phy>, <0>, <&usb_1_ss0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, @@ -1979,7 +1980,7 @@ i2c0: i2c@b80000 { compatible = "qcom,geni-i2c"; - reg = <0 0xb80000 0 0x4000>; + reg = <0 0x00b80000 0 0x4000>; interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>; @@ -2142,9 +2143,31 @@ status = "disabled"; }; + uart2: serial@b88000 { + compatible = "qcom,geni-uart"; + reg = <0 0x00b88000 0 0x4000>; + + interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart2_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + spi2: spi@b88000 { compatible = "qcom,geni-spi"; - reg = <0 0xb88000 0 0x4000>; + reg = <0 0x00b88000 0 0x4000>; interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>; @@ -2243,7 +2266,7 @@ i2c4: i2c@b90000 { compatible = "qcom,geni-i2c"; - reg = <0 0xb90000 0 0x4000>; + reg = <0 0x00b90000 0 0x4000>; interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>; @@ -2603,6 +2626,8 @@ #clock-cells = <1>; #phy-cells = <1>; + orientation-switch; + status = "disabled"; ports { @@ -2671,6 +2696,8 @@ #clock-cells = <1>; #phy-cells = <1>; + orientation-switch; + status = "disabled"; ports { @@ -2739,6 +2766,8 @@ #clock-cells = <1>; #phy-cells = <1>; + orientation-switch; + status = "disabled"; ports { @@ -2772,7 +2801,7 @@ cnoc_main: interconnect@1500000 { compatible = "qcom,x1e80100-cnoc-main"; - reg = <0 0x1500000 0 0x14400>; + reg = <0 0x01500000 0 0x14400>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2781,7 +2810,7 @@ config_noc: interconnect@1600000 { compatible = "qcom,x1e80100-cnoc-cfg"; - reg = <0 0x1600000 0 0x6600>; + reg = <0 0x01600000 0 0x6600>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2790,7 +2819,7 @@ system_noc: interconnect@1680000 { compatible = "qcom,x1e80100-system-noc"; - reg = <0 0x1680000 0 0x1c080>; + reg = <0 0x01680000 0 0x1c080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2799,7 +2828,7 @@ pcie_south_anoc: interconnect@16c0000 { compatible = "qcom,x1e80100-pcie-south-anoc"; - reg = <0 0x16c0000 0 0xd080>; + reg = <0 0x016c0000 0 0xd080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2808,7 +2837,7 @@ pcie_center_anoc: interconnect@16d0000 { compatible = "qcom,x1e80100-pcie-center-anoc"; - reg = <0 0x16d0000 0 0x7000>; + reg = <0 0x016d0000 0 0x7000>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2817,7 +2846,7 @@ aggre1_noc: interconnect@16e0000 { compatible = "qcom,x1e80100-aggre1-noc"; - reg = <0 0x16E0000 0 0x14400>; + reg = <0 0x016e0000 0 0x14400>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2826,7 +2855,7 @@ aggre2_noc: interconnect@1700000 { compatible = "qcom,x1e80100-aggre2-noc"; - reg = <0 0x1700000 0 0x1c400>; + reg = <0 0x01700000 0 0x1c400>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2835,7 +2864,7 @@ pcie_north_anoc: interconnect@1740000 { compatible = "qcom,x1e80100-pcie-north-anoc"; - reg = <0 0x1740000 0 0x9080>; + reg = <0 0x01740000 0 0x9080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2844,7 +2873,7 @@ usb_center_anoc: interconnect@1750000 { compatible = "qcom,x1e80100-usb-center-anoc"; - reg = <0 0x1750000 0 0x8800>; + reg = <0 0x01750000 0 0x8800>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2853,7 +2882,7 @@ usb_north_anoc: interconnect@1760000 { compatible = "qcom,x1e80100-usb-north-anoc"; - reg = <0 0x1760000 0 0x7080>; + reg = <0 0x01760000 0 0x7080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2862,7 +2891,7 @@ usb_south_anoc: interconnect@1770000 { compatible = "qcom,x1e80100-usb-south-anoc"; - reg = <0 0x1770000 0 0xf080>; + reg = <0 0x01770000 0 0xf080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2871,7 +2900,7 @@ mmss_noc: interconnect@1780000 { compatible = "qcom,x1e80100-mmss-noc"; - reg = <0 0x1780000 0 0x5B800>; + reg = <0 0x01780000 0 0x5B800>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -2895,14 +2924,14 @@ "mhi"; #address-cells = <3>; #size-cells = <2>; - ranges = <0x01000000 0 0x00000000 0 0x70200000 0 0x100000>, - <0x02000000 0 0x70300000 0 0x70300000 0 0x3d00000>; - bus-range = <0 0xff>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x70200000 0x0 0x100000>, + <0x02000000 0x0 0x70300000 0x0 0x70300000 0x0 0x1d00000>; + bus-range = <0x00 0xff>; dma-coherent; - linux,pci-domain = <7>; - num-lanes = <2>; + linux,pci-domain = <6>; + num-lanes = <4>; interrupts = <GIC_SPI 773 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 774 IRQ_TYPE_LEVEL_HIGH>, @@ -2959,6 +2988,7 @@ "link_down"; power-domains = <&gcc GCC_PCIE_6A_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie6a_phy>; phy-names = "pciephy"; @@ -2967,19 +2997,22 @@ }; pcie6a_phy: phy@1bfc000 { - compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy"; - reg = <0 0x01bfc000 0 0x2000>; + compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy"; + reg = <0 0x01bfc000 0 0x2000>, + <0 0x01bfe000 0 0x2000>; clocks = <&gcc GCC_PCIE_6A_PHY_AUX_CLK>, <&gcc GCC_PCIE_6A_CFG_AHB_CLK>, - <&rpmhcc RPMH_CXO_CLK>, + <&tcsr TCSR_PCIE_4L_CLKREF_EN>, <&gcc GCC_PCIE_6A_PHY_RCHNG_CLK>, - <&gcc GCC_PCIE_6A_PIPE_CLK>; + <&gcc GCC_PCIE_6A_PIPE_CLK>, + <&gcc GCC_PCIE_6A_PIPEDIV2_CLK>; clock-names = "aux", "cfg_ahb", "ref", "rchng", - "pipe"; + "pipe", + "pipediv2"; resets = <&gcc GCC_PCIE_6A_PHY_BCR>, <&gcc GCC_PCIE_6A_NOCSR_COM_PHY_BCR>; @@ -2991,6 +3024,8 @@ power-domains = <&gcc GCC_PCIE_6_PHY_GDSC>; + qcom,4ln-config-sel = <&tcsr 0x1a000 0>; + #clock-cells = <0>; clock-output-names = "pcie6a_pipe_clk"; @@ -2999,6 +3034,128 @@ status = "disabled"; }; + pcie5: pci@1c00000 { + device_type = "pci"; + compatible = "qcom,pcie-x1e80100"; + reg = <0 0x01c00000 0 0x3000>, + <0 0x7e000000 0 0xf1d>, + <0 0x7e000f40 0 0xa8>, + <0 0x7e001000 0 0x1000>, + <0 0x7e100000 0 0x100000>, + <0 0x01c03000 0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x7e200000 0x0 0x100000>, + <0x02000000 0x0 0x7e300000 0x0 0x7e300000 0x0 0x1d00000>; + bus-range = <0x00 0xff>; + + dma-coherent; + + linux,pci-domain = <5>; + num-lanes = <2>; + + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 0 0 70 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 71 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 72 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 73 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_PCIE_5_AUX_CLK>, + <&gcc GCC_PCIE_5_CFG_AHB_CLK>, + <&gcc GCC_PCIE_5_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_5_SLV_AXI_CLK>, + <&gcc GCC_PCIE_5_SLV_Q2A_AXI_CLK>, + <&gcc GCC_CFG_NOC_PCIE_ANOC_NORTH_AHB_CLK>, + <&gcc GCC_CNOC_PCIE_NORTH_SF_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "noc_aggr", + "cnoc_sf_axi"; + + assigned-clocks = <&gcc GCC_PCIE_5_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&pcie_north_anoc MASTER_PCIE_5 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &cnoc_main SLAVE_PCIE_5 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + resets = <&gcc GCC_PCIE_5_BCR>, + <&gcc GCC_PCIE_5_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + power-domains = <&gcc GCC_PCIE_5_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + phys = <&pcie5_phy>; + phy-names = "pciephy"; + + status = "disabled"; + }; + + pcie5_phy: phy@1c06000 { + compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy"; + reg = <0 0x01c06000 0 0x2000>; + + clocks = <&gcc GCC_PCIE_5_AUX_CLK>, + <&gcc GCC_PCIE_5_CFG_AHB_CLK>, + <&tcsr TCSR_PCIE_2L_5_CLKREF_EN>, + <&gcc GCC_PCIE_5_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_5_PIPE_CLK>, + <&gcc GCC_PCIE_5_PIPEDIV2_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "rchng", + "pipe", + "pipediv2"; + + resets = <&gcc GCC_PCIE_5_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_5_PHY_RCHNG_CLK>; + assigned-clock-rates = <100000000>; + + power-domains = <&gcc GCC_PCIE_5_PHY_GDSC>; + + #clock-cells = <0>; + clock-output-names = "pcie5_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + pcie4: pci@1c08000 { device_type = "pci"; compatible = "qcom,pcie-x1e80100"; @@ -3016,13 +3173,13 @@ "mhi"; #address-cells = <3>; #size-cells = <2>; - ranges = <0x01000000 0 0x00000000 0 0x7c200000 0 0x100000>, - <0x02000000 0 0x7c300000 0 0x7c300000 0 0x3d00000>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x7c200000 0x0 0x100000>, + <0x02000000 0x0 0x7c300000 0x0 0x7c300000 0x0 0x1d00000>; bus-range = <0x00 0xff>; dma-coherent; - linux,pci-domain = <5>; + linux,pci-domain = <4>; num-lanes = <2>; interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, @@ -3067,7 +3224,7 @@ assigned-clocks = <&gcc GCC_PCIE_4_AUX_CLK>; assigned-clock-rates = <19200000>; - interconnects = <&pcie_south_anoc MASTER_PCIE_4 QCOM_ICC_TAG_ALWAYS + interconnects = <&pcie_north_anoc MASTER_PCIE_4 QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS &cnoc_main SLAVE_PCIE_4 QCOM_ICC_TAG_ALWAYS>; @@ -3080,11 +3237,22 @@ "link_down"; power-domains = <&gcc GCC_PCIE_4_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie4_phy>; phy-names = "pciephy"; status = "disabled"; + + pcie4_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + bus-range = <0x01 0xff>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; }; pcie4_phy: phy@1c0e000 { @@ -3093,14 +3261,16 @@ clocks = <&gcc GCC_PCIE_4_AUX_CLK>, <&gcc GCC_PCIE_4_CFG_AHB_CLK>, - <&rpmhcc RPMH_CXO_CLK>, + <&tcsr TCSR_PCIE_2L_4_CLKREF_EN>, <&gcc GCC_PCIE_4_PHY_RCHNG_CLK>, - <&gcc GCC_PCIE_4_PIPE_CLK>; + <&gcc GCC_PCIE_4_PIPE_CLK>, + <&gcc GCC_PCIE_4_PIPEDIV2_CLK>; clock-names = "aux", "cfg_ahb", "ref", "rchng", - "pipe"; + "pipe", + "pipediv2"; resets = <&gcc GCC_PCIE_4_PHY_BCR>; reset-names = "phy"; @@ -3155,9 +3325,10 @@ interconnects = <&gem_noc MASTER_GFX3D 0 &mc_virt SLAVE_EBI1 0>; interconnect-names = "gfx-mem"; + status = "disabled"; + zap-shader { memory-region = <&gpu_microcode_mem>; - firmware-name = "qcom/gen70500_zap.mbn"; }; gpu_opp_table: opp-table { @@ -3288,7 +3459,7 @@ reg = <0x0 0x03da0000 0x0 0x40000>; #iommu-cells = <2>; #global-interrupts = <1>; - interrupts = <GIC_SPI 673 IRQ_TYPE_LEVEL_HIGH>, + interrupts = <GIC_SPI 674 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 678 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 679 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 680 IRQ_TYPE_LEVEL_HIGH>, @@ -3337,7 +3508,7 @@ nsp_noc: interconnect@320c0000 { compatible = "qcom,x1e80100-nsp-noc"; - reg = <0 0x320C0000 0 0xE080>; + reg = <0 0x320C0000 0 0xe080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -3372,6 +3543,8 @@ pinctrl-0 = <&wsa2_swr_active>; pinctrl-names = "default"; + resets = <&lpass_audiocc LPASS_AUDIO_SWR_WSA2_CGCR>; + reset-names = "swr_audio_cgcr"; qcom,din-ports = <4>; qcom,dout-ports = <9>; @@ -3420,6 +3593,8 @@ pinctrl-0 = <&rx_swr_active>; pinctrl-names = "default"; + resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>; + reset-names = "swr_audio_cgcr"; qcom,din-ports = <1>; qcom,dout-ports = <11>; @@ -3484,6 +3659,8 @@ pinctrl-0 = <&wsa_swr_active>; pinctrl-names = "default"; + resets = <&lpass_audiocc LPASS_AUDIO_SWR_WSA_CGCR>; + reset-names = "swr_audio_cgcr"; qcom,din-ports = <4>; qcom,dout-ports = <9>; @@ -3504,6 +3681,13 @@ status = "disabled"; }; + lpass_audiocc: clock-controller@6b6c000 { + compatible = "qcom,x1e80100-lpassaudiocc", "qcom,sc8280xp-lpassaudiocc"; + reg = <0 0x06b6c000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + swr2: soundwire@6d30000 { compatible = "qcom,soundwire-v2.0.0"; reg = <0 0x06d30000 0 0x10000>; @@ -3513,6 +3697,8 @@ <GIC_SPI 520 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "core", "wakeup"; label = "TX"; + resets = <&lpasscc LPASS_AUDIO_SWR_TX_CGCR>; + reset-names = "swr_audio_cgcr"; pinctrl-0 = <&tx_swr_active>; pinctrl-names = "default"; @@ -3669,9 +3855,16 @@ }; }; + lpasscc: clock-controller@6ea0000 { + compatible = "qcom,x1e80100-lpasscc", "qcom,sc8280xp-lpasscc"; + reg = <0 0x06ea0000 0 0x12000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + lpass_ag_noc: interconnect@7e40000 { compatible = "qcom,x1e80100-lpass-ag-noc"; - reg = <0 0x7e40000 0 0xE080>; + reg = <0 0x07e40000 0 0xe080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -3680,7 +3873,7 @@ lpass_lpiaon_noc: interconnect@7400000 { compatible = "qcom,x1e80100-lpass-lpiaon-noc"; - reg = <0 0x7400000 0 0x19080>; + reg = <0 0x07400000 0 0x19080>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -3689,7 +3882,7 @@ lpass_lpicx_noc: interconnect@7430000 { compatible = "qcom,x1e80100-lpass-lpicx-noc"; - reg = <0 0x7430000 0 0x3A200>; + reg = <0 0x07430000 0 0x3A200>; qcom,bcm-voters = <&apps_bcm_voter>; @@ -3710,6 +3903,90 @@ status = "disabled"; }; + usb_mp_hsphy0: phy@88e1000 { + compatible = "qcom,x1e80100-snps-eusb2-phy", + "qcom,sm8550-snps-eusb2-phy"; + reg = <0 0x088e1000 0 0x154>; + #phy-cells = <0>; + + clocks = <&tcsr TCSR_USB3_MP0_CLKREF_EN>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_HS0_MP_BCR>; + + status = "disabled"; + }; + + usb_mp_hsphy1: phy@88e2000 { + compatible = "qcom,x1e80100-snps-eusb2-phy", + "qcom,sm8550-snps-eusb2-phy"; + reg = <0 0x088e2000 0 0x154>; + #phy-cells = <0>; + + clocks = <&tcsr TCSR_USB3_MP1_CLKREF_EN>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_HS1_MP_BCR>; + + status = "disabled"; + }; + + usb_mp_qmpphy0: phy@88e3000 { + compatible = "qcom,x1e80100-qmp-usb3-uni-phy"; + reg = <0 0x088e3000 0 0x2000>; + + clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_UNIPHY_MP0_BCR>, + <&gcc GCC_USB3UNIPHY_PHY_MP0_BCR>; + reset-names = "phy", + "phy_phy"; + + power-domains = <&gcc GCC_USB3_MP_SS0_PHY_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb_mp_phy0_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_mp_qmpphy1: phy@88e5000 { + compatible = "qcom,x1e80100-qmp-usb3-uni-phy"; + reg = <0 0x088e5000 0 0x2000>; + + clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>, + <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "pipe"; + + resets = <&gcc GCC_USB3_UNIPHY_MP1_BCR>, + <&gcc GCC_USB3UNIPHY_PHY_MP1_BCR>; + reset-names = "phy", + "phy_phy"; + + power-domains = <&gcc GCC_USB3_MP_SS1_PHY_GDSC>; + + #clock-cells = <0>; + clock-output-names = "usb_mp_phy1_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + usb_1_ss2: usb@a0f8800 { compatible = "qcom,x1e80100-dwc3", "qcom,dwc3"; reg = <0 0x0a0f8800 0 0x400>; @@ -3884,6 +4161,92 @@ }; }; + usb_mp: usb@a4f8800 { + compatible = "qcom,x1e80100-dwc3-mp", "qcom,dwc3"; + reg = <0 0x0a4f8800 0 0x400>; + + clocks = <&gcc GCC_CFG_NOC_USB3_MP_AXI_CLK>, + <&gcc GCC_USB30_MP_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_MP_AXI_CLK>, + <&gcc GCC_USB30_MP_SLEEP_CLK>, + <&gcc GCC_USB30_MP_MOCK_UTMI_CLK>, + <&gcc GCC_AGGRE_USB_NOC_AXI_CLK>, + <&gcc GCC_AGGRE_NOC_USB_NORTH_AXI_CLK>, + <&gcc GCC_AGGRE_NOC_USB_SOUTH_AXI_CLK>, + <&gcc GCC_SYS_NOC_USB_AXI_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "noc_aggr", + "noc_aggr_north", + "noc_aggr_south", + "noc_sys"; + + assigned-clocks = <&gcc GCC_USB30_MP_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_MP_MASTER_CLK>; + assigned-clock-rates = <19200000>, + <200000000>; + + interrupts-extended = <&intc GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 52 IRQ_TYPE_EDGE_BOTH>, + <&pdc 51 IRQ_TYPE_EDGE_BOTH>, + <&pdc 54 IRQ_TYPE_EDGE_BOTH>, + <&pdc 53 IRQ_TYPE_EDGE_BOTH>, + <&pdc 55 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 56 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pwr_event_1", "pwr_event_2", + "hs_phy_1", "hs_phy_2", + "dp_hs_phy_1", "dm_hs_phy_1", + "dp_hs_phy_2", "dm_hs_phy_2", + "ss_phy_1", "ss_phy_2"; + + power-domains = <&gcc GCC_USB30_MP_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_MP_BCR>; + + interconnects = <&usb_north_anoc MASTER_USB3_MP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_USB3_MP QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "usb-ddr", + "apps-usb"; + + wakeup-source; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + usb_mp_dwc3: usb@a400000 { + compatible = "snps,dwc3"; + reg = <0 0x0a400000 0 0xcd00>; + + interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>; + + iommus = <&apps_smmu 0x1400 0x0>; + + phys = <&usb_mp_hsphy0>, <&usb_mp_qmpphy0>, + <&usb_mp_hsphy1>, <&usb_mp_qmpphy1>; + phy-names = "usb2-0", "usb3-0", + "usb2-1", "usb3-1"; + dr_mode = "host"; + + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,usb3_lpm_capable; + + dma-coherent; + }; + }; + usb_1_ss0: usb@a6f8800 { compatible = "qcom,x1e80100-dwc3", "qcom,dwc3"; reg = <0 0x0a6f8800 0 0x400>; @@ -4202,11 +4565,11 @@ mdss_dp0: displayport-controller@ae90000 { compatible = "qcom,x1e80100-dp"; - reg = <0 0xae90000 0 0x200>, - <0 0xae90200 0 0x200>, - <0 0xae90400 0 0x600>, - <0 0xae91000 0 0x400>, - <0 0xae91400 0 0x400>; + reg = <0 0x0ae90000 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0x600>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>; interrupts-extended = <&mdss 12>; @@ -4285,11 +4648,11 @@ mdss_dp1: displayport-controller@ae98000 { compatible = "qcom,x1e80100-dp"; - reg = <0 0xae98000 0 0x200>, - <0 0xae98200 0 0x200>, - <0 0xae98400 0 0x600>, - <0 0xae99000 0 0x400>, - <0 0xae99400 0 0x400>; + reg = <0 0x0ae98000 0 0x200>, + <0 0x0ae98200 0 0x200>, + <0 0x0ae98400 0 0x600>, + <0 0x0ae99000 0 0x400>, + <0 0x0ae99400 0 0x400>; interrupts-extended = <&mdss 13>; @@ -4368,11 +4731,11 @@ mdss_dp2: displayport-controller@ae9a000 { compatible = "qcom,x1e80100-dp"; - reg = <0 0xae9a000 0 0x200>, - <0 0xae9a200 0 0x200>, - <0 0xae9a400 0 0x600>, - <0 0xae9b000 0 0x400>, - <0 0xae9b400 0 0x400>; + reg = <0 0x0ae9a000 0 0x200>, + <0 0x0ae9a200 0 0x200>, + <0 0x0ae9a400 0 0x600>, + <0 0x0ae9b000 0 0x400>, + <0 0x0ae9b400 0 0x400>; interrupts-extended = <&mdss 14>; @@ -4389,14 +4752,14 @@ assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX2_LINK_CLK_SRC>, <&dispcc DISP_CC_MDSS_DPTX2_PIXEL0_CLK_SRC>; - assigned-clock-parents = <&mdss_dp2_phy 0>, - <&mdss_dp2_phy 1>; + assigned-clock-parents = <&usb_1_ss2_qmpphy QMP_USB43DP_DP_LINK_CLK>, + <&usb_1_ss2_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; operating-points-v2 = <&mdss_dp2_opp_table>; power-domains = <&rpmhpd RPMHPD_MMCX>; - phys = <&mdss_dp2_phy>; + phys = <&usb_1_ss2_qmpphy QMP_USB43DP_DP_PHY>; phy-names = "dp"; #sound-dai-cells = <0>; @@ -4450,11 +4813,11 @@ mdss_dp3: displayport-controller@aea0000 { compatible = "qcom,x1e80100-dp"; - reg = <0 0xaea0000 0 0x200>, - <0 0xaea0200 0 0x200>, - <0 0xaea0400 0 0x600>, - <0 0xaea1000 0 0x400>, - <0 0xaea1400 0 0x400>; + reg = <0 0x0aea0000 0 0x200>, + <0 0x0aea0200 0 0x200>, + <0 0x0aea0400 0 0x600>, + <0 0x0aea1000 0 0x400>, + <0 0x0aea1400 0 0x400>; interrupts-extended = <&mdss 15>; @@ -4584,8 +4947,8 @@ <&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, <&usb_1_ss1_qmpphy QMP_USB43DP_DP_LINK_CLK>, /* dp1 */ <&usb_1_ss1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, - <&mdss_dp2_phy 0>, /* dp2 */ - <&mdss_dp2_phy 1>, + <&usb_1_ss2_qmpphy QMP_USB43DP_DP_LINK_CLK>, /* dp2 */ + <&usb_1_ss2_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, <&mdss_dp3_phy 0>, /* dp3 */ <&mdss_dp3_phy 1>; power-domains = <&rpmhpd RPMHPD_MMCX>; @@ -4618,6 +4981,11 @@ #clock-cells = <0>; }; + sram@c3f0000 { + compatible = "qcom,rpmh-stats"; + reg = <0 0x0c3f0000 0 0x400>; + }; + spmi: arbiter@c400000 { compatible = "qcom,x1e80100-spmi-pmic-arb"; reg = <0 0x0c400000 0 0x3000>, @@ -5228,12 +5596,50 @@ bias-disable; }; + qup_uart2_default: qup-uart2-default-state { + cts-pins { + pins = "gpio8"; + function = "qup0_se2"; + drive-strength = <2>; + bias-disable; + }; + + rts-pins { + pins = "gpio9"; + function = "qup0_se2"; + drive-strength = <2>; + bias-disable; + }; + + tx-pins { + pins = "gpio10"; + function = "qup0_se2"; + drive-strength = <2>; + bias-disable; + }; + + rx-pins { + pins = "gpio11"; + function = "qup0_se2"; + drive-strength = <2>; + bias-disable; + }; + }; + qup_uart21_default: qup-uart21-default-state { - /* TX, RX */ - pins = "gpio86", "gpio87"; - function = "qup2_se5"; - drive-strength = <2>; - bias-disable; + tx-pins { + pins = "gpio86"; + function = "qup2_se5"; + drive-strength = <2>; + bias-disable; + }; + + rx-pins { + pins = "gpio87"; + function = "qup2_se5"; + drive-strength = <2>; + bias-disable; + }; }; }; @@ -5687,7 +6093,8 @@ <0 0x25a00000 0 0x200000>, <0 0x25c00000 0 0x200000>, <0 0x25e00000 0 0x200000>, - <0 0x26000000 0 0x200000>; + <0 0x26000000 0 0x200000>, + <0 0x26200000 0 0x200000>; reg-names = "llcc0_base", "llcc1_base", "llcc2_base", @@ -5696,7 +6103,8 @@ "llcc5_base", "llcc6_base", "llcc7_base", - "llcc_broadcast_base"; + "llcc_broadcast_base", + "llcc_broadcast_and_base"; interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>; }; diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile index fbd214a1a638..97228a3cb99c 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile @@ -112,9 +112,12 @@ dtb-$(CONFIG_ARCH_R8A77965) += r8a779m5-salvator-xs-panel-aa104xd12.dtb dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc.dtb dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-cru-csi-ov5645.dtbo +dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-du-adv7513.dtbo dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043-smarc-pmod.dtbo r9a07g043u11-smarc-cru-csi-ov5645-dtbs := r9a07g043u11-smarc.dtb r9a07g043u11-smarc-cru-csi-ov5645.dtbo dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-cru-csi-ov5645.dtb +r9a07g043u11-smarc-du-adv7513-dtbs := r9a07g043u11-smarc.dtb r9a07g043u11-smarc-du-adv7513.dtbo +dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-du-adv7513.dtb r9a07g043u11-smarc-pmod-dtbs := r9a07g043u11-smarc.dtb r9a07g043-smarc-pmod.dtbo dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043u11-smarc-pmod.dtb @@ -137,5 +140,7 @@ dtb-$(CONFIG_ARCH_R9A08G045) += r9a08g045s33-smarc.dtb dtb-$(CONFIG_ARCH_R9A09G011) += r9a09g011-v2mevk2.dtb +dtb-$(CONFIG_ARCH_R9A09G057) += r9a09g057h44-rzv2h-evk.dtb + dtb-$(CONFIG_ARCH_RCAR_GEN3) += draak-ebisu-panel-aa104xd12.dtbo dtb-$(CONFIG_ARCH_RCAR_GEN3) += salvator-panel-aa104xd12.dtbo diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index 1dbf9d56c68d..f065ee90649a 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -2277,6 +2277,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 314>; + iommus = <&ipmmu_ds1 32>; status = "disabled"; }; @@ -2290,6 +2291,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 313>; + iommus = <&ipmmu_ds1 33>; status = "disabled"; }; @@ -2303,6 +2305,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 312>; + iommus = <&ipmmu_ds1 34>; status = "disabled"; }; @@ -2316,6 +2319,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>; resets = <&cpg 311>; + iommus = <&ipmmu_ds1 35>; status = "disabled"; }; @@ -2464,6 +2468,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A774A1_PD_A3VC>; resets = <&cpg 615>; + iommus = <&ipmmu_vc0 16>; }; fcpvb0: fcp@fe96f000 { @@ -2472,6 +2477,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A774A1_PD_A3VC>; resets = <&cpg 607>; + iommus = <&ipmmu_vi0 5>; }; fcpvd0: fcp@fea27000 { diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi index 10f22c52e79e..117cb6950f91 100644 --- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi @@ -2004,6 +2004,14 @@ resets = <&cpg 502>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_mp 0>, <&ipmmu_mp 1>, + <&ipmmu_mp 2>, <&ipmmu_mp 3>, + <&ipmmu_mp 4>, <&ipmmu_mp 5>, + <&ipmmu_mp 6>, <&ipmmu_mp 7>, + <&ipmmu_mp 8>, <&ipmmu_mp 9>, + <&ipmmu_mp 10>, <&ipmmu_mp 11>, + <&ipmmu_mp 12>, <&ipmmu_mp 13>, + <&ipmmu_mp 14>, <&ipmmu_mp 15>; }; audma1: dma-controller@ec720000 { @@ -2038,6 +2046,14 @@ resets = <&cpg 501>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_mp 16>, <&ipmmu_mp 17>, + <&ipmmu_mp 18>, <&ipmmu_mp 19>, + <&ipmmu_mp 20>, <&ipmmu_mp 21>, + <&ipmmu_mp 22>, <&ipmmu_mp 23>, + <&ipmmu_mp 24>, <&ipmmu_mp 25>, + <&ipmmu_mp 26>, <&ipmmu_mp 27>, + <&ipmmu_mp 28>, <&ipmmu_mp 29>, + <&ipmmu_mp 30>, <&ipmmu_mp 31>; }; xhci0: usb@ee000000 { @@ -2145,6 +2161,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 314>; + iommus = <&ipmmu_ds1 32>; status = "disabled"; }; @@ -2158,6 +2175,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 313>; + iommus = <&ipmmu_ds1 33>; status = "disabled"; }; @@ -2171,6 +2189,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 312>; + iommus = <&ipmmu_ds1 34>; status = "disabled"; }; @@ -2184,6 +2203,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 311>; + iommus = <&ipmmu_ds1 35>; status = "disabled"; }; @@ -2211,6 +2231,7 @@ clocks = <&cpg CPG_MOD 815>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 815>; + iommus = <&ipmmu_hc 2>; status = "disabled"; }; @@ -2343,6 +2364,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A774B1_PD_A3VP>; resets = <&cpg 615>; + iommus = <&ipmmu_vp0 0>; }; vspb: vsp@fe960000 { @@ -2395,6 +2417,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A774B1_PD_A3VP>; resets = <&cpg 607>; + iommus = <&ipmmu_vp0 5>; }; fcpvd0: fcp@fea27000 { @@ -2403,6 +2426,7 @@ clocks = <&cpg CPG_MOD 603>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; }; fcpvd1: fcp@fea2f000 { @@ -2411,6 +2435,7 @@ clocks = <&cpg CPG_MOD 602>; power-domains = <&sysc R8A774B1_PD_ALWAYS_ON>; resets = <&cpg 602>; + iommus = <&ipmmu_vi0 9>; }; fcpvi0: fcp@fe9af000 { @@ -2419,6 +2444,7 @@ clocks = <&cpg CPG_MOD 611>; power-domains = <&sysc R8A774B1_PD_A3VP>; resets = <&cpg 611>; + iommus = <&ipmmu_vp0 8>; }; csi20: csi2@fea80000 { diff --git a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi index 3e2af50ce7c6..7655d5e3a034 100644 --- a/arch/arm64/boot/dts/renesas/r8a774c0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774c0.dtsi @@ -1637,6 +1637,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 314>; + iommus = <&ipmmu_ds1 32>; status = "disabled"; }; @@ -1650,6 +1651,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 313>; + iommus = <&ipmmu_ds1 33>; status = "disabled"; }; @@ -1663,6 +1665,7 @@ max-frequency = <200000000>; power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>; resets = <&cpg 311>; + iommus = <&ipmmu_ds1 35>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi index 1eeb4c7b4c4b..f845ca604de0 100644 --- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi @@ -2652,6 +2652,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 615>; + iommus = <&ipmmu_vp0 0>; }; fcpf1: fcp@fe951000 { @@ -2660,6 +2661,7 @@ clocks = <&cpg CPG_MOD 614>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 614>; + iommus = <&ipmmu_vp1 1>; }; fcpvb0: fcp@fe96f000 { @@ -2668,6 +2670,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 607>; + iommus = <&ipmmu_vp0 5>; }; fcpvb1: fcp@fe92f000 { @@ -2676,6 +2679,7 @@ clocks = <&cpg CPG_MOD 606>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 606>; + iommus = <&ipmmu_vp1 7>; }; fcpvi0: fcp@fe9af000 { @@ -2684,6 +2688,7 @@ clocks = <&cpg CPG_MOD 611>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 611>; + iommus = <&ipmmu_vp0 8>; }; fcpvi1: fcp@fe9bf000 { @@ -2692,6 +2697,7 @@ clocks = <&cpg CPG_MOD 610>; power-domains = <&sysc R8A774E1_PD_A3VP>; resets = <&cpg 610>; + iommus = <&ipmmu_vp1 9>; }; fcpvd0: fcp@fea27000 { @@ -2700,6 +2706,7 @@ clocks = <&cpg CPG_MOD 603>; power-domains = <&sysc R8A774E1_PD_ALWAYS_ON>; resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; }; fcpvd1: fcp@fea2f000 { @@ -2708,6 +2715,7 @@ clocks = <&cpg CPG_MOD 602>; power-domains = <&sysc R8A774E1_PD_ALWAYS_ON>; resets = <&cpg 602>; + iommus = <&ipmmu_vi0 9>; }; csi20: csi2@fea80000 { diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index 1122c470b72f..ee80f52dc7cf 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -2652,6 +2652,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A7796_PD_A3VC>; resets = <&cpg 615>; + iommus = <&ipmmu_vc0 16>; }; fcpvb0: fcp@fe96f000 { @@ -2660,6 +2661,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A7796_PD_A3VC>; resets = <&cpg 607>; + iommus = <&ipmmu_vi0 5>; }; fcpvi0: fcp@fe9af000 { diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi index bf1130af7de3..3b9066043a71 100644 --- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi @@ -2502,6 +2502,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A77961_PD_A3VC>; resets = <&cpg 615>; + iommus = <&ipmmu_vc0 16>; }; fcpvb0: fcp@fe96f000 { @@ -2510,6 +2511,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A77961_PD_A3VC>; resets = <&cpg 607>; + iommus = <&ipmmu_vi0 5>; }; fcpvi0: fcp@fe9af000 { diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index f02d1547b881..557bdf8fab17 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -2185,6 +2185,14 @@ resets = <&cpg 502>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_mp 0>, <&ipmmu_mp 1>, + <&ipmmu_mp 2>, <&ipmmu_mp 3>, + <&ipmmu_mp 4>, <&ipmmu_mp 5>, + <&ipmmu_mp 6>, <&ipmmu_mp 7>, + <&ipmmu_mp 8>, <&ipmmu_mp 9>, + <&ipmmu_mp 10>, <&ipmmu_mp 11>, + <&ipmmu_mp 12>, <&ipmmu_mp 13>, + <&ipmmu_mp 14>, <&ipmmu_mp 15>; }; audma1: dma-controller@ec720000 { @@ -2219,6 +2227,14 @@ resets = <&cpg 501>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_mp 16>, <&ipmmu_mp 17>, + <&ipmmu_mp 18>, <&ipmmu_mp 19>, + <&ipmmu_mp 20>, <&ipmmu_mp 21>, + <&ipmmu_mp 22>, <&ipmmu_mp 23>, + <&ipmmu_mp 24>, <&ipmmu_mp 25>, + <&ipmmu_mp 26>, <&ipmmu_mp 27>, + <&ipmmu_mp 28>, <&ipmmu_mp 29>, + <&ipmmu_mp 30>, <&ipmmu_mp 31>; }; xhci0: usb@ee000000 { @@ -2396,6 +2412,7 @@ clocks = <&cpg CPG_MOD 815>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 815>; + iommus = <&ipmmu_hc 2>; status = "disabled"; }; @@ -2490,6 +2507,7 @@ clocks = <&cpg CPG_MOD 615>; power-domains = <&sysc R8A77965_PD_A3VP>; resets = <&cpg 615>; + iommus = <&ipmmu_vp0 0>; }; vspb: vsp@fe960000 { @@ -2542,6 +2560,7 @@ clocks = <&cpg CPG_MOD 607>; power-domains = <&sysc R8A77965_PD_A3VP>; resets = <&cpg 607>; + iommus = <&ipmmu_vp0 5>; }; fcpvd0: fcp@fea27000 { @@ -2550,6 +2569,7 @@ clocks = <&cpg CPG_MOD 603>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; }; fcpvd1: fcp@fea2f000 { @@ -2558,6 +2578,7 @@ clocks = <&cpg CPG_MOD 602>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 602>; + iommus = <&ipmmu_vi0 9>; }; fcpvi0: fcp@fe9af000 { @@ -2566,6 +2587,7 @@ clocks = <&cpg CPG_MOD 611>; power-domains = <&sysc R8A77965_PD_A3VP>; resets = <&cpg 611>; + iommus = <&ipmmu_vp0 8>; }; cmm0: cmm@fea40000 { diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi index 64fb95b1c89a..38145fd6acf0 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi @@ -1092,6 +1092,7 @@ clocks = <&cpg CPG_MOD 603>; power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; }; csi40: csi2@feaa0000 { diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index 0c2b157036e7..55a6c622f873 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1266,6 +1266,7 @@ clocks = <&cpg CPG_MOD 813>; power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; resets = <&cpg 813>; + iommus = <&ipmmu_ds1 34>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1430,6 +1431,7 @@ clocks = <&cpg CPG_MOD 603>; power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; }; csi40: csi2@feaa0000 { diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi index d76347001cc1..1f4ab27acc33 100644 --- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi @@ -707,6 +707,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 0>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -755,6 +756,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 1>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -803,6 +805,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 2>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -851,6 +854,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 3>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -899,6 +903,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 4>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -947,6 +952,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_ds1 11>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -1168,7 +1174,8 @@ }; vin00: video@e6ef0000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef0000 0 0x1000>; interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 730>; @@ -1196,7 +1203,8 @@ }; vin01: video@e6ef1000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef1000 0 0x1000>; interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 731>; @@ -1224,7 +1232,8 @@ }; vin02: video@e6ef2000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef2000 0 0x1000>; interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 800>; @@ -1252,7 +1261,8 @@ }; vin03: video@e6ef3000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef3000 0 0x1000>; interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 801>; @@ -1280,7 +1290,8 @@ }; vin04: video@e6ef4000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef4000 0 0x1000>; interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 802>; @@ -1308,7 +1319,8 @@ }; vin05: video@e6ef5000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef5000 0 0x1000>; interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 803>; @@ -1336,7 +1348,8 @@ }; vin06: video@e6ef6000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef6000 0 0x1000>; interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 804>; @@ -1364,7 +1377,8 @@ }; vin07: video@e6ef7000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef7000 0 0x1000>; interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 805>; @@ -1392,7 +1406,8 @@ }; vin08: video@e6ef8000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef8000 0 0x1000>; interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 806>; @@ -1420,7 +1435,8 @@ }; vin09: video@e6ef9000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef9000 0 0x1000>; interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 807>; @@ -1448,7 +1464,8 @@ }; vin10: video@e6efa000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efa000 0 0x1000>; interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 808>; @@ -1476,7 +1493,8 @@ }; vin11: video@e6efb000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efb000 0 0x1000>; interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 809>; @@ -1504,7 +1522,8 @@ }; vin12: video@e6efc000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efc000 0 0x1000>; interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 810>; @@ -1532,7 +1551,8 @@ }; vin13: video@e6efd000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efd000 0 0x1000>; interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 811>; @@ -1560,7 +1580,8 @@ }; vin14: video@e6efe000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efe000 0 0x1000>; interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 812>; @@ -1588,7 +1609,8 @@ }; vin15: video@e6eff000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6eff000 0 0x1000>; interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 813>; @@ -1616,7 +1638,8 @@ }; vin16: video@e6ed0000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed0000 0 0x1000>; interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 814>; @@ -1644,7 +1667,8 @@ }; vin17: video@e6ed1000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed1000 0 0x1000>; interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 815>; @@ -1672,7 +1696,8 @@ }; vin18: video@e6ed2000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed2000 0 0x1000>; interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 816>; @@ -1700,7 +1725,8 @@ }; vin19: video@e6ed3000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed3000 0 0x1000>; interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 817>; @@ -1728,7 +1754,8 @@ }; vin20: video@e6ed4000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed4000 0 0x1000>; interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 818>; @@ -1756,7 +1783,8 @@ }; vin21: video@e6ed5000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed5000 0 0x1000>; interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 819>; @@ -1784,7 +1812,8 @@ }; vin22: video@e6ed6000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed6000 0 0x1000>; interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 820>; @@ -1812,7 +1841,8 @@ }; vin23: video@e6ed7000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed7000 0 0x1000>; interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 821>; @@ -1840,7 +1870,8 @@ }; vin24: video@e6ed8000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed8000 0 0x1000>; interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 822>; @@ -1868,7 +1899,8 @@ }; vin25: video@e6ed9000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ed9000 0 0x1000>; interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 823>; @@ -1896,7 +1928,8 @@ }; vin26: video@e6eda000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6eda000 0 0x1000>; interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 824>; @@ -1924,7 +1957,8 @@ }; vin27: video@e6edb000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6edb000 0 0x1000>; interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 825>; @@ -1952,7 +1986,8 @@ }; vin28: video@e6edc000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6edc000 0 0x1000>; interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 826>; @@ -1980,7 +2015,8 @@ }; vin29: video@e6edd000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6edd000 0 0x1000>; interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 827>; @@ -2008,7 +2044,8 @@ }; vin30: video@e6ede000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ede000 0 0x1000>; interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 828>; @@ -2036,7 +2073,8 @@ }; vin31: video@e6edf000 { - compatible = "renesas,vin-r8a779a0"; + compatible = "renesas,vin-r8a779a0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6edf000 0 0x1000>; interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 829>; @@ -2096,6 +2134,14 @@ resets = <&cpg 709>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>, + <&ipmmu_ds0 2>, <&ipmmu_ds0 3>, + <&ipmmu_ds0 4>, <&ipmmu_ds0 5>, + <&ipmmu_ds0 6>, <&ipmmu_ds0 7>, + <&ipmmu_ds0 8>, <&ipmmu_ds0 9>, + <&ipmmu_ds0 10>, <&ipmmu_ds0 11>, + <&ipmmu_ds0 12>, <&ipmmu_ds0 13>, + <&ipmmu_ds0 14>, <&ipmmu_ds0 15>; }; dmac2: dma-controller@e7351000 { @@ -2121,6 +2167,10 @@ resets = <&cpg 710>; #dma-cells = <1>; dma-channels = <8>; + iommus = <&ipmmu_ds0 16>, <&ipmmu_ds0 17>, + <&ipmmu_ds0 18>, <&ipmmu_ds0 19>, + <&ipmmu_ds0 20>, <&ipmmu_ds0 21>, + <&ipmmu_ds0 22>, <&ipmmu_ds0 23>; }; mmc0: mmc@ee140000 { @@ -2278,6 +2328,7 @@ clocks = <&cpg CPG_MOD 508>; power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; resets = <&cpg 508>; + iommus = <&ipmmu_vi1 6>; }; fcpvd1: fcp@fea11000 { @@ -2286,6 +2337,7 @@ clocks = <&cpg CPG_MOD 509>; power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; resets = <&cpg 509>; + iommus = <&ipmmu_vi1 7>; }; vspd0: vsp@fea20000 { @@ -2449,7 +2501,8 @@ }; isp0: isp@fed00000 { - compatible = "renesas,r8a779a0-isp"; + compatible = "renesas,r8a779a0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed00000 0 0x10000>; interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 612>; @@ -2532,7 +2585,8 @@ }; isp1: isp@fed20000 { - compatible = "renesas,r8a779a0-isp"; + compatible = "renesas,r8a779a0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed20000 0 0x10000>; interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 613>; @@ -2615,7 +2669,8 @@ }; isp2: isp@fed30000 { - compatible = "renesas,r8a779a0-isp"; + compatible = "renesas,r8a779a0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed30000 0 0x10000>; interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 614>; @@ -2698,7 +2753,8 @@ }; isp3: isp@fed40000 { - compatible = "renesas,r8a779a0-isp"; + compatible = "renesas,r8a779a0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed40000 0 0x10000>; interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 615>; diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi index 53d1d4d8197a..12900ebd098b 100644 --- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi @@ -175,6 +175,20 @@ clock-frequency = <0>; }; + pcie0_clkref: pcie0-clkref { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + pcie1_clkref: pcie1-clkref { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + pmu_a76 { compatible = "arm,cortex-a76-pmu"; interrupts-extended = <&gic GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>; @@ -553,6 +567,20 @@ status = "disabled"; }; + tsn0: ethernet@e6460000 { + compatible = "renesas,r8a779g0-ethertsn", "renesas,rcar-gen4-ethertsn"; + reg = <0 0xe6460000 0 0x7000>, + <0 0xe6449000 0 0x500>; + reg-names = "tsnes", "gptp"; + interrupts = <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tx", "rx"; + clocks = <&cpg CPG_MOD 2723>; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + resets = <&cpg 2723>; + status = "disabled"; + }; + i2c0: i2c@e6500000 { compatible = "renesas,i2c-r8a779g0", "renesas,rcar-gen4-i2c"; @@ -723,6 +751,126 @@ status = "disabled"; }; + pciec0: pcie@e65d0000 { + compatible = "renesas,r8a779g0-pcie", + "renesas,rcar-gen4-pcie"; + reg = <0 0xe65d0000 0 0x1000>, <0 0xe65d2000 0 0x0800>, + <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>, + <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>, + <0 0xfe000000 0 0x400000>; + reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config"; + interrupts = <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi", "dma", "sft_ce", "app"; + clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>; + clock-names = "core", "ref"; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + resets = <&cpg 624>; + reset-names = "pwr"; + max-link-speed = <4>; + num-lanes = <2>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x01000000 0 0x00000000 0 0xfe000000 0 0x00400000>, + <0x02000000 0 0x30000000 0 0x30000000 0 0x10000000>; + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>; + snps,enable-cdm-check; + status = "disabled"; + }; + + pciec1: pcie@e65d8000 { + compatible = "renesas,r8a779g0-pcie", + "renesas,rcar-gen4-pcie"; + reg = <0 0xe65d8000 0 0x1000>, <0 0xe65da000 0 0x0800>, + <0 0xe65db000 0 0x2000>, <0 0xe65dd000 0 0x1200>, + <0 0xe65de200 0 0x0e00>, <0 0xe65df000 0 0x0400>, + <0 0xee900000 0 0x400000>; + reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "config"; + interrupts = <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi", "dma", "sft_ce", "app"; + clocks = <&cpg CPG_MOD 625>, <&pcie1_clkref>; + clock-names = "core", "ref"; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + resets = <&cpg 625>; + reset-names = "pwr"; + max-link-speed = <4>; + num-lanes = <2>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00400000>, + <0x02000000 0 0xc0000000 0 0xc0000000 0 0x10000000>; + dma-ranges = <0x42000000 0 0x00000000 0 0x00000000 1 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>; + snps,enable-cdm-check; + status = "disabled"; + }; + + pciec0_ep: pcie-ep@e65d0000 { + compatible = "renesas,r8a779g0-pcie-ep", + "renesas,rcar-gen4-pcie-ep"; + reg = <0 0xe65d0000 0 0x2000>, <0 0xe65d2000 0 0x1000>, + <0 0xe65d3000 0 0x2000>, <0 0xe65d5000 0 0x1200>, + <0 0xe65d6200 0 0x0e00>, <0 0xe65d7000 0 0x0400>, + <0 0xfe000000 0 0x400000>; + reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space"; + interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dma", "sft_ce", "app"; + clocks = <&cpg CPG_MOD 624>, <&pcie0_clkref>; + clock-names = "core", "ref"; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + resets = <&cpg 624>; + reset-names = "pwr"; + max-link-speed = <4>; + num-lanes = <2>; + max-functions = /bits/ 8 <2>; + status = "disabled"; + }; + + pciec1_ep: pcie-ep@e65d8000 { + compatible = "renesas,r8a779g0-pcie-ep", + "renesas,rcar-gen4-pcie-ep"; + reg = <0 0xe65d8000 0 0x2000>, <0 0xe65da000 0 0x1000>, + <0 0xe65db000 0 0x2000>, <0 0xe65dd000 0 0x1200>, + <0 0xe65de200 0 0x0e00>, <0 0xe65df000 0 0x0400>, + <0 0xee900000 0 0x400000>; + reg-names = "dbi", "dbi2", "atu", "dma", "app", "phy", "addr_space"; + interrupts = <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dma", "sft_ce", "app"; + clocks = <&cpg CPG_MOD 625>, <&pcie1_clkref>; + clock-names = "core", "ref"; + power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; + resets = <&cpg 625>; + reset-names = "pwr"; + max-link-speed = <4>; + num-lanes = <2>; + max-functions = /bits/ 8 <2>; + status = "disabled"; + }; + canfd: can@e6660000 { compatible = "renesas,r8a779g0-canfd", "renesas,rcar-gen4-canfd"; @@ -815,6 +963,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_hc 0>; status = "disabled"; }; @@ -860,6 +1009,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_hc 1>; status = "disabled"; }; @@ -905,6 +1055,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_hc 2>; status = "disabled"; }; @@ -1184,7 +1335,8 @@ }; vin00: video@e6ef0000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef0000 0 0x1000>; interrupts = <GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 730>; @@ -1212,7 +1364,8 @@ }; vin01: video@e6ef1000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef1000 0 0x1000>; interrupts = <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 731>; @@ -1240,7 +1393,8 @@ }; vin02: video@e6ef2000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef2000 0 0x1000>; interrupts = <GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 800>; @@ -1268,7 +1422,8 @@ }; vin03: video@e6ef3000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef3000 0 0x1000>; interrupts = <GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 801>; @@ -1296,7 +1451,8 @@ }; vin04: video@e6ef4000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef4000 0 0x1000>; interrupts = <GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 802>; @@ -1324,7 +1480,8 @@ }; vin05: video@e6ef5000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef5000 0 0x1000>; interrupts = <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 803>; @@ -1352,7 +1509,8 @@ }; vin06: video@e6ef6000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef6000 0 0x1000>; interrupts = <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 804>; @@ -1380,7 +1538,8 @@ }; vin07: video@e6ef7000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef7000 0 0x1000>; interrupts = <GIC_SPI 536 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 805>; @@ -1408,7 +1567,8 @@ }; vin08: video@e6ef8000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef8000 0 0x1000>; interrupts = <GIC_SPI 537 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 806>; @@ -1436,7 +1596,8 @@ }; vin09: video@e6ef9000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef9000 0 0x1000>; interrupts = <GIC_SPI 538 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 807>; @@ -1464,7 +1625,8 @@ }; vin10: video@e6efa000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efa000 0 0x1000>; interrupts = <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 808>; @@ -1492,7 +1654,8 @@ }; vin11: video@e6efb000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efb000 0 0x1000>; interrupts = <GIC_SPI 540 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 809>; @@ -1520,7 +1683,8 @@ }; vin12: video@e6efc000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efc000 0 0x1000>; interrupts = <GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 810>; @@ -1548,7 +1712,8 @@ }; vin13: video@e6efd000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efd000 0 0x1000>; interrupts = <GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 811>; @@ -1576,7 +1741,8 @@ }; vin14: video@e6efe000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efe000 0 0x1000>; interrupts = <GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 812>; @@ -1604,7 +1770,8 @@ }; vin15: video@e6eff000 { - compatible = "renesas,vin-r8a779g0"; + compatible = "renesas,vin-r8a779g0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6eff000 0 0x1000>; interrupts = <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 813>; @@ -1987,6 +2154,7 @@ clocks = <&cpg CPG_MOD 508>; power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; resets = <&cpg 508>; + iommus = <&ipmmu_vi1 6>; }; fcpvd1: fcp@fea11000 { @@ -1995,6 +2163,7 @@ clocks = <&cpg CPG_MOD 509>; power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>; resets = <&cpg 509>; + iommus = <&ipmmu_vi1 7>; }; vspd0: vsp@fea20000 { @@ -2054,7 +2223,8 @@ }; isp0: isp@fed00000 { - compatible = "renesas,r8a779g0-isp"; + compatible = "renesas,r8a779g0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed00000 0 0x10000>; interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_LOW>; clocks = <&cpg CPG_MOD 612>; @@ -2137,7 +2307,8 @@ }; isp1: isp@fed20000 { - compatible = "renesas,r8a779g0-isp"; + compatible = "renesas,r8a779g0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed20000 0 0x10000>; interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_LOW>; clocks = <&cpg CPG_MOD 613>; diff --git a/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts b/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts index 2f79e5a61248..50a428572d9b 100644 --- a/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts +++ b/arch/arm64/boot/dts/renesas/r8a779g2-white-hawk-single.dts @@ -24,3 +24,54 @@ groups = "hscif0_data", "hscif0_ctrl"; function = "hscif0"; }; + +&pfc { + tsn0_pins: tsn0 { + mux { + groups = "tsn0_link", "tsn0_mdio", "tsn0_rgmii", + "tsn0_txcrefclk"; + function = "tsn0"; + }; + + link { + groups = "tsn0_link"; + bias-disable; + }; + + mdio { + groups = "tsn0_mdio"; + drive-strength = <24>; + bias-disable; + }; + + rgmii { + groups = "tsn0_rgmii"; + drive-strength = <24>; + bias-disable; + }; + }; +}; + +&tsn0 { + pinctrl-0 = <&tsn0_pins>; + pinctrl-names = "default"; + phy-mode = "rgmii"; + phy-handle = <&phy3>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; + reset-post-delay-us = <4000>; + + phy3: ethernet-phy@0 { + compatible = "ethernet-phy-id002b.0980", + "ethernet-phy-ieee802.3-c22"; + reg = <0>; + interrupt-parent = <&gpio4>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts b/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts index 2b9a19bb1c5d..9a1917b87f61 100644 --- a/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts +++ b/arch/arm64/boot/dts/renesas/r8a779h0-gray-hawk-single.dts @@ -5,10 +5,31 @@ * Copyright (C) 2023 Renesas Electronics Corp. * Copyright (C) 2024 Glider bv */ +/* + * [How to use Sound] + * + * Because R-Car V4M has only 1 SSI, it cannot handle both Playback/Capture + * at the same time. You need to switch the direction which is controlled + * by the GP0_01 pin via amixer. + * + * Playback (CN9500) + * > amixer set "MUX" "Playback" // for GP0_01 + * > amixer set "DAC 1" 85% + * > aplay xxx.wav + * + * Capture (CN9501) + * > amixer set "MUX" "Capture" // for GP0_01 + * > amixer set "Mic 1" 80% + * > amixer set "ADC 1" on + * > amixer set 'ADC 1' 80% + * > arecord xxx hoge.wav + */ /dts-v1/; #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> #include "r8a779h0.dtsi" @@ -26,11 +47,74 @@ ethernet0 = &avb0; }; + can_transceiver0: can-phy0 { + compatible = "nxp,tjr1443"; + #phy-cells = <0>; + enable-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + max-bitrate = <5000000>; + }; + chosen { bootargs = "ignore_loglevel rw root=/dev/nfs ip=on"; stdout-path = "serial0:921600n8"; }; + keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&keys_pins>; + pinctrl-names = "default"; + + key-1 { + gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; + linux,code = <KEY_1>; + label = "SW47"; + wakeup-source; + debounce-interval = <20>; + }; + + key-2 { + gpios = <&gpio5 1 GPIO_ACTIVE_LOW>; + linux,code = <KEY_2>; + label = "SW48"; + wakeup-source; + debounce-interval = <20>; + }; + + key-3 { + gpios = <&gpio5 2 GPIO_ACTIVE_LOW>; + linux,code = <KEY_3>; + label = "SW49"; + wakeup-source; + debounce-interval = <20>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-1 { + gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <1>; + }; + + led-2 { + gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <2>; + }; + + led-3 { + gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_INDICATOR; + function-enumerator = <3>; + }; + }; + memory@48000000 { device_type = "memory"; /* first 128MB is reserved for secure area. */ @@ -59,6 +143,24 @@ regulator-boot-on; regulator-always-on; }; + + sound_mux: sound-mux { + compatible = "simple-audio-mux"; + mux-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; + state-labels = "Playback", "Capture"; + }; + + sound_card: sound { + compatible = "audio-graph-card2"; + label = "rcar-sound"; + aux-devs = <&sound_mux>; // for GP0_01 + + links = <&rsnd_port>; // AK4619 Audio Codec + }; +}; + +&audio_clkin { + clock-frequency = <24576000>; }; &avb0 { @@ -79,6 +181,25 @@ }; }; +&can_clk { + clock-frequency = <40000000>; +}; + +&canfd { + pinctrl-0 = <&canfd0_pins>, <&canfd1_pins>, <&can_clk_pins>; + pinctrl-names = "default"; + status = "okay"; + + channel0 { + status = "okay"; + phys = <&can_transceiver0>; + }; + + channel1 { + status = "okay"; + }; +}; + &extal_clk { clock-frequency = <16666666>; }; @@ -87,6 +208,15 @@ clock-frequency = <32768>; }; +&gpio1 { + audio-power-hog { + gpio-hog; + gpios = <8 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "Audio-Power"; + }; +}; + &hscif0 { pinctrl-0 = <&hscif0_pins>; pinctrl-names = "default"; @@ -139,6 +269,29 @@ }; }; +&i2c3 { + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "default"; + + status = "okay"; + clock-frequency = <400000>; + + codec@10 { + compatible = "asahi-kasei,ak4619"; + reg = <0x10>; + + clocks = <&rcar_sound>; + clock-names = "mclk"; + + #sound-dai-cells = <0>; + port { + ak4619_endpoint: endpoint { + remote-endpoint = <&rsnd_endpoint>; + }; + }; + }; +}; + &mmc0 { pinctrl-0 = <&mmc_pins>; pinctrl-1 = <&mmc_pins>; @@ -178,6 +331,21 @@ }; }; + can_clk_pins: can-clk { + groups = "can_clk"; + function = "can_clk"; + }; + + canfd0_pins: canfd0 { + groups = "canfd0_data"; + function = "canfd0"; + }; + + canfd1_pins: canfd1 { + groups = "canfd1_data"; + function = "canfd1"; + }; + hscif0_pins: hscif0 { groups = "hscif0_data", "hscif0_ctrl"; function = "hscif0"; @@ -193,6 +361,16 @@ function = "i2c0"; }; + i2c3_pins: i2c3 { + groups = "i2c3"; + function = "i2c3"; + }; + + keys_pins: keys { + pins = "GP_5_0", "GP_5_1", "GP_5_2"; + bias-pull-up; + }; + mmc_pins: mmc { groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; function = "mmc"; @@ -213,6 +391,40 @@ groups = "scif_clk2"; function = "scif_clk2"; }; + + sound_clk_pins: sound_clk { + groups = "audio_clkin", "audio_clkout"; + function = "audio_clk"; + }; + + sound_pins: sound { + groups = "ssi_ctrl", "ssi_data"; + function = "ssi"; + }; +}; + +&rcar_sound { + pinctrl-0 = <&sound_clk_pins>, <&sound_pins>; + pinctrl-names = "default"; + + status = "okay"; + + /* audio_clkout */ + clock-frequency = <12288000>; + + ports { + rsnd_port: port { + rsnd_endpoint: endpoint { + remote-endpoint = <&ak4619_endpoint>; + bitclock-master; + frame-master; + + /* see above [How to use Sound] */ + playback = <&ssi0>; + capture = <&ssi0>; + }; + }; + }; }; &rpc { diff --git a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi index a03ab2b6a859..12d8be3fd579 100644 --- a/arch/arm64/boot/dts/renesas/r8a779h0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779h0.dtsi @@ -21,6 +21,13 @@ clock-frequency = <0>; }; + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + cluster0_opp: opp-table-0 { compatible = "operating-points-v2"; @@ -636,6 +643,40 @@ status = "disabled"; }; + canfd: can@e6660000 { + compatible = "renesas,r8a779h0-canfd", + "renesas,rcar-gen4-canfd"; + reg = <0 0xe6660000 0 0x8500>; + interrupts = <GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ch_int", "g_int"; + clocks = <&cpg CPG_MOD 328>, + <&cpg CPG_CORE R8A779H0_CLK_CANFD>, + <&can_clk>; + clock-names = "fck", "canfd", "can_clk"; + assigned-clocks = <&cpg CPG_CORE R8A779H0_CLK_CANFD>; + assigned-clock-rates = <80000000>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 328>; + status = "disabled"; + + channel0 { + status = "disabled"; + }; + + channel1 { + status = "disabled"; + }; + + channel2 { + status = "disabled"; + }; + + channel3 { + status = "disabled"; + }; + }; + avb0: ethernet@e6800000 { compatible = "renesas,etheravb-r8a779h0", "renesas,etheravb-rcar-gen4"; @@ -728,6 +769,7 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_hc 1>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -776,11 +818,62 @@ phy-mode = "rgmii"; rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; + iommus = <&ipmmu_hc 2>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; + pwm0: pwm@e6e30000 { + compatible = "renesas,pwm-r8a779h0", "renesas,pwm-rcar"; + reg = <0 0xe6e30000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a779h0", "renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a779h0", "renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a779h0", "renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a779h0", "renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x10>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A779H0_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + scif0: serial@e6e60000 { compatible = "renesas,scif-r8a779h0", "renesas,rcar-gen4-scif", "renesas,scif"; @@ -946,7 +1039,8 @@ }; vin00: video@e6ef0000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef0000 0 0x1000>; interrupts = <GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 730>; @@ -974,7 +1068,8 @@ }; vin01: video@e6ef1000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef1000 0 0x1000>; interrupts = <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 731>; @@ -1002,7 +1097,8 @@ }; vin02: video@e6ef2000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef2000 0 0x1000>; interrupts = <GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 800>; @@ -1030,7 +1126,8 @@ }; vin03: video@e6ef3000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef3000 0 0x1000>; interrupts = <GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 801>; @@ -1058,7 +1155,8 @@ }; vin04: video@e6ef4000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef4000 0 0x1000>; interrupts = <GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 802>; @@ -1086,7 +1184,8 @@ }; vin05: video@e6ef5000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef5000 0 0x1000>; interrupts = <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 803>; @@ -1114,7 +1213,8 @@ }; vin06: video@e6ef6000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef6000 0 0x1000>; interrupts = <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 804>; @@ -1142,7 +1242,8 @@ }; vin07: video@e6ef7000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef7000 0 0x1000>; interrupts = <GIC_SPI 536 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 805>; @@ -1170,7 +1271,8 @@ }; vin08: video@e6ef8000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef8000 0 0x1000>; interrupts = <GIC_SPI 537 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 806>; @@ -1198,7 +1300,8 @@ }; vin09: video@e6ef9000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6ef9000 0 0x1000>; interrupts = <GIC_SPI 538 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 807>; @@ -1226,7 +1329,8 @@ }; vin10: video@e6efa000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efa000 0 0x1000>; interrupts = <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 808>; @@ -1254,7 +1358,8 @@ }; vin11: video@e6efb000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efb000 0 0x1000>; interrupts = <GIC_SPI 540 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 809>; @@ -1282,7 +1387,8 @@ }; vin12: video@e6efc000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efc000 0 0x1000>; interrupts = <GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 810>; @@ -1310,7 +1416,8 @@ }; vin13: video@e6efd000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efd000 0 0x1000>; interrupts = <GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 811>; @@ -1338,7 +1445,8 @@ }; vin14: video@e6efe000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6efe000 0 0x1000>; interrupts = <GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 812>; @@ -1366,7 +1474,8 @@ }; vin15: video@e6eff000 { - compatible = "renesas,vin-r8a779h0"; + compatible = "renesas,vin-r8a779h0", + "renesas,rcar-gen4-vin"; reg = <0 0xe6eff000 0 0x1000>; interrupts = <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 813>; @@ -1720,7 +1829,8 @@ }; isp0: isp@fed00000 { - compatible = "renesas,r8a779h0-isp"; + compatible = "renesas,r8a779h0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed00000 0 0x10000>; interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_LOW>; clocks = <&cpg CPG_MOD 612>; @@ -1803,7 +1913,8 @@ }; isp1: isp@fed20000 { - compatible = "renesas,r8a779h0-isp"; + compatible = "renesas,r8a779h0-isp", + "renesas,rcar-gen4-isp"; reg = <0 0xfed20000 0 0x10000>; interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_LOW>; clocks = <&cpg CPG_MOD 613>; diff --git a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi index 2eccab9c8962..593c66b27ad1 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi @@ -725,6 +725,10 @@ power-domains = <&cpg>; #reset-cells = <1>; status = "disabled"; + + usb0_vbus_otg: regulator-vbus { + regulator-name = "vbus"; + }; }; ohci0: usb@11c50000 { diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi index 18ef297db933..a3998e5928f7 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi @@ -129,6 +129,55 @@ }; }; + vspd: vsp@10870000 { + compatible = "renesas,r9a07g043u-vsp2", "renesas,r9a07g044-vsp2"; + reg = <0 0x10870000 0 0x10000>; + interrupts = <SOC_PERIPHERAL_IRQ(149) IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G043_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_LCDC_RESET_N>; + renesas,fcp = <&fcpvd>; + }; + + fcpvd: fcp@10880000 { + compatible = "renesas,r9a07g043u-fcpvd", "renesas,fcpv"; + reg = <0 0x10880000 0 0x10000>; + clocks = <&cpg CPG_MOD R9A07G043_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_LCDC_RESET_N>; + }; + + du: display@10890000 { + compatible = "renesas,r9a07g043u-du"; + reg = <0 0x10890000 0 0x10000>; + interrupts = <SOC_PERIPHERAL_IRQ(152) IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD R9A07G043_LCDC_CLK_A>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_P>, + <&cpg CPG_MOD R9A07G043_LCDC_CLK_D>; + clock-names = "aclk", "pclk", "vclk"; + power-domains = <&cpg>; + resets = <&cpg R9A07G043_LCDC_RESET_N>; + renesas,vsps = <&vspd 0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + du_out_rgb: endpoint { + }; + }; + }; + }; + irqc: interrupt-controller@110a0000 { compatible = "renesas,r9a07g043u-irqc", "renesas,rzg2l-irqc"; @@ -210,8 +259,8 @@ #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; - reg = <0x0 0x11900000 0 0x40000>, - <0x0 0x11940000 0 0x60000>; + reg = <0x0 0x11900000 0 0x20000>, + <0x0 0x11940000 0 0x40000>; interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; }; }; diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc-du-adv7513.dtso b/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc-du-adv7513.dtso new file mode 100644 index 000000000000..ecd43a671000 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc-du-adv7513.dtso @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree overlay for the RZ/G2UL SMARC EVK with ADV7513 transmitter + * connected to DU enabled. + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +/dts-v1/; +/plugin/; + +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> + +#define ADV7513_PARENT_I2C i2c1 +#include "rz-smarc-du-adv7513.dtsi" + +&pinctrl { + du_pins: du { + data { + pinmux = <RZG2L_PORT_PINMUX(11, 2, 6)>, + <RZG2L_PORT_PINMUX(13, 1, 6)>, + <RZG2L_PORT_PINMUX(13, 0, 6)>, + <RZG2L_PORT_PINMUX(13, 4, 6)>, + <RZG2L_PORT_PINMUX(13, 3, 6)>, + <RZG2L_PORT_PINMUX(12, 1, 6)>, + <RZG2L_PORT_PINMUX(13, 2, 6)>, + <RZG2L_PORT_PINMUX(14, 0, 6)>, + <RZG2L_PORT_PINMUX(14, 2, 6)>, + <RZG2L_PORT_PINMUX(14, 1, 6)>, + <RZG2L_PORT_PINMUX(16, 0, 6)>, + <RZG2L_PORT_PINMUX(15, 0, 6)>, + <RZG2L_PORT_PINMUX(16, 1, 6)>, + <RZG2L_PORT_PINMUX(15, 1, 6)>, + <RZG2L_PORT_PINMUX(15, 3, 6)>, + <RZG2L_PORT_PINMUX(18, 0, 6)>, + <RZG2L_PORT_PINMUX(15, 2, 6)>, + <RZG2L_PORT_PINMUX(17, 0, 6)>, + <RZG2L_PORT_PINMUX(17, 2, 6)>, + <RZG2L_PORT_PINMUX(17, 1, 6)>, + <RZG2L_PORT_PINMUX(18, 1, 6)>, + <RZG2L_PORT_PINMUX(18, 2, 6)>, + <RZG2L_PORT_PINMUX(17, 3, 6)>, + <RZG2L_PORT_PINMUX(18, 3, 6)>; + drive-strength = <2>; + }; + + sync { + pinmux = <RZG2L_PORT_PINMUX(11, 0, 6)>, /* HSYNC */ + <RZG2L_PORT_PINMUX(12, 0, 6)>; /* VSYNC */ + drive-strength = <2>; + }; + + de { + pinmux = <RZG2L_PORT_PINMUX(11, 1, 6)>; /* DE */ + drive-strength = <2>; + }; + + clk { + pinmux = <RZG2L_PORT_PINMUX(11, 3, 6)>; /* CLK */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi index d3838e5820fc..6b1c77cd8261 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi @@ -1043,8 +1043,8 @@ #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; - reg = <0x0 0x11900000 0 0x40000>, - <0x0 0x11940000 0 0x60000>; + reg = <0x0 0x11900000 0 0x20000>, + <0x0 0x11940000 0 0x40000>; interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; }; @@ -1129,6 +1129,10 @@ power-domains = <&cpg>; #reset-cells = <1>; status = "disabled"; + + usb0_vbus_otg: regulator-vbus { + regulator-name = "vbus"; + }; }; ohci0: usb@11c50000 { diff --git a/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts index 0b90367b6d1e..ee5bf2c58051 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts +++ b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts @@ -47,6 +47,9 @@ #error "Cannot set as both PMOD_MTU3 and SW_RSPI_CAN are mutually exclusive" #endif +/* Please set SW_I2S0_I2S1. Default value is 0 */ +#define SW_I2S0_I2S1 0 + #include "r9a07g044c2.dtsi" #include "rzg2lc-smarc-som.dtsi" #include "rzg2lc-smarc.dtsi" diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi index 1de2e5f0917d..01f59914dd09 100644 --- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi @@ -1051,8 +1051,8 @@ #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; - reg = <0x0 0x11900000 0 0x40000>, - <0x0 0x11940000 0 0x60000>; + reg = <0x0 0x11900000 0 0x20000>, + <0x0 0x11940000 0 0x40000>; interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; }; @@ -1137,6 +1137,10 @@ power-domains = <&cpg>; #reset-cells = <1>; status = "disabled"; + + usb0_vbus_otg: regulator-vbus { + regulator-name = "vbus"; + }; }; ohci0: usb@11c50000 { diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi index 0d5c47a65e46..067a26a66c24 100644 --- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi @@ -72,6 +72,94 @@ status = "disabled"; }; + i2c0: i2c@10090000 { + compatible = "renesas,riic-r9a08g045", "renesas,riic-r9a09g057"; + reg = <0 0x10090000 0 0x400>; + interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 263 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 264 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A08G045_I2C0_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A08G045_I2C0_MRST>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@10090400 { + compatible = "renesas,riic-r9a08g045", "renesas,riic-r9a09g057"; + reg = <0 0x10090400 0 0x400>; + interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 271 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 272 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A08G045_I2C1_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A08G045_I2C1_MRST>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@10090800 { + compatible = "renesas,riic-r9a08g045", "renesas,riic-r9a09g057"; + reg = <0 0x10090800 0 0x400>; + interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 279 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 280 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A08G045_I2C2_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A08G045_I2C2_MRST>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@10090c00 { + compatible = "renesas,riic-r9a08g045", "renesas,riic-r9a09g057"; + reg = <0 0x10090c00 0 0x400>; + interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 287 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 288 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD R9A08G045_I2C3_PCLK>; + clock-frequency = <100000>; + resets = <&cpg R9A08G045_I2C3_MRST>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + cpg: clock-controller@11010000 { compatible = "renesas,r9a08g045-cpg"; reg = <0 0x11010000 0 0x10000>; @@ -181,6 +269,44 @@ resets = <&cpg R9A08G045_IA55_RESETN>; }; + dmac: dma-controller@11820000 { + compatible = "renesas,r9a08g045-dmac", + "renesas,rz-dmac"; + reg = <0 0x11820000 0 0x10000>, + <0 0x11830000 0 0x10000>; + interrupts = <GIC_SPI 111 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 112 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 113 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 114 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 115 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 119 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 121 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 122 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 123 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 124 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD R9A08G045_DMAC_ACLK>, + <&cpg CPG_MOD R9A08G045_DMAC_PCLK>; + clock-names = "main", "register"; + power-domains = <&cpg>; + resets = <&cpg R9A08G045_DMAC_ARESETN>, + <&cpg R9A08G045_DMAC_RST_ASYNC>; + reset-names = "arst", "rst_async"; + #dma-cells = <1>; + dma-channels = <16>; + }; + sdhi0: mmc@11c00000 { compatible = "renesas,sdhi-r9a08g045", "renesas,rzg2l-sdhi"; reg = <0x0 0x11c00000 0 0x10000>; @@ -269,8 +395,8 @@ #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; - reg = <0x0 0x12400000 0 0x40000>, - <0x0 0x12440000 0 0x60000>; + reg = <0x0 0x12400000 0 0x20000>, + <0x0 0x12440000 0 0x40000>; interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; }; diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi new file mode 100644 index 000000000000..abcdef3ba5bc --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi @@ -0,0 +1,603 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/V2H(P) SoC + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +#include <dt-bindings/clock/renesas,r9a09g057-cpg.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "renesas,r9a09g057"; + #address-cells = <2>; + #size-cells = <2>; + + audio_extal_clk: audio-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a55"; + reg = <0>; + device_type = "cpu"; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + }; + + cpu1: cpu@100 { + compatible = "arm,cortex-a55"; + reg = <0x100>; + device_type = "cpu"; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + }; + + cpu2: cpu@200 { + compatible = "arm,cortex-a55"; + reg = <0x200>; + device_type = "cpu"; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + }; + + cpu3: cpu@300 { + compatible = "arm,cortex-a55"; + reg = <0x300>; + device_type = "cpu"; + next-level-cache = <&L3_CA55>; + enable-method = "psci"; + }; + + L3_CA55: cache-controller-0 { + compatible = "cache"; + cache-unified; + cache-size = <0x100000>; + cache-level = <3>; + }; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + qextal_clk: qextal-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + rtxin_clk: rtxin-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + soc: soc { + compatible = "simple-bus"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + icu: interrupt-controller@10400000 { + compatible = "renesas,r9a09g057-icu"; + reg = <0 0x10400000 0 0x10000>; + #interrupt-cells = <2>; + #address-cells = <0>; + interrupt-controller; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 436 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 437 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 263 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 264 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 265 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "nmi", + "port_irq0", "port_irq1", "port_irq2", + "port_irq3", "port_irq4", "port_irq5", + "port_irq6", "port_irq7", "port_irq8", + "port_irq9", "port_irq10", "port_irq11", + "port_irq12", "port_irq13", "port_irq14", + "port_irq15", + "tint0", "tint1", "tint2", "tint3", + "tint4", "tint5", "tint6", "tint7", + "tint8", "tint9", "tint10", "tint11", + "tint12", "tint13", "tint14", "tint15", + "tint16", "tint17", "tint18", "tint19", + "tint20", "tint21", "tint22", "tint23", + "tint24", "tint25", "tint26", "tint27", + "tint28", "tint29", "tint30", "tint31", + "int-ca55-0", "int-ca55-1", + "int-ca55-2", "int-ca55-3", + "icu-error-ca55", + "gpt-u0-gtciada", "gpt-u0-gtciadb", + "gpt-u1-gtciada", "gpt-u1-gtciadb"; + clocks = <&cpg CPG_MOD 0x5>; + power-domains = <&cpg>; + resets = <&cpg 0x36>; + }; + + pinctrl: pinctrl@10410000 { + compatible = "renesas,r9a09g057-pinctrl"; + reg = <0 0x10410000 0 0x10000>; + clocks = <&cpg CPG_CORE R9A09G057_IOTOP_0_SHCLK>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl 0 0 96>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&icu>; + power-domains = <&cpg>; + resets = <&cpg 0xa5>, <&cpg 0xa6>; + }; + + cpg: clock-controller@10420000 { + compatible = "renesas,r9a09g057-cpg"; + reg = <0 0x10420000 0 0x10000>; + clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>; + clock-names = "audio_extal", "rtxin", "qextal"; + #clock-cells = <2>; + #reset-cells = <1>; + #power-domain-cells = <0>; + }; + + sys: system-controller@10430000 { + compatible = "renesas,r9a09g057-sys"; + reg = <0 0x10430000 0 0x10000>; + clocks = <&cpg CPG_CORE R9A09G057_SYS_0_PCLK>; + resets = <&cpg 0x30>; + status = "disabled"; + }; + + ostm0: timer@11800000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x11800000 0x0 0x1000>; + interrupts = <GIC_SPI 17 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x43>; + resets = <&cpg 0x6d>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm1: timer@11801000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x11801000 0x0 0x1000>; + interrupts = <GIC_SPI 18 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x44>; + resets = <&cpg 0x6e>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm2: timer@14000000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x14000000 0x0 0x1000>; + interrupts = <GIC_SPI 19 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x45>; + resets = <&cpg 0x6f>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm3: timer@14001000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x14001000 0x0 0x1000>; + interrupts = <GIC_SPI 20 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x46>; + resets = <&cpg 0x70>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm4: timer@12c00000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x12c00000 0x0 0x1000>; + interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x47>; + resets = <&cpg 0x71>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm5: timer@12c01000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x12c01000 0x0 0x1000>; + interrupts = <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x48>; + resets = <&cpg 0x72>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm6: timer@12c02000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x12c02000 0x0 0x1000>; + interrupts = <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x49>; + resets = <&cpg 0x73>; + power-domains = <&cpg>; + status = "disabled"; + }; + + ostm7: timer@12c03000 { + compatible = "renesas,r9a09g057-ostm", "renesas,ostm"; + reg = <0x0 0x12c03000 0x0 0x1000>; + interrupts = <GIC_SPI 24 IRQ_TYPE_EDGE_RISING>; + clocks = <&cpg CPG_MOD 0x4a>; + resets = <&cpg 0x74>; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt0: watchdog@11c00400 { + compatible = "renesas,r9a09g057-wdt"; + reg = <0 0x11c00400 0 0x400>; + clocks = <&cpg CPG_MOD 0x4b>, <&cpg CPG_MOD 0x4c>; + clock-names = "pclk", "oscclk"; + resets = <&cpg 0x75>; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt1: watchdog@14400000 { + compatible = "renesas,r9a09g057-wdt"; + reg = <0 0x14400000 0 0x400>; + clocks = <&cpg CPG_MOD 0x4d>, <&cpg CPG_MOD 0x4e>; + clock-names = "pclk", "oscclk"; + resets = <&cpg 0x76>; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt2: watchdog@13000000 { + compatible = "renesas,r9a09g057-wdt"; + reg = <0 0x13000000 0 0x400>; + clocks = <&cpg CPG_MOD 0x4f>, <&cpg CPG_MOD 0x50>; + clock-names = "pclk", "oscclk"; + resets = <&cpg 0x77>; + power-domains = <&cpg>; + status = "disabled"; + }; + + wdt3: watchdog@13000400 { + compatible = "renesas,r9a09g057-wdt"; + reg = <0 0x13000400 0 0x400>; + clocks = <&cpg CPG_MOD 0x51>, <&cpg CPG_MOD 0x52>; + clock-names = "pclk", "oscclk"; + resets = <&cpg 0x78>; + power-domains = <&cpg>; + status = "disabled"; + }; + + scif: serial@11c01400 { + compatible = "renesas,scif-r9a09g057"; + reg = <0 0x11c01400 0 0x400>; + interrupts = <GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 536 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 537 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "eri", "rxi", "txi", "bri", "dri", + "tei", "tei-dri", "rxi-edge", "txi-edge"; + clocks = <&cpg CPG_MOD 0x8f>; + clock-names = "fck"; + power-domains = <&cpg>; + resets = <&cpg 0x95>; + status = "disabled"; + }; + + i2c0: i2c@14400400 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14400400 0 0x400>; + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 507 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 506 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x94>; + resets = <&cpg 0x98>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@14400800 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14400800 0 0x400>; + interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 509 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 508 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x95>; + resets = <&cpg 0x99>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@14400c00 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14400c00 0 0x400>; + interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 511 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 510 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x96>; + resets = <&cpg 0x9a>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@14401000 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14401000 0 0x400>; + interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 513 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 512 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x97>; + resets = <&cpg 0x9b>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@14401400 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14401400 0 0x400>; + interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 515 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 514 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x98>; + resets = <&cpg 0x9c>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@14401800 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14401800 0 0x400>; + interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 517 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 516 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x99>; + resets = <&cpg 0x9d>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c6: i2c@14401c00 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14401c00 0 0x400>; + interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 519 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 518 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x9a>; + resets = <&cpg 0x9e>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c7: i2c@14402000 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x14402000 0 0x400>; + interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 521 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 520 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x9b>; + resets = <&cpg 0x9f>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c8: i2c@11c01000 { + compatible = "renesas,riic-r9a09g057"; + reg = <0 0x11c01000 0 0x400>; + interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 523 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 522 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tei", "ri", "ti", "spi", "sti", + "naki", "ali", "tmoi"; + clocks = <&cpg CPG_MOD 0x93>; + resets = <&cpg 0xa0>; + power-domains = <&cpg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + gic: interrupt-controller@14900000 { + compatible = "arm,gic-v3"; + reg = <0x0 0x14900000 0 0x20000>, + <0x0 0x14940000 0 0x80000>; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>; + }; + + sdhi0: mmc@15c00000 { + compatible = "renesas,sdhi-r9a09g057"; + reg = <0x0 0x15c00000 0 0x10000>; + interrupts = <GIC_SPI 735 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 736 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 0xa3>, <&cpg CPG_MOD 0xa5>, + <&cpg CPG_MOD 0xa4>, <&cpg CPG_MOD 0xa6>; + clock-names = "core", "clkh", "cd", "aclk"; + resets = <&cpg 0xa7>; + power-domains = <&cpg>; + status = "disabled"; + }; + + sdhi1: mmc@15c10000 { + compatible = "renesas,sdhi-r9a09g057"; + reg = <0x0 0x15c10000 0 0x10000>; + interrupts = <GIC_SPI 737 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 738 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 0xa7>, <&cpg CPG_MOD 0xa9>, + <&cpg CPG_MOD 0xa8>, <&cpg CPG_MOD 0xaa>; + clock-names = "core", "clkh", "cd", "aclk"; + resets = <&cpg 0xa8>; + power-domains = <&cpg>; + status = "disabled"; + }; + + sdhi2: mmc@15c20000 { + compatible = "renesas,sdhi-r9a09g057"; + reg = <0x0 0x15c20000 0 0x10000>; + interrupts = <GIC_SPI 739 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 740 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 0xab>, <&cpg CPG_MOD 0xad>, + <&cpg CPG_MOD 0xac>, <&cpg CPG_MOD 0xae>; + clock-names = "core", "clkh", "cd", "aclk"; + resets = <&cpg 0xa9>; + power-domains = <&cpg>; + status = "disabled"; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>, + <&gic GIC_PPI 12 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "sec-phys", "phys", "virt", "hyp-phys", "hyp-virt"; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts b/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts new file mode 100644 index 000000000000..4703da8e9cff --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Device Tree Source for the RZ/V2H EVK board + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +/dts-v1/; + +#include <dt-bindings/pinctrl/rzg2l-pinctrl.h> +#include <dt-bindings/gpio/gpio.h> +#include "r9a09g057.dtsi" + +/ { + model = "Renesas RZ/V2H EVK Board based on r9a09g057h44"; + compatible = "renesas,rzv2h-evk", "renesas,r9a09g057h44", "renesas,r9a09g057"; + + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c6 = &i2c6; + i2c7 = &i2c7; + i2c8 = &i2c8; + mmc1 = &sdhi1; + serial0 = &scif; + }; + + chosen { + bootargs = "ignore_loglevel"; + stdout-path = "serial0:115200n8"; + }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x1 0xF8000000>; + }; + + memory@240000000 { + device_type = "memory"; + reg = <0x2 0x40000000 0x2 0x00000000>; + }; + + reg_3p3v: regulator1 { + compatible = "regulator-fixed"; + + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + vqmmc_sdhi1: regulator-vccq-sdhi1 { + compatible = "regulator-gpio"; + regulator-name = "SDHI1 VccQ"; + gpios = <&pinctrl RZG2L_GPIO(10, 2) GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + gpios-states = <0>; + states = <3300000 0>, <1800000 1>; + }; +}; + +&audio_extal_clk { + clock-frequency = <22579200>; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c3 { + pinctrl-0 = <&i2c3_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c6 { + pinctrl-0 = <&i2c6_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c7 { + pinctrl-0 = <&i2c7_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&i2c8 { + pinctrl-0 = <&i2c8_pins>; + pinctrl-names = "default"; + clock-frequency = <400000>; + + status = "okay"; +}; + +&ostm0 { + status = "okay"; +}; + +&ostm1 { + status = "okay"; +}; + +&ostm2 { + status = "okay"; +}; + +&ostm3 { + status = "okay"; +}; + +&ostm4 { + status = "okay"; +}; + +&ostm5 { + status = "okay"; +}; + +&ostm6 { + status = "okay"; +}; + +&ostm7 { + status = "okay"; +}; + +&pinctrl { + i2c0_pins: i2c0 { + pinmux = <RZG2L_PORT_PINMUX(3, 0, 1)>, /* I2C0_SDA */ + <RZG2L_PORT_PINMUX(3, 1, 1)>; /* I2C0_SCL */ + }; + + i2c1_pins: i2c1 { + pinmux = <RZG2L_PORT_PINMUX(3, 2, 1)>, /* I2C1_SDA */ + <RZG2L_PORT_PINMUX(3, 3, 1)>; /* I2C1_SCL */ + }; + + i2c2_pins: i2c2 { + pinmux = <RZG2L_PORT_PINMUX(2, 0, 4)>, /* I2C2_SDA */ + <RZG2L_PORT_PINMUX(2, 1, 4)>; /* I2C2_SCL */ + }; + + i2c3_pins: i2c3 { + pinmux = <RZG2L_PORT_PINMUX(3, 6, 1)>, /* I2C3_SDA */ + <RZG2L_PORT_PINMUX(3, 7, 1)>; /* I2C3_SCL */ + }; + + i2c6_pins: i2c6 { + pinmux = <RZG2L_PORT_PINMUX(4, 4, 1)>, /* I2C6_SDA */ + <RZG2L_PORT_PINMUX(4, 5, 1)>; /* I2C6_SCL */ + }; + + i2c7_pins: i2c7 { + pinmux = <RZG2L_PORT_PINMUX(4, 6, 1)>, /* I2C7_SDA */ + <RZG2L_PORT_PINMUX(4, 7, 1)>; /* I2C7_SCL */ + }; + + i2c8_pins: i2c8 { + pinmux = <RZG2L_PORT_PINMUX(0, 6, 1)>, /* I2C8_SDA */ + <RZG2L_PORT_PINMUX(0, 7, 1)>; /* I2C8_SCL */ + }; + + scif_pins: scif { + pins = "SCIF_TXD", "SCIF_RXD"; + renesas,output-impedance = <1>; + }; + + sd1-pwr-en-hog { + gpio-hog; + gpios = <RZG2L_GPIO(10, 3) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "sd1_pwr_en"; + }; + + sdhi1_pins: sd1 { + sd1_dat_cmd { + pins = "SD1DAT0", "SD1DAT1", "SD1DAT2", "SD1DAT3", "SD1CMD"; + input-enable; + renesas,output-impedance = <3>; + slew-rate = <0>; + }; + + sd1_clk { + pins = "SD1CLK"; + renesas,output-impedance = <3>; + slew-rate = <0>; + }; + + sd1_cd { + pinmux = <RZG2L_PORT_PINMUX(9, 4, 14)>; /* SD1_CD */ + }; + }; +}; + +&qextal_clk { + clock-frequency = <24000000>; +}; + +&rtxin_clk { + clock-frequency = <32768>; +}; + +&scif { + pinctrl-0 = <&scif_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&sdhi1 { + pinctrl-0 = <&sdhi1_pins>; + pinctrl-1 = <&sdhi1_pins>; + pinctrl-names = "default", "state_uhs"; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <&vqmmc_sdhi1>; + bus-width = <4>; + sd-uhs-sdr50; + sd-uhs-sdr104; + status = "okay"; +}; + +&wdt1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi index b34855956ae0..63fa5cf1061b 100644 --- a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi +++ b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi @@ -131,9 +131,6 @@ &phyrst { status = "okay"; - usb0_vbus_otg: regulator-vbus { - regulator-name = "vbus"; - }; }; &scif0 { diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-du-adv7513.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-du-adv7513.dtsi new file mode 100644 index 000000000000..36707576030d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/rz-smarc-du-adv7513.dtsi @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Common Device Tree for the RZ/G2UL SMARC EVK (and alike EVKs) with + * ADV7513 transmitter connected to DU enabled. + * + * Copyright (C) 2024 Renesas Electronics Corp. + */ + +&{/} { + hdmi-out { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_out: endpoint { + remote-endpoint = <&adv7513_out>; + }; + }; + }; +}; + +&du { + pinctrl-0 = <&du_pins>; + pinctrl-names = "default"; + + status = "okay"; + + ports { + port@0 { + du_out_rgb: endpoint { + remote-endpoint = <&adv7513_in>; + }; + }; + }; +}; + +&ADV7513_PARENT_I2C { + #address-cells = <1>; + #size-cells = <0>; + + adv7513: adv7513@39 { + compatible = "adi,adv7513"; + reg = <0x39>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + + avdd-supply = <®_1p8v>; + dvdd-supply = <®_1p8v>; + pvdd-supply = <®_1p8v>; + dvdd-3v-supply = <®_3p3v>; + bgvdd-supply = <®_1p8v>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + adv7513_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + + adv7513_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc-pinfunction.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc-pinfunction.dtsi index 18c526c7a4cf..e9f244c33d55 100644 --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc-pinfunction.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc-pinfunction.dtsi @@ -143,6 +143,12 @@ <RZG2L_PORT_PINMUX(45, 3, 1)>; /* RXD */ }; + ssi1_pins: ssi1 { + pinmux = <RZG2L_PORT_PINMUX(46, 0, 1)>, /* BCK */ + <RZG2L_PORT_PINMUX(46, 1, 1)>, /* RCK */ + <RZG2L_PORT_PINMUX(46, 2, 1)>; /* TXD */ + }; + usb0_pins: usb0 { pinmux = <RZG2L_PORT_PINMUX(4, 0, 1)>, /* VBUS */ <RZG2L_PORT_PINMUX(5, 0, 1)>, /* OVC */ diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi index 4409c47239b9..83f5642d0d35 100644 --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi @@ -180,41 +180,63 @@ }; eth0_pins: eth0 { - pinmux = <RZG2L_PORT_PINMUX(28, 1, 1)>, /* ET0_LINKSTA */ - <RZG2L_PORT_PINMUX(27, 1, 1)>, /* ET0_MDC */ - <RZG2L_PORT_PINMUX(28, 0, 1)>, /* ET0_MDIO */ - <RZG2L_PORT_PINMUX(20, 0, 1)>, /* ET0_TXC */ - <RZG2L_PORT_PINMUX(20, 1, 1)>, /* ET0_TX_CTL */ - <RZG2L_PORT_PINMUX(20, 2, 1)>, /* ET0_TXD0 */ - <RZG2L_PORT_PINMUX(21, 0, 1)>, /* ET0_TXD1 */ - <RZG2L_PORT_PINMUX(21, 1, 1)>, /* ET0_TXD2 */ - <RZG2L_PORT_PINMUX(22, 0, 1)>, /* ET0_TXD3 */ - <RZG2L_PORT_PINMUX(24, 0, 1)>, /* ET0_RXC */ - <RZG2L_PORT_PINMUX(24, 1, 1)>, /* ET0_RX_CTL */ - <RZG2L_PORT_PINMUX(25, 0, 1)>, /* ET0_RXD0 */ - <RZG2L_PORT_PINMUX(25, 1, 1)>, /* ET0_RXD1 */ - <RZG2L_PORT_PINMUX(26, 0, 1)>, /* ET0_RXD2 */ - <RZG2L_PORT_PINMUX(26, 1, 1)>, /* ET0_RXD3 */ - <RZG2L_PORT_PINMUX(1, 0, 1)>; /* IRQ2 */ + txc { + pinmux = <RZG2L_PORT_PINMUX(20, 0, 1)>; /* ET0_TXC */ + power-source = <1800>; + output-enable; + }; + + mux { + pinmux = <RZG2L_PORT_PINMUX(28, 1, 1)>, /* ET0_LINKSTA */ + <RZG2L_PORT_PINMUX(27, 1, 1)>, /* ET0_MDC */ + <RZG2L_PORT_PINMUX(28, 0, 1)>, /* ET0_MDIO */ + <RZG2L_PORT_PINMUX(20, 1, 1)>, /* ET0_TX_CTL */ + <RZG2L_PORT_PINMUX(20, 2, 1)>, /* ET0_TXD0 */ + <RZG2L_PORT_PINMUX(21, 0, 1)>, /* ET0_TXD1 */ + <RZG2L_PORT_PINMUX(21, 1, 1)>, /* ET0_TXD2 */ + <RZG2L_PORT_PINMUX(22, 0, 1)>, /* ET0_TXD3 */ + <RZG2L_PORT_PINMUX(24, 0, 1)>, /* ET0_RXC */ + <RZG2L_PORT_PINMUX(24, 1, 1)>, /* ET0_RX_CTL */ + <RZG2L_PORT_PINMUX(25, 0, 1)>, /* ET0_RXD0 */ + <RZG2L_PORT_PINMUX(25, 1, 1)>, /* ET0_RXD1 */ + <RZG2L_PORT_PINMUX(26, 0, 1)>, /* ET0_RXD2 */ + <RZG2L_PORT_PINMUX(26, 1, 1)>; /* ET0_RXD3 */ + power-source = <1800>; + }; + + irq { + pinmux = <RZG2L_PORT_PINMUX(1, 0, 1)>; /* IRQ2 */ + }; }; eth1_pins: eth1 { - pinmux = <RZG2L_PORT_PINMUX(37, 2, 1)>, /* ET1_LINKSTA */ - <RZG2L_PORT_PINMUX(37, 0, 1)>, /* ET1_MDC */ - <RZG2L_PORT_PINMUX(37, 1, 1)>, /* ET1_MDIO */ - <RZG2L_PORT_PINMUX(29, 0, 1)>, /* ET1_TXC */ - <RZG2L_PORT_PINMUX(29, 1, 1)>, /* ET1_TX_CTL */ - <RZG2L_PORT_PINMUX(30, 0, 1)>, /* ET1_TXD0 */ - <RZG2L_PORT_PINMUX(30, 1, 1)>, /* ET1_TXD1 */ - <RZG2L_PORT_PINMUX(31, 0, 1)>, /* ET1_TXD2 */ - <RZG2L_PORT_PINMUX(31, 1, 1)>, /* ET1_TXD3 */ - <RZG2L_PORT_PINMUX(33, 1, 1)>, /* ET1_RXC */ - <RZG2L_PORT_PINMUX(34, 0, 1)>, /* ET1_RX_CTL */ - <RZG2L_PORT_PINMUX(34, 1, 1)>, /* ET1_RXD0 */ - <RZG2L_PORT_PINMUX(35, 0, 1)>, /* ET1_RXD1 */ - <RZG2L_PORT_PINMUX(35, 1, 1)>, /* ET1_RXD2 */ - <RZG2L_PORT_PINMUX(36, 0, 1)>, /* ET1_RXD3 */ - <RZG2L_PORT_PINMUX(1, 1, 1)>; /* IRQ3 */ + txc { + pinmux = <RZG2L_PORT_PINMUX(29, 0, 1)>; /* ET1_TXC */ + power-source = <1800>; + output-enable; + }; + + mux { + pinmux = <RZG2L_PORT_PINMUX(37, 2, 1)>, /* ET1_LINKSTA */ + <RZG2L_PORT_PINMUX(37, 0, 1)>, /* ET1_MDC */ + <RZG2L_PORT_PINMUX(37, 1, 1)>, /* ET1_MDIO */ + <RZG2L_PORT_PINMUX(29, 1, 1)>, /* ET1_TX_CTL */ + <RZG2L_PORT_PINMUX(30, 0, 1)>, /* ET1_TXD0 */ + <RZG2L_PORT_PINMUX(30, 1, 1)>, /* ET1_TXD1 */ + <RZG2L_PORT_PINMUX(31, 0, 1)>, /* ET1_TXD2 */ + <RZG2L_PORT_PINMUX(31, 1, 1)>, /* ET1_TXD3 */ + <RZG2L_PORT_PINMUX(33, 1, 1)>, /* ET1_RXC */ + <RZG2L_PORT_PINMUX(34, 0, 1)>, /* ET1_RX_CTL */ + <RZG2L_PORT_PINMUX(34, 1, 1)>, /* ET1_RXD0 */ + <RZG2L_PORT_PINMUX(35, 0, 1)>, /* ET1_RXD1 */ + <RZG2L_PORT_PINMUX(35, 1, 1)>, /* ET1_RXD2 */ + <RZG2L_PORT_PINMUX(36, 0, 1)>; /* ET1_RXD3 */ + power-source = <1800>; + }; + + irq { + pinmux = <RZG2L_PORT_PINMUX(1, 1, 1)>; /* IRQ3 */ + }; }; gpio-sd0-pwr-en-hog { diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi index 887dffe14910..ee3d96fdb616 100644 --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi @@ -30,6 +30,12 @@ }; }; }; + + sound_card { + compatible = "audio-graph-card"; + label = "HDMI-Audio"; + dais = <&i2s2_port>; + }; }; &cpu_dai { @@ -88,6 +94,13 @@ remote-endpoint = <&hdmi_con_out>; }; }; + + port@2 { + reg = <2>; + codec_endpoint: endpoint { + remote-endpoint = <&i2s2_cpu_endpoint>; + }; + }; }; }; }; @@ -170,6 +183,23 @@ status = "okay"; }; +&ssi1 { + pinctrl-0 = <&ssi1_pins>; + pinctrl-names = "default"; + + status = "okay"; + + i2s2_port: port { + i2s2_cpu_endpoint: endpoint { + remote-endpoint = <&codec_endpoint>; + dai-format = "i2s"; + + bitclock-master = <&i2s2_cpu_endpoint>; + frame-master = <&i2s2_cpu_endpoint>; + }; + }; +}; + &vccq_sdhi1 { gpios = <&pinctrl RZG2L_GPIO(39, 1) GPIO_ACTIVE_HIGH>; }; diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi index 5e4209d6fb42..b4ef5ea8a9e3 100644 --- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi @@ -128,22 +128,33 @@ &pinctrl { eth0_pins: eth0 { - pinmux = <RZG2L_PORT_PINMUX(28, 1, 1)>, /* ET0_LINKSTA */ - <RZG2L_PORT_PINMUX(27, 1, 1)>, /* ET0_MDC */ - <RZG2L_PORT_PINMUX(28, 0, 1)>, /* ET0_MDIO */ - <RZG2L_PORT_PINMUX(20, 0, 1)>, /* ET0_TXC */ - <RZG2L_PORT_PINMUX(20, 1, 1)>, /* ET0_TX_CTL */ - <RZG2L_PORT_PINMUX(20, 2, 1)>, /* ET0_TXD0 */ - <RZG2L_PORT_PINMUX(21, 0, 1)>, /* ET0_TXD1 */ - <RZG2L_PORT_PINMUX(21, 1, 1)>, /* ET0_TXD2 */ - <RZG2L_PORT_PINMUX(22, 0, 1)>, /* ET0_TXD3 */ - <RZG2L_PORT_PINMUX(24, 0, 1)>, /* ET0_RXC */ - <RZG2L_PORT_PINMUX(24, 1, 1)>, /* ET0_RX_CTL */ - <RZG2L_PORT_PINMUX(25, 0, 1)>, /* ET0_RXD0 */ - <RZG2L_PORT_PINMUX(25, 1, 1)>, /* ET0_RXD1 */ - <RZG2L_PORT_PINMUX(26, 0, 1)>, /* ET0_RXD2 */ - <RZG2L_PORT_PINMUX(26, 1, 1)>, /* ET0_RXD3 */ - <RZG2L_PORT_PINMUX(0, 0, 1)>; /* IRQ0 */ + txc { + pinmux = <RZG2L_PORT_PINMUX(20, 0, 1)>; /* ET0_TXC */ + power-source = <1800>; + output-enable; + }; + + mux { + pinmux = <RZG2L_PORT_PINMUX(28, 1, 1)>, /* ET0_LINKSTA */ + <RZG2L_PORT_PINMUX(27, 1, 1)>, /* ET0_MDC */ + <RZG2L_PORT_PINMUX(28, 0, 1)>, /* ET0_MDIO */ + <RZG2L_PORT_PINMUX(20, 1, 1)>, /* ET0_TX_CTL */ + <RZG2L_PORT_PINMUX(20, 2, 1)>, /* ET0_TXD0 */ + <RZG2L_PORT_PINMUX(21, 0, 1)>, /* ET0_TXD1 */ + <RZG2L_PORT_PINMUX(21, 1, 1)>, /* ET0_TXD2 */ + <RZG2L_PORT_PINMUX(22, 0, 1)>, /* ET0_TXD3 */ + <RZG2L_PORT_PINMUX(24, 0, 1)>, /* ET0_RXC */ + <RZG2L_PORT_PINMUX(24, 1, 1)>, /* ET0_RX_CTL */ + <RZG2L_PORT_PINMUX(25, 0, 1)>, /* ET0_RXD0 */ + <RZG2L_PORT_PINMUX(25, 1, 1)>, /* ET0_RXD1 */ + <RZG2L_PORT_PINMUX(26, 0, 1)>, /* ET0_RXD2 */ + <RZG2L_PORT_PINMUX(26, 1, 1)>; /* ET0_RXD3 */ + power-source = <1800>; + }; + + irq { + pinmux = <RZG2L_PORT_PINMUX(0, 0, 1)>; /* IRQ0 */ + }; }; gpio-sd0-pwr-en-hog { diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi index f21508640b6e..377849cbb462 100644 --- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi @@ -33,6 +33,16 @@ }; }; }; + +#if (SW_I2S0_I2S1) + /delete-node/ sound; + + sound_card { + compatible = "audio-graph-card"; + label = "HDMI-Audio"; + dais = <&i2s2_port>; + }; +#endif }; #if (SW_SCIF_CAN || SW_RSPI_CAN) @@ -48,9 +58,11 @@ }; #endif +#if (!SW_I2S0_I2S1) &cpu_dai { sound-dai = <&ssi0>; }; +#endif &dsi { status = "okay"; @@ -104,6 +116,15 @@ remote-endpoint = <&hdmi_con_out>; }; }; + +#if (SW_I2S0_I2S1) + port@2 { + reg = <2>; + codec_endpoint: endpoint { + remote-endpoint = <&i2s2_cpu_endpoint>; + }; + }; +#endif }; }; }; @@ -177,6 +198,18 @@ pinctrl-names = "default"; status = "okay"; + +#if (SW_I2S0_I2S1) + i2s2_port: port { + i2s2_cpu_endpoint: endpoint { + remote-endpoint = <&codec_endpoint>; + dai-format = "i2s"; + + bitclock-master = <&i2s2_cpu_endpoint>; + frame-master = <&i2s2_cpu_endpoint>; + }; + }; +#endif }; #if (SW_RSPI_CAN) diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi index 97cdad2a12e2..79443fb3f581 100644 --- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi @@ -142,41 +142,63 @@ }; eth0_pins: eth0 { - pinmux = <RZG2L_PORT_PINMUX(4, 5, 1)>, /* ET0_LINKSTA */ - <RZG2L_PORT_PINMUX(4, 3, 1)>, /* ET0_MDC */ - <RZG2L_PORT_PINMUX(4, 4, 1)>, /* ET0_MDIO */ - <RZG2L_PORT_PINMUX(1, 0, 1)>, /* ET0_TXC */ - <RZG2L_PORT_PINMUX(1, 1, 1)>, /* ET0_TX_CTL */ - <RZG2L_PORT_PINMUX(1, 2, 1)>, /* ET0_TXD0 */ - <RZG2L_PORT_PINMUX(1, 3, 1)>, /* ET0_TXD1 */ - <RZG2L_PORT_PINMUX(1, 4, 1)>, /* ET0_TXD2 */ - <RZG2L_PORT_PINMUX(2, 0, 1)>, /* ET0_TXD3 */ - <RZG2L_PORT_PINMUX(3, 0, 1)>, /* ET0_RXC */ - <RZG2L_PORT_PINMUX(3, 1, 1)>, /* ET0_RX_CTL */ - <RZG2L_PORT_PINMUX(3, 2, 1)>, /* ET0_RXD0 */ - <RZG2L_PORT_PINMUX(3, 3, 1)>, /* ET0_RXD1 */ - <RZG2L_PORT_PINMUX(4, 0, 1)>, /* ET0_RXD2 */ - <RZG2L_PORT_PINMUX(4, 1, 1)>, /* ET0_RXD3 */ - <RZG2L_PORT_PINMUX(5, 1, 7)>; /* IRQ2 */ + txc { + pinmux = <RZG2L_PORT_PINMUX(1, 0, 1)>; /* ET0_TXC */ + power-source = <1800>; + output-enable; + }; + + mux { + pinmux = <RZG2L_PORT_PINMUX(4, 5, 1)>, /* ET0_LINKSTA */ + <RZG2L_PORT_PINMUX(4, 3, 1)>, /* ET0_MDC */ + <RZG2L_PORT_PINMUX(4, 4, 1)>, /* ET0_MDIO */ + <RZG2L_PORT_PINMUX(1, 1, 1)>, /* ET0_TX_CTL */ + <RZG2L_PORT_PINMUX(1, 2, 1)>, /* ET0_TXD0 */ + <RZG2L_PORT_PINMUX(1, 3, 1)>, /* ET0_TXD1 */ + <RZG2L_PORT_PINMUX(1, 4, 1)>, /* ET0_TXD2 */ + <RZG2L_PORT_PINMUX(2, 0, 1)>, /* ET0_TXD3 */ + <RZG2L_PORT_PINMUX(3, 0, 1)>, /* ET0_RXC */ + <RZG2L_PORT_PINMUX(3, 1, 1)>, /* ET0_RX_CTL */ + <RZG2L_PORT_PINMUX(3, 2, 1)>, /* ET0_RXD0 */ + <RZG2L_PORT_PINMUX(3, 3, 1)>, /* ET0_RXD1 */ + <RZG2L_PORT_PINMUX(4, 0, 1)>, /* ET0_RXD2 */ + <RZG2L_PORT_PINMUX(4, 1, 1)>; /* ET0_RXD3 */ + power-source = <1800>; + }; + + irq { + pinmux = <RZG2L_PORT_PINMUX(5, 1, 7)>; /* IRQ2 */ + }; }; eth1_pins: eth1 { - pinmux = <RZG2L_PORT_PINMUX(10, 4, 1)>, /* ET1_LINKSTA */ - <RZG2L_PORT_PINMUX(10, 2, 1)>, /* ET1_MDC */ - <RZG2L_PORT_PINMUX(10, 3, 1)>, /* ET1_MDIO */ - <RZG2L_PORT_PINMUX(7, 0, 1)>, /* ET1_TXC */ - <RZG2L_PORT_PINMUX(7, 1, 1)>, /* ET1_TX_CTL */ - <RZG2L_PORT_PINMUX(7, 2, 1)>, /* ET1_TXD0 */ - <RZG2L_PORT_PINMUX(7, 3, 1)>, /* ET1_TXD1 */ - <RZG2L_PORT_PINMUX(7, 4, 1)>, /* ET1_TXD2 */ - <RZG2L_PORT_PINMUX(8, 0, 1)>, /* ET1_TXD3 */ - <RZG2L_PORT_PINMUX(8, 4, 1)>, /* ET1_RXC */ - <RZG2L_PORT_PINMUX(9, 0, 1)>, /* ET1_RX_CTL */ - <RZG2L_PORT_PINMUX(9, 1, 1)>, /* ET1_RXD0 */ - <RZG2L_PORT_PINMUX(9, 2, 1)>, /* ET1_RXD1 */ - <RZG2L_PORT_PINMUX(9, 3, 1)>, /* ET1_RXD2 */ - <RZG2L_PORT_PINMUX(10, 0, 1)>, /* ET1_RXD3 */ - <RZG2L_PORT_PINMUX(18, 5, 1)>; /* IRQ7 */ + txc { + pinmux = <RZG2L_PORT_PINMUX(7, 0, 1)>; /* ET1_TXC */ + power-source = <1800>; + output-enable; + }; + + mux { + pinmux = <RZG2L_PORT_PINMUX(10, 4, 1)>, /* ET1_LINKSTA */ + <RZG2L_PORT_PINMUX(10, 2, 1)>, /* ET1_MDC */ + <RZG2L_PORT_PINMUX(10, 3, 1)>, /* ET1_MDIO */ + <RZG2L_PORT_PINMUX(7, 1, 1)>, /* ET1_TX_CTL */ + <RZG2L_PORT_PINMUX(7, 2, 1)>, /* ET1_TXD0 */ + <RZG2L_PORT_PINMUX(7, 3, 1)>, /* ET1_TXD1 */ + <RZG2L_PORT_PINMUX(7, 4, 1)>, /* ET1_TXD2 */ + <RZG2L_PORT_PINMUX(8, 0, 1)>, /* ET1_TXD3 */ + <RZG2L_PORT_PINMUX(8, 4, 1)>, /* ET1_RXC */ + <RZG2L_PORT_PINMUX(9, 0, 1)>, /* ET1_RX_CTL */ + <RZG2L_PORT_PINMUX(9, 1, 1)>, /* ET1_RXD0 */ + <RZG2L_PORT_PINMUX(9, 2, 1)>, /* ET1_RXD1 */ + <RZG2L_PORT_PINMUX(9, 3, 1)>, /* ET1_RXD2 */ + <RZG2L_PORT_PINMUX(10, 0, 1)>; /* ET1_RXD3 */ + power-source = <1800>; + }; + + irq { + pinmux = <RZG2L_PORT_PINMUX(18, 5, 1)>; /* IRQ7 */ + }; }; sdhi0_emmc_pins: sd0emmc { diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi index 8a3d302f1535..21bfa4e03972 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi @@ -32,6 +32,7 @@ compatible = "renesas,rzg3s-smarcm", "renesas,r9a08g045s33", "renesas,r9a08g045"; aliases { + i2c1 = &i2c1; mmc0 = &sdhi0; #if SW_CONFIG3 == SW_OFF mmc2 = &sdhi2; @@ -150,6 +151,10 @@ clock-frequency = <24000000>; }; +&i2c1 { + status = "okay"; +}; + #if SW_CONFIG2 == SW_ON /* SD0 slot */ &sdhi0 { diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi index deb2ad37bb2e..7945d44e6ee1 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi @@ -11,6 +11,7 @@ / { aliases { + i2c0 = &i2c0; serial0 = &scif0; mmc1 = &sdhi1; }; @@ -66,6 +67,12 @@ }; }; +&i2c0 { + status = "okay"; + + clock-frequency = <1000000>; +}; + &pinctrl { key-1-gpio-hog { gpio-hog; diff --git a/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi b/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi index 80496fb3d476..3845b413bd24 100644 --- a/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi +++ b/arch/arm64/boot/dts/renesas/white-hawk-cpu-common.dtsi @@ -117,6 +117,12 @@ }; }; + pcie_clk: clk-9fgv0841-pci { + compatible = "fixed-clock"; + clock-frequency = <100000000>; + #clock-cells = <0>; + }; + reg_1p2v: regulator-1p2v { compatible = "regulator-fixed"; regulator-name = "fixed-1.2V"; @@ -288,6 +294,18 @@ status = "okay"; }; +&pcie0_clkref { + compatible = "gpio-gate-clock"; + clocks = <&pcie_clk>; + enable-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; + /delete-property/ clock-frequency; +}; + +&pciec0 { + reset-gpio = <&io_expander_a 0 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + &pfc { pinctrl-0 = <&scif_clk_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index fda1b980eb4b..09423070c992 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-ctouch2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-ctouch2-of10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-edimm2.2.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-firefly-jd4-core-mb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-ringneck-haikou.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-roc-cc.dtb @@ -20,6 +21,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb @@ -81,6 +83,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353ps.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353v.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353vs.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-odroid-m1s.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-orangepi-3b-v1.1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-orangepi-3b-v2.1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.1.dtb @@ -102,6 +105,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-blade.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-cm4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-model-a.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-box-demo.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-lckfb-tspi.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-lubancat-1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb @@ -118,9 +122,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-roc-pc.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3b.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-display-vz.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-wolfvision-pf5-io-expander.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-armsom-sige7.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-coolpi-cm5-evb.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-coolpi-cm5-genbook.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-wifi.dtbo dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6b-io.dtb @@ -128,6 +134,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-friendlyelec-cm3588-nas.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-jaguar.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nanopc-t6-lts.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-ok3588-c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-orangepi-5-plus.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-quartzpro64.dtb @@ -139,9 +146,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-tiger-haikou.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-toybrick-x0.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-turing-rk1.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-coolpi-4b.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-gameforce-ace.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-indiedroid-nova.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-khadas-edge2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6s.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-rock-5a.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb diff --git a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts new file mode 100644 index 000000000000..d03e6aef54dc --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core-mb.dts @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + */ + +/dts-v1/; +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> +#include "px30-firefly-jd4-core.dtsi" + +/ { + compatible = "firefly,px30-jd4-core-mb", "firefly,px30-jd4-core", + "rockchip,px30"; + model = "Firefly Core-PX30-JD4 on MB-JD4-PX30 baseboard"; + + aliases { + ethernet0 = &gmac; + mmc0 = &sdmmc; + mmc1 = &sdio; + mmc2 = &emmc; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + dc_12v: dc-12v-regulator { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1500000>; + poll-interval = <100>; + + button-recovery { + label = "Recovery"; + linux,code = <KEY_VENDOR>; + press-threshold-microvolt = <18000>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&blue_led>, <&green_led>; + + blue-led { + color = <LED_COLOR_ID_BLUE>; + default-state = "on"; + function = LED_FUNCTION_HEARTBEAT; + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + label = "px30-mb-jd4:blue:work"; + linux,default-trigger = "heartbeat"; + }; + + green-led { + color = <LED_COLOR_ID_GREEN>; + default-state = "on"; + function = LED_FUNCTION_POWER; + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + label = "px30-mb-jd4:blue:diy"; + linux,default-trigger = "default-on"; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ + }; + + vcc5v0_baseboard: vcc5v0-baseboard-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_baseboard"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; +}; + +&gmac { + clock_in_out = "output"; + phy-supply = <&vcc_rmii>; + snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 50000 50000>; + status = "okay"; +}; + +&pinctrl { + leds { + blue_led: blue-led { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + green_led: green-led { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <800>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + keep-power-in-suspend; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + sd-uhs-sdr104; + status = "okay"; +}; + +&u2phy { + status = "okay"; + + u2phy_host: host-port { + status = "okay"; + }; + + u2phy_otg: otg-port { + status = "okay"; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; + status = "okay"; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi new file mode 100644 index 000000000000..f18d7eb9a9c7 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-firefly-jd4-core.dtsi @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include "px30.dtsi" + +/ { + compatible = "firefly,px30-jd4-core", "rockchip,px30"; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + pinctrl-0 = <&emmc_reset>; + pinctrl-names = "default"; + reset-gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_baseboard>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + non-removable; + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v0>; + vqmmc-supply = <&vccio_flash>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_log>; + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <0>; + clock-output-names = "xin32k"; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v0: vcc_rmii: DCDC_REG4 { + regulator-name = "vcc_3v0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_sys: DCDC_REG5 { + regulator-name = "vcc3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v0: LDO_REG1 { + regulator-name = "vcc_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_1v8: vccio_flash: vccio_sdio: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v0_pmu: LDO_REG4 { + regulator-name = "vcc3v0_pmu"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc2v8_dvp: LDO_REG7 { + regulator-name = "vcc2v8_dvp"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc1v8_dvp: LDO_REG8 { + regulator-name = "vcc1v8_dvp"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v5_dvp: LDO_REG9 { + regulator-name = "vcc1v5_dvp"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcc3v3_lcd: SWITCH_REG1 { + regulator-name = "vcc3v3_lcd"; + regulator-boot-on; + }; + + vcc5v0_host: SWITCH_REG2 { + regulator-name = "vcc5v0_host"; + regulator-always-on; + regulator-boot-on; + }; + }; + }; +}; + +&io_domains { + vccio1-supply = <&vccio_sdio>; + vccio2-supply = <&vccio_sd>; + vccio3-supply = <&vcc_3v0>; + vccio4-supply = <&vcc3v0_pmu>; + vccio5-supply = <&vcc_3v0>; + vccio6-supply = <&vccio_flash>; + status = "okay"; +}; + +&pinctrl { + emmc { + emmc_reset: emmc-reset { + rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v0_pmu>; + pmuio2-supply = <&vcc3v0_pmu>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi index bb1aea82e666..b7163ed74232 100644 --- a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi @@ -66,7 +66,6 @@ bus-width = <8>; cap-mmc-highspeed; mmc-hs200-1_8v; - supports-emmc; mmc-pwrseq = <&emmc_pwrseq>; non-removable; vmmc-supply = <&vcc_3v3>; diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts index 9232357f4fec..d9e191ad1d77 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts @@ -36,14 +36,14 @@ power_led: led-0 { label = "firefly:red:power"; - linux,default-trigger = "ir-power-click"; + linux,default-trigger = "default-on"; default-state = "on"; gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; }; user_led: led-1 { label = "firefly:blue:user"; - linux,default-trigger = "ir-user-click"; + linux,default-trigger = "rc-feedback"; default-state = "off"; gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts new file mode 100644 index 000000000000..4b9ced67742d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * (C) Copyright 2018 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + */ + +/dts-v1/; +#include "rk3328-nanopi-r2s.dts" + +/ { + compatible = "friendlyarm,nanopi-r2s-plus", "rockchip,rk3328"; + model = "FriendlyElec NanoPi R2S Plus"; + + aliases { + mmc1 = &emmc; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + disable-wp; + mmc-hs200-1_8v; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts index a608a219543e..3e08e2fd0a78 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock-pi-e.dts @@ -387,7 +387,7 @@ pmic { pmic_int_l: pmic-int-l { - rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index b01efd6d042c..c01a4cad48f3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -754,8 +754,7 @@ compatible = "rockchip,rk3328-dw-hdmi"; reg = <0x0 0xff3c0000 0x0 0x20000>; reg-io-width = <4>; - interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cru PCLK_HDMI>, <&cru SCLK_HDMI_SFC>, <&cru SCLK_RTC32K>; @@ -910,6 +909,8 @@ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; fifo-depth = <0x100>; max-frequency = <150000000>; + resets = <&cru SRST_MMC0>; + reset-names = "reset"; status = "disabled"; }; @@ -922,6 +923,8 @@ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; fifo-depth = <0x100>; max-frequency = <150000000>; + resets = <&cru SRST_SDIO>; + reset-names = "reset"; status = "disabled"; }; @@ -934,6 +937,8 @@ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; fifo-depth = <0x100>; max-frequency = <150000000>; + resets = <&cru SRST_EMMC>; + reset-names = "reset"; status = "disabled"; }; @@ -1036,6 +1041,20 @@ status = "disabled"; }; + sdmmc_ext: mmc@ff5f0000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff5f0000 0x0 0x4000>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>, + <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + resets = <&cru SRST_SDMMCEXT>; + reset-names = "reset"; + status = "disabled"; + }; + usbdrd3: usb@ff600000 { compatible = "rockchip,rk3328-dwc3", "snps,dwc3"; reg = <0x0 0xff600000 0x0 0x100000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi index 8ac8acf4082d..ab3fda69a1fb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi @@ -61,7 +61,6 @@ fan: fan@18 { compatible = "ti,amc6821"; reg = <0x18>; - #cooling-cells = <2>; }; rtc_twi: rtc@6f { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi new file mode 100644 index 000000000000..9d5f5b083e3c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-base.dtsi @@ -0,0 +1,3019 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include <dt-bindings/clock/rk3399-cru.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/power/rk3399-power.h> +#include <dt-bindings/thermal/thermal.h> + +/ { + compatible = "rockchip,rk3399"; + + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c7; + i2c8 = &i2c8; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; + spi4 = &spi4; + spi5 = &spi5; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { /* Cortex-A53 */ + core0 { + cpu = <&cpu_l0>; + }; + core1 { + cpu = <&cpu_l1>; + }; + core2 { + cpu = <&cpu_l2>; + }; + core3 { + cpu = <&cpu_l3>; + }; + }; + + cluster1 { /* Cortex-A72 */ + core0 { + cpu = <&cpu_b0>; + }; + core1 { + cpu = <&cpu_b1>; + }; + }; + }; + + cpu_l0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x0>; + enable-method = "psci"; + capacity-dmips-mhz = <485>; + clocks = <&cru ARMCLKL>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l>; + }; + + cpu_l1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x1>; + enable-method = "psci"; + capacity-dmips-mhz = <485>; + clocks = <&cru ARMCLKL>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l>; + }; + + cpu_l2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x2>; + enable-method = "psci"; + capacity-dmips-mhz = <485>; + clocks = <&cru ARMCLKL>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l>; + }; + + cpu_l3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0 0x3>; + enable-method = "psci"; + capacity-dmips-mhz = <485>; + clocks = <&cru ARMCLKL>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&l2_cache_l>; + }; + + cpu_b0: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x0 0x100>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&cru ARMCLKB>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <436>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; + next-level-cache = <&l2_cache_b>; + + thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; + }; + + cpu_b1: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x0 0x101>; + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&cru ARMCLKB>; + #cooling-cells = <2>; /* min followed by max */ + dynamic-power-coefficient = <436>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <256>; + next-level-cache = <&l2_cache_b>; + + thermal-idle { + #cooling-cells = <2>; + duration-us = <10000>; + exit-latency-us = <500>; + }; + }; + + l2_cache_l: l2-cache-cluster0 { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x80000>; + cache-line-size = <64>; + cache-sets = <512>; + }; + + l2_cache_b: l2-cache-cluster1 { + compatible = "cache"; + cache-level = <2>; + cache-unified; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + }; + + idle-states { + entry-method = "psci"; + + CPU_SLEEP: cpu-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <120>; + exit-latency-us = <250>; + min-residency-us = <900>; + }; + + CLUSTER_SLEEP: cluster-sleep { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <400>; + exit-latency-us = <500>; + min-residency-us = <2000>; + }; + }; + }; + + display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vopl_out>, <&vopb_out>; + }; + + dmc: memory-controller { + compatible = "rockchip,rk3399-dmc"; + rockchip,pmu = <&pmugrf>; + devfreq-events = <&dfi>; + clocks = <&cru SCLK_DDRC>; + clock-names = "dmc_clk"; + status = "disabled"; + }; + + pmu_a53 { + compatible = "arm,cortex-a53-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>; + }; + + pmu_a72 { + compatible = "arm,cortex-a72-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>; + arm,no-tick-in-suspend; + }; + + xin24m: xin24m { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xin24m"; + #clock-cells = <0>; + }; + + pcie0: pcie@f8000000 { + compatible = "rockchip,rk3399-pcie"; + reg = <0x0 0xf8000000 0x0 0x2000000>, + <0x0 0xfd000000 0x0 0x1000000>; + reg-names = "axi-base", "apb-base"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + aspm-no-l0s; + bus-range = <0x0 0x1f>; + clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, + <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; + clock-names = "aclk", "aclk-perf", + "hclk", "pm"; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "sys", "legacy", "client"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie0_intc 0>, + <0 0 0 2 &pcie0_intc 1>, + <0 0 0 3 &pcie0_intc 2>, + <0 0 0 4 &pcie0_intc 3>; + max-link-speed = <1>; + msi-map = <0x0 &its 0x0 0x1000>; + phys = <&pcie_phy 0>, <&pcie_phy 1>, + <&pcie_phy 2>, <&pcie_phy 3>; + phy-names = "pcie-phy-0", "pcie-phy-1", + "pcie-phy-2", "pcie-phy-3"; + ranges = <0x82000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000>, + <0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>; + resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, + <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>, + <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, + <&cru SRST_A_PCIE>; + reset-names = "core", "mgmt", "mgmt-sticky", "pipe", + "pm", "pclk", "aclk"; + status = "disabled"; + + pcie0_intc: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + + pcie0_ep: pcie-ep@f8000000 { + compatible = "rockchip,rk3399-pcie-ep"; + reg = <0x0 0xfd000000 0x0 0x1000000>, + <0x0 0xfa000000 0x0 0x2000000>; + reg-names = "apb-base", "mem-base"; + clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, + <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; + clock-names = "aclk", "aclk-perf", + "hclk", "pm"; + max-functions = /bits/ 8 <8>; + num-lanes = <4>; + resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, + <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>, + <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, + <&cru SRST_A_PCIE>; + reset-names = "core", "mgmt", "mgmt-sticky", "pipe", + "pm", "pclk", "aclk"; + phys = <&pcie_phy 0>, <&pcie_phy 1>, + <&pcie_phy 2>, <&pcie_phy 3>; + phy-names = "pcie-phy-0", "pcie-phy-1", + "pcie-phy-2", "pcie-phy-3"; + rockchip,max-outbound-regions = <32>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqnb_cpm>; + status = "disabled"; + }; + + gmac: ethernet@fe300000 { + compatible = "rockchip,rk3399-gmac"; + reg = <0x0 0xfe300000 0x0 0x10000>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "macirq"; + clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>, + <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>, + <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_ref", + "clk_mac_refout", "aclk_mac", + "pclk_mac"; + power-domains = <&power RK3399_PD_GMAC>; + resets = <&cru SRST_A_GMAC>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; + snps,txpbl = <0x4>; + status = "disabled"; + }; + + sdio0: mmc@fe310000 { + compatible = "rockchip,rk3399-dw-mshc", + "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe310000 0x0 0x4000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH 0>; + max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + resets = <&cru SRST_SDIO0>; + reset-names = "reset"; + status = "disabled"; + }; + + sdmmc: mmc@fe320000 { + compatible = "rockchip,rk3399-dw-mshc", + "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe320000 0x0 0x4000>; + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>; + max-frequency = <150000000>; + assigned-clocks = <&cru HCLK_SD>; + assigned-clock-rates = <200000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + power-domains = <&power RK3399_PD_SD>; + resets = <&cru SRST_SDMMC>; + reset-names = "reset"; + status = "disabled"; + }; + + sdhci: mmc@fe330000 { + compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1"; + reg = <0x0 0xfe330000 0x0 0x10000>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>; + arasan,soc-ctl-syscon = <&grf>; + assigned-clocks = <&cru SCLK_EMMC>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>; + clock-names = "clk_xin", "clk_ahb"; + clock-output-names = "emmc_cardclock"; + #clock-cells = <0>; + phys = <&emmc_phy>; + phy-names = "phy_arasan"; + power-domains = <&power RK3399_PD_EMMC>; + disable-cqe-dcmd; + status = "disabled"; + }; + + usb_host0_ehci: usb@fe380000 { + compatible = "generic-ehci"; + reg = <0x0 0xfe380000 0x0 0x20000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, + <&u2phy0>; + phys = <&u2phy0_host>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host0_ohci: usb@fe3a0000 { + compatible = "generic-ohci"; + reg = <0x0 0xfe3a0000 0x0 0x20000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, + <&u2phy0>; + phys = <&u2phy0_host>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host1_ehci: usb@fe3c0000 { + compatible = "generic-ehci"; + reg = <0x0 0xfe3c0000 0x0 0x20000>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>, + <&u2phy1>; + phys = <&u2phy1_host>; + phy-names = "usb"; + status = "disabled"; + }; + + usb_host1_ohci: usb@fe3e0000 { + compatible = "generic-ohci"; + reg = <0x0 0xfe3e0000 0x0 0x20000>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>, + <&u2phy1>; + phys = <&u2phy1_host>; + phy-names = "usb"; + status = "disabled"; + }; + + debug@fe430000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe430000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_L>; + clock-names = "apb_pclk"; + cpu = <&cpu_l0>; + }; + + debug@fe432000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe432000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_L>; + clock-names = "apb_pclk"; + cpu = <&cpu_l1>; + }; + + debug@fe434000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe434000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_L>; + clock-names = "apb_pclk"; + cpu = <&cpu_l2>; + }; + + debug@fe436000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe436000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_L>; + clock-names = "apb_pclk"; + cpu = <&cpu_l3>; + }; + + debug@fe610000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe610000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_B>; + clock-names = "apb_pclk"; + cpu = <&cpu_b0>; + }; + + debug@fe710000 { + compatible = "arm,coresight-cpu-debug", "arm,primecell"; + reg = <0 0xfe710000 0 0x1000>; + clocks = <&cru PCLK_COREDBG_B>; + clock-names = "apb_pclk"; + cpu = <&cpu_b1>; + }; + + usbdrd3_0: usb@fe800000 { + compatible = "rockchip,rk3399-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>, + <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, + <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk", "aclk_usb3_rksoc_axi_perf", + "aclk_usb3", "grf_clk"; + resets = <&cru SRST_A_USB3_OTG0>; + reset-names = "usb3-otg"; + status = "disabled"; + + usbdrd_dwc3_0: usb@fe800000 { + compatible = "snps,dwc3"; + reg = <0x0 0xfe800000 0x0 0x100000>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_USB3OTG0_REF>, <&cru ACLK_USB3OTG0>, + <&cru SCLK_USB3OTG0_SUSPEND>; + clock-names = "ref", "bus_early", "suspend"; + dr_mode = "otg"; + phys = <&u2phy0_otg>, <&tcphy0_usb3>; + phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + snps,dis_enblslpm_quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + }; + }; + + usbdrd3_1: usb@fe900000 { + compatible = "rockchip,rk3399-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>, + <&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, + <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk", "aclk_usb3_rksoc_axi_perf", + "aclk_usb3", "grf_clk"; + resets = <&cru SRST_A_USB3_OTG1>; + reset-names = "usb3-otg"; + status = "disabled"; + + usbdrd_dwc3_1: usb@fe900000 { + compatible = "snps,dwc3"; + reg = <0x0 0xfe900000 0x0 0x100000>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_USB3OTG1_REF>, <&cru ACLK_USB3OTG1>, + <&cru SCLK_USB3OTG1_SUSPEND>; + clock-names = "ref", "bus_early", "suspend"; + dr_mode = "otg"; + phys = <&u2phy1_otg>, <&tcphy1_usb3>; + phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + snps,dis_enblslpm_quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + }; + }; + + cdn_dp: dp@fec00000 { + compatible = "rockchip,rk3399-cdn-dp"; + reg = <0x0 0xfec00000 0x0 0x100000>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH 0>; + assigned-clocks = <&cru SCLK_DP_CORE>, <&cru SCLK_SPDIF_REC_DPTX>; + assigned-clock-rates = <100000000>, <200000000>; + clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>, + <&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>; + clock-names = "core-clk", "pclk", "spdif", "grf"; + phys = <&tcphy0_dp>, <&tcphy1_dp>; + power-domains = <&power RK3399_PD_HDCP>; + resets = <&cru SRST_DPTX_SPDIF_REC>, <&cru SRST_P_UPHY0_DPTX>, + <&cru SRST_P_UPHY0_APB>, <&cru SRST_DP_CORE>; + reset-names = "spdif", "dptx", "apb", "core"; + rockchip,grf = <&grf>; + #sound-dai-cells = <1>; + status = "disabled"; + + ports { + dp_in: port { + #address-cells = <1>; + #size-cells = <0>; + + dp_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_dp>; + }; + + dp_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_dp>; + }; + }; + }; + }; + + gic: interrupt-controller@fee00000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + + reg = <0x0 0xfee00000 0 0x10000>, /* GICD */ + <0x0 0xfef00000 0 0xc0000>, /* GICR */ + <0x0 0xfff00000 0 0x10000>, /* GICC */ + <0x0 0xfff10000 0 0x10000>, /* GICH */ + <0x0 0xfff20000 0 0x10000>; /* GICV */ + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>; + its: msi-controller@fee20000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0xfee20000 0x0 0x20000>; + }; + + ppi-partitions { + ppi_cluster0: interrupt-partition-0 { + affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>; + }; + + ppi_cluster1: interrupt-partition-1 { + affinity = <&cpu_b0 &cpu_b1>; + }; + }; + }; + + saradc: saradc@ff100000 { + compatible = "rockchip,rk3399-saradc"; + reg = <0x0 0xff100000 0x0 0x100>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH 0>; + #io-channel-cells = <1>; + clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_P_SARADC>; + reset-names = "saradc-apb"; + status = "disabled"; + }; + + crypto0: crypto@ff8b0000 { + compatible = "rockchip,rk3399-crypto"; + reg = <0x0 0xff8b0000 0x0 0x4000>; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_M_CRYPTO0>, <&cru HCLK_S_CRYPTO0>, <&cru SCLK_CRYPTO0>; + clock-names = "hclk_master", "hclk_slave", "sclk"; + resets = <&cru SRST_CRYPTO0>, <&cru SRST_CRYPTO0_S>, <&cru SRST_CRYPTO0_M>; + reset-names = "master", "slave", "crypto-rst"; + }; + + crypto1: crypto@ff8b8000 { + compatible = "rockchip,rk3399-crypto"; + reg = <0x0 0xff8b8000 0x0 0x4000>; + interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru HCLK_M_CRYPTO1>, <&cru HCLK_S_CRYPTO1>, <&cru SCLK_CRYPTO1>; + clock-names = "hclk_master", "hclk_slave", "sclk"; + resets = <&cru SRST_CRYPTO1>, <&cru SRST_CRYPTO1_S>, <&cru SRST_CRYPTO1_M>; + reset-names = "master", "slave", "crypto-rst"; + }; + + i2c1: i2c@ff110000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff110000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C1>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@ff120000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff120000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C2>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@ff130000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff130000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C3>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@ff140000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff140000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C5>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c6: i2c@ff150000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff150000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C6>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c7: i2c@ff160000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff160000 0x0 0x1000>; + assigned-clocks = <&cru SCLK_I2C7>; + assigned-clock-rates = <200000000>; + clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart0: serial@ff180000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff180000 0x0 0x100>; + clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; + clock-names = "baudclk", "apb_pclk"; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer>; + status = "disabled"; + }; + + uart1: serial@ff190000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff190000 0x0 0x100>; + clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; + clock-names = "baudclk", "apb_pclk"; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer>; + status = "disabled"; + }; + + uart2: serial@ff1a0000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff1a0000 0x0 0x100>; + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2c_xfer>; + status = "disabled"; + }; + + uart3: serial@ff1b0000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff1b0000 0x0 0x100>; + clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; + clock-names = "baudclk", "apb_pclk"; + interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart3_xfer>; + status = "disabled"; + }; + + spi0: spi@ff1c0000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1c0000 0x0 0x1000>; + clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_peri 10>, <&dmac_peri 11>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@ff1d0000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1d0000 0x0 0x1000>; + clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_peri 12>, <&dmac_peri 13>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@ff1e0000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1e0000 0x0 0x1000>; + clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_peri 14>, <&dmac_peri 15>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi4: spi@ff1f0000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1f0000 0x0 0x1000>; + clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_peri 18>, <&dmac_peri 19>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi5: spi@ff200000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff200000 0x0 0x1000>; + clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_bus 8>, <&dmac_bus 9>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + thermal_zones: thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <100>; + polling-delay = <1000>; + + thermal-sensors = <&tsadc 0>; + + trips { + cpu_alert0: cpu_alert0 { + temperature = <70000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_alert1: cpu_alert1 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_crit: cpu_crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + map1 { + trip = <&cpu_alert1>; + cooling-device = + <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + + gpu_thermal: gpu-thermal { + polling-delay-passive = <100>; + polling-delay = <1000>; + + thermal-sensors = <&tsadc 1>; + + trips { + gpu_alert0: gpu_alert0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + gpu_crit: gpu_crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_alert0>; + cooling-device = + <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + tsadc: tsadc@ff260000 { + compatible = "rockchip,rk3399-tsadc"; + reg = <0x0 0xff260000 0x0 0x100>; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>; + assigned-clocks = <&cru SCLK_TSADC>; + assigned-clock-rates = <750000>; + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + resets = <&cru SRST_TSADC>; + reset-names = "tsadc-apb"; + rockchip,grf = <&grf>; + rockchip,hw-tshut-temp = <95000>; + pinctrl-names = "init", "default", "sleep"; + pinctrl-0 = <&otp_pin>; + pinctrl-1 = <&otp_out>; + pinctrl-2 = <&otp_pin>; + #thermal-sensor-cells = <1>; + status = "disabled"; + }; + + qos_emmc: qos@ffa58000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa58000 0x0 0x20>; + }; + + qos_gmac: qos@ffa5c000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa5c000 0x0 0x20>; + }; + + qos_pcie: qos@ffa60080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa60080 0x0 0x20>; + }; + + qos_usb_host0: qos@ffa60100 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa60100 0x0 0x20>; + }; + + qos_usb_host1: qos@ffa60180 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa60180 0x0 0x20>; + }; + + qos_usb_otg0: qos@ffa70000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa70000 0x0 0x20>; + }; + + qos_usb_otg1: qos@ffa70080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa70080 0x0 0x20>; + }; + + qos_sd: qos@ffa74000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa74000 0x0 0x20>; + }; + + qos_sdioaudio: qos@ffa76000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa76000 0x0 0x20>; + }; + + qos_hdcp: qos@ffa90000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa90000 0x0 0x20>; + }; + + qos_iep: qos@ffa98000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffa98000 0x0 0x20>; + }; + + qos_isp0_m0: qos@ffaa0000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffaa0000 0x0 0x20>; + }; + + qos_isp0_m1: qos@ffaa0080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffaa0080 0x0 0x20>; + }; + + qos_isp1_m0: qos@ffaa8000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffaa8000 0x0 0x20>; + }; + + qos_isp1_m1: qos@ffaa8080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffaa8080 0x0 0x20>; + }; + + qos_rga_r: qos@ffab0000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffab0000 0x0 0x20>; + }; + + qos_rga_w: qos@ffab0080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffab0080 0x0 0x20>; + }; + + qos_video_m0: qos@ffab8000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffab8000 0x0 0x20>; + }; + + qos_video_m1_r: qos@ffac0000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffac0000 0x0 0x20>; + }; + + qos_video_m1_w: qos@ffac0080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffac0080 0x0 0x20>; + }; + + qos_vop_big_r: qos@ffac8000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffac8000 0x0 0x20>; + }; + + qos_vop_big_w: qos@ffac8080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffac8080 0x0 0x20>; + }; + + qos_vop_little: qos@ffad0000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffad0000 0x0 0x20>; + }; + + qos_perihp: qos@ffad8080 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffad8080 0x0 0x20>; + }; + + qos_gpu: qos@ffae0000 { + compatible = "rockchip,rk3399-qos", "syscon"; + reg = <0x0 0xffae0000 0x0 0x20>; + }; + + pmu: power-management@ff310000 { + compatible = "rockchip,rk3399-pmu", "syscon", "simple-mfd"; + reg = <0x0 0xff310000 0x0 0x1000>; + + /* + * Note: RK3399 supports 6 voltage domains including VD_CORE_L, + * VD_CORE_B, VD_CENTER, VD_GPU, VD_LOGIC and VD_PMU. + * Some of the power domains are grouped together for every + * voltage domain. + * The detail contents as below. + */ + power: power-controller { + compatible = "rockchip,rk3399-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + /* These power domains are grouped by VD_CENTER */ + power-domain@RK3399_PD_IEP { + reg = <RK3399_PD_IEP>; + clocks = <&cru ACLK_IEP>, + <&cru HCLK_IEP>; + pm_qos = <&qos_iep>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_RGA { + reg = <RK3399_PD_RGA>; + clocks = <&cru ACLK_RGA>, + <&cru HCLK_RGA>; + pm_qos = <&qos_rga_r>, + <&qos_rga_w>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_VCODEC { + reg = <RK3399_PD_VCODEC>; + clocks = <&cru ACLK_VCODEC>, + <&cru HCLK_VCODEC>; + pm_qos = <&qos_video_m0>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_VDU { + reg = <RK3399_PD_VDU>; + clocks = <&cru ACLK_VDU>, + <&cru HCLK_VDU>, + <&cru SCLK_VDU_CA>, + <&cru SCLK_VDU_CORE>; + pm_qos = <&qos_video_m1_r>, + <&qos_video_m1_w>; + #power-domain-cells = <0>; + }; + + /* These power domains are grouped by VD_GPU */ + power-domain@RK3399_PD_GPU { + reg = <RK3399_PD_GPU>; + clocks = <&cru ACLK_GPU>; + pm_qos = <&qos_gpu>; + #power-domain-cells = <0>; + }; + + /* These power domains are grouped by VD_LOGIC */ + power-domain@RK3399_PD_EDP { + reg = <RK3399_PD_EDP>; + clocks = <&cru PCLK_EDP_CTRL>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_EMMC { + reg = <RK3399_PD_EMMC>; + clocks = <&cru ACLK_EMMC>; + pm_qos = <&qos_emmc>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_GMAC { + reg = <RK3399_PD_GMAC>; + clocks = <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>; + pm_qos = <&qos_gmac>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_SD { + reg = <RK3399_PD_SD>; + clocks = <&cru HCLK_SDMMC>, + <&cru SCLK_SDMMC>; + pm_qos = <&qos_sd>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_SDIOAUDIO { + reg = <RK3399_PD_SDIOAUDIO>; + clocks = <&cru HCLK_SDIO>; + pm_qos = <&qos_sdioaudio>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_TCPD0 { + reg = <RK3399_PD_TCPD0>; + clocks = <&cru SCLK_UPHY0_TCPDCORE>, + <&cru SCLK_UPHY0_TCPDPHY_REF>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_TCPD1 { + reg = <RK3399_PD_TCPD1>; + clocks = <&cru SCLK_UPHY1_TCPDCORE>, + <&cru SCLK_UPHY1_TCPDPHY_REF>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_USB3 { + reg = <RK3399_PD_USB3>; + clocks = <&cru ACLK_USB3>; + pm_qos = <&qos_usb_otg0>, + <&qos_usb_otg1>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_VIO { + reg = <RK3399_PD_VIO>; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + power-domain@RK3399_PD_HDCP { + reg = <RK3399_PD_HDCP>; + clocks = <&cru ACLK_HDCP>, + <&cru HCLK_HDCP>, + <&cru PCLK_HDCP>; + pm_qos = <&qos_hdcp>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_ISP0 { + reg = <RK3399_PD_ISP0>; + clocks = <&cru ACLK_ISP0>, + <&cru HCLK_ISP0>; + pm_qos = <&qos_isp0_m0>, + <&qos_isp0_m1>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_ISP1 { + reg = <RK3399_PD_ISP1>; + clocks = <&cru ACLK_ISP1>, + <&cru HCLK_ISP1>; + pm_qos = <&qos_isp1_m0>, + <&qos_isp1_m1>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_VO { + reg = <RK3399_PD_VO>; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + power-domain@RK3399_PD_VOPB { + reg = <RK3399_PD_VOPB>; + clocks = <&cru ACLK_VOP0>, + <&cru HCLK_VOP0>; + pm_qos = <&qos_vop_big_r>, + <&qos_vop_big_w>; + #power-domain-cells = <0>; + }; + power-domain@RK3399_PD_VOPL { + reg = <RK3399_PD_VOPL>; + clocks = <&cru ACLK_VOP1>, + <&cru HCLK_VOP1>; + pm_qos = <&qos_vop_little>; + #power-domain-cells = <0>; + }; + }; + }; + }; + }; + + pmugrf: syscon@ff320000 { + compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xff320000 0x0 0x1000>; + + pmu_io_domains: io-domains { + compatible = "rockchip,rk3399-pmu-io-voltage-domain"; + status = "disabled"; + }; + }; + + spi3: spi@ff350000 { + compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff350000 0x0 0x1000>; + clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>; + clock-names = "spiclk", "apb_pclk"; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart4: serial@ff370000 { + compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff370000 0x0 0x100>; + clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>; + clock-names = "baudclk", "apb_pclk"; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_xfer>; + status = "disabled"; + }; + + i2c0: i2c@ff3c0000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff3c0000 0x0 0x1000>; + assigned-clocks = <&pmucru SCLK_I2C0_PMU>; + assigned-clock-rates = <200000000>; + clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@ff3d0000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff3d0000 0x0 0x1000>; + assigned-clocks = <&pmucru SCLK_I2C4_PMU>; + assigned-clock-rates = <200000000>; + clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c8: i2c@ff3e0000 { + compatible = "rockchip,rk3399-i2c"; + reg = <0x0 0xff3e0000 0x0 0x1000>; + assigned-clocks = <&pmucru SCLK_I2C8_PMU>; + assigned-clock-rates = <200000000>; + clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm0: pwm@ff420000 { + compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff420000 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; + clocks = <&pmucru PCLK_RKPWM_PMU>; + status = "disabled"; + }; + + pwm1: pwm@ff420010 { + compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff420010 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1_pin>; + clocks = <&pmucru PCLK_RKPWM_PMU>; + status = "disabled"; + }; + + pwm2: pwm@ff420020 { + compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff420020 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pin>; + clocks = <&pmucru PCLK_RKPWM_PMU>; + status = "disabled"; + }; + + pwm3: pwm@ff420030 { + compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; + reg = <0x0 0xff420030 0x0 0x10>; + #pwm-cells = <3>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm3a_pin>; + clocks = <&pmucru PCLK_RKPWM_PMU>; + status = "disabled"; + }; + + dfi: dfi@ff630000 { + reg = <0x00 0xff630000 0x00 0x4000>; + compatible = "rockchip,rk3399-dfi"; + rockchip,pmu = <&pmugrf>; + interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru PCLK_DDR_MON>; + clock-names = "pclk_ddr_mon"; + }; + + vpu: video-codec@ff650000 { + compatible = "rockchip,rk3399-vpu"; + reg = <0x0 0xff650000 0x0 0x800>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "vepu", "vdpu"; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; + clock-names = "aclk", "hclk"; + iommus = <&vpu_mmu>; + power-domains = <&power RK3399_PD_VCODEC>; + }; + + vpu_mmu: iommu@ff650800 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff650800 0x0 0x40>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + power-domains = <&power RK3399_PD_VCODEC>; + }; + + vdec: video-codec@ff660000 { + compatible = "rockchip,rk3399-vdec"; + reg = <0x0 0xff660000 0x0 0x480>; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>, + <&cru SCLK_VDU_CA>, <&cru SCLK_VDU_CORE>; + clock-names = "axi", "ahb", "cabac", "core"; + iommus = <&vdec_mmu>; + power-domains = <&power RK3399_PD_VDU>; + }; + + vdec_mmu: iommu@ff660480 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff660480 0x0 0x40>, <0x0 0xff6604c0 0x0 0x40>; + interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3399_PD_VDU>; + #iommu-cells = <0>; + }; + + iep_mmu: iommu@ff670800 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff670800 0x0 0x40>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + status = "disabled"; + }; + + rga: rga@ff680000 { + compatible = "rockchip,rk3399-rga"; + reg = <0x0 0xff680000 0x0 0x10000>; + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA_CORE>; + clock-names = "aclk", "hclk", "sclk"; + resets = <&cru SRST_RGA_CORE>, <&cru SRST_A_RGA>, <&cru SRST_H_RGA>; + reset-names = "core", "axi", "ahb"; + power-domains = <&power RK3399_PD_RGA>; + }; + + efuse0: efuse@ff690000 { + compatible = "rockchip,rk3399-efuse"; + reg = <0x0 0xff690000 0x0 0x80>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru PCLK_EFUSE1024NS>; + clock-names = "pclk_efuse"; + + /* Data cells */ + cpu_id: cpu-id@7 { + reg = <0x07 0x10>; + }; + cpub_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + gpu_leakage: gpu-leakage@18 { + reg = <0x18 0x1>; + }; + center_leakage: center-leakage@19 { + reg = <0x19 0x1>; + }; + cpul_leakage: cpu-leakage@1a { + reg = <0x1a 0x1>; + }; + logic_leakage: logic-leakage@1b { + reg = <0x1b 0x1>; + }; + wafer_info: wafer-info@1c { + reg = <0x1c 0x1>; + }; + }; + + dmac_bus: dma-controller@ff6d0000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff6d0000 0x0 0x4000>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>; + #dma-cells = <1>; + arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC0_PERILP>; + clock-names = "apb_pclk"; + }; + + dmac_peri: dma-controller@ff6e0000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff6e0000 0x0 0x4000>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>; + #dma-cells = <1>; + arm,pl330-periph-burst; + clocks = <&cru ACLK_DMAC1_PERILP>; + clock-names = "apb_pclk"; + }; + + pmucru: clock-controller@ff750000 { + compatible = "rockchip,rk3399-pmucru"; + reg = <0x0 0xff750000 0x0 0x1000>; + clocks = <&xin24m>; + clock-names = "xin24m"; + rockchip,grf = <&pmugrf>; + #clock-cells = <1>; + #reset-cells = <1>; + assigned-clocks = <&pmucru PLL_PPLL>; + assigned-clock-rates = <676000000>; + }; + + cru: clock-controller@ff760000 { + compatible = "rockchip,rk3399-cru"; + reg = <0x0 0xff760000 0x0 0x1000>; + clocks = <&xin24m>; + clock-names = "xin24m"; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + assigned-clocks = + <&cru PLL_GPLL>, <&cru PLL_CPLL>, + <&cru PLL_NPLL>, + <&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>, + <&cru PCLK_PERIHP>, + <&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>, + <&cru PCLK_PERILP0>, <&cru ACLK_CCI>, + <&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>, + <&cru ACLK_VIO>, <&cru ACLK_HDCP>, + <&cru ACLK_GIC_PRE>, + <&cru PCLK_DDR>, + <&cru ACLK_VDU>; + assigned-clock-rates = + <594000000>, <800000000>, + <1000000000>, + <150000000>, <75000000>, + <37500000>, + <100000000>, <100000000>, + <50000000>, <600000000>, + <100000000>, <50000000>, + <400000000>, <400000000>, + <200000000>, + <200000000>, + <400000000>; + }; + + grf: syscon@ff770000 { + compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff770000 0x0 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + + io_domains: io-domains { + compatible = "rockchip,rk3399-io-voltage-domain"; + status = "disabled"; + }; + + mipi_dphy_rx0: mipi-dphy-rx0 { + compatible = "rockchip,rk3399-mipi-dphy-rx0"; + clocks = <&cru SCLK_MIPIDPHY_REF>, + <&cru SCLK_DPHY_RX0_CFG>, + <&cru PCLK_VIO_GRF>; + clock-names = "dphy-ref", "dphy-cfg", "grf"; + power-domains = <&power RK3399_PD_VIO>; + #phy-cells = <0>; + status = "disabled"; + }; + + u2phy0: usb2phy@e450 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe450 0x10>; + clocks = <&cru SCLK_USB2PHY0_REF>; + clock-names = "phyclk"; + #clock-cells = <0>; + clock-output-names = "clk_usbphy0_480m"; + status = "disabled"; + + u2phy0_host: host-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "linestate"; + status = "disabled"; + }; + + u2phy0_otg: otg-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "otg-bvalid", "otg-id", + "linestate"; + status = "disabled"; + }; + }; + + u2phy1: usb2phy@e460 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe460 0x10>; + clocks = <&cru SCLK_USB2PHY1_REF>; + clock-names = "phyclk"; + #clock-cells = <0>; + clock-output-names = "clk_usbphy1_480m"; + status = "disabled"; + + u2phy1_host: host-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "linestate"; + status = "disabled"; + }; + + u2phy1_otg: otg-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "otg-bvalid", "otg-id", + "linestate"; + status = "disabled"; + }; + }; + + emmc_phy: phy@f780 { + compatible = "rockchip,rk3399-emmc-phy"; + reg = <0xf780 0x24>; + clocks = <&sdhci>; + clock-names = "emmcclk"; + drive-impedance-ohm = <50>; + #phy-cells = <0>; + status = "disabled"; + }; + + pcie_phy: pcie-phy { + compatible = "rockchip,rk3399-pcie-phy"; + clocks = <&cru SCLK_PCIEPHY_REF>; + clock-names = "refclk"; + #phy-cells = <1>; + resets = <&cru SRST_PCIEPHY>; + reset-names = "phy"; + status = "disabled"; + }; + }; + + tcphy0: phy@ff7c0000 { + compatible = "rockchip,rk3399-typec-phy"; + reg = <0x0 0xff7c0000 0x0 0x40000>; + clocks = <&cru SCLK_UPHY0_TCPDCORE>, + <&cru SCLK_UPHY0_TCPDPHY_REF>; + clock-names = "tcpdcore", "tcpdphy-ref"; + assigned-clocks = <&cru SCLK_UPHY0_TCPDCORE>; + assigned-clock-rates = <50000000>; + power-domains = <&power RK3399_PD_TCPD0>; + resets = <&cru SRST_UPHY0>, + <&cru SRST_UPHY0_PIPE_L00>, + <&cru SRST_P_UPHY0_TCPHY>; + reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; + rockchip,grf = <&grf>; + status = "disabled"; + + tcphy0_dp: dp-port { + #phy-cells = <0>; + }; + + tcphy0_usb3: usb3-port { + #phy-cells = <0>; + }; + }; + + tcphy1: phy@ff800000 { + compatible = "rockchip,rk3399-typec-phy"; + reg = <0x0 0xff800000 0x0 0x40000>; + clocks = <&cru SCLK_UPHY1_TCPDCORE>, + <&cru SCLK_UPHY1_TCPDPHY_REF>; + clock-names = "tcpdcore", "tcpdphy-ref"; + assigned-clocks = <&cru SCLK_UPHY1_TCPDCORE>; + assigned-clock-rates = <50000000>; + power-domains = <&power RK3399_PD_TCPD1>; + resets = <&cru SRST_UPHY1>, + <&cru SRST_UPHY1_PIPE_L00>, + <&cru SRST_P_UPHY1_TCPHY>; + reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; + rockchip,grf = <&grf>; + status = "disabled"; + + tcphy1_dp: dp-port { + #phy-cells = <0>; + }; + + tcphy1_usb3: usb3-port { + #phy-cells = <0>; + }; + }; + + watchdog@ff848000 { + compatible = "rockchip,rk3399-wdt", "snps,dw-wdt"; + reg = <0x0 0xff848000 0x0 0x100>; + clocks = <&cru PCLK_WDT>; + interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>; + }; + + rktimer: rktimer@ff850000 { + compatible = "rockchip,rk3399-timer"; + reg = <0x0 0xff850000 0x0 0x1000>; + interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>; + clock-names = "pclk", "timer"; + }; + + spdif: spdif@ff870000 { + compatible = "rockchip,rk3399-spdif"; + reg = <0x0 0xff870000 0x0 0x1000>; + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_bus 7>; + dma-names = "tx"; + clock-names = "mclk", "hclk"; + clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_bus>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s0: i2s@ff880000 { + compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff880000 0x0 0x1000>; + rockchip,grf = <&grf>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_bus 0>, <&dmac_bus 1>; + dma-names = "tx", "rx"; + clock-names = "i2s_clk", "i2s_hclk"; + clocks = <&cru SCLK_I2S0_8CH>, <&cru HCLK_I2S0_8CH>; + pinctrl-names = "bclk_on", "bclk_off"; + pinctrl-0 = <&i2s0_8ch_bus>; + pinctrl-1 = <&i2s0_8ch_bus_bclk_off>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s1: i2s@ff890000 { + compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff890000 0x0 0x1000>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_bus 2>, <&dmac_bus 3>; + dma-names = "tx", "rx"; + clock-names = "i2s_clk", "i2s_hclk"; + clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_bus>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s2: i2s@ff8a0000 { + compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff8a0000 0x0 0x1000>; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dmac_bus 4>, <&dmac_bus 5>; + dma-names = "tx", "rx"; + clock-names = "i2s_clk", "i2s_hclk"; + clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>; + power-domains = <&power RK3399_PD_SDIOAUDIO>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + vopl: vop@ff8f0000 { + compatible = "rockchip,rk3399-vop-lit"; + reg = <0x0 0xff8f0000 0x0 0x2000>, <0x0 0xff8f2000 0x0 0x400>; + interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; + assigned-clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>; + assigned-clock-rates = <400000000>, <100000000>; + clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + iommus = <&vopl_mmu>; + power-domains = <&power RK3399_PD_VOPL>; + resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>; + reset-names = "axi", "ahb", "dclk"; + status = "disabled"; + + vopl_out: port { + #address-cells = <1>; + #size-cells = <0>; + + vopl_out_mipi: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_in_vopl>; + }; + + vopl_out_edp: endpoint@1 { + reg = <1>; + remote-endpoint = <&edp_in_vopl>; + }; + + vopl_out_hdmi: endpoint@2 { + reg = <2>; + remote-endpoint = <&hdmi_in_vopl>; + }; + + vopl_out_mipi1: endpoint@3 { + reg = <3>; + remote-endpoint = <&mipi1_in_vopl>; + }; + + vopl_out_dp: endpoint@4 { + reg = <4>; + remote-endpoint = <&dp_in_vopl>; + }; + }; + }; + + vopl_mmu: iommu@ff8f3f00 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff8f3f00 0x0 0x100>; + interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3399_PD_VOPL>; + #iommu-cells = <0>; + status = "disabled"; + }; + + vopb: vop@ff900000 { + compatible = "rockchip,rk3399-vop-big"; + reg = <0x0 0xff900000 0x0 0x2000>, <0x0 0xff902000 0x0 0x1000>; + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>; + assigned-clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>; + assigned-clock-rates = <400000000>, <100000000>; + clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + iommus = <&vopb_mmu>; + power-domains = <&power RK3399_PD_VOPB>; + resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>; + reset-names = "axi", "ahb", "dclk"; + status = "disabled"; + + vopb_out: port { + #address-cells = <1>; + #size-cells = <0>; + + vopb_out_edp: endpoint@0 { + reg = <0>; + remote-endpoint = <&edp_in_vopb>; + }; + + vopb_out_mipi: endpoint@1 { + reg = <1>; + remote-endpoint = <&mipi_in_vopb>; + }; + + vopb_out_hdmi: endpoint@2 { + reg = <2>; + remote-endpoint = <&hdmi_in_vopb>; + }; + + vopb_out_mipi1: endpoint@3 { + reg = <3>; + remote-endpoint = <&mipi1_in_vopb>; + }; + + vopb_out_dp: endpoint@4 { + reg = <4>; + remote-endpoint = <&dp_in_vopb>; + }; + }; + }; + + vopb_mmu: iommu@ff903f00 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff903f00 0x0 0x100>; + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3399_PD_VOPB>; + #iommu-cells = <0>; + status = "disabled"; + }; + + isp0: isp0@ff910000 { + compatible = "rockchip,rk3399-cif-isp"; + reg = <0x0 0xff910000 0x0 0x4000>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_ISP0>, + <&cru ACLK_ISP0_WRAPPER>, + <&cru HCLK_ISP0_WRAPPER>; + clock-names = "isp", "aclk", "hclk"; + iommus = <&isp0_mmu>; + phys = <&mipi_dphy_rx0>; + phy-names = "dphy"; + power-domains = <&power RK3399_PD_ISP0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; + + isp0_mmu: iommu@ff914000 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_ISP0_WRAPPER>, <&cru HCLK_ISP0_WRAPPER>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + power-domains = <&power RK3399_PD_ISP0>; + rockchip,disable-mmu-reset; + }; + + isp1: isp1@ff920000 { + compatible = "rockchip,rk3399-cif-isp"; + reg = <0x0 0xff920000 0x0 0x4000>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_ISP1>, + <&cru ACLK_ISP1_WRAPPER>, + <&cru HCLK_ISP1_WRAPPER>; + clock-names = "isp", "aclk", "hclk"; + iommus = <&isp1_mmu>; + phys = <&mipi_dsi1>; + phy-names = "dphy"; + power-domains = <&power RK3399_PD_ISP1>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; + + isp1_mmu: iommu@ff924000 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff924000 0x0 0x100>, <0x0 0xff925000 0x0 0x100>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_ISP1_WRAPPER>, <&cru HCLK_ISP1_WRAPPER>; + clock-names = "aclk", "iface"; + #iommu-cells = <0>; + power-domains = <&power RK3399_PD_ISP1>; + rockchip,disable-mmu-reset; + }; + + hdmi_sound: hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "hdmi-sound"; + status = "disabled"; + + simple-audio-card,cpu { + sound-dai = <&i2s2>; + }; + simple-audio-card,codec { + sound-dai = <&hdmi>; + }; + }; + + hdmi: hdmi@ff940000 { + compatible = "rockchip,rk3399-dw-hdmi"; + reg = <0x0 0xff940000 0x0 0x20000>; + reg-io-width = <4>; + interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru PCLK_HDMI_CTRL>, + <&cru SCLK_HDMI_SFR>, + <&cru SCLK_HDMI_CEC>, + <&cru PCLK_VIO_GRF>, + <&cru PLL_VPLL>; + clock-names = "iahb", "isfr", "cec", "grf", "ref"; + power-domains = <&power RK3399_PD_HDCP>; + rockchip,grf = <&grf>; + #sound-dai-cells = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + hdmi_in: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + hdmi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_hdmi>; + }; + hdmi_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_hdmi>; + }; + }; + + hdmi_out: port@1 { + reg = <1>; + }; + }; + }; + + mipi_dsi: dsi@ff960000 { + compatible = "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0x0 0xff960000 0x0 0x8000>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_DPHY_PLL>, <&cru PCLK_MIPI_DSI0>, + <&cru SCLK_DPHY_TX0_CFG>, <&cru PCLK_VIO_GRF>; + clock-names = "ref", "pclk", "phy_cfg", "grf"; + power-domains = <&power RK3399_PD_VIO>; + resets = <&cru SRST_P_MIPI_DSI0>; + reset-names = "apb"; + rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi_in: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_mipi>; + }; + + mipi_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_mipi>; + }; + }; + + mipi_out: port@1 { + reg = <1>; + }; + }; + }; + + mipi_dsi1: dsi@ff968000 { + compatible = "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0x0 0xff968000 0x0 0x8000>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru SCLK_DPHY_PLL>, <&cru PCLK_MIPI_DSI1>, + <&cru SCLK_DPHY_TX1RX1_CFG>, <&cru PCLK_VIO_GRF>; + clock-names = "ref", "pclk", "phy_cfg", "grf"; + power-domains = <&power RK3399_PD_VIO>; + resets = <&cru SRST_P_MIPI_DSI1>; + reset-names = "apb"; + rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi1_in: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_mipi1>; + }; + + mipi1_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_mipi1>; + }; + }; + + mipi1_out: port@1 { + reg = <1>; + }; + }; + }; + + edp: dp@ff970000 { + compatible = "rockchip,rk3399-edp"; + reg = <0x0 0xff970000 0x0 0x8000>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>, <&cru PCLK_VIO_GRF>; + clock-names = "dp", "pclk", "grf"; + pinctrl-names = "default"; + pinctrl-0 = <&edp_hpd>; + power-domains = <&power RK3399_PD_EDP>; + resets = <&cru SRST_P_EDP_CTRL>; + reset-names = "dp"; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + edp_in: port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + edp_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_edp>; + }; + + edp_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_edp>; + }; + }; + + edp_out: port@1 { + reg = <1>; + }; + }; + }; + + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "job", "mmu", "gpu"; + clocks = <&cru ACLK_GPU>; + #cooling-cells = <2>; + dynamic-power-coefficient = <2640>; + power-domains = <&power RK3399_PD_GPU>; + status = "disabled"; + }; + + pinctrl: pinctrl { + compatible = "rockchip,rk3399-pinctrl"; + rockchip,grf = <&grf>; + rockchip,pmu = <&pmugrf>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio0: gpio@ff720000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff720000 0x0 0x100>; + clocks = <&pmucru PCLK_GPIO0_PMU>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio1: gpio@ff730000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff730000 0x0 0x100>; + clocks = <&pmucru PCLK_GPIO1_PMU>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH 0>; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio2: gpio@ff780000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff780000 0x0 0x100>; + clocks = <&cru PCLK_GPIO2>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH 0>; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio3: gpio@ff788000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff788000 0x0 0x100>; + clocks = <&cru PCLK_GPIO3>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + gpio4: gpio@ff790000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff790000 0x0 0x100>; + clocks = <&cru PCLK_GPIO4>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; + + gpio-controller; + #gpio-cells = <0x2>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + pcfg_pull_up: pcfg-pull-up { + bias-pull-up; + }; + + pcfg_pull_down: pcfg-pull-down { + bias-pull-down; + }; + + pcfg_pull_none: pcfg-pull-none { + bias-disable; + }; + + pcfg_pull_none_12ma: pcfg-pull-none-12ma { + bias-disable; + drive-strength = <12>; + }; + + pcfg_pull_none_13ma: pcfg-pull-none-13ma { + bias-disable; + drive-strength = <13>; + }; + + pcfg_pull_none_18ma: pcfg-pull-none-18ma { + bias-disable; + drive-strength = <18>; + }; + + pcfg_pull_none_20ma: pcfg-pull-none-20ma { + bias-disable; + drive-strength = <20>; + }; + + pcfg_pull_up_2ma: pcfg-pull-up-2ma { + bias-pull-up; + drive-strength = <2>; + }; + + pcfg_pull_up_8ma: pcfg-pull-up-8ma { + bias-pull-up; + drive-strength = <8>; + }; + + pcfg_pull_up_18ma: pcfg-pull-up-18ma { + bias-pull-up; + drive-strength = <18>; + }; + + pcfg_pull_up_20ma: pcfg-pull-up-20ma { + bias-pull-up; + drive-strength = <20>; + }; + + pcfg_pull_down_4ma: pcfg-pull-down-4ma { + bias-pull-down; + drive-strength = <4>; + }; + + pcfg_pull_down_8ma: pcfg-pull-down-8ma { + bias-pull-down; + drive-strength = <8>; + }; + + pcfg_pull_down_12ma: pcfg-pull-down-12ma { + bias-pull-down; + drive-strength = <12>; + }; + + pcfg_pull_down_18ma: pcfg-pull-down-18ma { + bias-pull-down; + drive-strength = <18>; + }; + + pcfg_pull_down_20ma: pcfg-pull-down-20ma { + bias-pull-down; + drive-strength = <20>; + }; + + pcfg_output_high: pcfg-output-high { + output-high; + }; + + pcfg_output_low: pcfg-output-low { + output-low; + }; + + pcfg_input_enable: pcfg-input-enable { + input-enable; + }; + + pcfg_input_pull_up: pcfg-input-pull-up { + input-enable; + bias-pull-up; + }; + + pcfg_input_pull_down: pcfg-input-pull-down { + input-enable; + bias-pull-down; + }; + + clock { + clk_32k: clk-32k { + rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>; + }; + }; + + cif { + cif_clkin: cif-clkin { + rockchip,pins = + <2 RK_PB2 3 &pcfg_pull_none>; + }; + + cif_clkouta: cif-clkouta { + rockchip,pins = + <2 RK_PB3 3 &pcfg_pull_none>; + }; + }; + + edp { + edp_hpd: edp-hpd { + rockchip,pins = + <4 RK_PC7 2 &pcfg_pull_none>; + }; + }; + + gmac { + rgmii_pins: rgmii-pins { + rockchip,pins = + /* mac_txclk */ + <3 RK_PC1 1 &pcfg_pull_none_13ma>, + /* mac_rxclk */ + <3 RK_PB6 1 &pcfg_pull_none>, + /* mac_mdio */ + <3 RK_PB5 1 &pcfg_pull_none>, + /* mac_txen */ + <3 RK_PB4 1 &pcfg_pull_none_13ma>, + /* mac_clk */ + <3 RK_PB3 1 &pcfg_pull_none>, + /* mac_rxdv */ + <3 RK_PB1 1 &pcfg_pull_none>, + /* mac_mdc */ + <3 RK_PB0 1 &pcfg_pull_none>, + /* mac_rxd1 */ + <3 RK_PA7 1 &pcfg_pull_none>, + /* mac_rxd0 */ + <3 RK_PA6 1 &pcfg_pull_none>, + /* mac_txd1 */ + <3 RK_PA5 1 &pcfg_pull_none_13ma>, + /* mac_txd0 */ + <3 RK_PA4 1 &pcfg_pull_none_13ma>, + /* mac_rxd3 */ + <3 RK_PA3 1 &pcfg_pull_none>, + /* mac_rxd2 */ + <3 RK_PA2 1 &pcfg_pull_none>, + /* mac_txd3 */ + <3 RK_PA1 1 &pcfg_pull_none_13ma>, + /* mac_txd2 */ + <3 RK_PA0 1 &pcfg_pull_none_13ma>; + }; + + rmii_pins: rmii-pins { + rockchip,pins = + /* mac_mdio */ + <3 RK_PB5 1 &pcfg_pull_none>, + /* mac_txen */ + <3 RK_PB4 1 &pcfg_pull_none_13ma>, + /* mac_clk */ + <3 RK_PB3 1 &pcfg_pull_none>, + /* mac_rxer */ + <3 RK_PB2 1 &pcfg_pull_none>, + /* mac_rxdv */ + <3 RK_PB1 1 &pcfg_pull_none>, + /* mac_mdc */ + <3 RK_PB0 1 &pcfg_pull_none>, + /* mac_rxd1 */ + <3 RK_PA7 1 &pcfg_pull_none>, + /* mac_rxd0 */ + <3 RK_PA6 1 &pcfg_pull_none>, + /* mac_txd1 */ + <3 RK_PA5 1 &pcfg_pull_none_13ma>, + /* mac_txd0 */ + <3 RK_PA4 1 &pcfg_pull_none_13ma>; + }; + }; + + i2c0 { + i2c0_xfer: i2c0-xfer { + rockchip,pins = + <1 RK_PB7 2 &pcfg_pull_none>, + <1 RK_PC0 2 &pcfg_pull_none>; + }; + }; + + i2c1 { + i2c1_xfer: i2c1-xfer { + rockchip,pins = + <4 RK_PA2 1 &pcfg_pull_none>, + <4 RK_PA1 1 &pcfg_pull_none>; + }; + }; + + i2c2 { + i2c2_xfer: i2c2-xfer { + rockchip,pins = + <2 RK_PA1 2 &pcfg_pull_none_12ma>, + <2 RK_PA0 2 &pcfg_pull_none_12ma>; + }; + }; + + i2c3 { + i2c3_xfer: i2c3-xfer { + rockchip,pins = + <4 RK_PC1 1 &pcfg_pull_none>, + <4 RK_PC0 1 &pcfg_pull_none>; + }; + }; + + i2c4 { + i2c4_xfer: i2c4-xfer { + rockchip,pins = + <1 RK_PB4 1 &pcfg_pull_none>, + <1 RK_PB3 1 &pcfg_pull_none>; + }; + }; + + i2c5 { + i2c5_xfer: i2c5-xfer { + rockchip,pins = + <3 RK_PB3 2 &pcfg_pull_none>, + <3 RK_PB2 2 &pcfg_pull_none>; + }; + }; + + i2c6 { + i2c6_xfer: i2c6-xfer { + rockchip,pins = + <2 RK_PB2 2 &pcfg_pull_none>, + <2 RK_PB1 2 &pcfg_pull_none>; + }; + }; + + i2c7 { + i2c7_xfer: i2c7-xfer { + rockchip,pins = + <2 RK_PB0 2 &pcfg_pull_none>, + <2 RK_PA7 2 &pcfg_pull_none>; + }; + }; + + i2c8 { + i2c8_xfer: i2c8-xfer { + rockchip,pins = + <1 RK_PC5 1 &pcfg_pull_none>, + <1 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + i2s0 { + i2s0_2ch_bus: i2s0-2ch-bus { + rockchip,pins = + <3 RK_PD0 1 &pcfg_pull_none>, + <3 RK_PD1 1 &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>, + <4 RK_PA0 1 &pcfg_pull_none>; + }; + + i2s0_2ch_bus_bclk_off: i2s0-2ch-bus-bclk-off { + rockchip,pins = + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PD1 1 &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>, + <4 RK_PA0 1 &pcfg_pull_none>; + }; + + i2s0_8ch_bus: i2s0-8ch-bus { + rockchip,pins = + <3 RK_PD0 1 &pcfg_pull_none>, + <3 RK_PD1 1 &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD4 1 &pcfg_pull_none>, + <3 RK_PD5 1 &pcfg_pull_none>, + <3 RK_PD6 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>, + <4 RK_PA0 1 &pcfg_pull_none>; + }; + + i2s0_8ch_bus_bclk_off: i2s0-8ch-bus-bclk-off { + rockchip,pins = + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PD1 1 &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD4 1 &pcfg_pull_none>, + <3 RK_PD5 1 &pcfg_pull_none>, + <3 RK_PD6 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>, + <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + i2s1 { + i2s1_2ch_bus: i2s1-2ch-bus { + rockchip,pins = + <4 RK_PA3 1 &pcfg_pull_none>, + <4 RK_PA4 1 &pcfg_pull_none>, + <4 RK_PA5 1 &pcfg_pull_none>, + <4 RK_PA6 1 &pcfg_pull_none>, + <4 RK_PA7 1 &pcfg_pull_none>; + }; + + i2s1_2ch_bus_bclk_off: i2s1-2ch-bus-bclk-off { + rockchip,pins = + <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>, + <4 RK_PA4 1 &pcfg_pull_none>, + <4 RK_PA5 1 &pcfg_pull_none>, + <4 RK_PA6 1 &pcfg_pull_none>, + <4 RK_PA7 1 &pcfg_pull_none>; + }; + }; + + sdio0 { + sdio0_bus1: sdio0-bus1 { + rockchip,pins = + <2 RK_PC4 1 &pcfg_pull_up>; + }; + + sdio0_bus4: sdio0-bus4 { + rockchip,pins = + <2 RK_PC4 1 &pcfg_pull_up>, + <2 RK_PC5 1 &pcfg_pull_up>, + <2 RK_PC6 1 &pcfg_pull_up>, + <2 RK_PC7 1 &pcfg_pull_up>; + }; + + sdio0_cmd: sdio0-cmd { + rockchip,pins = + <2 RK_PD0 1 &pcfg_pull_up>; + }; + + sdio0_clk: sdio0-clk { + rockchip,pins = + <2 RK_PD1 1 &pcfg_pull_none>; + }; + + sdio0_cd: sdio0-cd { + rockchip,pins = + <2 RK_PD2 1 &pcfg_pull_up>; + }; + + sdio0_pwr: sdio0-pwr { + rockchip,pins = + <2 RK_PD3 1 &pcfg_pull_up>; + }; + + sdio0_bkpwr: sdio0-bkpwr { + rockchip,pins = + <2 RK_PD4 1 &pcfg_pull_up>; + }; + + sdio0_wp: sdio0-wp { + rockchip,pins = + <0 RK_PA3 1 &pcfg_pull_up>; + }; + + sdio0_int: sdio0-int { + rockchip,pins = + <0 RK_PA4 1 &pcfg_pull_up>; + }; + }; + + sdmmc { + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = + <4 RK_PB0 1 &pcfg_pull_up>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = + <4 RK_PB0 1 &pcfg_pull_up>, + <4 RK_PB1 1 &pcfg_pull_up>, + <4 RK_PB2 1 &pcfg_pull_up>, + <4 RK_PB3 1 &pcfg_pull_up>; + }; + + sdmmc_clk: sdmmc-clk { + rockchip,pins = + <4 RK_PB4 1 &pcfg_pull_none>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = + <4 RK_PB5 1 &pcfg_pull_up>; + }; + + sdmmc_cd: sdmmc-cd { + rockchip,pins = + <0 RK_PA7 1 &pcfg_pull_up>; + }; + + sdmmc_wp: sdmmc-wp { + rockchip,pins = + <0 RK_PB0 1 &pcfg_pull_up>; + }; + }; + + suspend { + ap_pwroff: ap-pwroff { + rockchip,pins = <1 RK_PA5 1 &pcfg_pull_none>; + }; + + ddrio_pwroff: ddrio-pwroff { + rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>; + }; + }; + + spdif { + spdif_bus: spdif-bus { + rockchip,pins = + <4 RK_PC5 1 &pcfg_pull_none>; + }; + + spdif_bus_1: spdif-bus-1 { + rockchip,pins = + <3 RK_PC0 3 &pcfg_pull_none>; + }; + }; + + spi0 { + spi0_clk: spi0-clk { + rockchip,pins = + <3 RK_PA6 2 &pcfg_pull_up>; + }; + spi0_cs0: spi0-cs0 { + rockchip,pins = + <3 RK_PA7 2 &pcfg_pull_up>; + }; + spi0_cs1: spi0-cs1 { + rockchip,pins = + <3 RK_PB0 2 &pcfg_pull_up>; + }; + spi0_tx: spi0-tx { + rockchip,pins = + <3 RK_PA5 2 &pcfg_pull_up>; + }; + spi0_rx: spi0-rx { + rockchip,pins = + <3 RK_PA4 2 &pcfg_pull_up>; + }; + }; + + spi1 { + spi1_clk: spi1-clk { + rockchip,pins = + <1 RK_PB1 2 &pcfg_pull_up>; + }; + spi1_cs0: spi1-cs0 { + rockchip,pins = + <1 RK_PB2 2 &pcfg_pull_up>; + }; + spi1_rx: spi1-rx { + rockchip,pins = + <1 RK_PA7 2 &pcfg_pull_up>; + }; + spi1_tx: spi1-tx { + rockchip,pins = + <1 RK_PB0 2 &pcfg_pull_up>; + }; + }; + + spi2 { + spi2_clk: spi2-clk { + rockchip,pins = + <2 RK_PB3 1 &pcfg_pull_up>; + }; + spi2_cs0: spi2-cs0 { + rockchip,pins = + <2 RK_PB4 1 &pcfg_pull_up>; + }; + spi2_rx: spi2-rx { + rockchip,pins = + <2 RK_PB1 1 &pcfg_pull_up>; + }; + spi2_tx: spi2-tx { + rockchip,pins = + <2 RK_PB2 1 &pcfg_pull_up>; + }; + }; + + spi3 { + spi3_clk: spi3-clk { + rockchip,pins = + <1 RK_PC1 1 &pcfg_pull_up>; + }; + spi3_cs0: spi3-cs0 { + rockchip,pins = + <1 RK_PC2 1 &pcfg_pull_up>; + }; + spi3_rx: spi3-rx { + rockchip,pins = + <1 RK_PB7 1 &pcfg_pull_up>; + }; + spi3_tx: spi3-tx { + rockchip,pins = + <1 RK_PC0 1 &pcfg_pull_up>; + }; + }; + + spi4 { + spi4_clk: spi4-clk { + rockchip,pins = + <3 RK_PA2 2 &pcfg_pull_up>; + }; + spi4_cs0: spi4-cs0 { + rockchip,pins = + <3 RK_PA3 2 &pcfg_pull_up>; + }; + spi4_rx: spi4-rx { + rockchip,pins = + <3 RK_PA0 2 &pcfg_pull_up>; + }; + spi4_tx: spi4-tx { + rockchip,pins = + <3 RK_PA1 2 &pcfg_pull_up>; + }; + }; + + spi5 { + spi5_clk: spi5-clk { + rockchip,pins = + <2 RK_PC6 2 &pcfg_pull_up>; + }; + spi5_cs0: spi5-cs0 { + rockchip,pins = + <2 RK_PC7 2 &pcfg_pull_up>; + }; + spi5_rx: spi5-rx { + rockchip,pins = + <2 RK_PC4 2 &pcfg_pull_up>; + }; + spi5_tx: spi5-tx { + rockchip,pins = + <2 RK_PC5 2 &pcfg_pull_up>; + }; + }; + + testclk { + test_clkout0: test-clkout0 { + rockchip,pins = + <0 RK_PA0 1 &pcfg_pull_none>; + }; + + test_clkout1: test-clkout1 { + rockchip,pins = + <2 RK_PD1 2 &pcfg_pull_none>; + }; + + test_clkout2: test-clkout2 { + rockchip,pins = + <0 RK_PB0 3 &pcfg_pull_none>; + }; + }; + + tsadc { + otp_pin: otp-pin { + rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + otp_out: otp-out { + rockchip,pins = <1 RK_PA6 1 &pcfg_pull_none>; + }; + }; + + uart0 { + uart0_xfer: uart0-xfer { + rockchip,pins = + <2 RK_PC0 1 &pcfg_pull_up>, + <2 RK_PC1 1 &pcfg_pull_none>; + }; + + uart0_cts: uart0-cts { + rockchip,pins = + <2 RK_PC2 1 &pcfg_pull_none>; + }; + + uart0_rts: uart0-rts { + rockchip,pins = + <2 RK_PC3 1 &pcfg_pull_none>; + }; + }; + + uart1 { + uart1_xfer: uart1-xfer { + rockchip,pins = + <3 RK_PB4 2 &pcfg_pull_up>, + <3 RK_PB5 2 &pcfg_pull_none>; + }; + }; + + uart2a { + uart2a_xfer: uart2a-xfer { + rockchip,pins = + <4 RK_PB0 2 &pcfg_pull_up>, + <4 RK_PB1 2 &pcfg_pull_none>; + }; + }; + + uart2b { + uart2b_xfer: uart2b-xfer { + rockchip,pins = + <4 RK_PC0 2 &pcfg_pull_up>, + <4 RK_PC1 2 &pcfg_pull_none>; + }; + }; + + uart2c { + uart2c_xfer: uart2c-xfer { + rockchip,pins = + <4 RK_PC3 1 &pcfg_pull_up>, + <4 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + uart3 { + uart3_xfer: uart3-xfer { + rockchip,pins = + <3 RK_PB6 2 &pcfg_pull_up>, + <3 RK_PB7 2 &pcfg_pull_none>; + }; + + uart3_cts: uart3-cts { + rockchip,pins = + <3 RK_PC0 2 &pcfg_pull_none>; + }; + + uart3_rts: uart3-rts { + rockchip,pins = + <3 RK_PC1 2 &pcfg_pull_none>; + }; + }; + + uart4 { + uart4_xfer: uart4-xfer { + rockchip,pins = + <1 RK_PA7 1 &pcfg_pull_up>, + <1 RK_PB0 1 &pcfg_pull_none>; + }; + }; + + uarthdcp { + uarthdcp_xfer: uarthdcp-xfer { + rockchip,pins = + <4 RK_PC5 2 &pcfg_pull_up>, + <4 RK_PC6 2 &pcfg_pull_none>; + }; + }; + + pwm0 { + pwm0_pin: pwm0-pin { + rockchip,pins = + <4 RK_PC2 1 &pcfg_pull_none>; + }; + + pwm0_pin_pull_down: pwm0-pin-pull-down { + rockchip,pins = + <4 RK_PC2 1 &pcfg_pull_down>; + }; + + vop0_pwm_pin: vop0-pwm-pin { + rockchip,pins = + <4 RK_PC2 2 &pcfg_pull_none>; + }; + + vop1_pwm_pin: vop1-pwm-pin { + rockchip,pins = + <4 RK_PC2 3 &pcfg_pull_none>; + }; + }; + + pwm1 { + pwm1_pin: pwm1-pin { + rockchip,pins = + <4 RK_PC6 1 &pcfg_pull_none>; + }; + + pwm1_pin_pull_down: pwm1-pin-pull-down { + rockchip,pins = + <4 RK_PC6 1 &pcfg_pull_down>; + }; + }; + + pwm2 { + pwm2_pin: pwm2-pin { + rockchip,pins = + <1 RK_PC3 1 &pcfg_pull_none>; + }; + + pwm2_pin_pull_down: pwm2-pin-pull-down { + rockchip,pins = + <1 RK_PC3 1 &pcfg_pull_down>; + }; + }; + + pwm3a { + pwm3a_pin: pwm3a-pin { + rockchip,pins = + <0 RK_PA6 1 &pcfg_pull_none>; + }; + }; + + pwm3b { + pwm3b_pin: pwm3b-pin { + rockchip,pins = + <1 RK_PB6 1 &pcfg_pull_none>; + }; + }; + + hdmi { + hdmi_i2c_xfer: hdmi-i2c-xfer { + rockchip,pins = + <4 RK_PC1 3 &pcfg_pull_none>, + <4 RK_PC0 3 &pcfg_pull_none>; + }; + + hdmi_cec: hdmi-cec { + rockchip,pins = + <4 RK_PC7 1 &pcfg_pull_none>; + }; + }; + + pcie { + pcie_clkreqn_cpm: pci-clkreqn-cpm { + rockchip,pins = + <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_clkreqnb_cpm: pci-clkreqnb-cpm { + rockchip,pins = + <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts b/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts index 173da81fc231..4feb78797982 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-eaidk-610.dts @@ -8,7 +8,6 @@ #include <dt-bindings/pwm/pwm.h> #include <dt-bindings/usb/pd.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "OPEN AI LAB EAIDK-610"; @@ -542,7 +541,7 @@ status = "okay"; rt5651: audio-codec@1a { - compatible = "rockchip,rt5651"; + compatible = "realtek,rt5651"; reg = <0x1a>; clocks = <&cru SCLK_I2S_8CH_OUT>; clock-names = "mclk"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index 55eca7a50a1f..54e67d2dac09 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -5,7 +5,7 @@ /dts-v1/; #include <dt-bindings/pwm/pwm.h> -#include "rk3399.dtsi" +#include "rk3399-base.dtsi" / { model = "Rockchip RK3399 Evaluation Board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts index 260415d99aeb..f4491317a1b0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts @@ -9,7 +9,6 @@ #include <dt-bindings/pwm/pwm.h> #include <dt-bindings/usb/pd.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Firefly-RK3399 Board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi index 3cd63d1e8f15..776c0eec04d7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi @@ -6,8 +6,7 @@ */ #include <dt-bindings/input/input.h> -#include "rk3399.dtsi" -#include "rk3399-op1-opp.dtsi" +#include "rk3399-op1.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts index 4a6ab6c2e24c..5a02502d21cd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts @@ -4,7 +4,6 @@ #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/irq.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Hugsun X99 TV BOX"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi index 9d9297bc5f04..c772985ae4e5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi @@ -9,7 +9,6 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/pwm/pwm.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts index 9586bb12a5d8..b0c1fb0b704e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts @@ -12,7 +12,6 @@ /dts-v1/; #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Kobol Helios64"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts index cb69e2145fa9..f12b1eb00575 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts @@ -8,7 +8,6 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/pwm/pwm.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Leez RK3399 P710"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi index b7f1e47978a6..7debc4a1b5fa 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi @@ -14,7 +14,6 @@ /dts-v1/; #include <dt-bindings/input/linux-event-codes.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-op1-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi index 783120e9cebe..b24bff511513 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-op1-opp.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-op1.dtsi @@ -3,6 +3,8 @@ * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd */ +#include "rk3399.dtsi" + / { cluster0_opp: opp-table-0 { compatible = "operating-points-v2"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi deleted file mode 100644 index fee5e7111279..000000000000 --- a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd - */ - -/ { - cluster0_opp: opp-table-0 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <408000000>; - opp-microvolt = <825000 825000 1250000>; - clock-latency-ns = <40000>; - }; - opp01 { - opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <825000 825000 1250000>; - }; - opp02 { - opp-hz = /bits/ 64 <816000000>; - opp-microvolt = <850000 850000 1250000>; - }; - opp03 { - opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <925000 925000 1250000>; - }; - opp04 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <1000000 1000000 1250000>; - }; - opp05 { - opp-hz = /bits/ 64 <1416000000>; - opp-microvolt = <1125000 1125000 1250000>; - }; - }; - - cluster1_opp: opp-table-1 { - compatible = "operating-points-v2"; - opp-shared; - - opp00 { - opp-hz = /bits/ 64 <408000000>; - opp-microvolt = <825000 825000 1250000>; - clock-latency-ns = <40000>; - }; - opp01 { - opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <825000 825000 1250000>; - }; - opp02 { - opp-hz = /bits/ 64 <816000000>; - opp-microvolt = <825000 825000 1250000>; - }; - opp03 { - opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <875000 875000 1250000>; - }; - opp04 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <950000 950000 1250000>; - }; - opp05 { - opp-hz = /bits/ 64 <1416000000>; - opp-microvolt = <1025000 1025000 1250000>; - }; - opp06 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <1100000 1100000 1250000>; - }; - opp07 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1200000 1200000 1250000>; - }; - }; - - gpu_opp_table: opp-table-2 { - compatible = "operating-points-v2"; - - opp00 { - opp-hz = /bits/ 64 <200000000>; - opp-microvolt = <825000 825000 1150000>; - }; - opp01 { - opp-hz = /bits/ 64 <297000000>; - opp-microvolt = <825000 825000 1150000>; - }; - opp02 { - opp-hz = /bits/ 64 <400000000>; - opp-microvolt = <825000 825000 1150000>; - }; - opp03 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <875000 875000 1150000>; - }; - opp04 { - opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <925000 925000 1150000>; - }; - opp05 { - opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <1100000 1100000 1150000>; - }; - }; -}; - -&cpu_l0 { - operating-points-v2 = <&cluster0_opp>; -}; - -&cpu_l1 { - operating-points-v2 = <&cluster0_opp>; -}; - -&cpu_l2 { - operating-points-v2 = <&cluster0_opp>; -}; - -&cpu_l3 { - operating-points-v2 = <&cluster0_opp>; -}; - -&cpu_b0 { - operating-points-v2 = <&cluster1_opp>; -}; - -&cpu_b1 { - operating-points-v2 = <&cluster1_opp>; -}; - -&gpu { - operating-points-v2 = <&gpu_opp_table>; -}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts index e26e2d86279c..07ec33f3f55f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts @@ -10,7 +10,6 @@ #include <dt-bindings/interrupt-controller/irq.h> #include "dt-bindings/usb/pd.h" #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Orange Pi RK3399 Board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts index 294eb2de263d..a5a7e374bc59 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts @@ -12,7 +12,6 @@ #include <dt-bindings/usb/pd.h> #include <dt-bindings/leds/common.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Pine64 Pinebook Pro"; @@ -32,12 +31,12 @@ backlight: edp-backlight { compatible = "pwm-backlight"; power-supply = <&vcc_12v>; - pwms = <&pwm0 0 740740 0>; + pwms = <&pwm0 0 125000 0>; }; bat: battery { compatible = "simple-battery"; - charge-full-design-microamp-hours = <9800000>; + charge-full-design-microamp-hours = <10000000>; voltage-max-design-microvolt = <4350000>; voltage-min-design-microvolt = <3000000>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts index ef754ea30a94..09a016ea8c76 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts @@ -14,7 +14,6 @@ #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/leds/common.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Pine64 PinePhone Pro"; @@ -167,7 +166,6 @@ regulator-max-microvolt = <1800000>; vin-supply = <&vcc3v3_sys>; gpio = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; }; /* MIPI DSI panel 2.8v supply */ @@ -179,7 +177,6 @@ regulator-max-microvolt = <2800000>; vin-supply = <&vcc3v3_sys>; gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; }; vibrator { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi index ccbe3a7a1d2c..650b1ba9c192 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi @@ -5,7 +5,6 @@ #include <dt-bindings/pwm/pwm.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { aliases { @@ -154,6 +153,22 @@ }; }; +&gpio3 { + /* + * The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module + * eMMC and SPI flash powered-down initially (in fact it keeps the + * reset signal asserted). BIOS_DISABLE_OVERRIDE pin allows to override + * that signal so that eMMC and SPI can be used regardless of the state + * of the signal. + */ + bios-disable-override-hog { + gpios = <RK_PD5 GPIO_ACTIVE_LOW>; + gpio-hog; + line-name = "bios_disable_override"; + output-high; + }; +}; + &gmac { assigned-clocks = <&cru SCLK_RMII_SRC>; assigned-clock-parents = <&clkin_gmac>; @@ -409,6 +424,7 @@ &i2s0 { pinctrl-0 = <&i2s0_2ch_bus>; + pinctrl-1 = <&i2s0_2ch_bus_bclk_off>; rockchip,playback-channels = <2>; rockchip,capture-channels = <2>; status = "okay"; @@ -417,8 +433,8 @@ /* * As Q7 does not specify neither a global nor a RX clock for I2S these * signals are not used. Furthermore I2S0_LRCK_RX is used as GPIO. - * Therefore we have to redefine the i2s0_2ch_bus definition to prevent - * conflicts. + * Therefore we have to redefine the i2s0_2ch_bus and i2s0_2ch_bus_bclk_off + * definitions to prevent conflicts. */ &i2s0_2ch_bus { rockchip,pins = @@ -428,6 +444,14 @@ <3 RK_PD7 1 &pcfg_pull_none>; }; +&i2s0_2ch_bus_bclk_off { + rockchip,pins = + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>; +}; + &io_domains { status = "okay"; bt656-supply = <&vcc_1v8>; @@ -449,9 +473,14 @@ &pinctrl { pinctrl-names = "default"; - pinctrl-0 = <&q7_thermal_pin>; + pinctrl-0 = <&q7_thermal_pin &bios_disable_override_hog_pin>; gpios { + bios_disable_override_hog_pin: bios-disable-override-hog-pin { + rockchip,pins = + <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + q7_thermal_pin: q7-thermal-pin { rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts index 7ba1c28f70a9..2f06bfdd70bf 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts @@ -114,7 +114,6 @@ es8388: es8388@11 { compatible = "everest,es8388"; reg = <0x11>; - clock-names = "mclk"; clocks = <&cru SCLK_I2S_8CH_OUT>; #sound-dai-cells = <0>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi index ca7a446b6568..d95b1cde1fc3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi @@ -7,7 +7,6 @@ #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/pwm/pwm.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { model = "Firefly ROC-RK3399-PC Board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts index 972aea843afd..475d57f64d58 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts @@ -7,8 +7,7 @@ /dts-v1/; #include <dt-bindings/leds/common.h> -#include "rk3399.dtsi" -#include "rk3399-t-opp.dtsi" +#include "rk3399-t.dtsi" / { model = "Radxa ROCK 4C+"; @@ -53,6 +52,21 @@ }; }; + rk809-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s0>; + }; + + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; clocks = <&rk809 1>; @@ -201,10 +215,13 @@ interrupt-parent = <&gpio1>; interrupts = <RK_PC5 IRQ_TYPE_LEVEL_LOW>; #clock-cells = <1>; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S_8CH_OUT>; clock-output-names = "rk808-clkout1", "rk808-clkout2"; pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l>; + pinctrl-0 = <&pmic_int_l>, <&i2s_8ch_mclk>; rockchip,system-power-controller; + #sound-dai-cells = <0>; wakeup-source; vcc1-supply = <&vcc5v0_sys>; @@ -446,6 +463,26 @@ status = "okay"; }; +&i2s0 { + status = "okay"; +}; + +&i2s0_8ch_bus { + rockchip,pins = + <3 RK_PD0 1 &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>; +}; + +&i2s0_8ch_bus_bclk_off { + rockchip,pins = + <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, + <3 RK_PD2 1 &pcfg_pull_none>, + <3 RK_PD3 1 &pcfg_pull_none>, + <3 RK_PD7 1 &pcfg_pull_none>; +}; + &i2s2 { status = "okay"; }; @@ -473,6 +510,12 @@ }; }; + i2s0 { + i2s_8ch_mclk: i2s-8ch-mclk { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + leds { user_led1: user-led1 { rockchip,pins = <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-4se.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-4se.dts index 7cfc198bbae7..a8b8d4acc337 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-4se.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-4se.dts @@ -5,8 +5,8 @@ */ /dts-v1/; +#include "rk3399-t.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-t-opp.dtsi" / { model = "Radxa ROCK 4SE"; @@ -17,14 +17,6 @@ }; }; -&pinctrl { - usb2 { - vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - &sdio0 { status = "okay"; @@ -56,10 +48,3 @@ vddio-supply = <&vcc_1v8>; }; }; - -&vcc5v0_host { - enable-active-high; - gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_host_en>; -}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index b9d6284bb804..9666504cd1c1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -4,11 +4,9 @@ * Copyright (c) 2019 Pragnesh Patel <Pragnesh_Patel@mentor.com> */ -/dts-v1/; #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/leds/common.h> #include <dt-bindings/pwm/pwm.h> -#include "rk3399.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts index f5a68d8d072d..725ac3c1f6f6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a-plus.dts @@ -5,8 +5,8 @@ */ /dts-v1/; +#include "rk3399-op1.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-op1-opp.dtsi" / { model = "Radxa ROCK Pi 4A+"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a.dts index c68f45849c44..32d6bce5e3d4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4a.dts @@ -5,8 +5,8 @@ */ /dts-v1/; +#include "rk3399.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-opp.dtsi" / { model = "Radxa ROCK Pi 4A"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts index 8a17c1eaae15..682e8b7297c1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b-plus.dts @@ -5,8 +5,8 @@ */ /dts-v1/; +#include "rk3399-op1.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-op1-opp.dtsi" / { model = "Radxa ROCK Pi 4B+"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts index 6ea3180e57ca..55285c7c6e54 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts @@ -5,8 +5,8 @@ */ /dts-v1/; +#include "rk3399.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-opp.dtsi" / { model = "Radxa ROCK Pi 4B"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts index 5274938bf1b8..82ad2ca6b5c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts @@ -6,8 +6,8 @@ */ /dts-v1/; +#include "rk3399.dtsi" #include "rk3399-rock-pi-4.dtsi" -#include "rk3399-opp.dtsi" / { model = "Radxa ROCK Pi 4C"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi index c920ddf44baf..ab890e7b6c59 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi @@ -5,9 +5,8 @@ * Copyright (c) 2018 Linaro Ltd. */ -#include "rk3399.dtsi" -#include "rk3399-opp.dtsi" #include <dt-bindings/interrupt-controller/irq.h> +#include "rk3399.dtsi" / { aliases { @@ -577,7 +576,7 @@ bluetooth { compatible = "brcm,bcm43438-bt"; clocks = <&rk808 1>; - clock-names = "ext_clock"; + clock-names = "txco"; device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>; host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi index f30b82a10ca3..11d99d8b34a2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi @@ -7,7 +7,6 @@ #include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/pwm/pwm.h> #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { aliases { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts index dbec2b7173a0..31ea3d0182c0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts @@ -163,7 +163,7 @@ status = "okay"; rt5651: rt5651@1a { - compatible = "rockchip,rt5651"; + compatible = "realtek,rt5651"; reg = <0x1a>; clocks = <&cru SCLK_I2S_8CH_OUT>; clock-names = "mclk"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi index b3ef1c85e754..31832aae9ab6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi @@ -6,7 +6,6 @@ #include "dt-bindings/pwm/pwm.h" #include "dt-bindings/input/input.h" #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" / { compatible = "rockchip,rk3399-sapphire", "rockchip,rk3399"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-t-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-t.dtsi index 1ababadda9df..72989f03fcb1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-t-opp.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-t.dtsi @@ -4,6 +4,8 @@ * Copyright (c) 2022 Radxa Limited */ +#include "rk3399-base.dtsi" + / { cluster0_opp: opp-table-0 { compatible = "operating-points-v2"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 9d5f5b083e3c..6bc1249d99e6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -1,3019 +1,135 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd + * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd */ -#include <dt-bindings/clock/rk3399-cru.h> -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> -#include <dt-bindings/interrupt-controller/irq.h> -#include <dt-bindings/pinctrl/rockchip.h> -#include <dt-bindings/power/rk3399-power.h> -#include <dt-bindings/thermal/thermal.h> +#include "rk3399-base.dtsi" / { - compatible = "rockchip,rk3399"; + cluster0_opp: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - aliases { - gpio0 = &gpio0; - gpio1 = &gpio1; - gpio2 = &gpio2; - gpio3 = &gpio3; - gpio4 = &gpio4; - i2c0 = &i2c0; - i2c1 = &i2c1; - i2c2 = &i2c2; - i2c3 = &i2c3; - i2c4 = &i2c4; - i2c5 = &i2c5; - i2c6 = &i2c6; - i2c7 = &i2c7; - i2c8 = &i2c8; - serial0 = &uart0; - serial1 = &uart1; - serial2 = &uart2; - serial3 = &uart3; - serial4 = &uart4; - spi0 = &spi0; - spi1 = &spi1; - spi2 = &spi2; - spi3 = &spi3; - spi4 = &spi4; - spi5 = &spi5; - }; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - cpu-map { - cluster0 { /* Cortex-A53 */ - core0 { - cpu = <&cpu_l0>; - }; - core1 { - cpu = <&cpu_l1>; - }; - core2 { - cpu = <&cpu_l2>; - }; - core3 { - cpu = <&cpu_l3>; - }; - }; - - cluster1 { /* Cortex-A72 */ - core0 { - cpu = <&cpu_b0>; - }; - core1 { - cpu = <&cpu_b1>; - }; - }; + opp00 { + opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <825000 825000 1250000>; + clock-latency-ns = <40000>; }; - - cpu_l0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x0 0x0>; - enable-method = "psci"; - capacity-dmips-mhz = <485>; - clocks = <&cru ARMCLKL>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <100>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2_cache_l>; - }; - - cpu_l1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x0 0x1>; - enable-method = "psci"; - capacity-dmips-mhz = <485>; - clocks = <&cru ARMCLKL>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <100>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2_cache_l>; + opp01 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <825000 825000 1250000>; }; - - cpu_l2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x0 0x2>; - enable-method = "psci"; - capacity-dmips-mhz = <485>; - clocks = <&cru ARMCLKL>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <100>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2_cache_l>; - }; - - cpu_l3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x0 0x3>; - enable-method = "psci"; - capacity-dmips-mhz = <485>; - clocks = <&cru ARMCLKL>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <100>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; - next-level-cache = <&l2_cache_l>; - }; - - cpu_b0: cpu@100 { - device_type = "cpu"; - compatible = "arm,cortex-a72"; - reg = <0x0 0x100>; - enable-method = "psci"; - capacity-dmips-mhz = <1024>; - clocks = <&cru ARMCLKB>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <436>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0xC000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <256>; - next-level-cache = <&l2_cache_b>; - - thermal-idle { - #cooling-cells = <2>; - duration-us = <10000>; - exit-latency-us = <500>; - }; - }; - - cpu_b1: cpu@101 { - device_type = "cpu"; - compatible = "arm,cortex-a72"; - reg = <0x0 0x101>; - enable-method = "psci"; - capacity-dmips-mhz = <1024>; - clocks = <&cru ARMCLKB>; - #cooling-cells = <2>; /* min followed by max */ - dynamic-power-coefficient = <436>; - cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; - i-cache-size = <0xC000>; - i-cache-line-size = <64>; - i-cache-sets = <256>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <256>; - next-level-cache = <&l2_cache_b>; - - thermal-idle { - #cooling-cells = <2>; - duration-us = <10000>; - exit-latency-us = <500>; - }; + opp02 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <850000 850000 1250000>; }; - - l2_cache_l: l2-cache-cluster0 { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x80000>; - cache-line-size = <64>; - cache-sets = <512>; + opp03 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <925000 925000 1250000>; }; - - l2_cache_b: l2-cache-cluster1 { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x100000>; - cache-line-size = <64>; - cache-sets = <1024>; + opp04 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1000000 1000000 1250000>; }; - - idle-states { - entry-method = "psci"; - - CPU_SLEEP: cpu-sleep { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <120>; - exit-latency-us = <250>; - min-residency-us = <900>; - }; - - CLUSTER_SLEEP: cluster-sleep { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <400>; - exit-latency-us = <500>; - min-residency-us = <2000>; - }; + opp05 { + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <1125000 1125000 1250000>; }; }; - display-subsystem { - compatible = "rockchip,display-subsystem"; - ports = <&vopl_out>, <&vopb_out>; - }; - - dmc: memory-controller { - compatible = "rockchip,rk3399-dmc"; - rockchip,pmu = <&pmugrf>; - devfreq-events = <&dfi>; - clocks = <&cru SCLK_DDRC>; - clock-names = "dmc_clk"; - status = "disabled"; - }; + cluster1_opp: opp-table-1 { + compatible = "operating-points-v2"; + opp-shared; - pmu_a53 { - compatible = "arm,cortex-a53-pmu"; - interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>; - }; - - pmu_a72 { - compatible = "arm,cortex-a72-pmu"; - interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>; - }; - - psci { - compatible = "arm,psci-1.0"; - method = "smc"; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>, - <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>, - <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>, - <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>; - arm,no-tick-in-suspend; - }; - - xin24m: xin24m { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xin24m"; - #clock-cells = <0>; - }; - - pcie0: pcie@f8000000 { - compatible = "rockchip,rk3399-pcie"; - reg = <0x0 0xf8000000 0x0 0x2000000>, - <0x0 0xfd000000 0x0 0x1000000>; - reg-names = "axi-base", "apb-base"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - aspm-no-l0s; - bus-range = <0x0 0x1f>; - clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, - <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; - clock-names = "aclk", "aclk-perf", - "hclk", "pm"; - interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "sys", "legacy", "client"; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie0_intc 0>, - <0 0 0 2 &pcie0_intc 1>, - <0 0 0 3 &pcie0_intc 2>, - <0 0 0 4 &pcie0_intc 3>; - max-link-speed = <1>; - msi-map = <0x0 &its 0x0 0x1000>; - phys = <&pcie_phy 0>, <&pcie_phy 1>, - <&pcie_phy 2>, <&pcie_phy 3>; - phy-names = "pcie-phy-0", "pcie-phy-1", - "pcie-phy-2", "pcie-phy-3"; - ranges = <0x82000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000>, - <0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>; - resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, - <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>, - <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, - <&cru SRST_A_PCIE>; - reset-names = "core", "mgmt", "mgmt-sticky", "pipe", - "pm", "pclk", "aclk"; - status = "disabled"; - - pcie0_intc: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; + opp00 { + opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <825000 825000 1250000>; + clock-latency-ns = <40000>; }; - }; - - pcie0_ep: pcie-ep@f8000000 { - compatible = "rockchip,rk3399-pcie-ep"; - reg = <0x0 0xfd000000 0x0 0x1000000>, - <0x0 0xfa000000 0x0 0x2000000>; - reg-names = "apb-base", "mem-base"; - clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, - <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; - clock-names = "aclk", "aclk-perf", - "hclk", "pm"; - max-functions = /bits/ 8 <8>; - num-lanes = <4>; - resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, - <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>, - <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, - <&cru SRST_A_PCIE>; - reset-names = "core", "mgmt", "mgmt-sticky", "pipe", - "pm", "pclk", "aclk"; - phys = <&pcie_phy 0>, <&pcie_phy 1>, - <&pcie_phy 2>, <&pcie_phy 3>; - phy-names = "pcie-phy-0", "pcie-phy-1", - "pcie-phy-2", "pcie-phy-3"; - rockchip,max-outbound-regions = <32>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqnb_cpm>; - status = "disabled"; - }; - - gmac: ethernet@fe300000 { - compatible = "rockchip,rk3399-gmac"; - reg = <0x0 0xfe300000 0x0 0x10000>; - interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "macirq"; - clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>, - <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>, - <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>, - <&cru PCLK_GMAC>; - clock-names = "stmmaceth", "mac_clk_rx", - "mac_clk_tx", "clk_mac_ref", - "clk_mac_refout", "aclk_mac", - "pclk_mac"; - power-domains = <&power RK3399_PD_GMAC>; - resets = <&cru SRST_A_GMAC>; - reset-names = "stmmaceth"; - rockchip,grf = <&grf>; - snps,txpbl = <0x4>; - status = "disabled"; - }; - - sdio0: mmc@fe310000 { - compatible = "rockchip,rk3399-dw-mshc", - "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xfe310000 0x0 0x4000>; - interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH 0>; - max-frequency = <150000000>; - clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, - <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - resets = <&cru SRST_SDIO0>; - reset-names = "reset"; - status = "disabled"; - }; - - sdmmc: mmc@fe320000 { - compatible = "rockchip,rk3399-dw-mshc", - "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xfe320000 0x0 0x4000>; - interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>; - max-frequency = <150000000>; - assigned-clocks = <&cru HCLK_SD>; - assigned-clock-rates = <200000000>; - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, - <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; - fifo-depth = <0x100>; - power-domains = <&power RK3399_PD_SD>; - resets = <&cru SRST_SDMMC>; - reset-names = "reset"; - status = "disabled"; - }; - - sdhci: mmc@fe330000 { - compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1"; - reg = <0x0 0xfe330000 0x0 0x10000>; - interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>; - arasan,soc-ctl-syscon = <&grf>; - assigned-clocks = <&cru SCLK_EMMC>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>; - clock-names = "clk_xin", "clk_ahb"; - clock-output-names = "emmc_cardclock"; - #clock-cells = <0>; - phys = <&emmc_phy>; - phy-names = "phy_arasan"; - power-domains = <&power RK3399_PD_EMMC>; - disable-cqe-dcmd; - status = "disabled"; - }; - - usb_host0_ehci: usb@fe380000 { - compatible = "generic-ehci"; - reg = <0x0 0xfe380000 0x0 0x20000>; - interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, - <&u2phy0>; - phys = <&u2phy0_host>; - phy-names = "usb"; - status = "disabled"; - }; - - usb_host0_ohci: usb@fe3a0000 { - compatible = "generic-ohci"; - reg = <0x0 0xfe3a0000 0x0 0x20000>; - interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, - <&u2phy0>; - phys = <&u2phy0_host>; - phy-names = "usb"; - status = "disabled"; - }; - - usb_host1_ehci: usb@fe3c0000 { - compatible = "generic-ehci"; - reg = <0x0 0xfe3c0000 0x0 0x20000>; - interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>, - <&u2phy1>; - phys = <&u2phy1_host>; - phy-names = "usb"; - status = "disabled"; - }; - - usb_host1_ohci: usb@fe3e0000 { - compatible = "generic-ohci"; - reg = <0x0 0xfe3e0000 0x0 0x20000>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>, - <&u2phy1>; - phys = <&u2phy1_host>; - phy-names = "usb"; - status = "disabled"; - }; - - debug@fe430000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe430000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_L>; - clock-names = "apb_pclk"; - cpu = <&cpu_l0>; - }; - - debug@fe432000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe432000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_L>; - clock-names = "apb_pclk"; - cpu = <&cpu_l1>; - }; - - debug@fe434000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe434000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_L>; - clock-names = "apb_pclk"; - cpu = <&cpu_l2>; - }; - - debug@fe436000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe436000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_L>; - clock-names = "apb_pclk"; - cpu = <&cpu_l3>; - }; - - debug@fe610000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe610000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_B>; - clock-names = "apb_pclk"; - cpu = <&cpu_b0>; - }; - - debug@fe710000 { - compatible = "arm,coresight-cpu-debug", "arm,primecell"; - reg = <0 0xfe710000 0 0x1000>; - clocks = <&cru PCLK_COREDBG_B>; - clock-names = "apb_pclk"; - cpu = <&cpu_b1>; - }; - - usbdrd3_0: usb@fe800000 { - compatible = "rockchip,rk3399-dwc3"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>, - <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, - <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; - clock-names = "ref_clk", "suspend_clk", - "bus_clk", "aclk_usb3_rksoc_axi_perf", - "aclk_usb3", "grf_clk"; - resets = <&cru SRST_A_USB3_OTG0>; - reset-names = "usb3-otg"; - status = "disabled"; - - usbdrd_dwc3_0: usb@fe800000 { - compatible = "snps,dwc3"; - reg = <0x0 0xfe800000 0x0 0x100000>; - interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_USB3OTG0_REF>, <&cru ACLK_USB3OTG0>, - <&cru SCLK_USB3OTG0_SUSPEND>; - clock-names = "ref", "bus_early", "suspend"; - dr_mode = "otg"; - phys = <&u2phy0_otg>, <&tcphy0_usb3>; - phy-names = "usb2-phy", "usb3-phy"; - phy_type = "utmi_wide"; - snps,dis_enblslpm_quirk; - snps,dis-u2-freeclk-exists-quirk; - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; + opp01 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <825000 825000 1250000>; }; - }; - - usbdrd3_1: usb@fe900000 { - compatible = "rockchip,rk3399-dwc3"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>, - <&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, - <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; - clock-names = "ref_clk", "suspend_clk", - "bus_clk", "aclk_usb3_rksoc_axi_perf", - "aclk_usb3", "grf_clk"; - resets = <&cru SRST_A_USB3_OTG1>; - reset-names = "usb3-otg"; - status = "disabled"; - - usbdrd_dwc3_1: usb@fe900000 { - compatible = "snps,dwc3"; - reg = <0x0 0xfe900000 0x0 0x100000>; - interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_USB3OTG1_REF>, <&cru ACLK_USB3OTG1>, - <&cru SCLK_USB3OTG1_SUSPEND>; - clock-names = "ref", "bus_early", "suspend"; - dr_mode = "otg"; - phys = <&u2phy1_otg>, <&tcphy1_usb3>; - phy-names = "usb2-phy", "usb3-phy"; - phy_type = "utmi_wide"; - snps,dis_enblslpm_quirk; - snps,dis-u2-freeclk-exists-quirk; - snps,dis_u2_susphy_quirk; - snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; - power-domains = <&power RK3399_PD_USB3>; - status = "disabled"; + opp02 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <825000 825000 1250000>; }; - }; - - cdn_dp: dp@fec00000 { - compatible = "rockchip,rk3399-cdn-dp"; - reg = <0x0 0xfec00000 0x0 0x100000>; - interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH 0>; - assigned-clocks = <&cru SCLK_DP_CORE>, <&cru SCLK_SPDIF_REC_DPTX>; - assigned-clock-rates = <100000000>, <200000000>; - clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>, - <&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>; - clock-names = "core-clk", "pclk", "spdif", "grf"; - phys = <&tcphy0_dp>, <&tcphy1_dp>; - power-domains = <&power RK3399_PD_HDCP>; - resets = <&cru SRST_DPTX_SPDIF_REC>, <&cru SRST_P_UPHY0_DPTX>, - <&cru SRST_P_UPHY0_APB>, <&cru SRST_DP_CORE>; - reset-names = "spdif", "dptx", "apb", "core"; - rockchip,grf = <&grf>; - #sound-dai-cells = <1>; - status = "disabled"; - - ports { - dp_in: port { - #address-cells = <1>; - #size-cells = <0>; - - dp_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_dp>; - }; - - dp_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_dp>; - }; - }; + opp03 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <875000 875000 1250000>; }; - }; - - gic: interrupt-controller@fee00000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <4>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - interrupt-controller; - - reg = <0x0 0xfee00000 0 0x10000>, /* GICD */ - <0x0 0xfef00000 0 0xc0000>, /* GICR */ - <0x0 0xfff00000 0 0x10000>, /* GICC */ - <0x0 0xfff10000 0 0x10000>, /* GICH */ - <0x0 0xfff20000 0 0x10000>; /* GICV */ - interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>; - its: msi-controller@fee20000 { - compatible = "arm,gic-v3-its"; - msi-controller; - #msi-cells = <1>; - reg = <0x0 0xfee20000 0x0 0x20000>; + opp04 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <950000 950000 1250000>; }; - - ppi-partitions { - ppi_cluster0: interrupt-partition-0 { - affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>; - }; - - ppi_cluster1: interrupt-partition-1 { - affinity = <&cpu_b0 &cpu_b1>; - }; + opp05 { + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <1025000 1025000 1250000>; }; - }; - - saradc: saradc@ff100000 { - compatible = "rockchip,rk3399-saradc"; - reg = <0x0 0xff100000 0x0 0x100>; - interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH 0>; - #io-channel-cells = <1>; - clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; - clock-names = "saradc", "apb_pclk"; - resets = <&cru SRST_P_SARADC>; - reset-names = "saradc-apb"; - status = "disabled"; - }; - - crypto0: crypto@ff8b0000 { - compatible = "rockchip,rk3399-crypto"; - reg = <0x0 0xff8b0000 0x0 0x4000>; - interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_M_CRYPTO0>, <&cru HCLK_S_CRYPTO0>, <&cru SCLK_CRYPTO0>; - clock-names = "hclk_master", "hclk_slave", "sclk"; - resets = <&cru SRST_CRYPTO0>, <&cru SRST_CRYPTO0_S>, <&cru SRST_CRYPTO0_M>; - reset-names = "master", "slave", "crypto-rst"; - }; - - crypto1: crypto@ff8b8000 { - compatible = "rockchip,rk3399-crypto"; - reg = <0x0 0xff8b8000 0x0 0x4000>; - interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru HCLK_M_CRYPTO1>, <&cru HCLK_S_CRYPTO1>, <&cru SCLK_CRYPTO1>; - clock-names = "hclk_master", "hclk_slave", "sclk"; - resets = <&cru SRST_CRYPTO1>, <&cru SRST_CRYPTO1_S>, <&cru SRST_CRYPTO1_M>; - reset-names = "master", "slave", "crypto-rst"; - }; - - i2c1: i2c@ff110000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff110000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C1>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c2: i2c@ff120000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff120000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C2>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c3: i2c@ff130000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff130000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C3>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c3_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c5: i2c@ff140000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff140000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C5>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c5_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c6: i2c@ff150000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff150000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C6>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c6_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c7: i2c@ff160000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff160000 0x0 0x1000>; - assigned-clocks = <&cru SCLK_I2C7>; - assigned-clock-rates = <200000000>; - clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c7_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart0: serial@ff180000 { - compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff180000 0x0 0x100>; - clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>; - reg-shift = <2>; - reg-io-width = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&uart0_xfer>; - status = "disabled"; - }; - - uart1: serial@ff190000 { - compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff190000 0x0 0x100>; - clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>; - reg-shift = <2>; - reg-io-width = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&uart1_xfer>; - status = "disabled"; - }; - - uart2: serial@ff1a0000 { - compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff1a0000 0x0 0x100>; - clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>; - reg-shift = <2>; - reg-io-width = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&uart2c_xfer>; - status = "disabled"; - }; - - uart3: serial@ff1b0000 { - compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff1b0000 0x0 0x100>; - clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>; - reg-shift = <2>; - reg-io-width = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&uart3_xfer>; - status = "disabled"; - }; - - spi0: spi@ff1c0000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff1c0000 0x0 0x1000>; - clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_peri 10>, <&dmac_peri 11>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi1: spi@ff1d0000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff1d0000 0x0 0x1000>; - clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_peri 12>, <&dmac_peri 13>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi2: spi@ff1e0000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff1e0000 0x0 0x1000>; - clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_peri 14>, <&dmac_peri 15>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi4: spi@ff1f0000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff1f0000 0x0 0x1000>; - clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_peri 18>, <&dmac_peri 19>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi5: spi@ff200000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff200000 0x0 0x1000>; - clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_bus 8>, <&dmac_bus 9>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - thermal_zones: thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <100>; - polling-delay = <1000>; - - thermal-sensors = <&tsadc 0>; - - trips { - cpu_alert0: cpu_alert0 { - temperature = <70000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_alert1: cpu_alert1 { - temperature = <75000>; - hysteresis = <2000>; - type = "passive"; - }; - cpu_crit: cpu_crit { - temperature = <95000>; - hysteresis = <2000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu_alert0>; - cooling-device = - <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu_alert1>; - cooling-device = - <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; + opp06 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <1100000 1100000 1250000>; }; - - gpu_thermal: gpu-thermal { - polling-delay-passive = <100>; - polling-delay = <1000>; - - thermal-sensors = <&tsadc 1>; - - trips { - gpu_alert0: gpu_alert0 { - temperature = <75000>; - hysteresis = <2000>; - type = "passive"; - }; - gpu_crit: gpu_crit { - temperature = <95000>; - hysteresis = <2000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&gpu_alert0>; - cooling-device = - <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; + opp07 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1200000 1200000 1250000>; }; }; - tsadc: tsadc@ff260000 { - compatible = "rockchip,rk3399-tsadc"; - reg = <0x0 0xff260000 0x0 0x100>; - interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>; - assigned-clocks = <&cru SCLK_TSADC>; - assigned-clock-rates = <750000>; - clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; - clock-names = "tsadc", "apb_pclk"; - resets = <&cru SRST_TSADC>; - reset-names = "tsadc-apb"; - rockchip,grf = <&grf>; - rockchip,hw-tshut-temp = <95000>; - pinctrl-names = "init", "default", "sleep"; - pinctrl-0 = <&otp_pin>; - pinctrl-1 = <&otp_out>; - pinctrl-2 = <&otp_pin>; - #thermal-sensor-cells = <1>; - status = "disabled"; - }; - - qos_emmc: qos@ffa58000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa58000 0x0 0x20>; - }; - - qos_gmac: qos@ffa5c000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa5c000 0x0 0x20>; - }; - - qos_pcie: qos@ffa60080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa60080 0x0 0x20>; - }; + gpu_opp_table: opp-table-2 { + compatible = "operating-points-v2"; - qos_usb_host0: qos@ffa60100 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa60100 0x0 0x20>; - }; - - qos_usb_host1: qos@ffa60180 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa60180 0x0 0x20>; - }; - - qos_usb_otg0: qos@ffa70000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa70000 0x0 0x20>; - }; - - qos_usb_otg1: qos@ffa70080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa70080 0x0 0x20>; - }; - - qos_sd: qos@ffa74000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa74000 0x0 0x20>; - }; - - qos_sdioaudio: qos@ffa76000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa76000 0x0 0x20>; - }; - - qos_hdcp: qos@ffa90000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa90000 0x0 0x20>; - }; - - qos_iep: qos@ffa98000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffa98000 0x0 0x20>; - }; - - qos_isp0_m0: qos@ffaa0000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffaa0000 0x0 0x20>; - }; - - qos_isp0_m1: qos@ffaa0080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffaa0080 0x0 0x20>; - }; - - qos_isp1_m0: qos@ffaa8000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffaa8000 0x0 0x20>; - }; - - qos_isp1_m1: qos@ffaa8080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffaa8080 0x0 0x20>; - }; - - qos_rga_r: qos@ffab0000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffab0000 0x0 0x20>; - }; - - qos_rga_w: qos@ffab0080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffab0080 0x0 0x20>; - }; - - qos_video_m0: qos@ffab8000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffab8000 0x0 0x20>; - }; - - qos_video_m1_r: qos@ffac0000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffac0000 0x0 0x20>; - }; - - qos_video_m1_w: qos@ffac0080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffac0080 0x0 0x20>; - }; - - qos_vop_big_r: qos@ffac8000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffac8000 0x0 0x20>; - }; - - qos_vop_big_w: qos@ffac8080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffac8080 0x0 0x20>; - }; - - qos_vop_little: qos@ffad0000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffad0000 0x0 0x20>; - }; - - qos_perihp: qos@ffad8080 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffad8080 0x0 0x20>; - }; - - qos_gpu: qos@ffae0000 { - compatible = "rockchip,rk3399-qos", "syscon"; - reg = <0x0 0xffae0000 0x0 0x20>; - }; - - pmu: power-management@ff310000 { - compatible = "rockchip,rk3399-pmu", "syscon", "simple-mfd"; - reg = <0x0 0xff310000 0x0 0x1000>; - - /* - * Note: RK3399 supports 6 voltage domains including VD_CORE_L, - * VD_CORE_B, VD_CENTER, VD_GPU, VD_LOGIC and VD_PMU. - * Some of the power domains are grouped together for every - * voltage domain. - * The detail contents as below. - */ - power: power-controller { - compatible = "rockchip,rk3399-power-controller"; - #power-domain-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - /* These power domains are grouped by VD_CENTER */ - power-domain@RK3399_PD_IEP { - reg = <RK3399_PD_IEP>; - clocks = <&cru ACLK_IEP>, - <&cru HCLK_IEP>; - pm_qos = <&qos_iep>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_RGA { - reg = <RK3399_PD_RGA>; - clocks = <&cru ACLK_RGA>, - <&cru HCLK_RGA>; - pm_qos = <&qos_rga_r>, - <&qos_rga_w>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_VCODEC { - reg = <RK3399_PD_VCODEC>; - clocks = <&cru ACLK_VCODEC>, - <&cru HCLK_VCODEC>; - pm_qos = <&qos_video_m0>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_VDU { - reg = <RK3399_PD_VDU>; - clocks = <&cru ACLK_VDU>, - <&cru HCLK_VDU>, - <&cru SCLK_VDU_CA>, - <&cru SCLK_VDU_CORE>; - pm_qos = <&qos_video_m1_r>, - <&qos_video_m1_w>; - #power-domain-cells = <0>; - }; - - /* These power domains are grouped by VD_GPU */ - power-domain@RK3399_PD_GPU { - reg = <RK3399_PD_GPU>; - clocks = <&cru ACLK_GPU>; - pm_qos = <&qos_gpu>; - #power-domain-cells = <0>; - }; - - /* These power domains are grouped by VD_LOGIC */ - power-domain@RK3399_PD_EDP { - reg = <RK3399_PD_EDP>; - clocks = <&cru PCLK_EDP_CTRL>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_EMMC { - reg = <RK3399_PD_EMMC>; - clocks = <&cru ACLK_EMMC>; - pm_qos = <&qos_emmc>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_GMAC { - reg = <RK3399_PD_GMAC>; - clocks = <&cru ACLK_GMAC>, - <&cru PCLK_GMAC>; - pm_qos = <&qos_gmac>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_SD { - reg = <RK3399_PD_SD>; - clocks = <&cru HCLK_SDMMC>, - <&cru SCLK_SDMMC>; - pm_qos = <&qos_sd>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_SDIOAUDIO { - reg = <RK3399_PD_SDIOAUDIO>; - clocks = <&cru HCLK_SDIO>; - pm_qos = <&qos_sdioaudio>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_TCPD0 { - reg = <RK3399_PD_TCPD0>; - clocks = <&cru SCLK_UPHY0_TCPDCORE>, - <&cru SCLK_UPHY0_TCPDPHY_REF>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_TCPD1 { - reg = <RK3399_PD_TCPD1>; - clocks = <&cru SCLK_UPHY1_TCPDCORE>, - <&cru SCLK_UPHY1_TCPDPHY_REF>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_USB3 { - reg = <RK3399_PD_USB3>; - clocks = <&cru ACLK_USB3>; - pm_qos = <&qos_usb_otg0>, - <&qos_usb_otg1>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_VIO { - reg = <RK3399_PD_VIO>; - #power-domain-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - power-domain@RK3399_PD_HDCP { - reg = <RK3399_PD_HDCP>; - clocks = <&cru ACLK_HDCP>, - <&cru HCLK_HDCP>, - <&cru PCLK_HDCP>; - pm_qos = <&qos_hdcp>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_ISP0 { - reg = <RK3399_PD_ISP0>; - clocks = <&cru ACLK_ISP0>, - <&cru HCLK_ISP0>; - pm_qos = <&qos_isp0_m0>, - <&qos_isp0_m1>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_ISP1 { - reg = <RK3399_PD_ISP1>; - clocks = <&cru ACLK_ISP1>, - <&cru HCLK_ISP1>; - pm_qos = <&qos_isp1_m0>, - <&qos_isp1_m1>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_VO { - reg = <RK3399_PD_VO>; - #power-domain-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - power-domain@RK3399_PD_VOPB { - reg = <RK3399_PD_VOPB>; - clocks = <&cru ACLK_VOP0>, - <&cru HCLK_VOP0>; - pm_qos = <&qos_vop_big_r>, - <&qos_vop_big_w>; - #power-domain-cells = <0>; - }; - power-domain@RK3399_PD_VOPL { - reg = <RK3399_PD_VOPL>; - clocks = <&cru ACLK_VOP1>, - <&cru HCLK_VOP1>; - pm_qos = <&qos_vop_little>; - #power-domain-cells = <0>; - }; - }; - }; + opp00 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <825000 825000 1150000>; }; - }; - - pmugrf: syscon@ff320000 { - compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd"; - reg = <0x0 0xff320000 0x0 0x1000>; - - pmu_io_domains: io-domains { - compatible = "rockchip,rk3399-pmu-io-voltage-domain"; - status = "disabled"; + opp01 { + opp-hz = /bits/ 64 <297000000>; + opp-microvolt = <825000 825000 1150000>; }; - }; - - spi3: spi@ff350000 { - compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi"; - reg = <0x0 0xff350000 0x0 0x1000>; - clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>; - clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart4: serial@ff370000 { - compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff370000 0x0 0x100>; - clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>; - reg-shift = <2>; - reg-io-width = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&uart4_xfer>; - status = "disabled"; - }; - - i2c0: i2c@ff3c0000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff3c0000 0x0 0x1000>; - assigned-clocks = <&pmucru SCLK_I2C0_PMU>; - assigned-clock-rates = <200000000>; - clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c4: i2c@ff3d0000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff3d0000 0x0 0x1000>; - assigned-clocks = <&pmucru SCLK_I2C4_PMU>; - assigned-clock-rates = <200000000>; - clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c4_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c8: i2c@ff3e0000 { - compatible = "rockchip,rk3399-i2c"; - reg = <0x0 0xff3e0000 0x0 0x1000>; - assigned-clocks = <&pmucru SCLK_I2C8_PMU>; - assigned-clock-rates = <200000000>; - clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>; - clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c8_xfer>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - pwm0: pwm@ff420000 { - compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; - reg = <0x0 0xff420000 0x0 0x10>; - #pwm-cells = <3>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm0_pin>; - clocks = <&pmucru PCLK_RKPWM_PMU>; - status = "disabled"; - }; - - pwm1: pwm@ff420010 { - compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; - reg = <0x0 0xff420010 0x0 0x10>; - #pwm-cells = <3>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm1_pin>; - clocks = <&pmucru PCLK_RKPWM_PMU>; - status = "disabled"; - }; - - pwm2: pwm@ff420020 { - compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; - reg = <0x0 0xff420020 0x0 0x10>; - #pwm-cells = <3>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm2_pin>; - clocks = <&pmucru PCLK_RKPWM_PMU>; - status = "disabled"; - }; - - pwm3: pwm@ff420030 { - compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm"; - reg = <0x0 0xff420030 0x0 0x10>; - #pwm-cells = <3>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm3a_pin>; - clocks = <&pmucru PCLK_RKPWM_PMU>; - status = "disabled"; - }; - - dfi: dfi@ff630000 { - reg = <0x00 0xff630000 0x00 0x4000>; - compatible = "rockchip,rk3399-dfi"; - rockchip,pmu = <&pmugrf>; - interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru PCLK_DDR_MON>; - clock-names = "pclk_ddr_mon"; - }; - - vpu: video-codec@ff650000 { - compatible = "rockchip,rk3399-vpu"; - reg = <0x0 0xff650000 0x0 0x800>; - interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "vepu", "vdpu"; - clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; - clock-names = "aclk", "hclk"; - iommus = <&vpu_mmu>; - power-domains = <&power RK3399_PD_VCODEC>; - }; - - vpu_mmu: iommu@ff650800 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff650800 0x0 0x40>; - interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; - power-domains = <&power RK3399_PD_VCODEC>; - }; - - vdec: video-codec@ff660000 { - compatible = "rockchip,rk3399-vdec"; - reg = <0x0 0xff660000 0x0 0x480>; - interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>, - <&cru SCLK_VDU_CA>, <&cru SCLK_VDU_CORE>; - clock-names = "axi", "ahb", "cabac", "core"; - iommus = <&vdec_mmu>; - power-domains = <&power RK3399_PD_VDU>; - }; - - vdec_mmu: iommu@ff660480 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff660480 0x0 0x40>, <0x0 0xff6604c0 0x0 0x40>; - interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>; - clock-names = "aclk", "iface"; - power-domains = <&power RK3399_PD_VDU>; - #iommu-cells = <0>; - }; - - iep_mmu: iommu@ff670800 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff670800 0x0 0x40>; - interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; - status = "disabled"; - }; - - rga: rga@ff680000 { - compatible = "rockchip,rk3399-rga"; - reg = <0x0 0xff680000 0x0 0x10000>; - interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA_CORE>; - clock-names = "aclk", "hclk", "sclk"; - resets = <&cru SRST_RGA_CORE>, <&cru SRST_A_RGA>, <&cru SRST_H_RGA>; - reset-names = "core", "axi", "ahb"; - power-domains = <&power RK3399_PD_RGA>; - }; - - efuse0: efuse@ff690000 { - compatible = "rockchip,rk3399-efuse"; - reg = <0x0 0xff690000 0x0 0x80>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&cru PCLK_EFUSE1024NS>; - clock-names = "pclk_efuse"; - - /* Data cells */ - cpu_id: cpu-id@7 { - reg = <0x07 0x10>; - }; - cpub_leakage: cpu-leakage@17 { - reg = <0x17 0x1>; - }; - gpu_leakage: gpu-leakage@18 { - reg = <0x18 0x1>; - }; - center_leakage: center-leakage@19 { - reg = <0x19 0x1>; - }; - cpul_leakage: cpu-leakage@1a { - reg = <0x1a 0x1>; - }; - logic_leakage: logic-leakage@1b { - reg = <0x1b 0x1>; - }; - wafer_info: wafer-info@1c { - reg = <0x1c 0x1>; - }; - }; - - dmac_bus: dma-controller@ff6d0000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0x0 0xff6d0000 0x0 0x4000>; - interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>; - #dma-cells = <1>; - arm,pl330-periph-burst; - clocks = <&cru ACLK_DMAC0_PERILP>; - clock-names = "apb_pclk"; - }; - - dmac_peri: dma-controller@ff6e0000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0x0 0xff6e0000 0x0 0x4000>; - interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>; - #dma-cells = <1>; - arm,pl330-periph-burst; - clocks = <&cru ACLK_DMAC1_PERILP>; - clock-names = "apb_pclk"; - }; - - pmucru: clock-controller@ff750000 { - compatible = "rockchip,rk3399-pmucru"; - reg = <0x0 0xff750000 0x0 0x1000>; - clocks = <&xin24m>; - clock-names = "xin24m"; - rockchip,grf = <&pmugrf>; - #clock-cells = <1>; - #reset-cells = <1>; - assigned-clocks = <&pmucru PLL_PPLL>; - assigned-clock-rates = <676000000>; - }; - - cru: clock-controller@ff760000 { - compatible = "rockchip,rk3399-cru"; - reg = <0x0 0xff760000 0x0 0x1000>; - clocks = <&xin24m>; - clock-names = "xin24m"; - rockchip,grf = <&grf>; - #clock-cells = <1>; - #reset-cells = <1>; - assigned-clocks = - <&cru PLL_GPLL>, <&cru PLL_CPLL>, - <&cru PLL_NPLL>, - <&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>, - <&cru PCLK_PERIHP>, - <&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>, - <&cru PCLK_PERILP0>, <&cru ACLK_CCI>, - <&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>, - <&cru ACLK_VIO>, <&cru ACLK_HDCP>, - <&cru ACLK_GIC_PRE>, - <&cru PCLK_DDR>, - <&cru ACLK_VDU>; - assigned-clock-rates = - <594000000>, <800000000>, - <1000000000>, - <150000000>, <75000000>, - <37500000>, - <100000000>, <100000000>, - <50000000>, <600000000>, - <100000000>, <50000000>, - <400000000>, <400000000>, - <200000000>, - <200000000>, - <400000000>; - }; - - grf: syscon@ff770000 { - compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd"; - reg = <0x0 0xff770000 0x0 0x10000>; - #address-cells = <1>; - #size-cells = <1>; - - io_domains: io-domains { - compatible = "rockchip,rk3399-io-voltage-domain"; - status = "disabled"; + opp02 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <825000 825000 1150000>; }; - - mipi_dphy_rx0: mipi-dphy-rx0 { - compatible = "rockchip,rk3399-mipi-dphy-rx0"; - clocks = <&cru SCLK_MIPIDPHY_REF>, - <&cru SCLK_DPHY_RX0_CFG>, - <&cru PCLK_VIO_GRF>; - clock-names = "dphy-ref", "dphy-cfg", "grf"; - power-domains = <&power RK3399_PD_VIO>; - #phy-cells = <0>; - status = "disabled"; + opp03 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <875000 875000 1150000>; }; - - u2phy0: usb2phy@e450 { - compatible = "rockchip,rk3399-usb2phy"; - reg = <0xe450 0x10>; - clocks = <&cru SCLK_USB2PHY0_REF>; - clock-names = "phyclk"; - #clock-cells = <0>; - clock-output-names = "clk_usbphy0_480m"; - status = "disabled"; - - u2phy0_host: host-port { - #phy-cells = <0>; - interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "linestate"; - status = "disabled"; - }; - - u2phy0_otg: otg-port { - #phy-cells = <0>; - interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "otg-bvalid", "otg-id", - "linestate"; - status = "disabled"; - }; - }; - - u2phy1: usb2phy@e460 { - compatible = "rockchip,rk3399-usb2phy"; - reg = <0xe460 0x10>; - clocks = <&cru SCLK_USB2PHY1_REF>; - clock-names = "phyclk"; - #clock-cells = <0>; - clock-output-names = "clk_usbphy1_480m"; - status = "disabled"; - - u2phy1_host: host-port { - #phy-cells = <0>; - interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "linestate"; - status = "disabled"; - }; - - u2phy1_otg: otg-port { - #phy-cells = <0>; - interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "otg-bvalid", "otg-id", - "linestate"; - status = "disabled"; - }; - }; - - emmc_phy: phy@f780 { - compatible = "rockchip,rk3399-emmc-phy"; - reg = <0xf780 0x24>; - clocks = <&sdhci>; - clock-names = "emmcclk"; - drive-impedance-ohm = <50>; - #phy-cells = <0>; - status = "disabled"; + opp04 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <925000 925000 1150000>; }; - - pcie_phy: pcie-phy { - compatible = "rockchip,rk3399-pcie-phy"; - clocks = <&cru SCLK_PCIEPHY_REF>; - clock-names = "refclk"; - #phy-cells = <1>; - resets = <&cru SRST_PCIEPHY>; - reset-names = "phy"; - status = "disabled"; + opp05 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1100000 1100000 1150000>; }; }; +}; - tcphy0: phy@ff7c0000 { - compatible = "rockchip,rk3399-typec-phy"; - reg = <0x0 0xff7c0000 0x0 0x40000>; - clocks = <&cru SCLK_UPHY0_TCPDCORE>, - <&cru SCLK_UPHY0_TCPDPHY_REF>; - clock-names = "tcpdcore", "tcpdphy-ref"; - assigned-clocks = <&cru SCLK_UPHY0_TCPDCORE>; - assigned-clock-rates = <50000000>; - power-domains = <&power RK3399_PD_TCPD0>; - resets = <&cru SRST_UPHY0>, - <&cru SRST_UPHY0_PIPE_L00>, - <&cru SRST_P_UPHY0_TCPHY>; - reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; - rockchip,grf = <&grf>; - status = "disabled"; - - tcphy0_dp: dp-port { - #phy-cells = <0>; - }; - - tcphy0_usb3: usb3-port { - #phy-cells = <0>; - }; - }; - - tcphy1: phy@ff800000 { - compatible = "rockchip,rk3399-typec-phy"; - reg = <0x0 0xff800000 0x0 0x40000>; - clocks = <&cru SCLK_UPHY1_TCPDCORE>, - <&cru SCLK_UPHY1_TCPDPHY_REF>; - clock-names = "tcpdcore", "tcpdphy-ref"; - assigned-clocks = <&cru SCLK_UPHY1_TCPDCORE>; - assigned-clock-rates = <50000000>; - power-domains = <&power RK3399_PD_TCPD1>; - resets = <&cru SRST_UPHY1>, - <&cru SRST_UPHY1_PIPE_L00>, - <&cru SRST_P_UPHY1_TCPHY>; - reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; - rockchip,grf = <&grf>; - status = "disabled"; - - tcphy1_dp: dp-port { - #phy-cells = <0>; - }; - - tcphy1_usb3: usb3-port { - #phy-cells = <0>; - }; - }; - - watchdog@ff848000 { - compatible = "rockchip,rk3399-wdt", "snps,dw-wdt"; - reg = <0x0 0xff848000 0x0 0x100>; - clocks = <&cru PCLK_WDT>; - interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>; - }; - - rktimer: rktimer@ff850000 { - compatible = "rockchip,rk3399-timer"; - reg = <0x0 0xff850000 0x0 0x1000>; - interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>; - clock-names = "pclk", "timer"; - }; - - spdif: spdif@ff870000 { - compatible = "rockchip,rk3399-spdif"; - reg = <0x0 0xff870000 0x0 0x1000>; - interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_bus 7>; - dma-names = "tx"; - clock-names = "mclk", "hclk"; - clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>; - pinctrl-names = "default"; - pinctrl-0 = <&spdif_bus>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - #sound-dai-cells = <0>; - status = "disabled"; - }; - - i2s0: i2s@ff880000 { - compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; - reg = <0x0 0xff880000 0x0 0x1000>; - rockchip,grf = <&grf>; - interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_bus 0>, <&dmac_bus 1>; - dma-names = "tx", "rx"; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S0_8CH>, <&cru HCLK_I2S0_8CH>; - pinctrl-names = "bclk_on", "bclk_off"; - pinctrl-0 = <&i2s0_8ch_bus>; - pinctrl-1 = <&i2s0_8ch_bus_bclk_off>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - #sound-dai-cells = <0>; - status = "disabled"; - }; - - i2s1: i2s@ff890000 { - compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; - reg = <0x0 0xff890000 0x0 0x1000>; - interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_bus 2>, <&dmac_bus 3>; - dma-names = "tx", "rx"; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s1_2ch_bus>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - #sound-dai-cells = <0>; - status = "disabled"; - }; - - i2s2: i2s@ff8a0000 { - compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; - reg = <0x0 0xff8a0000 0x0 0x1000>; - interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH 0>; - dmas = <&dmac_bus 4>, <&dmac_bus 5>; - dma-names = "tx", "rx"; - clock-names = "i2s_clk", "i2s_hclk"; - clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>; - power-domains = <&power RK3399_PD_SDIOAUDIO>; - #sound-dai-cells = <0>; - status = "disabled"; - }; - - vopl: vop@ff8f0000 { - compatible = "rockchip,rk3399-vop-lit"; - reg = <0x0 0xff8f0000 0x0 0x2000>, <0x0 0xff8f2000 0x0 0x400>; - interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; - assigned-clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>; - assigned-clock-rates = <400000000>, <100000000>; - clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>; - clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; - iommus = <&vopl_mmu>; - power-domains = <&power RK3399_PD_VOPL>; - resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>; - reset-names = "axi", "ahb", "dclk"; - status = "disabled"; - - vopl_out: port { - #address-cells = <1>; - #size-cells = <0>; - - vopl_out_mipi: endpoint@0 { - reg = <0>; - remote-endpoint = <&mipi_in_vopl>; - }; - - vopl_out_edp: endpoint@1 { - reg = <1>; - remote-endpoint = <&edp_in_vopl>; - }; - - vopl_out_hdmi: endpoint@2 { - reg = <2>; - remote-endpoint = <&hdmi_in_vopl>; - }; - - vopl_out_mipi1: endpoint@3 { - reg = <3>; - remote-endpoint = <&mipi1_in_vopl>; - }; - - vopl_out_dp: endpoint@4 { - reg = <4>; - remote-endpoint = <&dp_in_vopl>; - }; - }; - }; - - vopl_mmu: iommu@ff8f3f00 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff8f3f00 0x0 0x100>; - interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>; - clock-names = "aclk", "iface"; - power-domains = <&power RK3399_PD_VOPL>; - #iommu-cells = <0>; - status = "disabled"; - }; - - vopb: vop@ff900000 { - compatible = "rockchip,rk3399-vop-big"; - reg = <0x0 0xff900000 0x0 0x2000>, <0x0 0xff902000 0x0 0x1000>; - interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>; - assigned-clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>; - assigned-clock-rates = <400000000>, <100000000>; - clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>; - clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; - iommus = <&vopb_mmu>; - power-domains = <&power RK3399_PD_VOPB>; - resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>; - reset-names = "axi", "ahb", "dclk"; - status = "disabled"; - - vopb_out: port { - #address-cells = <1>; - #size-cells = <0>; - - vopb_out_edp: endpoint@0 { - reg = <0>; - remote-endpoint = <&edp_in_vopb>; - }; - - vopb_out_mipi: endpoint@1 { - reg = <1>; - remote-endpoint = <&mipi_in_vopb>; - }; - - vopb_out_hdmi: endpoint@2 { - reg = <2>; - remote-endpoint = <&hdmi_in_vopb>; - }; - - vopb_out_mipi1: endpoint@3 { - reg = <3>; - remote-endpoint = <&mipi1_in_vopb>; - }; - - vopb_out_dp: endpoint@4 { - reg = <4>; - remote-endpoint = <&dp_in_vopb>; - }; - }; - }; - - vopb_mmu: iommu@ff903f00 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff903f00 0x0 0x100>; - interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>; - clock-names = "aclk", "iface"; - power-domains = <&power RK3399_PD_VOPB>; - #iommu-cells = <0>; - status = "disabled"; - }; - - isp0: isp0@ff910000 { - compatible = "rockchip,rk3399-cif-isp"; - reg = <0x0 0xff910000 0x0 0x4000>; - interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_ISP0>, - <&cru ACLK_ISP0_WRAPPER>, - <&cru HCLK_ISP0_WRAPPER>; - clock-names = "isp", "aclk", "hclk"; - iommus = <&isp0_mmu>; - phys = <&mipi_dphy_rx0>; - phy-names = "dphy"; - power-domains = <&power RK3399_PD_ISP0>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - }; - }; - }; - - isp0_mmu: iommu@ff914000 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>; - interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_ISP0_WRAPPER>, <&cru HCLK_ISP0_WRAPPER>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; - power-domains = <&power RK3399_PD_ISP0>; - rockchip,disable-mmu-reset; - }; - - isp1: isp1@ff920000 { - compatible = "rockchip,rk3399-cif-isp"; - reg = <0x0 0xff920000 0x0 0x4000>; - interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_ISP1>, - <&cru ACLK_ISP1_WRAPPER>, - <&cru HCLK_ISP1_WRAPPER>; - clock-names = "isp", "aclk", "hclk"; - iommus = <&isp1_mmu>; - phys = <&mipi_dsi1>; - phy-names = "dphy"; - power-domains = <&power RK3399_PD_ISP1>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - }; - }; - }; - - isp1_mmu: iommu@ff924000 { - compatible = "rockchip,iommu"; - reg = <0x0 0xff924000 0x0 0x100>, <0x0 0xff925000 0x0 0x100>; - interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru ACLK_ISP1_WRAPPER>, <&cru HCLK_ISP1_WRAPPER>; - clock-names = "aclk", "iface"; - #iommu-cells = <0>; - power-domains = <&power RK3399_PD_ISP1>; - rockchip,disable-mmu-reset; - }; - - hdmi_sound: hdmi-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,name = "hdmi-sound"; - status = "disabled"; - - simple-audio-card,cpu { - sound-dai = <&i2s2>; - }; - simple-audio-card,codec { - sound-dai = <&hdmi>; - }; - }; - - hdmi: hdmi@ff940000 { - compatible = "rockchip,rk3399-dw-hdmi"; - reg = <0x0 0xff940000 0x0 0x20000>; - reg-io-width = <4>; - interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru PCLK_HDMI_CTRL>, - <&cru SCLK_HDMI_SFR>, - <&cru SCLK_HDMI_CEC>, - <&cru PCLK_VIO_GRF>, - <&cru PLL_VPLL>; - clock-names = "iahb", "isfr", "cec", "grf", "ref"; - power-domains = <&power RK3399_PD_HDCP>; - rockchip,grf = <&grf>; - #sound-dai-cells = <0>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - hdmi_in: port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - hdmi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_hdmi>; - }; - hdmi_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_hdmi>; - }; - }; - - hdmi_out: port@1 { - reg = <1>; - }; - }; - }; - - mipi_dsi: dsi@ff960000 { - compatible = "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"; - reg = <0x0 0xff960000 0x0 0x8000>; - interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_DPHY_PLL>, <&cru PCLK_MIPI_DSI0>, - <&cru SCLK_DPHY_TX0_CFG>, <&cru PCLK_VIO_GRF>; - clock-names = "ref", "pclk", "phy_cfg", "grf"; - power-domains = <&power RK3399_PD_VIO>; - resets = <&cru SRST_P_MIPI_DSI0>; - reset-names = "apb"; - rockchip,grf = <&grf>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - mipi_in: port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - mipi_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_mipi>; - }; - - mipi_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_mipi>; - }; - }; - - mipi_out: port@1 { - reg = <1>; - }; - }; - }; - - mipi_dsi1: dsi@ff968000 { - compatible = "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi"; - reg = <0x0 0xff968000 0x0 0x8000>; - interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru SCLK_DPHY_PLL>, <&cru PCLK_MIPI_DSI1>, - <&cru SCLK_DPHY_TX1RX1_CFG>, <&cru PCLK_VIO_GRF>; - clock-names = "ref", "pclk", "phy_cfg", "grf"; - power-domains = <&power RK3399_PD_VIO>; - resets = <&cru SRST_P_MIPI_DSI1>; - reset-names = "apb"; - rockchip,grf = <&grf>; - #address-cells = <1>; - #size-cells = <0>; - #phy-cells = <0>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - mipi1_in: port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - mipi1_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_mipi1>; - }; - - mipi1_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_mipi1>; - }; - }; - - mipi1_out: port@1 { - reg = <1>; - }; - }; - }; - - edp: dp@ff970000 { - compatible = "rockchip,rk3399-edp"; - reg = <0x0 0xff970000 0x0 0x8000>; - interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH 0>; - clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>, <&cru PCLK_VIO_GRF>; - clock-names = "dp", "pclk", "grf"; - pinctrl-names = "default"; - pinctrl-0 = <&edp_hpd>; - power-domains = <&power RK3399_PD_EDP>; - resets = <&cru SRST_P_EDP_CTRL>; - reset-names = "dp"; - rockchip,grf = <&grf>; - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - edp_in: port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - edp_in_vopb: endpoint@0 { - reg = <0>; - remote-endpoint = <&vopb_out_edp>; - }; - - edp_in_vopl: endpoint@1 { - reg = <1>; - remote-endpoint = <&vopl_out_edp>; - }; - }; - - edp_out: port@1 { - reg = <1>; - }; - }; - }; - - gpu: gpu@ff9a0000 { - compatible = "rockchip,rk3399-mali", "arm,mali-t860"; - reg = <0x0 0xff9a0000 0x0 0x10000>; - interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH 0>; - interrupt-names = "job", "mmu", "gpu"; - clocks = <&cru ACLK_GPU>; - #cooling-cells = <2>; - dynamic-power-coefficient = <2640>; - power-domains = <&power RK3399_PD_GPU>; - status = "disabled"; - }; - - pinctrl: pinctrl { - compatible = "rockchip,rk3399-pinctrl"; - rockchip,grf = <&grf>; - rockchip,pmu = <&pmugrf>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio0: gpio@ff720000 { - compatible = "rockchip,gpio-bank"; - reg = <0x0 0xff720000 0x0 0x100>; - clocks = <&pmucru PCLK_GPIO0_PMU>; - interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>; - - gpio-controller; - #gpio-cells = <0x2>; - - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - gpio1: gpio@ff730000 { - compatible = "rockchip,gpio-bank"; - reg = <0x0 0xff730000 0x0 0x100>; - clocks = <&pmucru PCLK_GPIO1_PMU>; - interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH 0>; - - gpio-controller; - #gpio-cells = <0x2>; - - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - gpio2: gpio@ff780000 { - compatible = "rockchip,gpio-bank"; - reg = <0x0 0xff780000 0x0 0x100>; - clocks = <&cru PCLK_GPIO2>; - interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH 0>; - - gpio-controller; - #gpio-cells = <0x2>; - - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - gpio3: gpio@ff788000 { - compatible = "rockchip,gpio-bank"; - reg = <0x0 0xff788000 0x0 0x100>; - clocks = <&cru PCLK_GPIO3>; - interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>; - - gpio-controller; - #gpio-cells = <0x2>; - - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - gpio4: gpio@ff790000 { - compatible = "rockchip,gpio-bank"; - reg = <0x0 0xff790000 0x0 0x100>; - clocks = <&cru PCLK_GPIO4>; - interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; - - gpio-controller; - #gpio-cells = <0x2>; - - interrupt-controller; - #interrupt-cells = <0x2>; - }; - - pcfg_pull_up: pcfg-pull-up { - bias-pull-up; - }; - - pcfg_pull_down: pcfg-pull-down { - bias-pull-down; - }; - - pcfg_pull_none: pcfg-pull-none { - bias-disable; - }; - - pcfg_pull_none_12ma: pcfg-pull-none-12ma { - bias-disable; - drive-strength = <12>; - }; - - pcfg_pull_none_13ma: pcfg-pull-none-13ma { - bias-disable; - drive-strength = <13>; - }; - - pcfg_pull_none_18ma: pcfg-pull-none-18ma { - bias-disable; - drive-strength = <18>; - }; - - pcfg_pull_none_20ma: pcfg-pull-none-20ma { - bias-disable; - drive-strength = <20>; - }; - - pcfg_pull_up_2ma: pcfg-pull-up-2ma { - bias-pull-up; - drive-strength = <2>; - }; - - pcfg_pull_up_8ma: pcfg-pull-up-8ma { - bias-pull-up; - drive-strength = <8>; - }; - - pcfg_pull_up_18ma: pcfg-pull-up-18ma { - bias-pull-up; - drive-strength = <18>; - }; - - pcfg_pull_up_20ma: pcfg-pull-up-20ma { - bias-pull-up; - drive-strength = <20>; - }; - - pcfg_pull_down_4ma: pcfg-pull-down-4ma { - bias-pull-down; - drive-strength = <4>; - }; - - pcfg_pull_down_8ma: pcfg-pull-down-8ma { - bias-pull-down; - drive-strength = <8>; - }; - - pcfg_pull_down_12ma: pcfg-pull-down-12ma { - bias-pull-down; - drive-strength = <12>; - }; - - pcfg_pull_down_18ma: pcfg-pull-down-18ma { - bias-pull-down; - drive-strength = <18>; - }; - - pcfg_pull_down_20ma: pcfg-pull-down-20ma { - bias-pull-down; - drive-strength = <20>; - }; - - pcfg_output_high: pcfg-output-high { - output-high; - }; - - pcfg_output_low: pcfg-output-low { - output-low; - }; - - pcfg_input_enable: pcfg-input-enable { - input-enable; - }; - - pcfg_input_pull_up: pcfg-input-pull-up { - input-enable; - bias-pull-up; - }; - - pcfg_input_pull_down: pcfg-input-pull-down { - input-enable; - bias-pull-down; - }; - - clock { - clk_32k: clk-32k { - rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>; - }; - }; - - cif { - cif_clkin: cif-clkin { - rockchip,pins = - <2 RK_PB2 3 &pcfg_pull_none>; - }; - - cif_clkouta: cif-clkouta { - rockchip,pins = - <2 RK_PB3 3 &pcfg_pull_none>; - }; - }; - - edp { - edp_hpd: edp-hpd { - rockchip,pins = - <4 RK_PC7 2 &pcfg_pull_none>; - }; - }; - - gmac { - rgmii_pins: rgmii-pins { - rockchip,pins = - /* mac_txclk */ - <3 RK_PC1 1 &pcfg_pull_none_13ma>, - /* mac_rxclk */ - <3 RK_PB6 1 &pcfg_pull_none>, - /* mac_mdio */ - <3 RK_PB5 1 &pcfg_pull_none>, - /* mac_txen */ - <3 RK_PB4 1 &pcfg_pull_none_13ma>, - /* mac_clk */ - <3 RK_PB3 1 &pcfg_pull_none>, - /* mac_rxdv */ - <3 RK_PB1 1 &pcfg_pull_none>, - /* mac_mdc */ - <3 RK_PB0 1 &pcfg_pull_none>, - /* mac_rxd1 */ - <3 RK_PA7 1 &pcfg_pull_none>, - /* mac_rxd0 */ - <3 RK_PA6 1 &pcfg_pull_none>, - /* mac_txd1 */ - <3 RK_PA5 1 &pcfg_pull_none_13ma>, - /* mac_txd0 */ - <3 RK_PA4 1 &pcfg_pull_none_13ma>, - /* mac_rxd3 */ - <3 RK_PA3 1 &pcfg_pull_none>, - /* mac_rxd2 */ - <3 RK_PA2 1 &pcfg_pull_none>, - /* mac_txd3 */ - <3 RK_PA1 1 &pcfg_pull_none_13ma>, - /* mac_txd2 */ - <3 RK_PA0 1 &pcfg_pull_none_13ma>; - }; - - rmii_pins: rmii-pins { - rockchip,pins = - /* mac_mdio */ - <3 RK_PB5 1 &pcfg_pull_none>, - /* mac_txen */ - <3 RK_PB4 1 &pcfg_pull_none_13ma>, - /* mac_clk */ - <3 RK_PB3 1 &pcfg_pull_none>, - /* mac_rxer */ - <3 RK_PB2 1 &pcfg_pull_none>, - /* mac_rxdv */ - <3 RK_PB1 1 &pcfg_pull_none>, - /* mac_mdc */ - <3 RK_PB0 1 &pcfg_pull_none>, - /* mac_rxd1 */ - <3 RK_PA7 1 &pcfg_pull_none>, - /* mac_rxd0 */ - <3 RK_PA6 1 &pcfg_pull_none>, - /* mac_txd1 */ - <3 RK_PA5 1 &pcfg_pull_none_13ma>, - /* mac_txd0 */ - <3 RK_PA4 1 &pcfg_pull_none_13ma>; - }; - }; - - i2c0 { - i2c0_xfer: i2c0-xfer { - rockchip,pins = - <1 RK_PB7 2 &pcfg_pull_none>, - <1 RK_PC0 2 &pcfg_pull_none>; - }; - }; - - i2c1 { - i2c1_xfer: i2c1-xfer { - rockchip,pins = - <4 RK_PA2 1 &pcfg_pull_none>, - <4 RK_PA1 1 &pcfg_pull_none>; - }; - }; - - i2c2 { - i2c2_xfer: i2c2-xfer { - rockchip,pins = - <2 RK_PA1 2 &pcfg_pull_none_12ma>, - <2 RK_PA0 2 &pcfg_pull_none_12ma>; - }; - }; - - i2c3 { - i2c3_xfer: i2c3-xfer { - rockchip,pins = - <4 RK_PC1 1 &pcfg_pull_none>, - <4 RK_PC0 1 &pcfg_pull_none>; - }; - }; - - i2c4 { - i2c4_xfer: i2c4-xfer { - rockchip,pins = - <1 RK_PB4 1 &pcfg_pull_none>, - <1 RK_PB3 1 &pcfg_pull_none>; - }; - }; - - i2c5 { - i2c5_xfer: i2c5-xfer { - rockchip,pins = - <3 RK_PB3 2 &pcfg_pull_none>, - <3 RK_PB2 2 &pcfg_pull_none>; - }; - }; - - i2c6 { - i2c6_xfer: i2c6-xfer { - rockchip,pins = - <2 RK_PB2 2 &pcfg_pull_none>, - <2 RK_PB1 2 &pcfg_pull_none>; - }; - }; - - i2c7 { - i2c7_xfer: i2c7-xfer { - rockchip,pins = - <2 RK_PB0 2 &pcfg_pull_none>, - <2 RK_PA7 2 &pcfg_pull_none>; - }; - }; - - i2c8 { - i2c8_xfer: i2c8-xfer { - rockchip,pins = - <1 RK_PC5 1 &pcfg_pull_none>, - <1 RK_PC4 1 &pcfg_pull_none>; - }; - }; - - i2s0 { - i2s0_2ch_bus: i2s0-2ch-bus { - rockchip,pins = - <3 RK_PD0 1 &pcfg_pull_none>, - <3 RK_PD1 1 &pcfg_pull_none>, - <3 RK_PD2 1 &pcfg_pull_none>, - <3 RK_PD3 1 &pcfg_pull_none>, - <3 RK_PD7 1 &pcfg_pull_none>, - <4 RK_PA0 1 &pcfg_pull_none>; - }; - - i2s0_2ch_bus_bclk_off: i2s0-2ch-bus-bclk-off { - rockchip,pins = - <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, - <3 RK_PD1 1 &pcfg_pull_none>, - <3 RK_PD2 1 &pcfg_pull_none>, - <3 RK_PD3 1 &pcfg_pull_none>, - <3 RK_PD7 1 &pcfg_pull_none>, - <4 RK_PA0 1 &pcfg_pull_none>; - }; - - i2s0_8ch_bus: i2s0-8ch-bus { - rockchip,pins = - <3 RK_PD0 1 &pcfg_pull_none>, - <3 RK_PD1 1 &pcfg_pull_none>, - <3 RK_PD2 1 &pcfg_pull_none>, - <3 RK_PD3 1 &pcfg_pull_none>, - <3 RK_PD4 1 &pcfg_pull_none>, - <3 RK_PD5 1 &pcfg_pull_none>, - <3 RK_PD6 1 &pcfg_pull_none>, - <3 RK_PD7 1 &pcfg_pull_none>, - <4 RK_PA0 1 &pcfg_pull_none>; - }; - - i2s0_8ch_bus_bclk_off: i2s0-8ch-bus-bclk-off { - rockchip,pins = - <3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>, - <3 RK_PD1 1 &pcfg_pull_none>, - <3 RK_PD2 1 &pcfg_pull_none>, - <3 RK_PD3 1 &pcfg_pull_none>, - <3 RK_PD4 1 &pcfg_pull_none>, - <3 RK_PD5 1 &pcfg_pull_none>, - <3 RK_PD6 1 &pcfg_pull_none>, - <3 RK_PD7 1 &pcfg_pull_none>, - <4 RK_PA0 1 &pcfg_pull_none>; - }; - }; - - i2s1 { - i2s1_2ch_bus: i2s1-2ch-bus { - rockchip,pins = - <4 RK_PA3 1 &pcfg_pull_none>, - <4 RK_PA4 1 &pcfg_pull_none>, - <4 RK_PA5 1 &pcfg_pull_none>, - <4 RK_PA6 1 &pcfg_pull_none>, - <4 RK_PA7 1 &pcfg_pull_none>; - }; - - i2s1_2ch_bus_bclk_off: i2s1-2ch-bus-bclk-off { - rockchip,pins = - <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>, - <4 RK_PA4 1 &pcfg_pull_none>, - <4 RK_PA5 1 &pcfg_pull_none>, - <4 RK_PA6 1 &pcfg_pull_none>, - <4 RK_PA7 1 &pcfg_pull_none>; - }; - }; - - sdio0 { - sdio0_bus1: sdio0-bus1 { - rockchip,pins = - <2 RK_PC4 1 &pcfg_pull_up>; - }; - - sdio0_bus4: sdio0-bus4 { - rockchip,pins = - <2 RK_PC4 1 &pcfg_pull_up>, - <2 RK_PC5 1 &pcfg_pull_up>, - <2 RK_PC6 1 &pcfg_pull_up>, - <2 RK_PC7 1 &pcfg_pull_up>; - }; - - sdio0_cmd: sdio0-cmd { - rockchip,pins = - <2 RK_PD0 1 &pcfg_pull_up>; - }; - - sdio0_clk: sdio0-clk { - rockchip,pins = - <2 RK_PD1 1 &pcfg_pull_none>; - }; - - sdio0_cd: sdio0-cd { - rockchip,pins = - <2 RK_PD2 1 &pcfg_pull_up>; - }; - - sdio0_pwr: sdio0-pwr { - rockchip,pins = - <2 RK_PD3 1 &pcfg_pull_up>; - }; - - sdio0_bkpwr: sdio0-bkpwr { - rockchip,pins = - <2 RK_PD4 1 &pcfg_pull_up>; - }; - - sdio0_wp: sdio0-wp { - rockchip,pins = - <0 RK_PA3 1 &pcfg_pull_up>; - }; - - sdio0_int: sdio0-int { - rockchip,pins = - <0 RK_PA4 1 &pcfg_pull_up>; - }; - }; - - sdmmc { - sdmmc_bus1: sdmmc-bus1 { - rockchip,pins = - <4 RK_PB0 1 &pcfg_pull_up>; - }; - - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = - <4 RK_PB0 1 &pcfg_pull_up>, - <4 RK_PB1 1 &pcfg_pull_up>, - <4 RK_PB2 1 &pcfg_pull_up>, - <4 RK_PB3 1 &pcfg_pull_up>; - }; - - sdmmc_clk: sdmmc-clk { - rockchip,pins = - <4 RK_PB4 1 &pcfg_pull_none>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = - <4 RK_PB5 1 &pcfg_pull_up>; - }; - - sdmmc_cd: sdmmc-cd { - rockchip,pins = - <0 RK_PA7 1 &pcfg_pull_up>; - }; - - sdmmc_wp: sdmmc-wp { - rockchip,pins = - <0 RK_PB0 1 &pcfg_pull_up>; - }; - }; - - suspend { - ap_pwroff: ap-pwroff { - rockchip,pins = <1 RK_PA5 1 &pcfg_pull_none>; - }; - - ddrio_pwroff: ddrio-pwroff { - rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>; - }; - }; - - spdif { - spdif_bus: spdif-bus { - rockchip,pins = - <4 RK_PC5 1 &pcfg_pull_none>; - }; - - spdif_bus_1: spdif-bus-1 { - rockchip,pins = - <3 RK_PC0 3 &pcfg_pull_none>; - }; - }; - - spi0 { - spi0_clk: spi0-clk { - rockchip,pins = - <3 RK_PA6 2 &pcfg_pull_up>; - }; - spi0_cs0: spi0-cs0 { - rockchip,pins = - <3 RK_PA7 2 &pcfg_pull_up>; - }; - spi0_cs1: spi0-cs1 { - rockchip,pins = - <3 RK_PB0 2 &pcfg_pull_up>; - }; - spi0_tx: spi0-tx { - rockchip,pins = - <3 RK_PA5 2 &pcfg_pull_up>; - }; - spi0_rx: spi0-rx { - rockchip,pins = - <3 RK_PA4 2 &pcfg_pull_up>; - }; - }; - - spi1 { - spi1_clk: spi1-clk { - rockchip,pins = - <1 RK_PB1 2 &pcfg_pull_up>; - }; - spi1_cs0: spi1-cs0 { - rockchip,pins = - <1 RK_PB2 2 &pcfg_pull_up>; - }; - spi1_rx: spi1-rx { - rockchip,pins = - <1 RK_PA7 2 &pcfg_pull_up>; - }; - spi1_tx: spi1-tx { - rockchip,pins = - <1 RK_PB0 2 &pcfg_pull_up>; - }; - }; - - spi2 { - spi2_clk: spi2-clk { - rockchip,pins = - <2 RK_PB3 1 &pcfg_pull_up>; - }; - spi2_cs0: spi2-cs0 { - rockchip,pins = - <2 RK_PB4 1 &pcfg_pull_up>; - }; - spi2_rx: spi2-rx { - rockchip,pins = - <2 RK_PB1 1 &pcfg_pull_up>; - }; - spi2_tx: spi2-tx { - rockchip,pins = - <2 RK_PB2 1 &pcfg_pull_up>; - }; - }; - - spi3 { - spi3_clk: spi3-clk { - rockchip,pins = - <1 RK_PC1 1 &pcfg_pull_up>; - }; - spi3_cs0: spi3-cs0 { - rockchip,pins = - <1 RK_PC2 1 &pcfg_pull_up>; - }; - spi3_rx: spi3-rx { - rockchip,pins = - <1 RK_PB7 1 &pcfg_pull_up>; - }; - spi3_tx: spi3-tx { - rockchip,pins = - <1 RK_PC0 1 &pcfg_pull_up>; - }; - }; - - spi4 { - spi4_clk: spi4-clk { - rockchip,pins = - <3 RK_PA2 2 &pcfg_pull_up>; - }; - spi4_cs0: spi4-cs0 { - rockchip,pins = - <3 RK_PA3 2 &pcfg_pull_up>; - }; - spi4_rx: spi4-rx { - rockchip,pins = - <3 RK_PA0 2 &pcfg_pull_up>; - }; - spi4_tx: spi4-tx { - rockchip,pins = - <3 RK_PA1 2 &pcfg_pull_up>; - }; - }; - - spi5 { - spi5_clk: spi5-clk { - rockchip,pins = - <2 RK_PC6 2 &pcfg_pull_up>; - }; - spi5_cs0: spi5-cs0 { - rockchip,pins = - <2 RK_PC7 2 &pcfg_pull_up>; - }; - spi5_rx: spi5-rx { - rockchip,pins = - <2 RK_PC4 2 &pcfg_pull_up>; - }; - spi5_tx: spi5-tx { - rockchip,pins = - <2 RK_PC5 2 &pcfg_pull_up>; - }; - }; - - testclk { - test_clkout0: test-clkout0 { - rockchip,pins = - <0 RK_PA0 1 &pcfg_pull_none>; - }; - - test_clkout1: test-clkout1 { - rockchip,pins = - <2 RK_PD1 2 &pcfg_pull_none>; - }; - - test_clkout2: test-clkout2 { - rockchip,pins = - <0 RK_PB0 3 &pcfg_pull_none>; - }; - }; - - tsadc { - otp_pin: otp-pin { - rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - otp_out: otp-out { - rockchip,pins = <1 RK_PA6 1 &pcfg_pull_none>; - }; - }; - - uart0 { - uart0_xfer: uart0-xfer { - rockchip,pins = - <2 RK_PC0 1 &pcfg_pull_up>, - <2 RK_PC1 1 &pcfg_pull_none>; - }; - - uart0_cts: uart0-cts { - rockchip,pins = - <2 RK_PC2 1 &pcfg_pull_none>; - }; - - uart0_rts: uart0-rts { - rockchip,pins = - <2 RK_PC3 1 &pcfg_pull_none>; - }; - }; - - uart1 { - uart1_xfer: uart1-xfer { - rockchip,pins = - <3 RK_PB4 2 &pcfg_pull_up>, - <3 RK_PB5 2 &pcfg_pull_none>; - }; - }; - - uart2a { - uart2a_xfer: uart2a-xfer { - rockchip,pins = - <4 RK_PB0 2 &pcfg_pull_up>, - <4 RK_PB1 2 &pcfg_pull_none>; - }; - }; - - uart2b { - uart2b_xfer: uart2b-xfer { - rockchip,pins = - <4 RK_PC0 2 &pcfg_pull_up>, - <4 RK_PC1 2 &pcfg_pull_none>; - }; - }; - - uart2c { - uart2c_xfer: uart2c-xfer { - rockchip,pins = - <4 RK_PC3 1 &pcfg_pull_up>, - <4 RK_PC4 1 &pcfg_pull_none>; - }; - }; - - uart3 { - uart3_xfer: uart3-xfer { - rockchip,pins = - <3 RK_PB6 2 &pcfg_pull_up>, - <3 RK_PB7 2 &pcfg_pull_none>; - }; - - uart3_cts: uart3-cts { - rockchip,pins = - <3 RK_PC0 2 &pcfg_pull_none>; - }; - - uart3_rts: uart3-rts { - rockchip,pins = - <3 RK_PC1 2 &pcfg_pull_none>; - }; - }; - - uart4 { - uart4_xfer: uart4-xfer { - rockchip,pins = - <1 RK_PA7 1 &pcfg_pull_up>, - <1 RK_PB0 1 &pcfg_pull_none>; - }; - }; - - uarthdcp { - uarthdcp_xfer: uarthdcp-xfer { - rockchip,pins = - <4 RK_PC5 2 &pcfg_pull_up>, - <4 RK_PC6 2 &pcfg_pull_none>; - }; - }; - - pwm0 { - pwm0_pin: pwm0-pin { - rockchip,pins = - <4 RK_PC2 1 &pcfg_pull_none>; - }; - - pwm0_pin_pull_down: pwm0-pin-pull-down { - rockchip,pins = - <4 RK_PC2 1 &pcfg_pull_down>; - }; - - vop0_pwm_pin: vop0-pwm-pin { - rockchip,pins = - <4 RK_PC2 2 &pcfg_pull_none>; - }; - - vop1_pwm_pin: vop1-pwm-pin { - rockchip,pins = - <4 RK_PC2 3 &pcfg_pull_none>; - }; - }; - - pwm1 { - pwm1_pin: pwm1-pin { - rockchip,pins = - <4 RK_PC6 1 &pcfg_pull_none>; - }; - - pwm1_pin_pull_down: pwm1-pin-pull-down { - rockchip,pins = - <4 RK_PC6 1 &pcfg_pull_down>; - }; - }; - - pwm2 { - pwm2_pin: pwm2-pin { - rockchip,pins = - <1 RK_PC3 1 &pcfg_pull_none>; - }; - - pwm2_pin_pull_down: pwm2-pin-pull-down { - rockchip,pins = - <1 RK_PC3 1 &pcfg_pull_down>; - }; - }; - - pwm3a { - pwm3a_pin: pwm3a-pin { - rockchip,pins = - <0 RK_PA6 1 &pcfg_pull_none>; - }; - }; +&cpu_l0 { + operating-points-v2 = <&cluster0_opp>; +}; - pwm3b { - pwm3b_pin: pwm3b-pin { - rockchip,pins = - <1 RK_PB6 1 &pcfg_pull_none>; - }; - }; +&cpu_l1 { + operating-points-v2 = <&cluster0_opp>; +}; - hdmi { - hdmi_i2c_xfer: hdmi-i2c-xfer { - rockchip,pins = - <4 RK_PC1 3 &pcfg_pull_none>, - <4 RK_PC0 3 &pcfg_pull_none>; - }; +&cpu_l2 { + operating-points-v2 = <&cluster0_opp>; +}; - hdmi_cec: hdmi-cec { - rockchip,pins = - <4 RK_PC7 1 &pcfg_pull_none>; - }; - }; +&cpu_l3 { + operating-points-v2 = <&cluster0_opp>; +}; - pcie { - pcie_clkreqn_cpm: pci-clkreqn-cpm { - rockchip,pins = - <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; - }; +&cpu_b0 { + operating-points-v2 = <&cluster1_opp>; +}; - pcie_clkreqnb_cpm: pci-clkreqnb-cpm { - rockchip,pins = - <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; +&cpu_b1 { + operating-points-v2 = <&cluster1_opp>; +}; - }; +&gpu { + operating-points-v2 = <&gpu_opp_table>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts index c58fb7658d7a..d3c628218ce3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-rock-pi-n10.dts @@ -7,7 +7,6 @@ /dts-v1/; #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" #include <arm/rockchip/rockchip-radxa-dalang-carrier.dtsi> #include "rk3399pro-vmarc-som.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts index a73cf30801ec..9816a4ed4599 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts @@ -92,7 +92,7 @@ }; &i2c2 { - pintctrl-names = "default"; + pinctrl-names = "default"; pinctrl-0 = <&i2c2m1_xfer>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts index e9954a33e8cd..a79a5614bcc8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts @@ -79,7 +79,7 @@ }; &i2c2 { - pintctrl-names = "default"; + pinctrl-names = "default"; pinctrl-0 = <&i2c2m1_xfer>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts index 0c18406e4c59..7d4680933823 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts @@ -449,9 +449,9 @@ bluetooth { compatible = "brcm,bcm43438-bt"; clocks = <&pmucru CLK_RTC_32K>; - clock-names = "ext_clock"; - device-wake-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; - host-wake-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; + clock-names = "txco"; + device-wakeup-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + host-wakeup-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts b/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts new file mode 100644 index 000000000000..7cd91f8000cb --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566-lckfb-tspi.dts @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/soc/rockchip,vop2.h> +#include <dt-bindings/soc/rockchip,boot-mode.h> +#include "rk3566.dtsi" + +/ { + model = "LCKFB Taishan Pi RK3566"; + compatible = "lckfb,tspi-rk3566", "rockchip,rk3566"; + + aliases { + mmc0 = &sdmmc0; + mmc1 = &sdhci; + mmc2 = &sdmmc1; + }; + + chosen: chosen { + stdout-path = "serial2:1500000n8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ramoops: ramoops@110000 { + compatible = "ramoops"; + reg = <0 0x110000 0 0xf0000>; + console-size = <0x80000>; + ftrace-size = <0x00000>; + pmsg-size = <0x50000>; + record-size = <0x20000>; + }; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-recovery { + label = "recovery"; + linux,code = <KEY_RESTART>; + press-threshold-microvolt = <108>; + }; + }; + + hdmi_con: hdmi-con { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds: leds { + compatible = "gpio-leds"; + + rgb_led_r: rgb-led-r { + color = <LED_COLOR_ID_RED>; + gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_LOW>; + label = "status-red"; + }; + + rgb_led_g: rgb-led-g { + gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; + color = <LED_COLOR_ID_GREEN>; + label = "status-green"; + }; + + rgb_led_b: rgb-led-b { + gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + color = <LED_COLOR_ID_BLUE>; + label = "status-blue"; + }; + }; + + multi_leds: multi-led { + compatible = "leds-group-multicolor"; + color = <LED_COLOR_ID_RGB>; + label = "status-rgb"; + function = LED_FUNCTION_INDICATOR; + leds = <&rgb_led_r>, <&rgb_led_g>, <&rgb_led_b>; + }; + + vcc12v0_dcin: regulator-12v0-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v0_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc3v3_sys: regulator-3v3-vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: regulator-5v0-vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v0_dcin>; + }; + + vcc5v0_host: regulator-5v0-vcc-host { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-name = "vcc5v0_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk809 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + assigned-clocks = <&cru I2S1_MCLKOUT_TX>; + assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; + #clock-cells = <1>; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; + clock-names = "mclk"; + clocks = <&cru I2S1_MCLKOUT_TX>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; + rockchip,system-power-controller; + #sound-dai-cells = <0>; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + codec { + rockchip,mic-in-differential; + }; + }; +}; + +&i2c1 { + status = "okay"; + /* Touch Screen */ +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m0_xfer>; + status = "okay"; + /* Camera */ +}; + +&i2s0_8ch { + status = "okay"; + /* HDMI */ +}; + +&i2s1_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s1m0_sclktx &i2s1m0_lrcktx &i2s1m0_sdi0 &i2s1m0_sdo0>; + rockchip,trcm-sync-tx-only; + status = "okay"; + /* PMIC */ +}; + +&i2s2_2ch { + rockchip,trcm-sync-tx-only; + status = "okay"; + /* AP6212 Bluetooth */ +}; + +&pinctrl { + bt { + bt_enable_h: bt-enable-h { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_host_wake_l: bt-host-wake-l { + rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + bt_wake_l: bt-wake-l { + rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hp-detect { + hp_det: hp-det { + rockchip,pins = <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wifi_host_wake_h: wifi-host-wake-l { + rockchip,pins = <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_1v8>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&pmugrf { + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x200>; + mode-normal = <BOOT_NORMAL>; + mode-loader = <BOOT_BL_DOWNLOAD>; + mode-recovery = <BOOT_RECOVERY>; + mode-bootloader = <BOOT_FASTBOOT>; + }; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; + /* Channel 0: Recovery Button */ + /* Channel 1: Hardware ID */ +}; + +&sdhci { + bus-width = <8>; + max-frequency = <200000000>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe &emmc_rstnout>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc1 { + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + max-frequency = <150000000>; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sys>; + vqmmc-supply = <&vcc_1v8>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + brcmf: wifi@1 { + compatible = "brcm,bcm4329-fmac"; + reg = <1>; + interrupt-parent = <&gpio2>; + interrupts = <RK_PB2 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wake"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_h>; + }; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>; + uart-has-rtscts; + status = "okay"; + + bluetooth: bluetooth { + compatible = "brcm,bcm43438-bt"; + clocks = <&rk809 1>; + clock-names = "lpo"; + max-speed = <3000000>; + pinctrl-names = "default"; + pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>; + shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + vbat-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "otg"; + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_sys>; + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_sys>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = <ROCKCHIP_VOP2_EP_HDMI0>; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts index c1194d1e438d..9a2f59a351de 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts @@ -507,7 +507,6 @@ non-removable; pinctrl-names = "default"; pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; - supports-emmc; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-odroid-m1s.dts b/arch/arm64/boot/dts/rockchip/rk3566-odroid-m1s.dts new file mode 100644 index 000000000000..33bc5249d729 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566-odroid-m1s.dts @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/soc/rockchip,vop2.h> +#include "rk3566.dtsi" + +/ { + model = "Hardkernel ODROID-M1S"; + compatible = "hardkernel,odroid-m1s", "rockchip,rk3566"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdhci; + mmc1 = &sdmmc0; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + hdmi-con { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_led>, <&sys_led>; + + led_pwr: led-0 { + color = <LED_COLOR_ID_RED>; + default-state = "on"; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "default-on"; + }; + + led_sys: led-1 { + color = <LED_COLOR_ID_BLUE>; + default-state = "on"; + function = LED_FUNCTION_HEARTBEAT; + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + vcc3v3_lcd: regulator-3v3-vcc-lcd { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pwren>; + regulator-name = "vcc3v3_lcd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + }; + + vcc3v3_pcie: regulator-3v3-vcc-pcie { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pwren>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + }; + + vcc3v3_sys: regulator-3v3-vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: regulator-5v0-vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc5v0_usb2_host: regulator-5v0-vcc-usb2-host { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_host_pwren>; + regulator-name = "vcc5v0_usb2_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb2_otg: regulator-5v0-vcc-usb2-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_otg_pwren>; + regulator-name = "vcc5v0_usb2_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb3_host: regulator-5v0-vcc-usb3-host { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_host_pwren>; + regulator-name = "vcc5v0_usb3_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "Analog RK809"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s1_8ch>; + }; + + simple-audio-card,codec { + sound-dai = <&rk809>; + }; + }; +}; + +&combphy1 { + status = "okay"; +}; + +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; +}; + +&gmac1 { + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>; + clock_in_out = "input"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-id"; + phy-supply = <&vcc_3v3>; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus + &gmac1m1_clkinout>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + avdd-0v9-supply = <&vdda0v9_image>; + avdd-1v8-supply = <&vcca1v8_image>; + status = "okay"; +}; + +&hdmi_in { + hdmi_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi>; + }; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&hdmi_sound { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + vdd_cpu: regulator@1c { + compatible = "tcs,tcs4525"; + reg = <0x1c>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk809: pmic@20 { + compatible = "rockchip,rk809"; + reg = <0x20>; + assigned-clocks = <&cru I2S1_MCLKOUT_TX>; + assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; + #clock-cells = <1>; + clocks = <&cru I2S1_MCLKOUT_TX>; + clock-names = "mclk"; + clock-output-names = "rk809-clkout1", "rk809-clkout2"; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; + #sound-dai-cells = <0>; + system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2s0_8ch { + status = "okay"; +}; + +&i2s1_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s1m0_sclktx + &i2s1m0_lrcktx + &i2s1m0_sdi0 + &i2s1m0_sdo0>; + rockchip,trcm-sync-tx-only; + status = "okay"; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie20_pins>; + reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + lcd { + lcd_pwren: lcd-pwren { + rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + pwr_led: pwr-led { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led: sys-led { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie20_pins: pcie20-pins { + rockchip,pins = + <1 RK_PB0 4 &pcfg_pull_none>, + <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PB1 4 &pcfg_pull_none>; + }; + + pcie_pwren: pcie-pwren { + rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + usb2_host_pwren: usb2-host-pwren { + rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usb2_otg_pwren: usb2-otg-pwren { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usb3_host_pwren: usb3-host-pwren { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + pmuio1-supply = <&vcc3v3_pmu>; + pmuio2-supply = <&vcc3v3_pmu>; + vccio1-supply = <&vccio_acodec>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vccio_sd>; + vccio4-supply = <&vcc_3v3>; + vccio5-supply = <&vcc_3v3>; + vccio6-supply = <&vcc_3v3>; + vccio7-supply = <&vcc_3v3>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + cap-mmc-highspeed; + max-frequency = <200000000>; + mmc-hs200-1_8v; + no-sd; + no-sdio; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe &emmc_rstnout>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sdmmc0 { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; + sd-uhs-sdr50; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb2phy0 { + status = "okay"; +}; + +&usb2phy0_host { + phy-supply = <&vcc5v0_usb3_host>; + status = "okay"; +}; + +&usb2phy0_otg { + phy-supply = <&vcc5v0_usb2_otg>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +&usb2phy1_host { + phy-supply = <&vcc5v0_usb2_host>; + status = "okay"; +}; + +&usb2phy1_otg { + phy-supply = <&vcc5v0_usb2_host>; + status = "okay"; +}; + +&vop { + assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; + assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = <ROCKCHIP_VOP2_EP_HDMI0>; + remote-endpoint = <&hdmi_in_vp0>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi index ae2536c65a83..0131f2cdd312 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi @@ -684,11 +684,11 @@ compatible = "brcm,bcm43438-bt"; clocks = <&rk817 1>; clock-names = "lpo"; - device-wake-gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>; - host-wake-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>; + device-wakeup-gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>; + host-wakeup-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&bt_enable_h>, <&bt_host_wake_l>, <&bt_wake_h>; pinctrl-names = "default"; + shutdown-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; vbat-supply = <&vcc_wl>; vddio-supply = <&vcca_1v8_pmu>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts index 13e599a85eb8..c164074ddf54 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts @@ -648,6 +648,8 @@ }; &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi index 45de2630bb50..1e36f73840da 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-cm3.dtsi @@ -402,9 +402,9 @@ clock-names = "lpo"; device-wakeup-gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_HIGH>; host-wakeup-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&bt_host_wake_h &bt_reg_on_h &bt_wake_host_h>; + shutdown-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; vbat-supply = <&vcc_3v3>; vddio-supply = <&vcc_1v8>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi index 9cc7aa3298d0..de390d92c35e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-radxa-zero-3.dtsi @@ -493,7 +493,6 @@ }; &usb_host0_xhci { - dr_mode = "peripheral"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts index b5e67990dd0f..8e5c182ef76c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dts @@ -20,9 +20,9 @@ cap-mmc-highspeed; cap-sd-highspeed; disable-wp; - max-frequency = <150000000>; no-sdio; no-mmc; + sd-uhs-sdr50; pinctrl-names = "default"; pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; vmmc-supply = <&vcc3v3_sd>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts index ce2a5e1ccefc..d27eb37b5b35 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r68s.dts @@ -39,12 +39,6 @@ &gmac0_rx_bus2 &gmac0_rgmii_clk &gmac0_rgmii_bus>; - snps,reset-gpio = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - /* Reset time is 15ms, 50ms for rtl8211f */ - snps,reset-delays-us = <0 15000 50000>; - tx_delay = <0x3c>; - rx_delay = <0x2f>; status = "okay"; }; @@ -61,12 +55,6 @@ &gmac1m1_rx_bus2 &gmac1m1_rgmii_clk &gmac1m1_rgmii_bus>; - snps,reset-gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - /* Reset time is 15ms, 50ms for rtl8211f */ - snps,reset-delays-us = <0 15000 50000>; - tx_delay = <0x4f>; - rx_delay = <0x26>; status = "okay"; }; @@ -76,6 +64,9 @@ reg = <0x1>; pinctrl-0 = <ð_phy0_reset_pin>; pinctrl-names = "default"; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; }; }; @@ -85,6 +76,9 @@ reg = <0x1>; pinctrl-0 = <ð_phy1_reset_pin>; pinctrl-names = "default"; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts index a3112d5df200..b505a4537ee8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts @@ -589,7 +589,6 @@ non-removable; pinctrl-names = "default"; pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; - supports-emmc; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts b/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts index c2dfffc638d1..c491dc4d4947 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-mecsbc.dts @@ -89,6 +89,20 @@ }; }; +&can0 { + compatible = "rockchip,rk3568v3-canfd", "rockchip,rk3568v2-canfd"; + pinctrl-names = "default"; + pinctrl-0 = <&can0m0_pins>; + status = "okay"; +}; + +&can1 { + compatible = "rockchip,rk3568v3-canfd", "rockchip,rk3568v2-canfd"; + pinctrl-names = "default"; + pinctrl-0 = <&can1m1_pins>; + status = "okay"; +}; + &combphy0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts index a337f547caf5..6a02db4f073f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts @@ -13,7 +13,7 @@ / { model = "Hardkernel ODROID-M1"; - compatible = "rockchip,rk3568-odroid-m1", "rockchip,rk3568"; + compatible = "hardkernel,odroid-m1", "rockchip,rk3568"; aliases { ethernet0 = &gmac0; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts index 6a998166003c..e601d9271ba8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-qnap-ts433.dts @@ -6,12 +6,190 @@ /dts-v1/; +#include <dt-bindings/input/input.h> +#include <dt-bindings/leds/common.h> #include <dt-bindings/gpio/gpio.h> #include "rk3568.dtsi" / { model = "Qnap TS-433-4G NAS System 4-Bay"; compatible = "qnap,ts433", "rockchip,rk3568"; + + aliases { + ethernet0 = &gmac0; + mmc0 = &sdhci; + rtc0 = &rtc_rv8263; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <©_button_pin>, <&reset_button_pin>; + pinctrl-names = "default"; + + key-copy { + label = "copy"; + gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>; + linux,code = <KEY_COPY>; + }; + + key-reset { + label = "reset"; + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>; + linux,code = <KEY_RESTART>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DISK; + gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + pinctrl-names = "default"; + pinctrl-0 = <&hdd1_led_pin>; + }; + + led-1 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DISK; + gpios = <&gpio1 RK_PD6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + pinctrl-names = "default"; + pinctrl-0 = <&hdd2_led_pin>; + }; + + led-2 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DISK; + gpios = <&gpio1 RK_PD7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + pinctrl-names = "default"; + pinctrl-0 = <&hdd3_led_pin>; + }; + + led-3 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_DISK; + gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + pinctrl-names = "default"; + pinctrl-0 = <&hdd4_led_pin>; + }; + }; + + dc_12v: regulator-dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc3v3_pcie: regulator-vcc3v3-pcie { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: regulator-vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&dc_12v>; + }; + + vcc5v0_host: regulator-vcc5v0-host { + compatible = "regulator-fixed"; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc5v0_host"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_otg: regulator-vcc5v0-otg { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_otg_en>; + regulator-name = "vcc5v0_otg"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_sys: regulator-vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + + vcc5v0_usb: regulator-vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; +}; + +/* connected to usb_host0_xhci */ +&combphy0 { + status = "okay"; +}; + +/* connected to sata1 */ +&combphy1 { + status = "okay"; +}; + +/* connected to sata2 */ +&combphy2 { + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu1 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu2 { + cpu-supply = <&vdd_cpu>; +}; + +&cpu3 { + cpu-supply = <&vdd_cpu>; }; &gmac0 { @@ -20,35 +198,282 @@ assigned-clock-rates = <0>, <125000000>; clock_in_out = "output"; phy-handle = <&rgmii_phy0>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; pinctrl-names = "default"; pinctrl-0 = <&gmac0_miim &gmac0_tx_bus2 &gmac0_rx_bus2 &gmac0_rgmii_clk &gmac0_rgmii_bus>; - rx_delay = <0x2f>; - tx_delay = <0x3c>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; status = "okay"; }; &i2c0 { + status = "okay"; + pmic@20 { compatible = "rockchip,rk809"; reg = <0x20>; interrupt-parent = <&gpio0>; - interrupts = <3 IRQ_TYPE_LEVEL_LOW>; + interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + system-power-controller; + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + wakeup-source; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-initial-mode = <0x2>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_npu: DCDC_REG4 { + regulator-name = "vdd_npu"; + regulator-initial-mode = <0x2>; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG5 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_image: LDO_REG1 { + regulator-name = "vdda0v9_image"; + regulator-always-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v9: LDO_REG2 { + regulator-name = "vdda_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v9_pmu: LDO_REG3 { + regulator-name = "vdda0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_acodec: LDO_REG4 { + regulator-name = "vccio_acodec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_pmu: LDO_REG6 { + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcca_1v8: LDO_REG7 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca1v8_pmu: LDO_REG8 { + regulator-name = "vcca1v8_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcca1v8_image: LDO_REG9 { + regulator-name = "vcca1v8_image"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_sd: SWITCH_REG2 { + regulator-name = "vcc3v3_sd"; + /* + * turning this off, breaks access to both + * PCIe controllers, refclk generator perhaps + */ + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; }; }; &i2c1 { status = "okay"; - rtc@51 { + rtc_rv8263: rtc@51 { compatible = "microcrystal,rv8263"; reg = <0x51>; wakeup-source; }; + + /* eeprom for vital-product-data on the mainboard */ + eeprom@54 { + compatible = "giantec,gt24c04a", "atmel,24c04"; + reg = <0x54>; + label = "VPD_MB"; + num-addresses = <2>; + pagesize = <16>; + read-only; + }; + + /* eeprom for vital-product-data on the backplane */ + eeprom@56 { + compatible = "giantec,gt24c04a", "atmel,24c04"; + reg = <0x56>; + label = "VPD_BP"; + num-addresses = <2>; + pagesize = <16>; + read-only; + }; }; &mdio0 { @@ -59,12 +484,82 @@ }; &pcie30phy { + data-lanes = <1 2>; status = "okay"; }; +/* Connected to a JMicron AHCI SATA controller */ &pcie3x1 { - /* The downstream dts has: rockchip,bifurcation, XXX: find out what this is about */ reset-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +/* Connected to the 2.5G NIC for the upper network jack */ +&pcie3x2 { + num-lanes = <1>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + keys { + copy_button_pin: copy-button-pin { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + hdd1_led_pin: hdd1-led-pin { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + hdd2_led_pin: hdd2-led-pin { + rockchip,pins = <1 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + hdd3_led_pin: hdd3-led-pin { + rockchip,pins = <1 RK_PD7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + hdd4_led_pin: hdd4_led-pin { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_otg_en: vcc5v0-otg-en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + vccio4-supply = <&vcc_1v8>; + vccio6-supply = <&vcc_1v8>; + status = "okay"; +}; + +&sata1 { + status = "okay"; +}; + +&sata2 { status = "okay"; }; @@ -75,6 +570,20 @@ status = "okay"; }; +&tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +/* + * Connected to an MCU, that provides access to more LEDs, + * buzzer, fan control and more. + */ +&uart0 { + status = "okay"; +}; + /* * Pins available on CN3 connector at TTL voltage level (3V3). * ,_ _. @@ -84,3 +593,53 @@ &uart2 { status = "okay"; }; + +&usb2phy0 { + status = "okay"; +}; + +/* connected to usb_host0_xhci */ +&usb2phy0_otg { + phy-supply = <&vcc5v0_otg>; + status = "okay"; +}; + +&usb2phy1 { + status = "okay"; +}; + +/* connected to usb_host1_ehci/ohci */ +&usb2phy1_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +/* connected to usb_host0_ehci/ohci */ +&usb2phy1_otg { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +/* right port backside */ +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +/* front port */ +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +/* left port backside */ +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi index 45b03dcbbad4..19d309654bdb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-radxa-cm3i.dtsi @@ -108,10 +108,6 @@ cpu-supply = <&vdd_cpu>; }; -&display_subsystem { - status = "disabled"; -}; - &gpu { mali-supply = <&vdd_gpu>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts b/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts index 72ad74c38a2b..84a0789fad96 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-radxa-e25.dts @@ -103,6 +103,10 @@ phy-supply = <&vcc3v3_pcie30x1>; }; +&display_subsystem { + status = "disabled"; +}; + &pcie2x1 { pinctrl-names = "default"; pinctrl-0 = <&pcie20_reset_h>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts index e333449ead04..2fa89a0eeafc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-roc-pc.dts @@ -272,7 +272,6 @@ regulator-name = "vdd_logic"; regulator-always-on; regulator-boot-on; - regulator-init-microvolt = <900000>; regulator-initial-mode = <0x2>; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1350000>; @@ -285,7 +284,6 @@ vdd_gpu: DCDC_REG2 { regulator-name = "vdd_gpu"; - regulator-init-microvolt = <900000>; regulator-initial-mode = <0x2>; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1350000>; @@ -309,7 +307,6 @@ vdd_npu: DCDC_REG4 { regulator-name = "vdd_npu"; - regulator-init-microvolt = <900000>; regulator-initial-mode = <0x2>; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1350000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display-vz.dtso b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display-vz.dtso new file mode 100644 index 000000000000..70c23e1bf14b --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display-vz.dtso @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Device tree overlay for the WolfVision PF5 Visualizer display. + * + * Copyright (C) 2024 WolfVision GmbH. + */ + +/dts-v1/; +/plugin/; + +#include "rk3568-wolfvision-pf5-display.dtsi" + +&st7789 { + compatible = "jasonic,jt240mhqs-hwt-ek-e3", + "sitronix,st7789v"; + rotation = <270>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display.dtsi new file mode 100644 index 000000000000..b22bb543ecbb --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-wolfvision-pf5-display.dtsi @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Device tree overlay base for the WolfVision PF5 displays. + * + * Copyright (C) 2024 WolfVision GmbH. + */ + +/dts-v1/; +/plugin/; + +#include <dt-bindings/clock/rk3568-cru.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/soc/rockchip,vop2.h> + +&{/} { + display_backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = <0 255>; + default-brightness-level = <255>; + num-interpolated-steps = <255>; + power-supply = <&vcc3v3_sd>; + pwms = <&pwm10 0 1000000 0>; + }; + + display_spi: spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_LOW>; + miso-gpios = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_HIGH>; + num-chipselects = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_spi>; + sck-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>; + + st7789: panel@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + assigned-clocks = <&cru PLL_VPLL>; + assigned-clock-rates = <700000000>; + backlight = <&display_backlight>; + pinctrl-names = "default"; + pinctrl-0 = <&lcdc_clock &lcdc_data18 &lcd_rstn>; + power-supply = <&vcc3v3_sw>; + reset-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>; + spi-max-frequency = <100000>; + + port { + panel_in_vp2: endpoint { + remote-endpoint = <&vp2_out_rgb>; + }; + }; + }; + }; +}; + +&i2c1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + st1624: touchscreen@55 { + compatible = "sitronix,st1624", "sitronix,st1633"; + reg = <0x55>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PB5 IRQ_TYPE_EDGE_FALLING>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_int &touch_rstn>; + wakeup-source; + }; +}; + +&pinctrl { + display: display-pinctrl { + lcd_rstn: lcd-rstn-pinctrl { + rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lcd_spi: lcd-spi-pinctrl { + rockchip,pins = + /* lcd_sdo */ + <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>, + /* lcd_csn */ + <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>, + /* lcd_scl */ + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>, + /* lcd_sdi */ + <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + touchscreen: touchscreen-pinctrl { + touch_int: touch-int-pinctrl { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + touch_rstn: touch-rstn-pinctrl { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm10 { + pinctrl-names = "default"; + pinctrl-0 = <&pwm10m1_pins>; + status = "okay"; +}; + +&vp2 { + #address-cells = <1>; + #size-cells = <0>; + + vp2_out_rgb: endpoint@ROCKCHIP_VOP2_EP_RGB0 { + reg = <ROCKCHIP_VOP2_EP_RGB0>; + remote-endpoint = <&panel_in_vp2>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index f1be76a54ceb..0946310e8c12 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -213,6 +213,45 @@ }; }; + can0: can@fe570000 { + compatible = "rockchip,rk3568v2-canfd"; + reg = <0x0 0xfe570000 0x0 0x1000>; + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru CLK_CAN0>, <&cru PCLK_CAN0>; + clock-names = "baud", "pclk"; + resets = <&cru SRST_CAN0>, <&cru SRST_P_CAN0>; + reset-names = "core", "apb"; + pinctrl-names = "default"; + pinctrl-0 = <&can0m0_pins>; + status = "disabled"; + }; + + can1: can@fe580000 { + compatible = "rockchip,rk3568v2-canfd"; + reg = <0x0 0xfe580000 0x0 0x1000>; + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru CLK_CAN1>, <&cru PCLK_CAN1>; + clock-names = "baud", "pclk"; + resets = <&cru SRST_CAN1>, <&cru SRST_P_CAN1>; + reset-names = "core", "apb"; + pinctrl-names = "default"; + pinctrl-0 = <&can1m0_pins>; + status = "disabled"; + }; + + can2: can@fe590000 { + compatible = "rockchip,rk3568v2-canfd"; + reg = <0x0 0xfe590000 0x0 0x1000>; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru CLK_CAN2>, <&cru PCLK_CAN2>; + clock-names = "baud", "pclk"; + resets = <&cru SRST_CAN2>, <&cru SRST_P_CAN2>; + reset-names = "core", "apb"; + pinctrl-names = "default"; + pinctrl-0 = <&can2m0_pins>; + status = "disabled"; + }; + combphy0: phy@fe820000 { compatible = "rockchip,rk3568-naneng-combphy"; reg = <0x0 0xfe820000 0x0 0x100>; @@ -257,6 +296,10 @@ }; }; +&rng { + status = "okay"; +}; + &usb_host0_xhci { phys = <&usb2phy0_otg>, <&combphy0 PHY_TYPE_USB3>; phy-names = "usb2-phy", "usb3-phy"; diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi index 4690be841a1c..0ee0ada6f0ab 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -1113,6 +1113,15 @@ status = "disabled"; }; + rng: rng@fe388000 { + compatible = "rockchip,rk3568-rng"; + reg = <0x0 0xfe388000 0x0 0x4000>; + clocks = <&cru CLK_TRNG_NS>, <&cru HCLK_TRNG_NS>; + clock-names = "core", "ahb"; + resets = <&cru SRST_TRNG_NS>; + status = "disabled"; + }; + i2s0_8ch: i2s@fe400000 { compatible = "rockchip,rk3568-i2s-tdm"; reg = <0x0 0xfe400000 0x0 0x1000>; @@ -1592,10 +1601,9 @@ <&cru SRST_TSADCPHY>; rockchip,grf = <&grf>; rockchip,hw-tshut-temp = <95000>; - pinctrl-names = "init", "default", "sleep"; - pinctrl-0 = <&tsadc_pin>; - pinctrl-1 = <&tsadc_shutorg>; - pinctrl-2 = <&tsadc_pin>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&tsadc_shutorg>; + pinctrl-1 = <&tsadc_pin>; #thermal-sensor-cells = <1>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi index 30db12c4fc82..d1368418502a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi @@ -2449,15 +2449,15 @@ /* sdio_clk_m1 */ <3 RK_PA5 2 &pcfg_pull_none>, /* sdio_cmd_m1 */ - <3 RK_PA4 2 &pcfg_pull_none>, + <3 RK_PA4 2 &pcfg_pull_up>, /* sdio_d0_m1 */ - <3 RK_PA0 2 &pcfg_pull_none>, + <3 RK_PA0 2 &pcfg_pull_up>, /* sdio_d1_m1 */ - <3 RK_PA1 2 &pcfg_pull_none>, + <3 RK_PA1 2 &pcfg_pull_up>, /* sdio_d2_m1 */ - <3 RK_PA2 2 &pcfg_pull_none>, + <3 RK_PA2 2 &pcfg_pull_up>, /* sdio_d3_m1 */ - <3 RK_PA3 2 &pcfg_pull_none>; + <3 RK_PA3 2 &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi index b6e4df180f0b..fc67585b64b7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi @@ -337,15 +337,19 @@ cache-unified; next-level-cache = <&l3_cache>; }; + }; - l3_cache: l3-cache { - compatible = "cache"; - cache-size = <3145728>; - cache-line-size = <64>; - cache-sets = <4096>; - cache-level = <3>; - cache-unified; - }; + /* + * The L3 cache belongs to the DynamIQ Shared Unit (DSU), + * so it's represented here, outside the "cpus" node + */ + l3_cache: l3-cache { + compatible = "cache"; + cache-size = <3145728>; + cache-line-size = <64>; + cache-sets = <4096>; + cache-level = <3>; + cache-unified; }; display_subsystem: display-subsystem { @@ -582,14 +586,14 @@ }; vo0_grf: syscon@fd5a6000 { - compatible = "rockchip,rk3588-vo-grf", "syscon"; + compatible = "rockchip,rk3588-vo0-grf", "syscon"; reg = <0x0 0xfd5a6000 0x0 0x2000>; clocks = <&cru PCLK_VO0GRF>; }; vo1_grf: syscon@fd5a8000 { - compatible = "rockchip,rk3588-vo-grf", "syscon"; - reg = <0x0 0xfd5a8000 0x0 0x100>; + compatible = "rockchip,rk3588-vo1-grf", "syscon"; + reg = <0x0 0xfd5a8000 0x0 0x4000>; clocks = <&cru PCLK_VO1GRF>; }; @@ -1122,6 +1126,118 @@ }; }; + vpu121: video-codec@fdb50000 { + compatible = "rockchip,rk3588-vpu121", "rockchip,rk3568-vpu"; + reg = <0x0 0xfdb50000 0x0 0x800>; + interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "vdpu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "hclk"; + iommus = <&vpu121_mmu>; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vpu121_mmu: iommu@fdb50800 { + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; + reg = <0x0 0xfdb50800 0x0 0x40>; + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>; + clock-names = "aclk", "iface"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + power-domains = <&power RK3588_PD_VDPU>; + #iommu-cells = <0>; + }; + + rga: rga@fdb80000 { + compatible = "rockchip,rk3588-rga", "rockchip,rk3288-rga"; + reg = <0x0 0xfdb80000 0x0 0x180>; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_RGA2>, <&cru HCLK_RGA2>, <&cru CLK_RGA2_CORE>; + clock-names = "aclk", "hclk", "sclk"; + resets = <&cru SRST_RGA2_CORE>, <&cru SRST_A_RGA2>, <&cru SRST_H_RGA2>; + reset-names = "core", "axi", "ahb"; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vepu121_0: video-codec@fdba0000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdba0000 0x0 0x800>; + interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; + clock-names = "aclk", "hclk"; + iommus = <&vepu121_0_mmu>; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vepu121_0_mmu: iommu@fdba0800 { + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; + reg = <0x0 0xfdba0800 0x0 0x40>; + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3588_PD_VDPU>; + #iommu-cells = <0>; + }; + + vepu121_1: video-codec@fdba4000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdba4000 0x0 0x800>; + interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; + clock-names = "aclk", "hclk"; + iommus = <&vepu121_1_mmu>; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vepu121_1_mmu: iommu@fdba4800 { + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; + reg = <0x0 0xfdba4800 0x0 0x40>; + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3588_PD_VDPU>; + #iommu-cells = <0>; + }; + + vepu121_2: video-codec@fdba8000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdba8000 0x0 0x800>; + interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; + clock-names = "aclk", "hclk"; + iommus = <&vepu121_2_mmu>; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vepu121_2_mmu: iommu@fdba8800 { + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; + reg = <0x0 0xfdba8800 0x0 0x40>; + interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3588_PD_VDPU>; + #iommu-cells = <0>; + }; + + vepu121_3: video-codec@fdbac000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdbac000 0x0 0x800>; + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; + clock-names = "aclk", "hclk"; + iommus = <&vepu121_3_mmu>; + power-domains = <&power RK3588_PD_VDPU>; + }; + + vepu121_3_mmu: iommu@fdbac800 { + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; + reg = <0x0 0xfdbac800 0x0 0x40>; + interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; + clock-names = "aclk", "iface"; + power-domains = <&power RK3588_PD_VDPU>; + #iommu-cells = <0>; + }; + av1d: video-codec@fdc70000 { compatible = "rockchip,rk3588-av1-vpu"; reg = <0x0 0xfdc70000 0x0 0x800>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts new file mode 100644 index 000000000000..6418286efe40 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include <dt-bindings/leds/common.h> +#include "rk3588-coolpi-cm5.dtsi" + +/ { + model = "CoolPi CM5 GenBook"; + compatible = "coolpi,pi-cm5-genbook", "coolpi,pi-cm5", "rockchip,rk3588"; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&bl_en>; + power-supply = <&vcc12v_dcin>; + pwms = <&pwm6 0 25000 0>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <9800000>; + voltage-max-design-microvolt = <4350000>; + voltage-min-design-microvolt = <3000000>; + }; + + charger: dc-charger { + compatible = "gpio-charger"; + charger-type = "mains"; + gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; + }; + + leds: leds { + compatible = "gpio-leds"; + + heartbeat_led: led-0 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + + wlan_led: led-1 { + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_WLAN; + gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + }; + + charging_red: led-2 { + function = LED_FUNCTION_CHARGING; + color = <LED_COLOR_ID_RED>; + gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + }; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_sys: vcc-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <7000000>; + regulator-max-microvolt = <7000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <7000000>; + regulator-max-microvolt = <7000000>; + vin-supply = <&vcc_sys>; + }; + + vcc3v3_sys: vcc3v3-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_lcd: vcc3v3-lcd-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_lcd"; + enable-active-high; + gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcdpwr_en>; + vin-supply = <&vcc3v3_sys>; + }; + + vcc5v0_usb: vcc5v0-usb-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-boot-on; + regulator-always-on; + enable-active-high; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_pwren>; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_usb_host0: vcc5v0_usb30_host: vcc5v0-usb-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + enable-active-high; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_host_pwren>; + vin-supply = <&vcc5v0_usb>; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_xfer>; + + cw2015@62 { + compatible = "cellwise,cw2015"; + reg = <0x62>; + + cellwise,battery-profile = /bits/ 8 < + 0x17 0x67 0x69 0x63 0x63 0x62 0x62 0x5F + 0x52 0x73 0x4C 0x5A 0x5B 0x4B 0x42 0x3A + 0x33 0x2D 0x29 0x28 0x2E 0x31 0x3C 0x49 + 0x2C 0x2C 0x0C 0xCD 0x30 0x51 0x50 0x66 + 0x74 0x74 0x75 0x78 0x41 0x1B 0x84 0x5F + 0x0B 0x34 0x1C 0x45 0x89 0x92 0xA0 0x13 + 0x2C 0x55 0xAB 0xCB 0x80 0x5E 0x7B 0xCB + 0x2F 0x00 0x64 0xA5 0xB5 0x10 0x18 0x21 + >; + + cellwise,monitor-interval-ms = <3000>; + monitored-battery = <&battery>; + power-supplies = <&charger>; + }; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m3_xfer>; + + touchpad: touchpad@2c { + compatible = "hid-over-i2c"; + reg = <0x2c>; + interrupt-parent = <&gpio1>; + interrupts = <RK_PD6 IRQ_TYPE_LEVEL_LOW>; + hid-descr-addr = <0x0020>; + }; +}; + +&gmac0 { + status = "disabled"; +}; + +/* M.2 E-Key */ +&pcie2x1l0 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_sys>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreq &pcie_wake &pcie_rst &wifi_pwron &bt_pwron>; + status = "okay"; +}; + +&pcie2x1l2 { + status = "disabled"; +}; + +&pcie30phy { + status = "okay"; +}; + +/* M.2 M-Key ssd */ +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_sys>; + status = "okay"; +}; + +&pinctrl { + lcd { + lcdpwr_en: lcdpwr-en { + rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + bl_en: bl-en { + rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + usb_pwren: usb-pwren { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + usb_otg_pwren: usb-otg-pwren { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + usb_host_pwren: usb-host-pwren { + rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + wifi { + bt_pwron: bt-pwron { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + pcie_clkreq: pcie-clkreq { + rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + pcie_rst: pcie-rst { + rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + wifi_pwron: wifi-pwron { + rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + pcie_wake: pcie-wake { + rockchip,pins = <4 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm6 { + pinctrl-0 = <&pwm6m1_pins>; + status = "okay"; +}; + +&sdmmc { + status = "disabled"; +}; + +&sfc { + pinctrl-names = "default"; + pinctrl-0 = <&fspim2_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <100000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&usbdp_phy0 { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_usb_host0>; + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_usb>; + status = "okay"; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +/* For Keypad */ +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +/* Type C port */ +&usb_host0_xhci { + dr_mode = "peripheral"; + maximum-speed = "high-speed"; + status = "okay"; +}; + +/* connected to a HUB for camera and BT */ +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +/* USB A out */ +&usb_host1_xhci { + dr_mode = "host"; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts new file mode 100644 index 000000000000..2d92bbb4027d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6-lts.dts @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * Copyright (c) 2023 Thomas McKahan + * Copyright (c) 2024 Linaro Ltd. + * + */ + +/dts-v1/; + +#include "rk3588-nanopc-t6.dtsi" + +/ { + model = "FriendlyElec NanoPC-T6 LTS"; + compatible = "friendlyarm,nanopc-t6-lts", "rockchip,rk3588"; + + /* provide power for on-board USB 2.0 hub */ + vcc5v0_usb20_host: vcc5v0-usb20-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usb20_host_pwren>; + pinctrl-names = "default"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_usb20_host"; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&pinctrl { + usb { + usb20_host_pwren: usb20-host-pwren { + rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_usb20_host>; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&usb_host1_xhci { + dr_mode = "host"; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts index ad8e36a339dc..92321c1d3ff1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts @@ -2,175 +2,18 @@ /* * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * Copyright (c) 2023 Thomas McKahan + * Copyright (c) 2024 Linaro Ltd. * */ /dts-v1/; -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/pinctrl/rockchip.h> -#include <dt-bindings/usb/pd.h> -#include "rk3588.dtsi" +#include "rk3588-nanopc-t6.dtsi" / { model = "FriendlyElec NanoPC-T6"; compatible = "friendlyarm,nanopc-t6", "rockchip,rk3588"; - aliases { - mmc0 = &sdhci; - mmc1 = &sdmmc; - }; - - chosen { - stdout-path = "serial2:1500000n8"; - }; - - leds { - compatible = "gpio-leds"; - - sys_led: led-0 { - gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; - label = "system-led"; - linux,default-trigger = "heartbeat"; - pinctrl-names = "default"; - pinctrl-0 = <&sys_led_pin>; - }; - - usr_led: led-1 { - gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; - label = "user-led"; - pinctrl-names = "default"; - pinctrl-0 = <&usr_led_pin>; - }; - }; - - sound { - compatible = "simple-audio-card"; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - - simple-audio-card,name = "realtek,rt5616-codec"; - simple-audio-card,format = "i2s"; - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>; - simple-audio-card,hp-pin-name = "Headphones"; - - simple-audio-card,widgets = - "Headphone", "Headphones", - "Microphone", "Microphone Jack"; - simple-audio-card,routing = - "Headphones", "HPOL", - "Headphones", "HPOR", - "MIC1", "Microphone Jack", - "Microphone Jack", "micbias1"; - - simple-audio-card,cpu { - sound-dai = <&i2s0_8ch>; - }; - simple-audio-card,codec { - sound-dai = <&rt5616>; - }; - }; - - vcc12v_dcin: vcc12v-dcin-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc12v_dcin"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - }; - - /* vcc5v0_sys powers peripherals */ - vcc5v0_sys: vcc5v0-sys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; - }; - - /* vcc4v0_sys powers the RK806, RK860's */ - vcc4v0_sys: vcc4v0-sys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc4v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <4000000>; - regulator-max-microvolt = <4000000>; - vin-supply = <&vcc12v_dcin>; - }; - - vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc-1v1-nldo-s3"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; - vin-supply = <&vcc4v0_sys>; - }; - - vcc_3v3_pcie20: vcc3v3-pcie20-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_3v3_pcie20"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc_3v3_s3>; - }; - - vbus5v0_typec: vbus5v0-typec-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&typec5v_pwren>; - regulator-name = "vbus5v0_typec"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc5v0_sys>; - }; - - vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_m2_1_pwren>; - regulator-name = "vcc3v3_pcie2x1l0"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc5v0_sys>; - }; - - vcc3v3_pcie30: vcc3v3-pcie30-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_m2_0_pwren>; - regulator-name = "vcc3v3_pcie30"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc5v0_sys>; - }; - - vcc3v3_sd_s0: vcc3v3-sd-s0-regulator { - compatible = "regulator-fixed"; - enable-active-low; - gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_LOW>; - regulator-boot-on; - regulator-max-microvolt = <3300000>; - regulator-min-microvolt = <3300000>; - regulator-name = "vcc3v3_sd_s0"; - vin-supply = <&vcc_3v3_s3>; - }; - vdd_4g_3v3: vdd-4g-3v3-regulator { compatible = "regulator-fixed"; enable-active-high; @@ -184,762 +27,14 @@ }; }; -&combphy0_ps { - status = "okay"; -}; - -&combphy1_ps { - status = "okay"; -}; - -&combphy2_psu { - status = "okay"; -}; - -&cpu_l0 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l1 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l2 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_b0 { - cpu-supply = <&vdd_cpu_big0_s0>; -}; - -&cpu_b1 { - cpu-supply = <&vdd_cpu_big0_s0>; -}; - -&cpu_b2 { - cpu-supply = <&vdd_cpu_big1_s0>; -}; - -&cpu_b3 { - cpu-supply = <&vdd_cpu_big1_s0>; -}; - -&gpio0 { - gpio-line-names = /* GPIO0 A0-A7 */ - "", "", "", "", - "", "", "", "", - /* GPIO0 B0-B7 */ - "", "", "", "", - "", "", "", "", - /* GPIO0 C0-C7 */ - "", "", "", "", - "HEADER_10", "HEADER_08", "HEADER_32", "", - /* GPIO0 D0-D7 */ - "", "", "", "", - "", "", "", ""; -}; - -&gpio1 { - gpio-line-names = /* GPIO1 A0-A7 */ - "HEADER_27", "HEADER_28", "", "", - "", "", "", "HEADER_15", - /* GPIO1 B0-B7 */ - "HEADER_26", "HEADER_21", "HEADER_19", "HEADER_23", - "HEADER_24", "HEADER_22", "", "", - /* GPIO1 C0-C7 */ - "", "", "", "", - "", "", "", "", - /* GPIO1 D0-D7 */ - "", "", "", "", - "", "", "HEADER_05", "HEADER_03"; -}; - -&gpio2 { - gpio-line-names = /* GPIO2 A0-A7 */ - "", "", "", "", - "", "", "", "", - /* GPIO2 B0-B7 */ - "", "", "", "", - "", "", "", "", - /* GPIO2 C0-C7 */ - "", "CSI1_11", "CSI1_12", "", - "", "", "", "", - /* GPIO2 D0-D7 */ - "", "", "", "", - "", "", "", ""; -}; - -&gpio3 { - gpio-line-names = /* GPIO3 A0-A7 */ - "HEADER_35", "HEADER_38", "HEADER_40", "HEADER_36", - "HEADER_37", "", "DSI0_12", "", - /* GPIO3 B0-B7 */ - "HEADER_33", "DSI0_10", "HEADER_07", "HEADER_16", - "HEADER_18", "HEADER_29", "HEADER_31", "HEADER_12", - /* GPIO3 C0-C7 */ - "DSI0_08", "DSI0_14", "HEADER_11", "HEADER_13", - "", "", "", "", - /* GPIO3 D0-D7 */ - "", "", "", "", - "", "DSI1_10", "", ""; -}; - -&gpio4 { - gpio-line-names = /* GPIO4 A0-A7 */ - "DSI1_08", "DSI1_14", "", "DSI1_12", - "", "", "", "", - /* GPIO4 B0-B7 */ - "", "", "", "", - "", "", "", "", - /* GPIO4 C0-C7 */ - "", "", "", "", - "CSI0_11", "CSI0_12", "", "", - /* GPIO4 D0-D7 */ - "", "", "", "", - "", "", "", ""; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0m2_xfer>; - status = "okay"; - - vdd_cpu_big0_s0: regulator@42 { - compatible = "rockchip,rk8602"; - reg = <0x42>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_cpu_big0_s0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <1050000>; - regulator-ramp-delay = <2300>; - vin-supply = <&vcc4v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_big1_s0: regulator@43 { - compatible = "rockchip,rk8603", "rockchip,rk8602"; - reg = <0x43>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_cpu_big1_s0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <1050000>; - regulator-ramp-delay = <2300>; - vin-supply = <&vcc4v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; -}; - -&i2c2 { - status = "okay"; - - vdd_npu_s0: regulator@42 { - compatible = "rockchip,rk8602"; - reg = <0x42>; - rockchip,suspend-voltage-selector = <1>; - regulator-name = "vdd_npu_s0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <2300>; - vin-supply = <&vcc4v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; -}; - -&i2c6 { - clock-frequency = <200000>; - status = "okay"; - - fusb302: typec-portc@22 { - compatible = "fcs,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio0>; - interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>; - pinctrl-0 = <&usbc0_int>; - pinctrl-names = "default"; - vbus-supply = <&vbus5v0_typec>; - - connector { - compatible = "usb-c-connector"; - data-role = "dual"; - label = "USB-C"; - power-role = "dual"; - try-power-role = "sink"; - source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>; - sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>; - op-sink-microwatt = <1000000>; - }; - }; - - hym8563: rtc@51 { - compatible = "haoyu,hym8563"; - reg = <0x51>; - #clock-cells = <0>; - clock-output-names = "hym8563"; - pinctrl-names = "default"; - pinctrl-0 = <&hym8563_int>; - interrupt-parent = <&gpio0>; - interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; - wakeup-source; - }; -}; - -&i2c7 { - clock-frequency = <200000>; - status = "okay"; - - rt5616: codec@1b { - compatible = "realtek,rt5616"; - reg = <0x1b>; - clocks = <&cru I2S0_8CH_MCLKOUT>; - clock-names = "mclk"; - #sound-dai-cells = <0>; - assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; - assigned-clock-rates = <12288000>; - - port { - rt5616_p0_0: endpoint { - remote-endpoint = <&i2s0_8ch_p0_0>; - }; - }; - }; - - /* connected with MIPI-CSI1 */ -}; - -&i2c8 { - pinctrl-0 = <&i2c8m2_xfer>; -}; - -&i2s0_8ch { - pinctrl-names = "default"; - pinctrl-0 = <&i2s0_lrck - &i2s0_mclk - &i2s0_sclk - &i2s0_sdi0 - &i2s0_sdo0>; - status = "okay"; - - i2s0_8ch_p0: port { - i2s0_8ch_p0_0: endpoint { - dai-format = "i2s"; - mclk-fs = <256>; - remote-endpoint = <&rt5616_p0_0>; - }; - }; -}; - -&pcie2x1l0 { - reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc_3v3_pcie20>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie2_0_rst>; - status = "okay"; -}; - -&pcie2x1l1 { - reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc3v3_pcie2x1l0>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie2_1_rst>; - status = "okay"; -}; - -&pcie2x1l2 { - reset-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc_3v3_pcie20>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie2_2_rst>; - status = "okay"; -}; - -&pcie30phy { - status = "okay"; -}; - -&pcie3x4 { - reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc3v3_pcie30>; - status = "okay"; -}; - &pinctrl { - gpio-leds { - sys_led_pin: sys-led-pin { - rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - usr_led_pin: usr-led-pin { - rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - headphone { - hp_det: hp-det { - rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - hym8563 { - hym8563_int: hym8563-int { - rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - pcie { - pcie2_0_rst: pcie2-0-rst { - rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pcie2_1_rst: pcie2-1-rst { - rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pcie2_2_rst: pcie2-2-rst { - rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pcie_m2_0_pwren: pcie-m20-pwren { - rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pcie_m2_1_pwren: pcie-m21-pwren { - rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - usb { pin_4g_lte_pwren: 4g-lte-pwren { rockchip,pins = <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; }; - - typec5v_pwren: typec5v-pwren { - rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - usbc0_int: usbc0-int { - rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; -}; - -&pwm1 { - pinctrl-0 = <&pwm1m1_pins>; - status = "okay"; -}; - -&saradc { - vref-supply = <&avcc_1v8_s0>; - status = "okay"; -}; - -&sdhci { - bus-width = <8>; - no-sdio; - no-sd; - non-removable; - max-frequency = <200000000>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; - status = "okay"; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; - disable-wp; - no-mmc; - no-sdio; - sd-uhs-sdr104; - vmmc-supply = <&vcc3v3_sd_s0>; - vqmmc-supply = <&vccio_sd_s0>; - status = "okay"; -}; - -&spi2 { - status = "okay"; - assigned-clocks = <&cru CLK_SPI2>; - assigned-clock-rates = <200000000>; - pinctrl-names = "default"; - pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; - num-cs = <1>; - - pmic@0 { - compatible = "rockchip,rk806"; - spi-max-frequency = <1000000>; - reg = <0x0>; - - interrupt-parent = <&gpio0>; - interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - - pinctrl-names = "default"; - pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, - <&rk806_dvs2_null>, <&rk806_dvs3_null>; - - system-power-controller; - - vcc1-supply = <&vcc4v0_sys>; - vcc2-supply = <&vcc4v0_sys>; - vcc3-supply = <&vcc4v0_sys>; - vcc4-supply = <&vcc4v0_sys>; - vcc5-supply = <&vcc4v0_sys>; - vcc6-supply = <&vcc4v0_sys>; - vcc7-supply = <&vcc4v0_sys>; - vcc8-supply = <&vcc4v0_sys>; - vcc9-supply = <&vcc4v0_sys>; - vcc10-supply = <&vcc4v0_sys>; - vcc11-supply = <&vcc_2v0_pldo_s3>; - vcc12-supply = <&vcc4v0_sys>; - vcc13-supply = <&vcc_1v1_nldo_s3>; - vcc14-supply = <&vcc_1v1_nldo_s3>; - vcca-supply = <&vcc4v0_sys>; - - gpio-controller; - #gpio-cells = <2>; - - rk806_dvs1_null: dvs1-null-pins { - pins = "gpio_pwrctrl1"; - function = "pin_fun0"; - }; - - rk806_dvs2_null: dvs2-null-pins { - pins = "gpio_pwrctrl2"; - function = "pin_fun0"; - }; - - rk806_dvs3_null: dvs3-null-pins { - pins = "gpio_pwrctrl3"; - function = "pin_fun0"; - }; - - regulators { - vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_gpu_s0"; - regulator-enable-ramp-delay = <400>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_cpu_lit_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_log_s0: dcdc-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <675000>; - regulator-max-microvolt = <750000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_log_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <750000>; - }; - }; - - vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-init-microvolt = <750000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_vdenc_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_ddr_s0: dcdc-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <675000>; - regulator-max-microvolt = <900000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_ddr_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <850000>; - }; - }; - - vdd2_ddr_s3: dcdc-reg6 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vdd2_ddr_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_2v0_pldo_s3: dcdc-reg7 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <2000000>; - regulator-max-microvolt = <2000000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_2v0_pldo_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <2000000>; - }; - }; - - vcc_3v3_s3: dcdc-reg8 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_3v3_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vddq_ddr_s0: dcdc-reg9 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vddq_ddr_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_1v8_s3: dcdc-reg10 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_1v8_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - avcc_1v8_s0: pldo-reg1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "avcc_1v8_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_1v8_s0: pldo-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_1v8_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - avdd_1v2_s0: pldo-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-name = "avdd_1v2_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_3v3_s0: pldo-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <12500>; - regulator-name = "vcc_3v3_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vccio_sd_s0: pldo-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <12500>; - regulator-name = "vccio_sd_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - pldo6_s3: pldo-reg6 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "pldo6_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd_0v75_s3: nldo-reg1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "vdd_0v75_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <750000>; - }; - }; - - vdd_ddr_pll_s0: nldo-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-name = "vdd_ddr_pll_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <850000>; - }; - }; - - avdd_0v75_s0: nldo-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "avdd_0v75_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_0v85_s0: nldo-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-name = "vdd_0v85_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_0v75_s0: nldo-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "vdd_0v75_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - }; }; }; -&tsadc { - status = "okay"; -}; - -&uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; -}; - &u2phy2_host { phy-supply = <&vdd_4g_3v3>; - status = "okay"; -}; - -&u2phy3_host { - status = "okay"; -}; - -&u2phy2 { - status = "okay"; -}; - -&u2phy3 { - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host0_ohci { - status = "okay"; -}; - -&usb_host1_ehci { - status = "okay"; -}; - -&usb_host1_ohci { - status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi new file mode 100644 index 000000000000..fc131789b4c3 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dtsi @@ -0,0 +1,1041 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * Copyright (c) 2023 Thomas McKahan + * + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/usb/pd.h> +#include "rk3588.dtsi" + +/ { + model = "FriendlyElec NanoPC-T6"; + compatible = "friendlyarm,nanopc-t6", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + }; + + adc-keys-0 { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-maskrom { + label = "Mask Rom"; + linux,code = <KEY_SETUP>; + press-threshold-microvolt = <2000>; + }; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + ir-receiver { + compatible = "gpio-ir-receiver"; + gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&ir_receiver_pin>; + }; + + leds { + compatible = "gpio-leds"; + + sys_led: led-0 { + gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + label = "system-led"; + linux,default-trigger = "heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&sys_led_pin>; + }; + + usr_led: led-1 { + gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; + label = "user-led"; + pinctrl-names = "default"; + pinctrl-0 = <&usr_led_pin>; + }; + }; + + sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + + simple-audio-card,name = "realtek,rt5616-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>; + + simple-audio-card,widgets = + "Headphone", "Headphones", + "Microphone", "Microphone Jack"; + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "MIC1", "Microphone Jack", + "Microphone Jack", "micbias1"; + + simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + }; + simple-audio-card,codec { + sound-dai = <&rt5616>; + }; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + /* vcc5v0_sys powers peripherals */ + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + /* vcc4v0_sys powers the RK806, RK860's */ + vcc4v0_sys: vcc4v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc4v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <4000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc-1v1-nldo-s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc4v0_sys>; + }; + + vcc_3v3_pcie20: vcc3v3-pcie20-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_pcie20"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vbus5v0_typec: vbus5v0-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + regulator-always-on; + regulator-boot-on; + regulator-name = "vbus5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_pcie2x1l0: vcc3v3-pcie2x1l0-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_m2_1_pwren>; + regulator-name = "vcc3v3_pcie2x1l0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_m2_0_pwren>; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_sd_s0: vcc3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_LOW>; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc3v3_sd_s0"; + vin-supply = <&vcc_3v3_s3>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&gpio0 { + gpio-line-names = /* GPIO0 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 C0-C7 */ + "", "", "", "", + "HEADER_10", "HEADER_08", "HEADER_32", "", + /* GPIO0 D0-D7 */ + "", "", "", "", + "IR receiver [PWM3_IR_M0]", "", "", ""; +}; + +&gpio1 { + gpio-line-names = /* GPIO1 A0-A7 */ + "HEADER_27", "HEADER_28", "", "", + "", "", "", "HEADER_15", + /* GPIO1 B0-B7 */ + "HEADER_26", "HEADER_21", "HEADER_19", "HEADER_23", + "HEADER_24", "HEADER_22", "", "", + /* GPIO1 C0-C7 */ + "", "", "", "", + "", "", "", "", + /* GPIO1 D0-D7 */ + "", "", "", "", + "", "", "HEADER_05", "HEADER_03"; +}; + +&gpio2 { + gpio-line-names = /* GPIO2 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO2 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO2 C0-C7 */ + "", "CSI1_11", "CSI1_12", "", + "", "", "", "", + /* GPIO2 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&gpio3 { + gpio-line-names = /* GPIO3 A0-A7 */ + "HEADER_35", "HEADER_38", "HEADER_40", "HEADER_36", + "HEADER_37", "", "DSI0_12", "", + /* GPIO3 B0-B7 */ + "HEADER_33", "DSI0_10", "HEADER_07", "HEADER_16", + "HEADER_18", "HEADER_29", "HEADER_31", "HEADER_12", + /* GPIO3 C0-C7 */ + "DSI0_08", "DSI0_14", "HEADER_11", "HEADER_13", + "", "", "", "", + /* GPIO3 D0-D7 */ + "", "", "", "", + "", "DSI1_10", "", ""; +}; + +&gpio4 { + gpio-line-names = /* GPIO4 A0-A7 */ + "DSI1_08", "DSI1_14", "", "DSI1_12", + "", "", "", "", + /* GPIO4 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO4 C0-C7 */ + "", "", "", "", + "CSI0_11", "CSI0_12", "", "", + /* GPIO4 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + clock-frequency = <200000>; + status = "okay"; + + fusb302: typec-portc@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&usbc0_int>; + pinctrl-names = "default"; + vbus-supply = <&vbus5v0_typec>; + + connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + power-role = "source"; + source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_hs: endpoint { + remote-endpoint = <&usb_host0_xhci_drd_sw>; + }; + }; + + port@1 { + reg = <1>; + usbc0_ss: endpoint { + remote-endpoint = <&usbdp_phy0_typec_ss>; + }; + }; + + port@2 { + reg = <2>; + usbc0_sbu: endpoint { + remote-endpoint = <&usbdp_phy0_typec_sbu>; + }; + }; + }; + }; + }; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; + wakeup-source; + }; +}; + +&i2c7 { + clock-frequency = <200000>; + status = "okay"; + + rt5616: codec@1b { + compatible = "realtek,rt5616"; + reg = <0x1b>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + + port { + rt5616_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; + + /* connected with MIPI-CSI1 */ +}; + +&i2c8 { + pinctrl-0 = <&i2c8m2_xfer>; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&rt5616_p0_0>; + }; + }; +}; + +&pcie2x1l0 { + reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_rst>; + status = "okay"; +}; + +&pcie2x1l1 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie2x1l0>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_1_rst>; + status = "okay"; +}; + +&pcie2x1l2 { + reset-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_2_rst>; + status = "okay"; +}; + +&pcie30phy { + status = "okay"; +}; + +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + status = "okay"; +}; + +&pinctrl { + gpio-leds { + sys_led_pin: sys-led-pin { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usr_led_pin: usr-led-pin { + rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + ir-receiver { + ir_receiver_pin: ir-receiver-pin { + rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie2_0_rst: pcie2-0-rst { + rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_1_rst: pcie2-1-rst { + rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_2_rst: pcie2-2-rst { + rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_m2_0_pwren: pcie-m20-pwren { + rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_m2_1_pwren: pcie-m21-pwren { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + typec5v_pwren: typec5v-pwren { + rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usbc0_int: usbc0-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm1 { + pinctrl-0 = <&pwm1m1_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +/* optional on non-LTS, populated on LTS version */ +&sfc { + pinctrl-names = "default"; + pinctrl-0 = <&fspim1_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <104000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + system-power-controller; + + vcc1-supply = <&vcc4v0_sys>; + vcc2-supply = <&vcc4v0_sys>; + vcc3-supply = <&vcc4v0_sys>; + vcc4-supply = <&vcc4v0_sys>; + vcc5-supply = <&vcc4v0_sys>; + vcc6-supply = <&vcc4v0_sys>; + vcc7-supply = <&vcc4v0_sys>; + vcc8-supply = <&vcc4v0_sys>; + vcc9-supply = <&vcc4v0_sys>; + vcc10-supply = <&vcc4v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc4v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc4v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy2_host { + status = "okay"; +}; + +&u2phy3_host { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&usbdp_phy0 { + mode-switch; + orientation-switch; + sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; + sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + usbdp_phy0_typec_ss: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_ss>; + }; + + usbdp_phy0_typec_sbu: endpoint@1 { + reg = <1>; + remote-endpoint = <&usbc0_sbu>; + }; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; + usb-role-switch; + + port { + usb_host0_xhci_drd_sw: endpoint { + remote-endpoint = <&usbc0_hs>; + }; + }; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts index e74871491ef5..dd4c79bcad87 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts @@ -105,6 +105,13 @@ }; }; + rfkill { + compatible = "rfkill-gpio"; + label = "rfkill-pcie-wlan"; + radio-type = "wlan"; + shutdown-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; + }; + sound { compatible = "simple-audio-card"; pinctrl-names = "default"; @@ -321,7 +328,6 @@ compatible = "everest,es8388"; reg = <0x11>; clocks = <&cru I2S0_8CH_MCLKOUT>; - clock-names = "mclk"; AVDD-supply = <&vcc_1v8_s0>; DVDD-supply = <&vcc_1v8_s0>; HPVDD-supply = <&vcc_3v3_s0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts index e4a20cda65ed..b38dab009ccc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts @@ -316,7 +316,6 @@ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; assigned-clock-rates = <12288000>; clocks = <&cru I2S0_8CH_MCLKOUT>; - clock-names = "mclk"; AVDD-supply = <&avcc_1v8_codec_s0>; DVDD-supply = <&avcc_1v8_codec_s0>; HPVDD-supply = <&vcc_3v3_s0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts index 966bbc582d89..6bd06e46a101 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -304,12 +304,12 @@ }; cooling-maps { - map1 { + map0 { trip = <&package_fan0>; cooling-device = <&fan THERMAL_NO_LIMIT 1>; }; - map2 { + map1 { trip = <&package_fan1>; cooling-device = <&fan 2 THERMAL_NO_LIMIT>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts index d0021524e7f9..328dcb894ccb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts @@ -428,7 +428,6 @@ regulator-boot-on; regulator-min-microvolt = <550000>; regulator-max-microvolt = <950000>; - regulator-init-microvolt = <750000>; regulator-ramp-delay = <12500>; regulator-state-mem { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi index dbaa94ca69f4..432133251e31 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi @@ -296,6 +296,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; + system-power-controller; vcc1-supply = <&vcc5v0_sys>; vcc2-supply = <&vcc5v0_sys>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts new file mode 100644 index 000000000000..467f69594089 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588s-gameforce-ace.dts @@ -0,0 +1,1237 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/linux-event-codes.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/thermal/thermal.h> +#include <dt-bindings/usb/pd.h> +#include "rk3588s.dtsi" + +/ { + model = "Gameforce Ace"; + chassis-type = "handset"; + compatible = "gameforce,ace", "rockchip,rk3588s"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + mmc2 = &sdio; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <60>; + + button-vol-up { + label = "VOLUMEUP"; + linux,code = <KEY_VOLUMEUP>; + press-threshold-microvolt = <17000>; + }; + + button-vol-down { + label = "VOLUMEDOWN"; + linux,code = <KEY_VOLUMEDOWN>; + press-threshold-microvolt = <417000>; + }; + }; + + /* Joystick range values based on hardware observation. */ + adc_joystick: adc-joystick { + compatible = "adc-joystick"; + io-channels = <&saradc 2>, <&saradc 3>, + <&saradc 4>, <&saradc 5>; + poll-interval = <60>; + #address-cells = <1>; + #size-cells = <0>; + + axis@0 { + reg = <0>; + abs-flat = <40>; + abs-fuzz = <30>; + abs-range = <0 4095>; + linux,code = <ABS_RX>; + }; + + axis@1 { + reg = <1>; + abs-flat = <40>; + abs-fuzz = <30>; + abs-range = <0 4095>; + linux,code = <ABS_RY>; + }; + + axis@2 { + reg = <2>; + abs-flat = <40>; + abs-fuzz = <30>; + abs-range = <0 4095>; + linux,code = <ABS_Y>; + }; + + axis@3 { + reg = <3>; + abs-flat = <40>; + abs-fuzz = <30>; + abs-range = <0 4095>; + linux,code = <ABS_X>; + }; + }; + + /* Trigger range values based on hardware observation. */ + adc_triggers: adc-trigger { + compatible = "adc-joystick"; + io-channels = <&ti_adc 6>, + <&ti_adc 7>; + poll-interval = <60>; + #address-cells = <1>; + #size-cells = <0>; + + axis@0 { + reg = <0>; + abs-flat = <15>; + abs-fuzz = <15>; + abs-range = <890 1530>; + linux,code = <ABS_HAT2X>; + }; + + axis@1 { + reg = <1>; + abs-flat = <15>; + abs-fuzz = <15>; + abs-range = <1010 1550>; + linux,code = <ABS_HAT2Y>; + }; + }; + + analog-sound { + compatible = "simple-audio-card"; + pinctrl-0 = <&hp_detect>; + pinctrl-names = "default"; + simple-audio-card,aux-devs = <&_headphone>, <&_speaker>; + simple-audio-card,bitclock-master = <&masterdai>; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&masterdai>; + simple-audio-card,hp-det-gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "rockchip,es8388-codec"; + simple-audio-card,pin-switches = "Headphones", "Speaker"; + simple-audio-card,routing = + "Speaker Amplifier INL", "LOUT2", + "Speaker Amplifier INR", "ROUT2", + "Speaker", "Speaker Amplifier OUTL", + "Speaker", "Speaker Amplifier OUTR", + "Headphones Amplifier INL", "LOUT1", + "Headphones Amplifier INR", "ROUT1", + "Headphones", "Headphones Amplifier OUTL", + "Headphones", "Headphones Amplifier OUTR", + "LINPUT1", "Microphone Jack", + "RINPUT1", "Microphone Jack", + "LINPUT2", "Onboard Microphone", + "RINPUT2", "Onboard Microphone"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Microphone", "Onboard Microphone", + "Headphone", "Headphones", + "Speaker", "Speaker"; + + masterdai: simple-audio-card,codec { + sound-dai = <&es8388>; + system-clock-frequency = <12288000>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&lcd_bl_en>; + pinctrl-names = "default"; + pwms = <&pwm13 0 25000 PWM_POLARITY_INVERTED>; + }; + + battery: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <3700000>; + constant-charge-current-max-microamp = <2500000>; + constant-charge-voltage-max-microvolt = <8750000>; + voltage-min-design-microvolt = <7400000>; + }; + + gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&btn_pins_ctrl>; + pinctrl-names = "default"; + + button-a { + gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>; + label = "EAST"; + linux,code = <BTN_EAST>; + }; + + button-b { + gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>; + label = "SOUTH"; + linux,code = <BTN_SOUTH>; + }; + + button-down { + gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; + label = "DPAD-DOWN"; + linux,code = <BTN_DPAD_DOWN>; + }; + + button-home { + gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_LOW>; + label = "FUNCTION"; + linux,code = <BTN_MODE>; + }; + + button-l1 { + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + label = "L1"; + linux,code = <BTN_TL>; + }; + + button-left { + gpios = <&gpio1 RK_PD7 GPIO_ACTIVE_LOW>; + label = "DPAD-LEFT"; + linux,code = <BTN_DPAD_LEFT>; + }; + + button-menu { + gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>; + label = "HOME"; + linux,code = <KEY_HOME>; + }; + + button-r1 { + gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_LOW>; + label = "R1"; + linux,code = <BTN_TR>; + }; + + button-right { + gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>; + label = "DPAD-RIGHT"; + linux,code = <BTN_DPAD_RIGHT>; + }; + + button-select { + gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_LOW>; + label = "SELECT"; + linux,code = <BTN_SELECT>; + }; + + button-start { + gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>; + label = "START"; + linux,code = <BTN_START>; + }; + + button-thumbl { + gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_LOW>; + label = "THUMBL"; + linux,code = <BTN_THUMBL>; + }; + + button-thumbr { + gpios = <&gpio1 RK_PD6 GPIO_ACTIVE_LOW>; + label = "THUMBR"; + linux,code = <BTN_THUMBR>; + }; + + button-up { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; + label = "DPAD-UP"; + linux,code = <BTN_DPAD_UP>; + }; + + button-x { + gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + label = "NORTH"; + linux,code = <BTN_NORTH>; + }; + + button-y { + gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_LOW>; + label = "WEST"; + linux,code = <BTN_WEST>; + }; + }; + + gpio_leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + green_led: led-0 { + color = <LED_COLOR_ID_GREEN>; + gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_STATUS; + }; + + red_led: led-1 { + color = <LED_COLOR_ID_RED>; + gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CHARGING; + }; + }; + + amp_headphone: headphone-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&headphone_amplifier_en>; + pinctrl-names = "default"; + sound-name-prefix = "Headphones Amplifier"; + }; + + pwm_fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + cooling-levels = <0 120 150 180 210 240 255>; + fan-supply = <&vcc5v0_sys>; + interrupt-parent = <&gpio4>; + interrupts = <RK_PB2 IRQ_TYPE_EDGE_RISING>; + pulses-per-revolution = <4>; + pwms = <&pwm12 0 50000 PWM_POLARITY_INVERTED>; + }; + + pwm_gpio33: pwm-33 { + compatible = "pwm-gpio"; + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vib_right_h>; + pinctrl-names = "default"; + #pwm-cells = <3>; + }; + + pwm_gpio132: pwm-132 { + compatible = "pwm-gpio"; + gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vib_left_h>; + pinctrl-names = "default"; + #pwm-cells = <3>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clock-names = "ext_clock"; + clocks = <&rtc_hym8563>; + pinctrl-0 = <&wifi_enable_h>; + pinctrl-names = "default"; + post-power-on-delay-ms = <200>; + power-off-delay-us = <5000000>; + reset-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + }; + + amp_speaker: speaker-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&speaker_amplifier_en>; + pinctrl-names = "default"; + sound-name-prefix = "Speaker Amplifier"; + VCC-supply = <&vcc5v0_spk>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + regulator-name = "vcc_1v1_nldo_s3"; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_lcd0_n: vcc3v3-lcd0-n-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vcc_lcd_h>; + pinctrl-names = "default"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc3v3_lcd0_n"; + vin-supply = <&vcc_3v3_s3>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&sd_s0_pwr>; + pinctrl-names = "default"; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc_3v3_sd_s0"; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc5v0_spk: vcc5v0-spk-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&vcc5v0_spk_pwr>; + pinctrl-names = "default"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_spk"; + vin-supply = <&vcc5v0_sys>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "vcc5v0_sys"; + }; + + vibrator_l: vibrator-l { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm_gpio132 0 20000000 0>; + }; + + vibrator_r: vibrator-r { + compatible = "pwm-vibrator"; + pwm-names = "enable"; + pwms = <&pwm_gpio33 0 20000000 0>; + }; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0m2_xfer>; + pinctrl-names = "default"; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-max-microvolt = <1050000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-max-microvolt = <1050000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_npu_s0"; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c3 { + status = "okay"; + + touchscreen@14 { + compatible = "goodix,gt911"; + reg = <0x14>; + interrupt-parent = <&gpio1>; + interrupts = <RK_PA6 IRQ_TYPE_LEVEL_LOW>; + irq-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&touch_int>, <&touch_rst>; + pinctrl-names = "default"; + reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + touchscreen-inverted-x; + touchscreen-size-x = <1080>; + touchscreen-size-y = <1920>; + touchscreen-swapped-x-y; + }; +}; + +&i2c4 { + pinctrl-0 = <&i2c4m2_xfer>; + status = "okay"; + + ti_adc: adc@48 { + compatible = "ti,ads1015"; + reg = <0x48>; + #address-cells = <1>; + #io-channel-cells = <1>; + #size-cells = <0>; + + channel@4 { + reg = <4>; + }; + + channel@5 { + reg = <5>; + }; + + channel@6 { + reg = <6>; + }; + + channel@7 { + reg = <7>; + }; + }; + + imu@68 { + compatible = "invensense,mpu6880"; + reg = <0x68>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PD3 IRQ_TYPE_EDGE_RISING>; + }; +}; + +&i2c6 { + pinctrl-0 = <&i2c6m3_xfer>; + status = "okay"; + + rtc_hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + interrupt-parent = <&gpio0>; + interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&hym8563_int>, <&clk32k_in>; + pinctrl-names = "default"; + wakeup-source; + }; + + /* Battery profile from BSP device tree. */ + battery@62 { + compatible = "cellwise,cw2015"; + reg = <0x62>; + + cellwise,battery-profile = /bits/ 8 + <0x18 0x0A 0x76 0x6A 0x6A 0x6A 0x68 0x66 + 0x62 0x5E 0x5A 0x58 0x5F 0x59 0x46 0x3D + 0x35 0x2D 0x28 0x21 0x29 0x38 0x44 0x50 + 0x1A 0x85 0x07 0xAE 0x14 0x28 0x48 0x56 + 0x66 0x66 0x66 0x6A 0x3E 0x1A 0x6C 0x3D + 0x09 0x38 0x1A 0x49 0x7B 0x96 0xA2 0x15 + 0x3B 0x77 0x9A 0xB1 0x80 0x87 0xB0 0xCB + 0x2F 0x00 0x64 0xA5 0xB5 0x1C 0xF0 0x49>; + cellwise,monitor-interval-ms = <5000>; + monitored-battery = <&battery>; + status = "okay"; + }; +}; + +&i2c7 { + status = "okay"; + + es8388: audio-codec@11 { + compatible = "everest,es8388"; + reg = <0x11>; + assigned-clock-rates = <12288000>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + AVDD-supply = <&vcc_3v3_s3>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + DVDD-supply = <&vcc_1v8_s3>; + HPVDD-supply = <&vcc_3v3_s3>; + PVDD-supply = <&vcc_1v8_s3>; + #sound-dai-cells = <0>; + }; +}; + +&i2s0_8ch { + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; +}; + +&package_thermal { + polling-delay = <1000>; + + trips { + package_fan0: package-fan0 { + temperature = <55000>; + hysteresis = <2000>; + type = "active"; + }; + + package_fan1: package-fan1 { + temperature = <65000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + map1 { + trip = <&package_fan0>; + cooling-device = <&pwm_fan THERMAL_NO_LIMIT 1>; + }; + + map2 { + trip = <&package_fan1>; + cooling-device = <&pwm_fan 2 THERMAL_NO_LIMIT>; + }; + }; +}; + +/* + * Attempts to use an M.2 SATA in this slot worked intermittently + * with the correct nodes enabled in device-tree, but eventually + * resulted in a destroyed board. Advise caution. + */ +&pcie2x1l1 { + pinctrl-0 = <&pcie_rst>; + pinctrl-names = "default"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pinctrl { + audio-amplifier { + headphone_amplifier_en: headphone-amplifier-en { + rockchip,pins = + <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + hp_detect: headphone-detect { + rockchip,pins = + <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + speaker_amplifier_en: speaker-amplifier-en { + rockchip,pins = + <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + bt { + bt_enable_h: bt-enable-h { + rockchip,pins = + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_host_wake_l: bt-host-wake-l { + rockchip,pins = + <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + bt_wake_l: bt-wake-l { + rockchip,pins = + <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + charger { + boost_enable_h: boost-enable-h { + rockchip,pins = + <4 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + charger_int_h: charger-int-h { + rockchip,pins = + <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = + <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-btns { + btn_pins_ctrl: btn-pins-ctrl { + rockchip,pins = + <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-leds { + led_pins: led-pins { + rockchip,pins = + <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>, + <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + lcd_bl_en { + lcd_bl_en: lcd-bl-en { + rockchip,pins = + <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie-pins { + pcie_rst: pcie-rst { + rockchip,pins = + <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd-pwr { + sd_s0_pwr: sd-s0-pwr { + rockchip,pins = + <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + spk-pwr { + vcc5v0_spk_pwr: vcc5v0-spk-pwr { + rockchip,pins = + <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + touch { + touch_int: touch-int { + rockchip,pins = + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + touch_rst: touch-rst { + rockchip,pins = + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = + <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + vcc3v3-lcd { + vcc_lcd_h: vcc-lcd-h { + rockchip,pins = + <4 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + vibrator { + vib_left_h: vib-left-h { + rockchip,pins = + <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vib_right_h: vib-right-h { + rockchip,pins = + <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + wifi { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = + <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + +&pwm12 { + pinctrl-0 = <&pwm12m1_pins>; + status = "okay"; +}; + +&pwm13 { + pinctrl-0 = <&pwm13m1_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + no-sd; + no-sdio; + non-removable; + status = "okay"; +}; + +&sdio { + #address-cells = <1>; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + disable-wp; + keep-power-in-suspend; + max-frequency = <150000000>; + mmc-pwrseq = <&sdio_pwrseq>; + no-mmc; + no-sd; + sd-uhs-sdr104; + #size-cells = <0>; + status = "okay"; + + brcmf: wifi@1 { + compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac"; + reg = <1>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wake"; + pinctrl-0 = <&wifi_host_wake_irq>; + pinctrl-names = "default"; + }; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + no-sdio; + no-mmc; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + #address-cells = <1>; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-0 = <&spi2m2_pins>, <&spi2m2_cs0>; + pinctrl-names = "default"; + #size-cells = <0>; + status = "okay"; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + pinctrl-names = "default"; + spi-max-frequency = <1000000>; + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: dcdc-reg1 { + regulator-boot-on; + regulator-enable-ramp-delay = <400>; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_gpu_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_logic_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <750000>; + regulator-min-microvolt = <675000>; + regulator-name = "vdd_logic_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <550000>; + regulator-name = "vdd_vdenc_s0"; + regulator-ramp-delay = <12500>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <2000000>; + regulator-min-microvolt = <2000000>; + regulator-name = "vdd_2v0_pldo_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1200000>; + regulator-min-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vccio_sd_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3_pldo6: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3_pldo6"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <750000>; + regulator-min-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <850000>; + regulator-min-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <837500>; + regulator-min-microvolt = <837500>; + regulator-name = "avdd_0v75_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&uart9 { + pinctrl-0 = <&uart9m2_xfer>, <&uart9m2_ctsn>, <&uart9m2_rtsn>; + uart-has-rtscts; + status = "okay"; + + bluetooth { + compatible = "brcm,bcm4345c5"; + clocks = <&rtc_hym8563>; + clock-names = "lpo"; + device-wakeup-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio3>; + interrupts = <RK_PB0 IRQ_TYPE_EDGE_FALLING>; + pinctrl-0 = <&bt_enable_h>, <&bt_host_wake_l>, <&bt_wake_l>; + pinctrl-names = "default"; + shutdown-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts index d8c50fdcca3b..8ba111d9283f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts @@ -377,7 +377,6 @@ assigned-clock-rates = <12288000>; assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; AVDD-supply = <&vcc_3v3_s3>; - clock-names = "mclk"; clocks = <&cru I2S0_8CH_MCLKOUT>; DVDD-supply = <&vcc_1v8_s3>; HPVDD-supply = <&vcc_3v3_s3>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts new file mode 100644 index 000000000000..63d91236ba9f --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588s-odroid-m2.dts @@ -0,0 +1,903 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/usb/pd.h> +#include "rk3588s.dtsi" + +/ { + model = "Hardkernel ODROID-M2"; + compatible = "hardkernel,odroid-m2", "rockchip,rk3588s"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdhci; + mmc1 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_led>, <&sys_led>; + + led_pwr: led-0 { + color = <LED_COLOR_ID_RED>; + default-state = "on"; + function = LED_FUNCTION_POWER; + gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + + led_sys: led-1 { + color = <LED_COLOR_ID_BLUE>; + default-state = "on"; + function = LED_FUNCTION_HEARTBEAT; + gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + cooling-levels = <0 192 224 255>; + fan-supply = <&vcc5v0_sys>; + pwms = <&pwm0 0 22222 0>; + }; + + vcc_1v1_nldo_s3: regulator-1v1-vcc-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc4v0_sys>; + }; + + vcc3v3_lcd: regulator-3v3-vcc-lcd { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pwren>; + regulator-name = "vcc3v3_lcd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc3v3_pcie: regulator-3v3-vcc-pcie { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pwren>; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc_3v3_s0: regulator-3v3-vcc-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc4v0_sys: regulator-4v0-vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc4v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4800000>; + regulator-max-microvolt = <4800000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_sys: regulator-5v0-vcc-sys { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_pwren>; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb2_host: regulator-5v0-vcc-usb2-host { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_host_pwren>; + regulator-name = "vcc5v0_usb2_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb3_host: regulator-5v0-vcc-usb3-host { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_host_pwren>; + regulator-name = "vcc5v0_usb3_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb3_typec: regulator-5v0-vcc-usb3-typec { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_typec_pwren>; + regulator-name = "vcc5v0_usb3_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcca: regulator-5v0-vcca { + compatible = "regulator-fixed"; + regulator-name = "vcca"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc12v_dcin: regulator-12v0-vcc-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-id"; + phy-supply = <&vcc_3v3_s0>; + pinctrl-names = "default"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus + &gmac1_clkinout>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c8 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + status = "okay"; + + usbc0: usb-typec@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio4>; + interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vcc5v0_usb3_typec>; + + connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + op-sink-microwatt = <1000000>; + power-role = "dual"; + sink-pdos = <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>; + source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>; + try-power-role = "source"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usbc0_role_switch: endpoint { + remote-endpoint = <&usb_host0_xhci_role_switch>; + }; + }; + + port@1 { + reg = <1>; + + usbc0_orientation_switch: endpoint { + remote-endpoint = <&usbdp_phy0_orientation_switch>; + }; + }; + + port@2 { + reg = <2>; + + usbc0_dp_altmode_mux: endpoint { + remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; + }; + }; + }; + }; + }; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + interrupt-parent = <&gpio0>; + interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pcf8563_int>; + wakeup-source; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id001c.c916"; + reg = <1>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; +}; + +&package_thermal { + polling-delay = <1000>; + + trips { + package_fan0: package-fan0 { + hysteresis = <2000>; + temperature = <60000>; + type = "active"; + }; + }; + + cooling-maps { + map0 { + cooling-device = <&fan 1 THERMAL_NO_LIMIT>; + trip = <&package_fan0>; + }; + }; +}; + +&pcie2x1l2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie20x1_pins>; + reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + lcd { + lcd_pwren: lcd-pwren { + rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + pwr_led: pwr-led { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led: sys-led { + rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie20x1_pins: pcie20x1-pins { + rockchip,pins = + <1 RK_PA0 4 &pcfg_pull_none>, + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PA1 4 &pcfg_pull_none>; + }; + + pcie_pwren: pcie-pwren { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + regulator { + vcc5v0_pwren: vcc5v0-pwren { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rtc { + pcf8563_int: pcf8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + usb2_host_pwren: usb2-host-pwren { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usb3_host_pwren: usb3-host-pwren { + rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usb3_typec_pwren: usb3-typec-pwren { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + usbc0_int: usbc0-int { + rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0m2_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + no-sd; + no-sdio; + non-removable; + vmmc-supply = <&vcc_3v3_s0>; + vqmmc-supply = <&vcc_1v8_s0>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0>, <&spi2m2_pins>; + status = "okay"; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + #gpio-cells = <2>; + gpio-controller; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + spi-max-frequency = <1000000>; + system-power-controller; + + vcc1-supply = <&vcc4v0_sys>; + vcc2-supply = <&vcc4v0_sys>; + vcc3-supply = <&vcc4v0_sys>; + vcc4-supply = <&vcc4v0_sys>; + vcc5-supply = <&vcc4v0_sys>; + vcc6-supply = <&vcc4v0_sys>; + vcc7-supply = <&vcc4v0_sys>; + vcc8-supply = <&vcc4v0_sys>; + vcc9-supply = <&vcc4v0_sys>; + vcc10-supply = <&vcc4v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc4v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcca>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: dcdc-reg1 { + regulator-name = "vdd_gpu_s0"; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_logic_s0: dcdc-reg3 { + regulator-name = "vdd_logic_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: dcdc-reg4 { + regulator-name = "vdd_vdenc_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-name = "vdd_ddr_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-name = "vdd2_ddr_s3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-name = "vdd_2v0_pldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-name = "vcc_3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-name = "vddq_ddr_s0"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-name = "vcc_1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_1v8_s0: pldo-reg1 { + regulator-name = "vcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_1v8_s0: pldo-reg2 { + regulator-name = "vcca_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdda_1v2_s0: pldo-reg3 { + regulator-name = "vdda_1v2_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_3v3_s0: pldo-reg4 { + regulator-name = "vcca_3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-name = "vccio_sd_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3_pldo6: pldo-reg6 { + regulator-name = "vcc_1v8_s3_pldo6"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-name = "vdd_0v75_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdda_ddr_pll_s0: nldo-reg2 { + regulator-name = "vdda_ddr_pll_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdda_0v75_s0: nldo-reg3 { + regulator-name = "vdda_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <837500>; + regulator-max-microvolt = <837500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v85_s0: nldo-reg4 { + regulator-name = "vdda_0v85_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + /* Schematics show not in use */ + nldo-reg5 { + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_usb2_host>; + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_usb3_host>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + usb-role-switch; + status = "okay"; + + port { + usb_host0_xhci_role_switch: endpoint { + remote-endpoint = <&usbc0_role_switch>; + }; + }; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; + +&usbdp_phy0 { + mode-switch; + orientation-switch; + sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; + sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + usbdp_phy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orientation_switch>; + }; + + usbdp_phy0_dp_altmode_mux: endpoint@1 { + reg = <1>; + remote-endpoint = <&usbc0_dp_altmode_mux>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts index 03ed48246d36..294b99dd50da 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -65,6 +65,18 @@ regulator-max-microvolt = <12000000>; }; + vcc3v3_wf: vcc3v3-wf-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_wf"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pow_en>; + pinctrl-names = "default"; + vin-supply = <&vcc5v0_sys>; + }; + vcc5v0_host: vcc5v0-host-regulator { compatible = "regulator-fixed"; regulator-name = "vcc5v0_host"; @@ -114,6 +126,10 @@ }; }; +&combphy0_ps { + status = "okay"; +}; + &combphy2_psu { status = "okay"; }; @@ -293,6 +309,14 @@ }; }; +&pcie2x1l2 { + pinctrl-0 = <&pcie20x1m0_pins>; + pinctrl-names = "default"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_wf>; + status = "okay"; +}; + &pinctrl { leds { io_led: io-led { @@ -300,6 +324,12 @@ }; }; + pcie { + pow_en: pow-en { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + power { vcc_5v0_en: vcc-5v0-en { rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; @@ -317,28 +347,6 @@ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; }; }; - - wifibt { - wl_reset: wl-reset { - rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - wl_dis: wl-dis { - rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_output_high>; - }; - - wl_wake_host: wl-wake-host { - rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - bt_dis: bt-dis { - rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_output_high>; - }; - - bt_wake_host: bt-wake-host { - rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; }; &pwm3 { @@ -754,8 +762,6 @@ &usb_host0_ehci { status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&wl_reset &wl_dis &wl_wake_host &bt_dis &bt_wake_host>; }; &usb_host0_ohci { diff --git a/arch/arm64/boot/dts/sprd/sc2731.dtsi b/arch/arm64/boot/dts/sprd/sc2731.dtsi index e15409f55f43..12136e68dada 100644 --- a/arch/arm64/boot/dts/sprd/sc2731.dtsi +++ b/arch/arm64/boot/dts/sprd/sc2731.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Spreadtrum SC2731 PMIC dts file * * Copyright (C) 2018, Spreadtrum Communications Inc. - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ &adi_bus { @@ -95,7 +94,7 @@ nvmem-cells = <&adc_big_scale>, <&adc_small_scale>; }; - fgu@a00 { + fuel-gauge@a00 { compatible = "sprd,sc2731-fgu"; reg = <0xa00>; bat-detect-gpio = <&pmic_eic 9 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/sprd/sc9836-openphone.dts b/arch/arm64/boot/dts/sprd/sc9836-openphone.dts index e5657c35cd10..b98589ea5ac2 100644 --- a/arch/arm64/boot/dts/sprd/sc9836-openphone.dts +++ b/arch/arm64/boot/dts/sprd/sc9836-openphone.dts @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) /* * Spreadtrum SC9836 openphone board DTS file * * Copyright (C) 2014, Spreadtrum Communications Inc. - * - * This file is licensed under a dual GPLv2 or X11 license. */ /dts-v1/; diff --git a/arch/arm64/boot/dts/sprd/sc9836.dtsi b/arch/arm64/boot/dts/sprd/sc9836.dtsi index 8bb8a70966d2..bc3fc9fc3d90 100644 --- a/arch/arm64/boot/dts/sprd/sc9836.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9836.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) /* * Spreadtrum SC9836 SoC DTS file * * Copyright (C) 2014, Spreadtrum Communications Inc. - * - * This file is licensed under a dual GPLv2 or X11 license. */ #include "sharkl64.dtsi" diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi index 31952d361a8a..d2456d633c39 100644 --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Spreadtrum SC9860 SoC * * Copyright (C) 2016, Spreadtrum Communications Inc. - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ #include <dt-bindings/interrupt-controller/arm-gic.h> diff --git a/arch/arm64/boot/dts/sprd/sc9863a.dtsi b/arch/arm64/boot/dts/sprd/sc9863a.dtsi index 53e5b77d70b5..e5a2857721e2 100644 --- a/arch/arm64/boot/dts/sprd/sc9863a.dtsi +++ b/arch/arm64/boot/dts/sprd/sc9863a.dtsi @@ -551,14 +551,14 @@ #size-cells = <2>; ranges; - sdio0: sdio@20300000 { + sdio0: mmc@20300000 { compatible = "sprd,sdhci-r11"; reg = <0 0x20300000 0 0x1000>; interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sdio", "enable"; clocks = <&aon_clk CLK_SDIO0_2X>, <&apahb_gate CLK_SDIO0_EB>; + clock-names = "sdio", "enable"; assigned-clocks = <&aon_clk CLK_SDIO0_2X>; assigned-clock-parents = <&rpll CLK_RPLL_390M>; @@ -567,14 +567,14 @@ no-mmc; }; - sdio3: sdio@20600000 { + sdio3: mmc@20600000 { compatible = "sprd,sdhci-r11"; reg = <0 0x20600000 0 0x1000>; interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sdio", "enable"; clocks = <&aon_clk CLK_EMMC_2X>, <&apahb_gate CLK_EMMC_EB>; + clock-names = "sdio", "enable"; assigned-clocks = <&aon_clk CLK_EMMC_2X>; assigned-clock-parents = <&rpll CLK_RPLL_390M>; diff --git a/arch/arm64/boot/dts/sprd/sharkl64.dtsi b/arch/arm64/boot/dts/sprd/sharkl64.dtsi index 69f64e7fce7c..bf58702c4e07 100644 --- a/arch/arm64/boot/dts/sprd/sharkl64.dtsi +++ b/arch/arm64/boot/dts/sprd/sharkl64.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) /* * Spreadtrum Sharkl64 platform DTS file * * Copyright (C) 2014, Spreadtrum Communications Inc. - * - * This file is licensed under a dual GPLv2 or X11 license. */ / { diff --git a/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts b/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts index 1ce3cbbd9668..095b24a31313 100644 --- a/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts +++ b/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Spreadtrum SP9860g board * * Copyright (C) 2017, Spreadtrum Communications Inc. - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /dts-v1/; diff --git a/arch/arm64/boot/dts/sprd/ums512.dtsi b/arch/arm64/boot/dts/sprd/ums512.dtsi index 4c080df48724..efa14309cc4e 100644 --- a/arch/arm64/boot/dts/sprd/ums512.dtsi +++ b/arch/arm64/boot/dts/sprd/ums512.dtsi @@ -849,9 +849,9 @@ compatible = "sprd,sdhci-r11"; reg = <0x1100000 0x1000>; interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sdio", "enable"; clocks = <&ap_clk CLK_SDIO0_2X>, <&apapb_gate CLK_SDIO0_EB>; + clock-names = "sdio", "enable"; assigned-clocks = <&ap_clk CLK_SDIO0_2X>; assigned-clock-parents = <&pll1 CLK_RPLL>; status = "disabled"; @@ -861,9 +861,9 @@ compatible = "sprd,sdhci-r11"; reg = <0x1400000 0x1000>; interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sdio", "enable"; clocks = <&ap_clk CLK_EMMC_2X>, <&apapb_gate CLK_EMMC_EB>; + clock-names = "sdio", "enable"; assigned-clocks = <&ap_clk CLK_EMMC_2X>; assigned-clock-parents = <&pll1 CLK_RPLL>; status = "disabled"; diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi index 7068bfd2f4c3..a551e14ce826 100644 --- a/arch/arm64/boot/dts/sprd/whale2.dtsi +++ b/arch/arm64/boot/dts/sprd/whale2.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Spreadtrum Whale2 platform peripherals * * Copyright (C) 2016, Spreadtrum Communications Inc. - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ #include <dt-bindings/clock/sprd,sc9860-clk.h> @@ -75,9 +74,10 @@ "sprd,sc9836-uart"; reg = <0x0 0x100>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "enable", "uart", "source"; clocks = <&apapb_gate CLK_UART0_EB>, - <&ap_clk CLK_UART0>, <&ext_26m>; + <&ap_clk CLK_UART0>, + <&ext_26m>; + clock-names = "enable", "uart", "source"; status = "disabled"; }; @@ -86,9 +86,10 @@ "sprd,sc9836-uart"; reg = <0x100000 0x100>; interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "enable", "uart", "source"; clocks = <&apapb_gate CLK_UART1_EB>, - <&ap_clk CLK_UART1>, <&ext_26m>; + <&ap_clk CLK_UART1>, + <&ext_26m>; + clock-names = "enable", "uart", "source"; status = "disabled"; }; @@ -97,9 +98,10 @@ "sprd,sc9836-uart"; reg = <0x200000 0x100>; interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "enable", "uart", "source"; clocks = <&apapb_gate CLK_UART2_EB>, - <&ap_clk CLK_UART2>, <&ext_26m>; + <&ap_clk CLK_UART2>, + <&ext_26m>; + clock-names = "enable", "uart", "source"; status = "disabled"; }; @@ -108,9 +110,10 @@ "sprd,sc9836-uart"; reg = <0x300000 0x100>; interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "enable", "uart", "source"; clocks = <&apapb_gate CLK_UART3_EB>, - <&ap_clk CLK_UART3>, <&ext_26m>; + <&ap_clk CLK_UART3>, + <&ext_26m>; + clock-names = "enable", "uart", "source"; status = "disabled"; }; }; @@ -129,19 +132,19 @@ /* For backwards compatibility: */ #dma-channels = <32>; dma-channels = <32>; - clock-names = "enable"; clocks = <&apahb_gate CLK_DMA_EB>; + clock-names = "enable"; }; - sdio3: sdio@50430000 { + sdio3: mmc@50430000 { compatible = "sprd,sdhci-r11"; reg = <0 0x50430000 0 0x1000>; interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sdio", "enable", "2x_enable"; clocks = <&aon_prediv CLK_EMMC_2X>, - <&apahb_gate CLK_EMMC_EB>, - <&aon_gate CLK_EMMC_2X_EN>; + <&apahb_gate CLK_EMMC_EB>, + <&aon_gate CLK_EMMC_2X_EN>; + clock-names = "sdio", "enable", "2x_enable"; assigned-clocks = <&aon_prediv CLK_EMMC_2X>; assigned-clock-parents = <&clk_l0_409m6>; @@ -194,8 +197,8 @@ compatible = "sprd,hwspinlock-r3p0"; reg = <0 0x40500000 0 0x1000>; #hwlock-cells = <1>; - clock-names = "enable"; clocks = <&aon_gate CLK_SPLK_EB>; + clock-names = "enable"; }; eic_debounce: gpio@40210000 { @@ -258,9 +261,9 @@ reg = <0 0x40310000 0 0x1000>; interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; timeout-sec = <12>; - clock-names = "enable", "rtc_enable"; clocks = <&aon_gate CLK_APCPU_WDG_EB>, - <&aon_gate CLK_AP_WDG_RTC_EB>; + <&aon_gate CLK_AP_WDG_RTC_EB>; + clock-names = "enable", "rtc_enable"; }; }; @@ -277,9 +280,9 @@ /* For backwards compatibility: */ #dma-channels = <32>; dma-channels = <32>; - clock-names = "enable", "ashb_eb"; clocks = <&agcp_gate CLK_AGCP_DMAAP_EB>, - <&agcp_gate CLK_AGCP_AP_ASHB_EB>; + <&agcp_gate CLK_AGCP_AP_ASHB_EB>; + clock-names = "enable", "ashb_eb"; }; }; }; diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile index e20b27ddf901..bcd392c3206e 100644 --- a/arch/arm64/boot/dts/ti/Makefile +++ b/arch/arm64/boot/dts/ti/Makefile @@ -73,10 +73,16 @@ k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb \ k3-am654-pcie-usb3.dtbo k3-am654-evm-dtbs := k3-am654-base-board.dtb k3-am654-icssg2.dtbo k3-am654-idk-dtbs := k3-am654-evm.dtb k3-am654-idk.dtbo k3-am654-pcie-usb2.dtbo +k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-dtbs := k3-am6548-iot2050-advanced-m2.dtb \ + k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie.dtbo +k3-am6548-iot2050-advanced-m2-bkey-usb3-dtbs := k3-am6548-iot2050-advanced-m2.dtb \ + k3-am6548-iot2050-advanced-m2-bkey-usb3.dtbo dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-m2.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie.dtb +dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-m2-bkey-usb3.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-sm.dtb dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb @@ -110,6 +116,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm.dtb dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-pcie1-ep.dtbo # Boards with J722s SoC +dtb-$(CONFIG_ARCH_K3) += k3-am67a-beagley-ai.dtb dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb # Boards with J784s4 SoC diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi index 328929c740dc..5b92aef5b284 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi @@ -241,6 +241,7 @@ bootph-pre-ram; compatible = "ti,j721e-esm"; reg = <0x00 0x420000 0x00 0x1000>; + /* Interrupt sources: rti0, rti1, rti15, wrti0, rti2, rti3 */ ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi index e66d486ef1f2..bb43a411f59b 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi @@ -19,6 +19,7 @@ bootph-pre-ram; compatible = "ti,j721e-esm"; reg = <0x00 0x4100000 0x00 0x1000>; + /* Interrupt sources: esm0_cfg, esm0_hi, esm0_low, mrti0 */ ti,esm-pins = <0>, <1>, <2>, <85>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi index 12ba833002a1..3c6a80aebd9f 100644 --- a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi @@ -12,12 +12,29 @@ thermal_zones: thermal-zones { thermal-sensors = <&wkup_vtm0 0>; trips { + main0_alert: main0-alert { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + main0_crit: main0-crit { temperature = <105000>; /* milliCelsius */ hysteresis = <2000>; /* milliCelsius */ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&main0_alert>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; main1_thermal: main1-thermal { @@ -26,11 +43,28 @@ thermal_zones: thermal-zones { thermal-sensors = <&wkup_vtm0 1>; trips { + main1_alert: main1-alert { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + main1_crit: main1-crit { temperature = <105000>; /* milliCelsius */ hysteresis = <2000>; /* milliCelsius */ type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&main1_alert>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts index 70de288d728e..a1cd47d7f5e3 100644 --- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts +++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts @@ -888,7 +888,8 @@ mcu { compatible = "ti,cc1352p7"; - reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_LOW>; + bootloader-backdoor-gpios = <&main_gpio0 13 GPIO_ACTIVE_HIGH>; + reset-gpios = <&main_gpio0 14 GPIO_ACTIVE_HIGH>; vdds-supply = <&vdd_3v3>; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am625.dtsi b/arch/arm64/boot/dts/ti/k3-am625.dtsi index 4014add6320d..c3d1db47dc9f 100644 --- a/arch/arm64/boot/dts/ti/k3-am625.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am625.dtsi @@ -50,6 +50,7 @@ next-level-cache = <&L2_0>; operating-points-v2 = <&a53_opp_table>; clocks = <&k3_clks 135 0>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -66,6 +67,7 @@ next-level-cache = <&L2_0>; operating-points-v2 = <&a53_opp_table>; clocks = <&k3_clks 136 0>; + #cooling-cells = <2>; }; cpu2: cpu@2 { @@ -82,6 +84,7 @@ next-level-cache = <&L2_0>; operating-points-v2 = <&a53_opp_table>; clocks = <&k3_clks 137 0>; + #cooling-cells = <2>; }; cpu3: cpu@3 { @@ -98,6 +101,7 @@ next-level-cache = <&L2_0>; operating-points-v2 = <&a53_opp_table>; clocks = <&k3_clks 138 0>; + #cooling-cells = <2>; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi index 916fcf3cc57d..16a578ae2b41 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi @@ -265,6 +265,14 @@ pinctrl-single,function-mask = <0xffffffff>; }; + main_esm: esm@420000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x420000 0x0 0x1000>; + bootph-pre-ram; + /* Interrupt sources: rti0, rti1, wrti0, rti4, rti2, rti3 */ + ti,esm-pins = <192>, <193>, <195>, <204>, <209>, <210>; + }; + main_timer0: timer@2400000 { compatible = "ti,am654-timer"; reg = <0x00 0x2400000 0x00 0x400>; @@ -1088,4 +1096,14 @@ clocks = <&k3_clks 204 2>; power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>; }; + + e5010: jpeg-encoder@fd20000 { + compatible = "ti,am62a-jpeg-enc", "img,e5010-jpeg-enc"; + reg = <0x00 0xfd20000 0x00 0x100>, + <0x00 0xfd20200 0x00 0x200>; + reg-names = "core", "mmu"; + clocks = <&k3_clks 201 0>; + power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi index 8c36e56f4138..0469c766b769 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi @@ -15,6 +15,14 @@ status = "disabled"; }; + mcu_esm: esm@4100000 { + compatible = "ti,j721e-esm"; + reg = <0x0 0x4100000 0x0 0x1000>; + bootph-pre-ram; + /* Interrupt sources: esm0_cfg, esm0_hi, esm0_low, mrti0 */ + ti,esm-pins = <0>, <1>, <2>, <85>; + }; + /* * The MCU domain timer interrupts are routed only to the ESM module, * and not currently available for Linux. The MCU domain timers are diff --git a/arch/arm64/boot/dts/ti/k3-am62a.dtsi b/arch/arm64/boot/dts/ti/k3-am62a.dtsi index b1b884600293..4d79b3e9486a 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62a.dtsi @@ -61,6 +61,8 @@ <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */ <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */ <0x00 0x0fd00000 0x00 0x0fd00000 0x00 0x00020000>, /* GPU */ + <0x00 0x0fd20000 0x00 0x0fd20000 0x00 0x00000100>, /* JPEGENC0_CORE */ + <0x00 0x0fd20200 0x00 0x0fd20200 0x00 0x00000200>, /* JPEGENC0_CORE_MMU */ <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */ <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */ <0x00 0x30101000 0x00 0x30101000 0x00 0x00010100>, /* CSI window */ diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi index 9701fc69aed9..9b6f51379108 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi @@ -260,8 +260,9 @@ main_esm: esm@420000 { compatible = "ti,j721e-esm"; reg = <0x00 0x420000 0x00 0x1000>; - ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>; bootph-pre-ram; + /* Interrupt sources: rti0, rti1, wrti0 rti2, rti3, rti15 */ + ti,esm-pins = <224>, <225>, <227>, <241>, <242>, <248>; }; main_timer0: timer@2400000 { diff --git a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi index df7945156397..b33aff0d65c9 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-mcu.dtsi @@ -26,9 +26,9 @@ mcu_esm: esm@4100000 { compatible = "ti,j721e-esm"; reg = <0x00 0x4100000 0x00 0x1000>; - ti,esm-pins = <0>, <1>, <2>, <85>; - status = "reserved"; bootph-pre-ram; + /* Interrupt sources: esm0_cfg, esm0_hi, esm0_low, mrti0, wrti0 */ + ti,esm-pins = <0>, <1>, <2>, <85>, <86>; }; /* diff --git a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi index 0ce9721b4176..420c77c8e9e5 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi @@ -65,5 +65,6 @@ &main_gpio1 { gpio-ranges = <&main_pmx0 0 94 32>, <&main_pmx0 42 137 5>, <&main_pmx0 47 143 3>, <&main_pmx0 50 149 2>; + gpio-reserved-ranges = <32 10>; ti,ngpio = <52>; }; diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts index ff65955551a3..3efa12bb7254 100644 --- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts @@ -645,8 +645,6 @@ wkup_uart0_pins_default: wkup-uart0-default-pins { pinctrl-single,pins = < - AM62PX_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */ - AM62PX_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (C6) WKUP_UART0_RTSn */ AM62PX_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (D8) WKUP_UART0_RXD */ AM62PX_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */ >; diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi index f8370dd03350..7eae18399caa 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi @@ -389,7 +389,8 @@ bootph-pre-ram; compatible = "ti,j721e-esm"; reg = <0x00 0x420000 0x00 0x1000>; - ti,esm-pins = <160>, <161>; + /* Interrupt sources: rti0, rti1, rti8, rti9, rti10, rti11 */ + ti,esm-pins = <160>, <161>, <162>, <163>, <164>, <165>; }; main_uart0: serial@2800000 { @@ -677,6 +678,7 @@ assigned-clock-parents = <&k3_clks 13 9>; clock-names = "fck"; power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>; + status = "disabled"; dmas = <&main_pktdma 0xC500 15>, <&main_pktdma 0xC501 15>, @@ -701,6 +703,7 @@ phys = <&phy_gmii_sel 1>; mac-address = [00 00 00 00 00 00]; ti,syscon-efuse = <&main_conf 0x200>; + status = "disabled"; }; cpsw_port2: port@2 { @@ -709,6 +712,7 @@ label = "port2"; phys = <&phy_gmii_sel 2>; mac-address = [00 00 00 00 00 00]; + status = "disabled"; }; }; @@ -759,7 +763,7 @@ }; usbss0: cdns-usb@f900000 { - compatible = "ti,am64-usb"; + compatible = "ti,am64-usb", "ti,j721e-usb"; reg = <0x00 0xf900000 0x00 0x100>; power-domains = <&k3_pds 161 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 161 9>, <&k3_clks 161 1>; diff --git a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi index ec17285869da..ad4bed5d3f9e 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi @@ -158,6 +158,7 @@ bootph-pre-ram; compatible = "ti,j721e-esm"; reg = <0x00 0x4100000 0x00 0x1000>; - ti,esm-pins = <0>, <1>; + /* Interrupt sources: esm0_cfg, esm0_hi, esm0_low, mrti0 */ + ti,esm-pins = <0>, <1>, <2>, <85>; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi index ea7c58fb67e2..6bece2fb4e95 100644 --- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi @@ -185,6 +185,7 @@ &cpsw3g { pinctrl-names = "default"; pinctrl-0 = <&cpsw_rgmii1_pins_default>; + status = "okay"; }; &cpsw3g_mdio { @@ -208,10 +209,7 @@ &cpsw_port1 { phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy1>; -}; - -&cpsw_port2 { - status = "disabled"; + status = "okay"; }; &mailbox0_cluster2 { diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso index f08c0e272b53..92faf762894c 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso +++ b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso @@ -12,7 +12,7 @@ #include "k3-pinctrl.h" &main_pmx0 { - gpmc0_pins_default: gpmc0-pins-default { + gpmc0_default_pins: gpmc0-default-pins { bootph-all; pinctrl-single,pins = < AM64X_IOPAD(0x0094, PIN_INPUT, 7) /* (T19) GPMC0_BE1n.GPIO0_36 */ @@ -50,7 +50,7 @@ }; &main_gpio0 { - gpio0-36 { + gpmc0-hog { bootph-all; gpio-hog; gpios = <36 0>; @@ -67,7 +67,7 @@ &gpmc0 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&gpmc0_pins_default>; + pinctrl-0 = <&gpmc0_default_pins>; #address-cells = <2>; #size-cells = <1>; diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts index 6bb1ad2e56ec..97ca16f00cd2 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts @@ -616,17 +616,20 @@ bootph-all; pinctrl-names = "default"; pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>; + status = "okay"; }; &cpsw_port1 { bootph-all; phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy0>; + status = "okay"; }; &cpsw_port2 { phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy3>; + status = "okay"; }; &cpsw3g_mdio { @@ -646,6 +649,10 @@ &tscadc0 { /* ADC is reserved for R5 usage */ status = "reserved"; + + adc { + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; }; &ospi0 { diff --git a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts index 30729b49dd69..60285d736e07 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts @@ -28,6 +28,8 @@ model = "PHYTEC phyBOARD-Electra-AM64x RDK"; aliases { + ethernet1 = &icssg0_emac0; + ethernet2 = &icssg0_emac1; mmc1 = &sdhci1; serial2 = &main_uart0; serial3 = &main_uart1; @@ -55,6 +57,73 @@ standby-gpios = <&main_gpio0 35 GPIO_ACTIVE_HIGH>; }; + /* Dual Ethernet application node on PRU-ICSSG0 */ + ethernet { + compatible = "ti,am642-icssg-prueth"; + pinctrl-names = "default"; + pinctrl-0 = <&icssg0_rgmii1_pins_default>, <&icssg0_rgmii2_pins_default>; + + interrupt-parent = <&icssg0_intc>; + interrupts = <24 0 2>, <25 1 3>; + interrupt-names = "tx_ts0", "tx_ts1"; + + sram = <&oc_sram>; + firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", + "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", + "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", + "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", + "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", + "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf"; + + dmas = <&main_pktdma 0xc100 15>, /* egress slice 0 */ + <&main_pktdma 0xc101 15>, /* egress slice 0 */ + <&main_pktdma 0xc102 15>, /* egress slice 0 */ + <&main_pktdma 0xc103 15>, /* egress slice 0 */ + <&main_pktdma 0xc104 15>, /* egress slice 1 */ + <&main_pktdma 0xc105 15>, /* egress slice 1 */ + <&main_pktdma 0xc106 15>, /* egress slice 1 */ + <&main_pktdma 0xc107 15>, /* egress slice 1 */ + <&main_pktdma 0x4100 15>, /* ingress slice 0 */ + <&main_pktdma 0x4101 15>; /* ingress slice 1 */ + dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", + "tx1-0", "tx1-1", "tx1-2", "tx1-3", + "rx0", "rx1"; + + ti,prus = <&pru0_0>, <&rtu0_0>, <&tx_pru0_0>, <&pru0_1>, <&rtu0_1>, <&tx_pru0_1>; + ti,pruss-gp-mux-sel = <2>, /* MII mode */ + <2>, + <2>, + <2>, /* MII mode */ + <2>, + <2>; + + ti,mii-g-rt = <&icssg0_mii_g_rt>; + ti,mii-rt = <&icssg0_mii_rt>; + ti,iep = <&icssg0_iep0>, <&icssg0_iep1>; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + icssg0_emac0: port@0 { + reg = <0>; + phy-handle = <&icssg0_phy1>; + phy-mode = "rgmii-id"; + /* Filled in by bootloader */ + local-mac-address = [00 00 00 00 00 00]; + ti,syscon-rgmii-delay = <&main_conf 0x4100>; + }; + + icssg0_emac1: port@1 { + reg = <1>; + phy-handle = <&icssg0_phy2>; + phy-mode = "rgmii-id"; + /* Filled in by bootloader */ + local-mac-address = [00 00 00 00 00 00]; + ti,syscon-rgmii-delay = <&main_conf 0x4104>; + }; + }; + }; + keys { compatible = "gpio-keys"; autorepeat; @@ -118,6 +187,12 @@ >; }; + clkout0_pins_default: clkout0-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0274, PIN_OUTPUT, 5) /* (A19) EXT_REFCLK1.CLKOUT0 */ + >; + }; + gpio_keys_pins_default: gpio-keys-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0044, PIN_INPUT, 7) /* (T18) GPMC0_AD2.GPIO0_17 */ @@ -125,6 +200,49 @@ >; }; + icssg0_mdio_pins_default: icssg0-mdio-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0200, PIN_INPUT, 0) /* (P2) PRG0_MDIO0_MDIO */ + AM64X_IOPAD(0x0204, PIN_OUTPUT, 0) /* (P3) PRG0_MDIO0_MDC */ + AM64X_IOPAD(0x01A8, PIN_OUTPUT, 7) /* (V1) PRG0_PRU0_GPO18.GPIO1_18 */ + AM64X_IOPAD(0x01AC, PIN_OUTPUT, 7) /* (W1) PRG0_PRU0_GPO19.GPIO1_19 */ + >; + }; + + icssg0_rgmii1_pins_default: icssg0-rgmii1-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0160, PIN_INPUT, 2) /* (Y1) PRG0_PRU0_GPO0.PRG0_RGMII1_RD0 */ + AM64X_IOPAD(0x0164, PIN_INPUT, 2) /* (R4) PRG0_PRU0_GPO1.PRG0_RGMII1_RD1 */ + AM64X_IOPAD(0x0168, PIN_INPUT, 2) /* (U2) PRG0_PRU0_GPO2.PRG0_RGMII1_RD2 */ + AM64X_IOPAD(0x016c, PIN_INPUT, 2) /* (V2) PRG0_PRU0_GPO3.PRG0_RGMII1_RD3 */ + AM64X_IOPAD(0x0170, PIN_INPUT, 2) /* (AA2) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */ + AM64X_IOPAD(0x0178, PIN_INPUT, 2) /* (T3) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */ + AM64X_IOPAD(0x018c, PIN_OUTPUT, 2) /* (Y3) PRG0_PRU0_GPO11.PRG0_RGMII1_TD0 */ + AM64X_IOPAD(0x0190, PIN_OUTPUT, 2) /* (AA3) PRG0_PRU0_GPO12.PRG0_RGMII1_TD1 */ + AM64X_IOPAD(0x0194, PIN_OUTPUT, 2) /* (R6) PRG0_PRU0_GPO13.PRG0_RGMII1_TD2 */ + AM64X_IOPAD(0x0198, PIN_OUTPUT, 2) /* (V4) PRG0_PRU0_GPO14.PRG0_RGMII1_TD3 */ + AM64X_IOPAD(0x019c, PIN_OUTPUT, 2) /* (T5) PRG0_PRU0_GPO15.PRG0_RGMII1_TX_CTL */ + AM64X_IOPAD(0x01a0, PIN_OUTPUT, 2) /* (U4) PRG0_PRU0_GPO16.PRG0_RGMII1_TXC */ + >; + }; + + icssg0_rgmii2_pins_default: icssg0-rgmii2-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x01b0, PIN_INPUT, 2) /* (Y2) PRG0_PRU1_GPO0.PRG0_RGMII2_RD0 */ + AM64X_IOPAD(0x01b4, PIN_INPUT, 2) /* (W2) PRG0_PRU1_GPO1.PRG0_RGMII2_RD1 */ + AM64X_IOPAD(0x01b8, PIN_INPUT, 2) /* (V3) PRG0_PRU1_GPO2.PRG0_RGMII2_RD2 */ + AM64X_IOPAD(0x01bc, PIN_INPUT, 2) /* (T4) PRG0_PRU1_GPO3.PRG0_RGMII2_RD3 */ + AM64X_IOPAD(0x01c0, PIN_INPUT, 2) /* (W3) PRG0_PRU1_GPO4.PRG0_RGMII2_RX_CTL */ + AM64X_IOPAD(0x01c8, PIN_INPUT, 2) /* (R5) PRG0_PRU1_GPO6.PRG0_RGMII2_RXC */ + AM64X_IOPAD(0x01dc, PIN_OUTPUT, 2) /* (W4) PRG0_PRU1_GPO11.PRG0_RGMII2_TD0 */ + AM64X_IOPAD(0x01e0, PIN_OUTPUT, 2) /* (Y4) PRG0_PRU1_GPO12.PRG0_RGMII2_TD1 */ + AM64X_IOPAD(0x01e4, PIN_OUTPUT, 2) /* (T6) PRG0_PRU1_GPO13.PRG0_RGMII2_TD2 */ + AM64X_IOPAD(0x01e8, PIN_OUTPUT, 2) /* (U6) PRG0_PRU1_GPO14.PRG0_RGMII2_TD3 */ + AM64X_IOPAD(0x01ec, PIN_OUTPUT, 2) /* (U5) PRG0_PRU1_GPO15.PRG0_RGMII2_TX_CTL */ + AM64X_IOPAD(0x01f0, PIN_OUTPUT, 2) /* (AA4) PRG0_PRU1_GPO16.PRG0_RGMII2_TXC */ + >; + }; + main_i2c1_pins_default: main-i2c1-default-pins { pinctrl-single,pins = < AM64X_IOPAD(0x0268, PIN_INPUT, 0) /* (C18) I2C1_SCL */ @@ -198,6 +316,34 @@ }; }; +&icssg0_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&icssg0_mdio_pins_default &clkout0_pins_default>; + status = "okay"; + + icssg0_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + reset-gpios = <&main_gpio1 18 GPIO_ACTIVE_LOW>; + reset-assert-us = <1000>; + reset-deassert-us = <1000>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + }; + + icssg0_phy2: ethernet-phy@2 { + compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22"; + reg = <0x2>; + tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + reset-gpios = <&main_gpio1 19 GPIO_ACTIVE_LOW>; + reset-assert-us = <1000>; + reset-deassert-us = <1000>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + }; +}; + &main_i2c1 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts index 44ecbcf1c844..86369525259c 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts @@ -527,16 +527,19 @@ &cpsw3g { pinctrl-names = "default"; pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>; + status = "okay"; }; &cpsw_port1 { phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy0>; + status = "okay"; }; &cpsw_port2 { phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy1>; + status = "okay"; }; &cpsw3g_mdio { diff --git a/arch/arm64/boot/dts/ti/k3-am642-sr-som.dtsi b/arch/arm64/boot/dts/ti/k3-am642-sr-som.dtsi index c19d0b8bbf0f..a5cec9a07510 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-sr-som.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am642-sr-som.dtsi @@ -177,6 +177,7 @@ &cpsw3g { pinctrl-names = "default"; pinctrl-0 = <&rgmii1_default_pins>; + status = "okay"; }; &cpsw3g_mdio { @@ -210,10 +211,7 @@ &cpsw_port1 { phy-mode = "rgmii-id"; phy-handle = <ðernet_phy0>; -}; - -&cpsw_port2 { - status = "disabled"; + status = "okay"; }; &icssg1_mdio { diff --git a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts index c40ad67cee01..e06a3b178b34 100644 --- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts +++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts @@ -24,6 +24,8 @@ aliases { ethernet0 = &cpsw_port1; + ethernet1 = &icssg1_emac0; + ethernet2 = &icssg1_emac1; i2c1 = &mcu_i2c0; mmc1 = &sdhci1; serial0 = &mcu_uart0; @@ -71,6 +73,66 @@ }; }; + icssg1_eth: icssg1-eth { + compatible = "ti,am642-icssg-prueth"; + pinctrl-names = "default"; + pinctrl-0 = <&pru_icssg1_rgmii1_pins>, <&pru_icssg1_rgmii2_pins>; + interrupt-parent = <&icssg1_intc>; + interrupts = <24 0 2>, <25 1 3>; + interrupt-names = "tx_ts0", "tx_ts1"; + dmas = <&main_pktdma 0xc200 15>, /* egress slice 0 */ + <&main_pktdma 0xc201 15>, /* egress slice 0 */ + <&main_pktdma 0xc202 15>, /* egress slice 0 */ + <&main_pktdma 0xc203 15>, /* egress slice 0 */ + <&main_pktdma 0xc204 15>, /* egress slice 1 */ + <&main_pktdma 0xc205 15>, /* egress slice 1 */ + <&main_pktdma 0xc206 15>, /* egress slice 1 */ + <&main_pktdma 0xc207 15>, /* egress slice 1 */ + <&main_pktdma 0x4200 15>, /* ingress slice 0 */ + <&main_pktdma 0x4201 15>; /* ingress slice 1 */ + dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", + "tx1-0", "tx1-1", "tx1-2", "tx1-3", + "rx0", "rx1"; + sram = <&oc_sram>; + firmware-name = "ti-pruss/am64x-sr2-pru0-prueth-fw.elf", + "ti-pruss/am64x-sr2-rtu0-prueth-fw.elf", + "ti-pruss/am64x-sr2-txpru0-prueth-fw.elf", + "ti-pruss/am64x-sr2-pru1-prueth-fw.elf", + "ti-pruss/am64x-sr2-rtu1-prueth-fw.elf", + "ti-pruss/am64x-sr2-txpru1-prueth-fw.elf"; + ti,prus = <&pru1_0>, <&rtu1_0>, <&tx_pru1_0>, <&pru1_1>, <&rtu1_1>, <&tx_pru1_1>; + ti,pruss-gp-mux-sel = <2>, /* MII mode */ + <2>, + <2>, + <2>, /* MII mode */ + <2>, + <2>; + ti,mii-g-rt = <&icssg1_mii_g_rt>; + ti,mii-rt = <&icssg1_mii_rt>; + ti,iep = <&icssg1_iep0>, <&icssg1_iep1>; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + icssg1_emac0: port@0 { + reg = <0>; + phy-handle = <&icssg1_phy0c>; + phy-mode = "rgmii-id"; + /* Filled in by bootloader */ + local-mac-address = [00 00 00 00 00 00]; + }; + + icssg1_emac1: port@1 { + reg = <1>; + phy-handle = <&icssg1_phy03>; + phy-mode = "rgmii-id"; + /* Filled in by bootloader */ + local-mac-address = [00 00 00 00 00 00]; + }; + }; + }; + fan0: pwm-fan { compatible = "pwm-fan"; pinctrl-names = "default"; @@ -119,15 +181,13 @@ &cpsw3g { pinctrl-names = "default"; pinctrl-0 = <&cpsw_pins>; + status = "okay"; }; &cpsw_port1 { phy-mode = "rgmii-rxid"; phy-handle = <&cpsw3g_phy0>; -}; - -&cpsw_port2 { - status = "disabled"; + status = "okay"; }; &cpsw3g_mdio { @@ -154,6 +214,42 @@ status = "okay"; }; +&icssg1_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&pru_icssg1_mdio_pins>; + status = "okay"; + + /* phy-mode is fixed up to rgmii-rxid by prueth driver to account for + * the SoC integration, so the only rx-internal-delay and no + * tx-internal-delay is set for the PHYs. + */ + + icssg1_phy03: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x3>; + reset-gpios = <&main_gpio1 47 GPIO_ACTIVE_LOW>; + reset-assert-us = <1000>; + reset-deassert-us = <1000>; + ti,rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + ti,tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>; + }; + + icssg1_phy0c: ethernet-phy@c { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0xc>; + reset-gpios = <&main_gpio1 51 GPIO_ACTIVE_LOW>; + reset-assert-us = <1000>; + reset-deassert-us = <1000>; + ti,rx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + ti,tx-fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>; + }; +}; + + &main_gpio0 { pinctrl-names = "default"; pinctrl-0 = <&main_gpio0_digital_pins>, diff --git a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi index e2584a5efe34..b3c4c0eec3dc 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi @@ -9,11 +9,6 @@ * Common bits of the IOT2050 Basic and Advanced variants, PG2 */ -&mcu_r5fss0 { - /* lock-step mode not supported on PG2 boards */ - ti,cluster-mode = <0>; -}; - &main_pmx0 { cp2102n_reset_pin_default: cp2102n-reset-default-pins { pinctrl-single,pins = < diff --git a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi index ef34b851e178..e5136ed94765 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi @@ -627,11 +627,62 @@ reg = <0>; ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_LAN; + }; + + led@1 { + reg = <1>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_SPEED_LAN; + }; + + led@2 { + reg = <2>; + color = <LED_COLOR_ID_YELLOW>; + function = LED_FUNCTION_SPEED_LAN; + }; + }; }; icssg0_eth1_phy: ethernet-phy@1 { reg = <1>; ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_LAN; + }; + + led@1 { + reg = <1>; + color = <LED_COLOR_ID_GREEN>; + function = LED_FUNCTION_SPEED_LAN; + }; + + led@2 { + reg = <2>; + color = <LED_COLOR_ID_YELLOW>; + function = LED_FUNCTION_SPEED_LAN; + }; + }; }; }; + +&mcu_r5fss0 { + /* lock-step mode not supported on iot2050 boards */ + ti,cluster-mode = <0>; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi index 1af3dedde1f6..1f1af7ea2330 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi @@ -54,6 +54,14 @@ }; }; + main_esm: esm@700000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x700000 0x00 0x1000>; + bootph-pre-ram; + /* Interrupt sources: rti0, rti1, rti2, rti3 */ + ti,esm-pins = <224>, <225>, <226>, <227>; + }; + serdes0: serdes@900000 { compatible = "ti,phy-am654-serdes"; reg = <0x0 0x900000 0x0 0x2000>; @@ -478,7 +486,7 @@ ranges = <0x0 0x0 0x00100000 0x1c000>; serdes0_clk: clock@4080 { - compatible = "ti,am654-serdes-ctrl", "syscon"; + compatible = "ti,am654-serdes-ctrl", "syscon", "simple-mfd"; reg = <0x4080 0x4>; serdes0_mux: mux-controller { @@ -489,7 +497,7 @@ }; serdes1_clk: clock@4090 { - compatible = "ti,am654-serdes-ctrl", "syscon"; + compatible = "ti,am654-serdes-ctrl", "syscon", "simple-mfd"; reg = <0x4090 0x4>; serdes1_mux: mux-controller { diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi index 43c6118d2bf0..7cf1f646500a 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi @@ -292,13 +292,13 @@ ranges = <0x0 0x47000000 0x0 0x47000000 0x0 0x100>, /* FSS Control */ <0x0 0x47040000 0x0 0x47040000 0x0 0x100>, /* OSPI0 Control */ <0x0 0x47050000 0x0 0x47050000 0x0 0x100>, /* OSPI1 Control */ - <0x5 0x00000000 0x5 0x00000000 0x1 0x0000000>, /* OSPI0 Memory */ - <0x7 0x00000000 0x7 0x00000000 0x1 0x0000000>; /* OSPI1 Memory */ + <0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>, /* FSS data region 1 */ + <0x4 0x00000000 0x4 0x00000000 0x4 0x00000000>; /* FSS data region 0/3 */ ospi0: spi@47040000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x0 0x47040000 0x0 0x100>, - <0x5 0x00000000 0x1 0x0000000>; + <0x5 0x00000000 0x1 0x00000000>; interrupts = <GIC_SPI 552 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; @@ -316,7 +316,7 @@ ospi1: spi@47050000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x0 0x47050000 0x0 0x100>, - <0x7 0x00000000 0x1 0x00000000>; + <0x7 0x00000000 0x1 0x00000000>; interrupts = <GIC_SPI 553 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; @@ -440,6 +440,14 @@ }; }; + mcu_esm: esm@40800000 { + compatible = "ti,j721e-esm"; + reg = <0x00 0x40800000 0x00 0x1000>; + bootph-pre-ram; + /* Interrupt sources: mrti0, mrti1 */ + ti,esm-pins = <104>, <105>; + }; + mcu_rti1: watchdog@40610000 { compatible = "ti,j7-rti-wdt"; reg = <0x0 0x40610000 0x0 0x100>; diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi index c59baebc5a25..c74a0a25832c 100644 --- a/arch/arm64/boot/dts/ti/k3-am65.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi @@ -69,11 +69,10 @@ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, - <0x00 0x50000000 0x00 0x50000000 0x00 0x8000000>, + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A53 PERIPHBASE */ - <0x00 0x70000000 0x00 0x70000000 0x00 0x200000>, - <0x05 0x00000000 0x05 0x00000000 0x01 0x0000000>, - <0x07 0x00000000 0x07 0x00000000 0x01 0x0000000>; + <0x00 0x70000000 0x00 0x70000000 0x00 0x00200000>, + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; cbass_mcu: bus@28380000 { compatible = "simple-bus"; @@ -89,9 +88,8 @@ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI space 1 */ - <0x00 0x50000000 0x00 0x50000000 0x00 0x8000000>, /* FSS OSPI0 data region 1 */ - <0x05 0x00000000 0x05 0x00000000 0x01 0x0000000>, /* FSS OSPI0 data region 3*/ - <0x07 0x00000000 0x07 0x00000000 0x01 0x0000000>; /* FSS OSPI1 data region 3*/ + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */ + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */ cbass_wakeup: bus@42040000 { compatible = "simple-bus"; diff --git a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic.dts b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic.dts index 29a31891b3db..4968a47f31ea 100644 --- a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic.dts +++ b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic.dts @@ -22,8 +22,3 @@ compatible = "siemens,iot2050-basic", "ti,am654"; model = "SIMATIC IOT2050 Basic"; }; - -&mcu_r5fss0 { - /* lock-step mode not supported on this board */ - ti,cluster-mode = <0>; -}; diff --git a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso index 8bdb87fcbde0..b0ce2cb2fdc8 100644 --- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso +++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso @@ -8,6 +8,7 @@ /dts-v1/; /plugin/; +#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/net/ti-dp83867.h> #include "k3-pinctrl.h" @@ -58,9 +59,7 @@ <&main_udmap 0xc107>, /* egress slice 1 */ <&main_udmap 0x4100>, /* ingress slice 0 */ - <&main_udmap 0x4101>, /* ingress slice 1 */ - <&main_udmap 0x4102>, /* mgmnt rsp slice 0 */ - <&main_udmap 0x4103>; /* mgmnt rsp slice 1 */ + <&main_udmap 0x4101>; /* ingress slice 1 */ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", "tx1-0", "tx1-1", "tx1-2", "tx1-3", "rx0", "rx1"; @@ -126,9 +125,7 @@ <&main_udmap 0xc207>, /* egress slice 1 */ <&main_udmap 0x4200>, /* ingress slice 0 */ - <&main_udmap 0x4201>, /* ingress slice 1 */ - <&main_udmap 0x4202>, /* mgmnt rsp slice 0 */ - <&main_udmap 0x4203>; /* mgmnt rsp slice 1 */ + <&main_udmap 0x4201>; /* ingress slice 1 */ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", "tx1-0", "tx1-1", "tx1-2", "tx1-3", "rx0", "rx1"; @@ -154,6 +151,24 @@ }; }; }; + + transceiver1: can-phy0 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&mcan0_gpio_pins_default>; + standby-gpios = <&main_gpio1 47 GPIO_ACTIVE_LOW>; + }; + + transceiver2: can-phy1 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&mcan1_gpio_pins_default>; + standby-gpios = <&main_gpio1 67 GPIO_ACTIVE_LOW>; + }; }; &main_pmx0 { @@ -243,6 +258,34 @@ AM65X_IOPAD(0x012c, PIN_INPUT, 2) /* (AG26) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */ >; }; + + mcan0_gpio_pins_default: mcan0-gpio-default-pins { + pinctrl-single,pins = < + AM65X_IOPAD(0x023c, PIN_INPUT, 7) /* (V25) PRG0_PRU0_GPIO18:GPIO1_47 */ + >; + }; + + mcan1_gpio_pins_default: mcan1-gpio-default-pins { + pinctrl-single,pins = < + AM65X_IOPAD(0x028c, PIN_INPUT, 7) /* (Y26) PRG0_PRU1_GPIO18.GPIO1_67 */ + >; + }; +}; + +&wkup_pmx0 { + mcu_mcan0_pins_default: mcu-mcan0-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00ac, PIN_INPUT_PULLUP, 0) /* (W2) MCU_MCAN0_RX */ + AM65X_WKUP_IOPAD(0x00a8, PIN_OUTPUT_PULLUP, 0) /* (W1) MCU_MCAN0_TX */ + >; + }; + + mcu_mcan1_pins_default: mcu-mcan1-default-pins { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00c4, PIN_INPUT_PULLUP, 1) /* (AD3) WKUP_GPIO0_5.MCU_MCAN1_RX */ + AM65X_WKUP_IOPAD(0x00c0, PIN_OUTPUT_PULLUP, 1) /* (AC3) WKUP_GPIO0_4.MCU_MCAN1_TX */ + >; + }; }; &icssg0_mdio { @@ -294,3 +337,17 @@ pinctrl-names = "default"; pinctrl-0 = <&icssg1_iep0_pins_default>; }; + +&m_can0 { + pinctrl-names = "default"; + pinctrl-0 = <&mcu_mcan0_pins_default>; + phys = <&transceiver1>; + status = "okay"; +}; + +&m_can1 { + pinctrl-names = "default"; + pinctrl-0 = <&mcu_mcan1_pins_default>; + phys = <&transceiver2>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie.dtso b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie.dtso new file mode 100644 index 000000000000..666237f6d79c --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IOT2050 M.2 variant, overlay for B-key PCIE0_LANE0 + E-key PCIE1_LANE0 + * Copyright (c) Siemens AG, 2022-2024 + * + * Authors: + * Chao Zeng <chao.zeng@siemens.com> + * Jan Kiszka <jan.kiszka@siemens.com> + */ + +/dts-v1/; +/plugin/; + +#include <dt-bindings/phy/phy.h> +#include <dt-bindings/gpio/gpio.h> + +&pcie0_rc { + num-lanes = <1>; + phys = <&serdes0 PHY_TYPE_PCIE 1>; + phy-names = "pcie-phy0"; + reset-gpios = <&main_gpio1 15 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie1_rc { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-usb3.dtso b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-usb3.dtso new file mode 100644 index 000000000000..0f86235c9771 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2-bkey-usb3.dtso @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IOT2050 M.2 variant, overlay for B-key USB3.0 + E-key PCIE1_LANE0 + * Copyright (c) Siemens AG, 2022-2024 + * + * Authors: + * Chao Zeng <chao.zeng@siemens.com> + * Jan Kiszka <jan.kiszka@siemens.com> + */ + +/dts-v1/; +/plugin/; + +#include <dt-bindings/phy/phy.h> +#include <dt-bindings/gpio/gpio.h> + +&serdes0 { + assigned-clock-parents = <&k3_clks 153 7>, <&k3_clks 153 4>; +}; + +&pcie0_rc { + status = "disabled"; +}; + +&pcie1_rc { + pinctrl-names = "default"; + pinctrl-0 = <&minipcie_pins_default>; + + num-lanes = <1>; + phys = <&serdes1 PHY_TYPE_PCIE 0>; + phy-names = "pcie-phy0"; + reset-gpios = <&wkup_gpio0 27 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&dwc3_0 { + assigned-clock-parents = <&k3_clks 151 4>, /* set REF_CLK to 20MHz i.e. PER0_PLL/48 */ + <&k3_clks 151 8>; /* set PIPE3_TXB_CLK to WIZ8B2M4VSB */ + phys = <&serdes0 PHY_TYPE_USB3 0>; + phy-names = "usb3-phy"; +}; + +&usb0 { + maximum-speed = "super-speed"; + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts b/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts new file mode 100644 index 000000000000..44dfbdf89277 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * https://beagley-ai.org/ + * + * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ + * Copyright (C) 2024 Robert Nelson, BeagleBoard.org Foundation + */ + +/dts-v1/; + +#include <dt-bindings/leds/common.h> +#include <dt-bindings/net/ti-dp83867.h> +#include "k3-j722s.dtsi" + +/ { + compatible = "beagle,am67a-beagley-ai", "ti,j722s"; + model = "BeagleBoard.org BeagleY-AI"; + + aliases { + serial0 = &wkup_uart0; + serial2 = &main_uart0; + mmc1 = &sdhci1; + rtc0 = &rtc; + }; + + chosen { + stdout-path = &main_uart0; + }; + + memory@80000000 { + /* 4G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>, + <0x00000008 0x80000000 0x00000000 0x80000000>; + device_type = "memory"; + bootph-pre-ram; + }; + + reserved_memory: reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure_tfa_ddr: tfa@9e780000 { + reg = <0x00 0x9e780000 0x00 0x80000>; + no-map; + }; + + secure_ddr: optee@9e800000 { + reg = <0x00 0x9e800000 0x00 0x01800000>; + no-map; + }; + + wkup_r5fss0_core0_memory_region: r5f-memory@a0100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa0100000 0x00 0xf00000>; + no-map; + }; + }; + + vsys_5v0: regulator-1 { + compatible = "regulator-fixed"; + regulator-name = "vsys_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + bootph-all; + }; + + vdd_3v3: regulator-2 { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vsys_5v0>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_mmc1: regulator-3 { + compatible = "regulator-fixed"; + regulator-name = "vdd_mmc1"; + pinctrl-names = "default"; + pinctrl-0 = <&vdd_3v3_sd_pins_default>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + enable-active-high; + gpio = <&main_gpio1 50 GPIO_ACTIVE_HIGH>; + bootph-all; + }; + + vdd_sd_dv: regulator-4 { + compatible = "regulator-gpio"; + regulator-name = "tlv71033"; + pinctrl-names = "default"; + pinctrl-0 = <&vdd_sd_dv_pins_default>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + vin-supply = <&vsys_5v0>; + gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>; + states = <1800000 0x0>, + <3300000 0x1>; + bootph-all; + }; + + vsys_io_1v8: regulator-5 { + compatible = "regulator-fixed"; + regulator-name = "vsys_io_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + vsys_io_1v2: regulator-6 { + compatible = "regulator-fixed"; + regulator-name = "vsys_io_1v2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_default>; + + led-0 { + gpios = <&main_gpio0 11 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led-1 { + gpios = <&main_gpio0 12 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; + default-state = "on"; + }; + }; +}; + +&main_pmx0 { + main_i2c0_pins_default: main-i2c0-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (D23) I2C0_SCL */ + J722S_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (B22) I2C0_SDA */ + >; + bootph-all; + }; + + main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x01c8, PIN_INPUT, 0) /* (A22) UART0_RXD */ + J722S_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (B22) UART0_TXD */ + >; + bootph-all; + }; + + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x0244, PIN_OUTPUT, 7) /* (A24) MMC1_SDWP.GPIO1_49 */ + >; + bootph-all; + }; + + main_mmc1_pins_default: main-mmc1-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x023c, PIN_INPUT, 0) /* (H22) MMC1_CMD */ + J722S_IOPAD(0x0234, PIN_OUTPUT, 0) /* (H24) MMC1_CLK */ + J722S_IOPAD(0x0230, PIN_INPUT, 0) /* (H23) MMC1_DAT0 */ + J722S_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H20) MMC1_DAT1 */ + J722S_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (J23) MMC1_DAT2 */ + J722S_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */ + J722S_IOPAD(0x0240, PIN_INPUT, 7) /* (B24) MMC1_SDCD.GPIO1_48 */ + >; + bootph-all; + }; + + mdio_pins_default: mdio-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x0160, PIN_OUTPUT, 0) /* (AC24) MDIO0_MDC */ + J722S_IOPAD(0x015c, PIN_INPUT, 0) /* (AD25) MDIO0_MDIO */ + >; + }; + + rgmii1_pins_default: rgmii1-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x014c, PIN_INPUT, 0) /* (AC25) RGMII1_RD0 */ + J722S_IOPAD(0x0150, PIN_INPUT, 0) /* (AD27) RGMII1_RD1 */ + J722S_IOPAD(0x0154, PIN_INPUT, 0) /* (AE24) RGMII1_RD2 */ + J722S_IOPAD(0x0158, PIN_INPUT, 0) /* (AE26) RGMII1_RD3 */ + J722S_IOPAD(0x0148, PIN_INPUT, 0) /* (AE27) RGMII1_RXC */ + J722S_IOPAD(0x0144, PIN_INPUT, 0) /* (AD23) RGMII1_RX_CTL */ + J722S_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AF27) RGMII1_TD0 */ + J722S_IOPAD(0x0138, PIN_OUTPUT, 0) /* (AE23) RGMII1_TD1 */ + J722S_IOPAD(0x013c, PIN_OUTPUT, 0) /* (AG25) RGMII1_TD2 */ + J722S_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AF24) RGMII1_TD3 */ + J722S_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AG26) RGMII1_TXC */ + J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */ + >; + }; + + led_pins_default: led-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x002c, PIN_OUTPUT, 7) /* (K26) OSPI0_CSn0.GPIO0_11 */ + J722S_IOPAD(0x0030, PIN_OUTPUT, 7) /* (K23) OSPI0_CSn1.GPIO0_12 */ + >; + }; + + pmic_irq_pins_default: pmic-irq-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x01f4, PIN_INPUT_PULLUP, 0) /* (B23) EXTINTn */ + >; + }; + + vdd_3v3_sd_pins_default: vdd-3v3-sd-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x0254, PIN_OUTPUT, 7) /* (E25) USB0_DRVVBUS.GPIO1_50 */ + >; + }; +}; + +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins_default>; + status = "okay"; +}; + +&cpsw3g_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins_default>; + status = "okay"; + + cpsw3g_phy0: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; + ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + ti,min-output-impedance; + }; +}; + +&cpsw_port1 { + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy0>; + status = "okay"; +}; + +&main_gpio1 { + status = "okay"; +}; + +&main_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; + bootph-all; + status = "okay"; +}; + +&mcu_pmx0 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < + J722S_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */ + J722S_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (C6) WKUP_UART0_RTSn */ + J722S_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (D8) WKUP_UART0_RXD */ + J722S_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */ + >; + bootph-all; + }; + + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + J722S_MCU_IOPAD(0x04c, PIN_INPUT_PULLUP, 0) /* (C7) WKUP_I2C0_SCL */ + J722S_MCU_IOPAD(0x050, PIN_INPUT_PULLUP, 0) /* (C6) WKUP_I2C1_SDA */ + >; + bootph-all; + }; +}; + +&wkup_uart0 { + /* WKUP UART0 is used by Device Manager firmware */ + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; + bootph-all; + status = "reserved"; +}; + +&wkup_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <100000>; + bootph-all; + status = "okay"; + + tps65219: pmic@30 { + compatible = "ti,tps65219"; + reg = <0x30>; + buck1-supply = <&vsys_5v0>; + buck2-supply = <&vsys_5v0>; + buck3-supply = <&vsys_5v0>; + ldo1-supply = <&vdd_3v3>; + ldo3-supply = <&vdd_3v3>; + ldo4-supply = <&vdd_3v3>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_irq_pins_default>; + interrupt-parent = <&gic500>; + interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + bootph-all; + system-power-controller; + ti,power-button; + + regulators { + buck1_reg: buck1 { + regulator-name = "VDD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + buck2_reg: buck2 { + regulator-name = "VDD_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: ldo1 { + regulator-name = "VDDSHV5_SDIO"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-allow-bypass; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: ldo2 { + regulator-name = "VDD_1V2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3_reg: ldo3 { + regulator-name = "VDDA_PHY_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4_reg: ldo4 { + regulator-name = "VDDA_PLL_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; + + rtc: rtc@68 { + compatible = "dallas,ds1340"; + reg = <0x68>; + }; +}; + +&sdhci1 { + /* SD/MMC */ + vmmc-supply = <&vdd_mmc1>; + vqmmc-supply = <&vdd_sd_dv>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; + disable-wp; + cd-gpios = <&main_gpio1 48 GPIO_ACTIVE_LOW>; + cd-debounce-delay-ms = <100>; + bootph-all; + ti,fails-without-test-cd; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts index 90dbe31c5b81..d5ceab79536c 100644 --- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts @@ -204,6 +204,7 @@ pinctrl-single,pins = < J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */ J721S2_IOPAD(0x108, PIN_INPUT, 0) /* (N24) MMC1_CMD */ + J721S2_IOPAD(0x100, PIN_INPUT, 0) /* (###) MMC1_CLKLB */ J721S2_IOPAD(0x0fc, PIN_INPUT, 0) /* (M23) MMC1_DAT0 */ J721S2_IOPAD(0x0f8, PIN_INPUT, 0) /* (P24) MMC1_DAT1 */ J721S2_IOPAD(0x0f4, PIN_INPUT, 0) /* (R24) MMC1_DAT2 */ diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi index 5c66e0ec6e82..5bc0d2fb4b8f 100644 --- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi @@ -215,9 +215,9 @@ reg = <0x680000 0x40000>; }; - partition@740000 { + partition@6c0000 { label = "ospi.env.backup"; - reg = <0x740000 0x40000>; + reg = <0x6c0000 0x40000>; }; partition@800000 { @@ -302,6 +302,39 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer3 { + status = "reserved"; +}; + +&main_timer4 { + status = "reserved"; +}; + +&main_timer5 { + status = "reserved"; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts index 3f655852244e..1e36965a1403 100644 --- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts @@ -979,6 +979,59 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer3 { + status = "reserved"; +}; + +&main_timer4 { + status = "reserved"; +}; + +&main_timer5 { + status = "reserved"; +}; + +&main_timer6 { + status = "reserved"; +}; + +&main_timer7 { + status = "reserved"; +}; + +&main_timer8 { + status = "reserved"; +}; + +&main_timer9 { + status = "reserved"; +}; + +&main_r5fss2 { + ti,cluster-mode = <0>; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi index 21fe194a5766..e78b4622a7d1 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi @@ -84,13 +84,13 @@ }; }; - mux0: mux-controller { + mux0: mux-controller-0 { compatible = "gpio-mux"; #mux-state-cells = <1>; mux-gpios = <&exp_som 1 GPIO_ACTIVE_HIGH>; }; - mux1: mux-controller { + mux1: mux-controller-1 { compatible = "gpio-mux"; #mux-state-cells = <1>; mux-gpios = <&exp_som 2 GPIO_ACTIVE_HIGH>; @@ -262,6 +262,23 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts index a2925555fe81..fb899c99753e 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts @@ -123,7 +123,7 @@ no-map; }; - c66_1_dma_memory_region: c66-dma-memory@a6000000 { + c66_0_dma_memory_region: c66-dma-memory@a6000000 { compatible = "shared-dma-pool"; reg = <0x00 0xa6000000 0x00 0x100000>; no-map; @@ -135,7 +135,7 @@ no-map; }; - c66_0_dma_memory_region: c66-dma-memory@a7000000 { + c66_1_dma_memory_region: c66-dma-memory@a7000000 { compatible = "shared-dma-pool"; reg = <0x00 0xa7000000 0x00 0x100000>; no-map; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi index 6b6ef6a30614..3731ffb4a5c9 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi @@ -354,8 +354,8 @@ <0x0 0x47034000 0x0 0x47034000 0x0 0x100>, /* HBMC Control */ <0x0 0x47040000 0x0 0x47040000 0x0 0x100>, /* OSPI0 Control */ <0x0 0x47050000 0x0 0x47050000 0x0 0x100>, /* OSPI1 Control */ - <0x5 0x00000000 0x5 0x00000000 0x1 0x0000000>, /* HBMC/OSPI0 Memory */ - <0x7 0x00000000 0x7 0x00000000 0x1 0x0000000>; /* OSPI1 Memory */ + <0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>, /* FSS data region 1 */ + <0x4 0x00000000 0x4 0x00000000 0x4 0x00000000>; /* FSS data region 0/3 */ hbmc_mux: mux-controller@47000004 { compatible = "reg-mux"; @@ -367,7 +367,7 @@ hbmc: hyperbus@47034000 { compatible = "ti,am654-hbmc"; reg = <0x00 0x47034000 0x00 0x100>, - <0x05 0x00000000 0x01 0x0000000>; + <0x05 0x00000000 0x01 0x00000000>; power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>; clocks = <&k3_clks 102 0>; assigned-clocks = <&k3_clks 102 5>; @@ -381,7 +381,7 @@ ospi0: spi@47040000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x0 0x47040000 0x0 0x100>, - <0x5 0x00000000 0x1 0x0000000>; + <0x5 0x00000000 0x1 0x00000000>; interrupts = <GIC_SPI 840 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; @@ -399,7 +399,7 @@ ospi1: spi@47050000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x0 0x47050000 0x0 0x100>, - <0x7 0x00000000 0x1 0x00000000>; + <0x7 0x00000000 0x1 0x00000000>; interrupts = <GIC_SPI 841 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts index 89fbfb21e5d3..6285e8d94dde 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts @@ -120,7 +120,7 @@ no-map; }; - c66_1_dma_memory_region: c66-dma-memory@a6000000 { + c66_0_dma_memory_region: c66-dma-memory@a6000000 { compatible = "shared-dma-pool"; reg = <0x00 0xa6000000 0x00 0x100000>; no-map; @@ -132,7 +132,7 @@ no-map; }; - c66_0_dma_memory_region: c66-dma-memory@a7000000 { + c66_1_dma_memory_region: c66-dma-memory@a7000000 { compatible = "shared-dma-pool"; reg = <0x00 0xa7000000 0x00 0x100000>; no-map; @@ -1311,6 +1311,43 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer12 { + status = "reserved"; +}; + +&main_timer13 { + status = "reserved"; +}; + +&main_timer14 { + status = "reserved"; +}; + +&main_timer15 { + status = "reserved"; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi index 5ba947771b84..cef47c67493f 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi @@ -561,6 +561,43 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer12 { + status = "reserved"; +}; + +&main_timer13 { + status = "reserved"; +}; + +&main_timer14 { + status = "reserved"; +}; + +&main_timer15 { + status = "reserved"; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi index 5a72c518ceb6..a7f2f52f42f7 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi @@ -145,8 +145,7 @@ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; cbass_mcu_wakeup: bus@28380000 { compatible = "simple-bus"; @@ -162,9 +161,8 @@ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */ - <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS OSPI0/1 data region 0 */ - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS OSPI0 data region 3 */ - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/ + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */ + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */ }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso index 1be28283c7d9..8583178fa1f3 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso +++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso @@ -48,7 +48,7 @@ }; &exp1 { - p15 { + p15-hog { /* P15 - EXP_MUX2 */ gpio-hog; gpios = <13 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi index 8feb42c89e47..9d96b19d0e7c 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi @@ -622,8 +622,8 @@ #address-cells = <2>; #size-cells = <2>; ranges = <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; ospi0: spi@47040000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi index 82aacc01e8fe..89252e4a5f1b 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi @@ -134,13 +134,13 @@ }; }; - mux0: mux-controller { + mux0: mux-controller-0 { compatible = "gpio-mux"; #mux-state-cells = <1>; mux-gpios = <&exp_som 1 GPIO_ACTIVE_HIGH>; }; - mux1: mux-controller { + mux1: mux-controller-1 { compatible = "gpio-mux"; #mux-state-cells = <1>; mux-gpios = <&exp_som 2 GPIO_ACTIVE_HIGH>; @@ -516,6 +516,39 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer3 { + status = "reserved"; +}; + +&main_timer4 { + status = "reserved"; +}; + +&main_timer5 { + status = "reserved"; +}; + &main_r5fss0_core0 { mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; memory-region = <&main_r5fss0_core0_dma_memory_region>, diff --git a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi index 568e6a04619d..ea16f82822ae 100644 --- a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi @@ -141,8 +141,7 @@ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; cbass_mcu_wakeup: bus@28380000 { compatible = "simple-bus"; @@ -158,9 +157,8 @@ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */ - <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS OSPI0/1 data region 0 */ - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS OSPI0 data region 3 */ - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/ + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */ + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */ }; diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts index dd3b5f7039d7..a00f4a7d20d9 100644 --- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts @@ -20,6 +20,7 @@ aliases { serial0 = &wkup_uart0; serial2 = &main_uart0; + serial3 = &main_uart5; mmc0 = &sdhci0; mmc1 = &sdhci1; }; @@ -51,12 +52,71 @@ no-map; }; + wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa0000000 0x00 0x100000>; + no-map; + }; + wkup_r5fss0_core0_memory_region: r5f-memory@a0100000 { compatible = "shared-dma-pool"; reg = <0x00 0xa0100000 0x00 0xf00000>; no-map; }; + mcu_r5fss0_core0_dma_memory_region: mcu-r5fss-dma-memory-region@a1000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa1000000 0x00 0x100000>; + no-map; + }; + + mcu_r5fss0_core0_memory_region: mcu-r5fss-memory-region@a1100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa1100000 0x00 0xf00000>; + no-map; + }; + + main_r5fss0_core0_dma_memory_region: main-r5fss-dma-memory-region@a2000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa2000000 0x00 0x100000>; + no-map; + }; + + main_r5fss0_core0_memory_region: main-r5fss-memory-region@a2100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa2100000 0x00 0xf00000>; + no-map; + }; + + c7x_0_dma_memory_region: c7x-dma-memory@a3000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa3000000 0x00 0x100000>; + no-map; + }; + + c7x_0_memory_region: c7x-memory@a3100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa3100000 0x00 0xf00000>; + no-map; + }; + + c7x_1_dma_memory_region: c7x-dma-memory@a4000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa4000000 0x00 0x100000>; + no-map; + }; + + c7x_1_memory_region: c7x-memory@a4100000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xa4100000 0x00 0xf00000>; + no-map; + }; + + rtos_ipc_memory_region: ipc-memories@a5000000 { + reg = <0x00 0xa5000000 0x00 0x1c00000>; + alignment = <0x1000>; + no-map; + }; }; vmain_pd: regulator-0 { @@ -162,10 +222,39 @@ clocks = <&audio_refclk1>; }; }; + + transceiver0: can-phy0 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_mcan0_gpio_pins_default>; + standby-gpios = <&mcu_gpio0 12 GPIO_ACTIVE_HIGH>; + }; + + transceiver1: can-phy1 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + }; + + transceiver2: can-phy2 { + compatible = "ti,tcan1042"; + #phy-cells = <0>; + max-bitrate = <5000000>; + standby-gpios = <&exp1 17 GPIO_ACTIVE_HIGH>; + }; }; &main_pmx0 { + main_mcan0_pins_default: main-mcan0-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x1dc, PIN_INPUT, 0) /* (C22) MCAN0_RX */ + J722S_IOPAD(0x1d8, PIN_OUTPUT, 0) /*(D22) MCAN0_TX */ + >; + }; + main_i2c0_pins_default: main-i2c0-default-pins { pinctrl-single,pins = < J722S_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (D23) I2C0_SCL */ @@ -182,6 +271,13 @@ bootph-all; }; + main_uart5_pins_default: main-uart5-default-pins { + pinctrl-single,pins = < + J722S_IOPAD(0x0108, PIN_INPUT, 3) /* (J27) UART5_RXD */ + J722S_IOPAD(0x010c, PIN_OUTPUT, 3) /* (H27) UART5_TXD */ + >; + }; + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { pinctrl-single,pins = < J722S_IOPAD(0x0120, PIN_INPUT, 7) /* (F27) MMC2_CMD.GPIO0_70 */ @@ -301,8 +397,35 @@ bootph-all; }; +&main_uart5 { + /* MAIN UART 5 is used by System firmware */ + pinctrl-names = "default"; + pinctrl-0 = <&main_uart5_pins_default>; + status = "reserved"; +}; + &mcu_pmx0 { + mcu_mcan0_pins_default: mcu-mcan0-default-pins { + pinctrl-single,pins = < + J722S_MCU_IOPAD(0x038, PIN_INPUT, 0) /* (D8) MCU_MCAN0_RX */ + J722S_MCU_IOPAD(0x034, PIN_OUTPUT, 0) /* (B2) MCU_MCAN0_TX */ + >; + }; + + mcu_mcan1_pins_default: mcu-mcan1-default-pins { + pinctrl-single,pins = < + J722S_MCU_IOPAD(0x040, PIN_INPUT, 0) /* (B1) MCU_MCAN1_RX */ + J722S_MCU_IOPAD(0x03C, PIN_OUTPUT, 0) /*(C1) MCU_MCAN1_TX */ + >; + }; + + mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins { + pinctrl-single,pins = < + J722S_MCU_IOPAD(0x0030, PIN_OUTPUT, 7) /* (C3) MCU_GPIO0_12 */ + >; + }; + wkup_uart0_pins_default: wkup-uart0-default-pins { pinctrl-single,pins = < J722S_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */ @@ -494,6 +617,104 @@ bootph-all; }; +&mailbox0_cluster0 { + status = "okay"; + + mbox_wkup_r5_0: mbox-wkup-r5-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; +}; + +&mailbox0_cluster1 { + status = "okay"; + + mbox_mcu_r5_0: mbox-mcu-r5-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; +}; + +&mailbox0_cluster2 { + status = "okay"; + + mbox_c7x_0: mbox-c7x-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; +}; + +&mailbox0_cluster3 { + status = "okay"; + + mbox_main_r5_0: mbox-main-r5-0 { + ti,mbox-rx = <0 0 0>; + ti,mbox-tx = <1 0 0>; + }; + + mbox_c7x_1: mbox-c7x-1 { + ti,mbox-rx = <2 0 0>; + ti,mbox-tx = <3 0 0>; + }; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&wkup_r5fss0 { + status = "okay"; +}; + +&wkup_r5fss0_core0 { + mboxes = <&mailbox0_cluster0 &mbox_wkup_r5_0>; + memory-region = <&wkup_r5fss0_core0_dma_memory_region>, + <&wkup_r5fss0_core0_memory_region>; +}; + +&mcu_r5fss0 { + status = "okay"; +}; + +&mcu_r5fss0_core0 { + mboxes = <&mailbox0_cluster1 &mbox_mcu_r5_0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; +}; + +&main_r5fss0 { + status = "okay"; +}; + +&main_r5fss0_core0 { + mboxes = <&mailbox0_cluster3 &mbox_main_r5_0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; +}; + +&c7x_0 { + mboxes = <&mailbox0_cluster2 &mbox_c7x_0>; + memory-region = <&c7x_0_dma_memory_region>, + <&c7x_0_memory_region>; + status = "okay"; +}; + +&c7x_1 { + mboxes = <&mailbox0_cluster3 &mbox_c7x_1>; + memory-region = <&c7x_1_dma_memory_region>, + <&c7x_1_memory_region>; + status = "okay"; +}; + &serdes_ln_ctrl { idle-states = <J722S_SERDES0_LANE0_USB>, <J722S_SERDES1_LANE0_PCIE0_LANE0>; @@ -566,3 +787,28 @@ 0 0 0 0 >; }; + +&mcu_mcan0 { + pinctrl-names = "default"; + pinctrl-0 = <&mcu_mcan0_pins_default>; + phys = <&transceiver0>; + status = "okay"; +}; + +&mcu_mcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&mcu_mcan1_pins_default>; + phys = <&transceiver1>; + status = "okay"; +}; + +&main_mcan0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_mcan0_pins_default>; + phys = <&transceiver2>; + status = "okay"; +}; + +&mcu_gpio0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi index dde4bd5c6645..ed6f4ba08afc 100644 --- a/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j722s-main.dtsi @@ -153,6 +153,67 @@ dr_mode = "otg"; }; }; + + main_r5fss0: r5fss@78400000 { + compatible = "ti,am62-r5fss"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x78400000 0x00 0x78400000 0x8000>, + <0x78500000 0x00 0x78500000 0x8000>; + power-domains = <&k3_pds 261 TI_SCI_PD_EXCLUSIVE>; + status = "disabled"; + + main_r5fss0_core0: r5f@78400000 { + compatible = "ti,am62-r5f"; + reg = <0x78400000 0x00008000>, + <0x78500000 0x00008000>; + reg-names = "atcm", "btcm"; + resets = <&k3_reset 262 1>; + firmware-name = "j722s-main-r5f0_0-fw"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <262>; + ti,sci-proc-ids = <0x04 0xff>; + ti,atcm-enable = <1>; + ti,btcm-enable = <1>; + ti,loczrama = <1>; + }; + }; + + c7x_0: dsp@7e000000 { + compatible = "ti,am62a-c7xv-dsp"; + reg = <0x00 0x7e000000 0x00 0x00200000>; + reg-names = "l2sram"; + resets = <&k3_reset 208 1>; + firmware-name = "j722s-c71_0-fw"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <208>; + ti,sci-proc-ids = <0x30 0xff>; + status = "disabled"; + }; + + c7x_1: dsp@7e200000 { + compatible = "ti,am62a-c7xv-dsp"; + reg = <0x00 0x7e200000 0x00 0x00200000>; + reg-names = "l2sram"; + resets = <&k3_reset 268 1>; + firmware-name = "j722s-c71_1-fw"; + ti,sci = <&dmsc>; + ti,sci-dev-id = <268>; + ti,sci-proc-ids = <0x31 0xff>; + status = "disabled"; + }; +}; + +/* MCU domain overrides */ + +&mcu_r5fss0_core0 { + firmware-name = "j722s-mcu-r5f0_0-fw"; +}; + +/* Wakeup domain overrides */ + +&wkup_r5fss0_core0 { + firmware-name = "j722s-wkup-r5f0_0-fw"; }; &main_conf { @@ -214,5 +275,6 @@ &main_gpio1 { gpio-ranges = <&main_pmx0 7 101 25>, <&main_pmx0 42 137 5>, <&main_pmx0 47 143 3>, <&main_pmx0 50 149 2>; + gpio-reserved-ranges = <0 7>, <32 10>; ti,ngpio = <73>; }; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts index ffa38f41679d..6695ebbcb4d0 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts +++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts @@ -1154,6 +1154,59 @@ <&mcu_r5fss0_core1_memory_region>; }; +&main_r5fss0 { + ti,cluster-mode = <0>; +}; + +&main_r5fss1 { + ti,cluster-mode = <0>; +}; + +&main_r5fss2 { + ti,cluster-mode = <0>; +}; + +/* Timers are used by Remoteproc firmware */ +&main_timer0 { + status = "reserved"; +}; + +&main_timer1 { + status = "reserved"; +}; + +&main_timer2 { + status = "reserved"; +}; + +&main_timer3 { + status = "reserved"; +}; + +&main_timer4 { + status = "reserved"; +}; + +&main_timer5 { + status = "reserved"; +}; + +&main_timer6 { + status = "reserved"; +}; + +&main_timer7 { + status = "reserved"; +}; + +&main_timer8 { + status = "reserved"; +}; + +&main_timer9 { + status = "reserved"; +}; + &main_r5fss0_core0 { status = "okay"; mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; @@ -1407,10 +1460,11 @@ serdes1_pcie0_link: phy@0 { reg = <0>; - cdns,num-lanes = <2>; + cdns,num-lanes = <4>; #phy-cells = <0>; cdns,phy-type = <PHY_TYPE_PCIE>; - resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>; + resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>, + <&serdes_wiz1 3>, <&serdes_wiz1 4>; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi index d4ac1c9872a5..e73bb750b09a 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi @@ -2429,7 +2429,7 @@ watchdog0: watchdog@2200000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2200000 0x00 0x100>; - clocks = <&k3_clks 348 1>; + clocks = <&k3_clks 348 0>; power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 348 0>; assigned-clock-parents = <&k3_clks 348 4>; @@ -2438,7 +2438,7 @@ watchdog1: watchdog@2210000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2210000 0x00 0x100>; - clocks = <&k3_clks 349 1>; + clocks = <&k3_clks 349 0>; power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 349 0>; assigned-clock-parents = <&k3_clks 349 4>; @@ -2447,7 +2447,7 @@ watchdog2: watchdog@2220000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2220000 0x00 0x100>; - clocks = <&k3_clks 350 1>; + clocks = <&k3_clks 350 0>; power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 350 0>; assigned-clock-parents = <&k3_clks 350 4>; @@ -2456,7 +2456,7 @@ watchdog3: watchdog@2230000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2230000 0x00 0x100>; - clocks = <&k3_clks 351 1>; + clocks = <&k3_clks 351 0>; power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 351 0>; assigned-clock-parents = <&k3_clks 351 4>; @@ -2465,7 +2465,7 @@ watchdog4: watchdog@2240000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2240000 0x00 0x100>; - clocks = <&k3_clks 352 1>; + clocks = <&k3_clks 352 0>; power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 352 0>; assigned-clock-parents = <&k3_clks 352 4>; @@ -2474,7 +2474,7 @@ watchdog5: watchdog@2250000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2250000 0x00 0x100>; - clocks = <&k3_clks 353 1>; + clocks = <&k3_clks 353 0>; power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 353 0>; assigned-clock-parents = <&k3_clks 353 4>; @@ -2483,7 +2483,7 @@ watchdog6: watchdog@2260000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2260000 0x00 0x100>; - clocks = <&k3_clks 354 1>; + clocks = <&k3_clks 354 0>; power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 354 0>; assigned-clock-parents = <&k3_clks 354 4>; @@ -2492,7 +2492,7 @@ watchdog7: watchdog@2270000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2270000 0x00 0x100>; - clocks = <&k3_clks 355 1>; + clocks = <&k3_clks 355 0>; power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 355 0>; assigned-clock-parents = <&k3_clks 355 4>; @@ -2506,7 +2506,7 @@ watchdog8: watchdog@22f0000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x22f0000 0x00 0x100>; - clocks = <&k3_clks 360 1>; + clocks = <&k3_clks 360 0>; power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 360 0>; assigned-clock-parents = <&k3_clks 360 4>; @@ -2517,7 +2517,7 @@ watchdog9: watchdog@2300000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2300000 0x00 0x100>; - clocks = <&k3_clks 356 1>; + clocks = <&k3_clks 356 0>; power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 356 0>; assigned-clock-parents = <&k3_clks 356 4>; @@ -2528,7 +2528,7 @@ watchdog10: watchdog@2310000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2310000 0x00 0x100>; - clocks = <&k3_clks 357 1>; + clocks = <&k3_clks 357 0>; power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 357 0>; assigned-clock-parents = <&k3_clks 357 4>; @@ -2539,7 +2539,7 @@ watchdog11: watchdog@2320000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2320000 0x00 0x100>; - clocks = <&k3_clks 358 1>; + clocks = <&k3_clks 358 0>; power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 358 0>; assigned-clock-parents = <&k3_clks 358 4>; @@ -2550,7 +2550,7 @@ watchdog12: watchdog@2330000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2330000 0x00 0x100>; - clocks = <&k3_clks 359 1>; + clocks = <&k3_clks 359 0>; power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 359 0>; assigned-clock-parents = <&k3_clks 359 4>; @@ -2561,7 +2561,7 @@ watchdog13: watchdog@23c0000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x23c0000 0x00 0x100>; - clocks = <&k3_clks 361 1>; + clocks = <&k3_clks 361 0>; power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 361 0>; assigned-clock-parents = <&k3_clks 361 4>; @@ -2572,7 +2572,7 @@ watchdog14: watchdog@23d0000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x23d0000 0x00 0x100>; - clocks = <&k3_clks 362 1>; + clocks = <&k3_clks 362 0>; power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 362 0>; assigned-clock-parents = <&k3_clks 362 4>; @@ -2583,7 +2583,7 @@ watchdog15: watchdog@23e0000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x23e0000 0x00 0x100>; - clocks = <&k3_clks 363 1>; + clocks = <&k3_clks 363 0>; power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 363 0>; assigned-clock-parents = <&k3_clks 363 4>; @@ -2594,7 +2594,7 @@ watchdog16: watchdog@23f0000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x23f0000 0x00 0x100>; - clocks = <&k3_clks 364 1>; + clocks = <&k3_clks 364 0>; power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 364 0>; assigned-clock-parents = <&k3_clks 364 4>; @@ -2605,7 +2605,7 @@ watchdog17: watchdog@2540000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2540000 0x00 0x100>; - clocks = <&k3_clks 365 1>; + clocks = <&k3_clks 365 0>; power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 365 0>; assigned-clock-parents = <&k3_clks 366 4>; @@ -2616,7 +2616,7 @@ watchdog18: watchdog@2550000 { compatible = "ti,j7-rti-wdt"; reg = <0x00 0x2550000 0x00 0x100>; - clocks = <&k3_clks 366 1>; + clocks = <&k3_clks 366 0>; power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>; assigned-clocks = <&k3_clks 366 0>; assigned-clock-parents = <&k3_clks 366 4>; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi index f3a6ed1c979d..f603380fc91c 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi @@ -678,16 +678,16 @@ compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; - ranges = <0x0 0x47000000 0x0 0x47000000 0x0 0x100>, /* FSS Control */ - <0x0 0x47040000 0x0 0x47040000 0x0 0x100>, /* OSPI0 Control */ - <0x0 0x47050000 0x0 0x47050000 0x0 0x100>, /* OSPI1 Control */ - <0x5 0x00000000 0x5 0x00000000 0x1 0x0000000>, /* OSPI0 Memory */ - <0x7 0x00000000 0x7 0x00000000 0x1 0x0000000>; /* OSPI1 Memory */ + ranges = <0x00 0x47000000 0x00 0x47000000 0x00 0x00000100>, /* FSS Control */ + <0x00 0x47040000 0x00 0x47040000 0x00 0x00000100>, /* OSPI0 Control */ + <0x00 0x47050000 0x00 0x47050000 0x00 0x00000100>, /* OSPI1 Control */ + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */ + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */ ospi0: spi@47040000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x00 0x47040000 0x00 0x100>, - <0x05 0x0000000 0x01 0x0000000>; + <0x05 0x00000000 0x01 0x00000000>; interrupts = <GIC_SPI 840 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; @@ -705,7 +705,7 @@ ospi1: spi@47050000 { compatible = "ti,am654-ospi", "cdns,qspi-nor"; reg = <0x00 0x47050000 0x00 0x100>, - <0x07 0x0000000 0x01 0x0000000>; + <0x07 0x00000000 0x01 0x00000000>; interrupts = <GIC_SPI 841 IRQ_TYPE_LEVEL_HIGH>; cdns,fifo-depth = <256>; cdns,fifo-width = <4>; diff --git a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi index 73cc3c1fec08..5e84c6b4f5ad 100644 --- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi @@ -271,8 +271,7 @@ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; cbass_mcu_wakeup: bus@28380000 { bootph-all; @@ -289,9 +288,8 @@ <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */ <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */ <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */ - <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS OSPI0/1 data region 0 */ - <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS OSPI0 data region 3 */ - <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/ + <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS data region 1 */ + <0x04 0x00000000 0x04 0x00000000 0x04 0x00000000>; /* FSS data region 0/3 */ }; }; diff --git a/arch/arm64/boot/dts/toshiba/tmpv7708.dtsi b/arch/arm64/boot/dts/toshiba/tmpv7708.dtsi index b04829b3175d..39806f0ae513 100644 --- a/arch/arm64/boot/dts/toshiba/tmpv7708.dtsi +++ b/arch/arm64/boot/dts/toshiba/tmpv7708.dtsi @@ -196,8 +196,8 @@ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&uart0_pins>; - clocks = <&pismu TMPV770X_CLK_PIUART0>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PIUART0>, <&pismu TMPV770X_CLK_PIUART0>; + clock-names = "uartclk", "apb_pclk"; status = "disabled"; }; @@ -207,8 +207,8 @@ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&uart1_pins>; - clocks = <&pismu TMPV770X_CLK_PIUART1>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PIUART1>, <&pismu TMPV770X_CLK_PIUART1>; + clock-names = "uartclk", "apb_pclk"; status = "disabled"; }; @@ -218,8 +218,8 @@ interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; - clocks = <&pismu TMPV770X_CLK_PIUART2>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PIUART2>, <&pismu TMPV770X_CLK_PIUART2>; + clock-names = "uartclk", "apb_pclk"; status = "disabled"; }; @@ -229,8 +229,8 @@ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; - clocks = <&pismu TMPV770X_CLK_PIUART2>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PIUART2>, <&pismu TMPV770X_CLK_PIUART2>; + clock-names = "uartclk", "apb_pclk"; status = "disabled"; }; @@ -360,8 +360,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI1>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI1>, <&pismu TMPV770X_CLK_PISPI1>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -374,8 +374,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI1>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI1>, <&pismu TMPV770X_CLK_PISPI1>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -388,8 +388,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI2>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI2>, <&pismu TMPV770X_CLK_PISPI2>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -402,8 +402,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI3>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI3>, <&pismu TMPV770X_CLK_PISPI3>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -416,8 +416,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI4>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI4>, <&pismu TMPV770X_CLK_PISPI4>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -430,8 +430,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI5>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI5>, <&pismu TMPV770X_CLK_PISPI5>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; @@ -444,8 +444,8 @@ num-cs = <1>; #address-cells = <1>; #size-cells = <0>; - clocks = <&pismu TMPV770X_CLK_PISPI6>; - clock-names = "apb_pclk"; + clocks = <&pismu TMPV770X_CLK_PISPI6>, <&pismu TMPV770X_CLK_PISPI6>; + clock-names = "sspclk", "apb_pclk"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts index ad8f23a0ec67..d2175f3dd099 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts @@ -941,6 +941,7 @@ &pcie { status = "okay"; + phys = <&psgtr 0 PHY_TYPE_PCIE 0 0>; }; &psgtr { diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7d32fca64996..5fdbfea7a5b2 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -232,6 +232,7 @@ CONFIG_PCIE_KIRIN=y CONFIG_PCIE_HISI_STB=y CONFIG_PCIE_ARMADA_8K=y CONFIG_PCIE_TEGRA194_HOST=m +CONFIG_PCIE_TEGRA194_EP=m CONFIG_PCIE_QCOM=y CONFIG_PCIE_RCAR_GEN4_HOST=m CONFIG_PCIE_RCAR_GEN4_EP=m @@ -366,6 +367,7 @@ CONFIG_R8169=m CONFIG_SH_ETH=y CONFIG_RAVB=y CONFIG_RENESAS_ETHER_SWITCH=y +CONFIG_RTSN=y CONFIG_SMC91X=y CONFIG_SMSC911X=y CONFIG_SNI_AVE=y @@ -516,6 +518,7 @@ CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_BCM2835=m CONFIG_I2C_CADENCE=m +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_GPIO=m CONFIG_I2C_IMX=y @@ -655,6 +658,7 @@ CONFIG_GPIO_XGENE_SB=y CONFIG_GPIO_MAX732X=y CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GPIO_ADP5585=m CONFIG_GPIO_BD9571MWV=m CONFIG_GPIO_MAX77620=y CONFIG_GPIO_SL28CPLD=m @@ -736,6 +740,7 @@ CONFIG_UNIPHIER_WATCHDOG=y CONFIG_PM8916_WATCHDOG=m CONFIG_BCM2835_WDT=y CONFIG_BCM7038_WDT=m +CONFIG_MFD_ADP5585=m CONFIG_MFD_ALTERA_SYSMGR=y CONFIG_MFD_BD9571MWV=y CONFIG_MFD_AXP20X_I2C=y @@ -785,6 +790,7 @@ CONFIG_REGULATOR_PCA9450=y CONFIG_REGULATOR_PF8X00=y CONFIG_REGULATOR_PFUZE100=y CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_QCOM_REFGEN=m CONFIG_REGULATOR_QCOM_RPMH=y CONFIG_REGULATOR_QCOM_SMD_RPM=y CONFIG_REGULATOR_QCOM_SPMI=y @@ -820,6 +826,7 @@ CONFIG_VIDEO_CADENCE_CSI2RX=m CONFIG_VIDEO_MEDIATEK_JPEG=m CONFIG_VIDEO_MEDIATEK_VCODEC=m CONFIG_VIDEO_WAVE_VPU=m +CONFIG_VIDEO_E5010_JPEG_ENC=m CONFIG_VIDEO_IMX7_CSI=m CONFIG_VIDEO_IMX_MIPI_CSIS=m CONFIG_VIDEO_IMX8_ISI=m @@ -887,6 +894,7 @@ CONFIG_DRM_PANEL_KHADAS_TS050=m CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m CONFIG_DRM_PANEL_NOVATEK_NT36672E=m CONFIG_DRM_PANEL_RAYDIUM_RM67191=m +CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20=m CONFIG_DRM_PANEL_SITRONIX_ST7703=m CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m CONFIG_DRM_PANEL_VISIONOX_VTDR6130=m @@ -960,6 +968,8 @@ CONFIG_SND_SOC_MT8192=m CONFIG_SND_SOC_MT8192_MT6359_RT1015_RT5682=m CONFIG_SND_SOC_MT8195=m CONFIG_SND_SOC_MT8195_MT6359=m +CONFIG_SND_SOC_MT8365=m +CONFIG_SND_SOC_MT8365_MT6357=m CONFIG_SND_MESON_AXG_SOUND_CARD=m CONFIG_SND_MESON_GX_SOUND_CARD=m CONFIG_SND_SOC_QCOM=m @@ -1005,6 +1015,7 @@ CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m CONFIG_SND_SOC_DAVINCI_MCASP=m CONFIG_SND_SOC_J721E_EVM=m CONFIG_SND_SOC_AK4613=m +CONFIG_SND_SOC_AK4619=m CONFIG_SND_SOC_DA7213=m CONFIG_SND_SOC_ES7134=m CONFIG_SND_SOC_ES7241=m @@ -1484,6 +1495,7 @@ CONFIG_IIO_ST_MAGN_3AXIS=m CONFIG_IIO_CROS_EC_BARO=m CONFIG_MPL3115=m CONFIG_PWM=y +CONFIG_PWM_ADP5585=m CONFIG_PWM_BCM2835=m CONFIG_PWM_BRCMSTB=m CONFIG_PWM_CROS_EC=m diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c index ce9b28e3c7d6..a523b519700f 100644 --- a/arch/arm64/crypto/aes-ce-ccm-glue.c +++ b/arch/arm64/crypto/aes-ce-ccm-glue.c @@ -9,7 +9,7 @@ */ #include <asm/neon.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/aes.h> #include <crypto/scatterwalk.h> #include <crypto/internal/aead.h> diff --git a/arch/arm64/crypto/aes-ce-glue.c b/arch/arm64/crypto/aes-ce-glue.c index e921823ca103..00b8749013c5 100644 --- a/arch/arm64/crypto/aes-ce-glue.c +++ b/arch/arm64/crypto/aes-ce-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/aes.h> #include <crypto/algapi.h> #include <crypto/internal/simd.h> diff --git a/arch/arm64/crypto/crct10dif-ce-core.S b/arch/arm64/crypto/crct10dif-ce-core.S index 5604de61d06d..87dd6d46224d 100644 --- a/arch/arm64/crypto/crct10dif-ce-core.S +++ b/arch/arm64/crypto/crct10dif-ce-core.S @@ -1,8 +1,11 @@ // // Accelerated CRC-T10DIF using arm64 NEON and Crypto Extensions instructions // -// Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org> -// Copyright (C) 2019 Google LLC <ebiggers@google.com> +// Copyright (C) 2016 Linaro Ltd +// Copyright (C) 2019-2024 Google LLC +// +// Authors: Ard Biesheuvel <ardb@google.com> +// Eric Biggers <ebiggers@google.com> // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -71,161 +74,117 @@ init_crc .req w0 buf .req x1 len .req x2 - fold_consts_ptr .req x3 + fold_consts_ptr .req x5 fold_consts .req v10 - ad .req v14 - - k00_16 .req v15 - k32_48 .req v16 - t3 .req v17 t4 .req v18 t5 .req v19 t6 .req v20 t7 .req v21 t8 .req v22 - t9 .req v23 - perm1 .req v24 - perm2 .req v25 - perm3 .req v26 - perm4 .req v27 - - bd1 .req v28 - bd2 .req v29 - bd3 .req v30 - bd4 .req v31 - - .macro __pmull_init_p64 - .endm + perm .req v27 - .macro __pmull_pre_p64, bd + .macro pmull16x64_p64, a16, b64, c64 + pmull2 \c64\().1q, \a16\().2d, \b64\().2d + pmull \b64\().1q, \a16\().1d, \b64\().1d .endm - .macro __pmull_init_p8 - // k00_16 := 0x0000000000000000_000000000000ffff - // k32_48 := 0x00000000ffffffff_0000ffffffffffff - movi k32_48.2d, #0xffffffff - mov k32_48.h[2], k32_48.h[0] - ushr k00_16.2d, k32_48.2d, #32 - - // prepare the permutation vectors - mov_q x5, 0x080f0e0d0c0b0a09 - movi perm4.8b, #8 - dup perm1.2d, x5 - eor perm1.16b, perm1.16b, perm4.16b - ushr perm2.2d, perm1.2d, #8 - ushr perm3.2d, perm1.2d, #16 - ushr perm4.2d, perm1.2d, #24 - sli perm2.2d, perm1.2d, #56 - sli perm3.2d, perm1.2d, #48 - sli perm4.2d, perm1.2d, #40 + /* + * Pairwise long polynomial multiplication of two 16-bit values + * + * { w0, w1 }, { y0, y1 } + * + * by two 64-bit values + * + * { x0, x1, x2, x3, x4, x5, x6, x7 }, { z0, z1, z2, z3, z4, z5, z6, z7 } + * + * where each vector element is a byte, ordered from least to most + * significant. + * + * This can be implemented using 8x8 long polynomial multiplication, by + * reorganizing the input so that each pairwise 8x8 multiplication + * produces one of the terms from the decomposition below, and + * combining the results of each rank and shifting them into place. + * + * Rank + * 0 w0*x0 ^ | y0*z0 ^ + * 1 (w0*x1 ^ w1*x0) << 8 ^ | (y0*z1 ^ y1*z0) << 8 ^ + * 2 (w0*x2 ^ w1*x1) << 16 ^ | (y0*z2 ^ y1*z1) << 16 ^ + * 3 (w0*x3 ^ w1*x2) << 24 ^ | (y0*z3 ^ y1*z2) << 24 ^ + * 4 (w0*x4 ^ w1*x3) << 32 ^ | (y0*z4 ^ y1*z3) << 32 ^ + * 5 (w0*x5 ^ w1*x4) << 40 ^ | (y0*z5 ^ y1*z4) << 40 ^ + * 6 (w0*x6 ^ w1*x5) << 48 ^ | (y0*z6 ^ y1*z5) << 48 ^ + * 7 (w0*x7 ^ w1*x6) << 56 ^ | (y0*z7 ^ y1*z6) << 56 ^ + * 8 w1*x7 << 64 | y1*z7 << 64 + * + * The inputs can be reorganized into + * + * { w0, w0, w0, w0, y0, y0, y0, y0 }, { w1, w1, w1, w1, y1, y1, y1, y1 } + * { x0, x2, x4, x6, z0, z2, z4, z6 }, { x1, x3, x5, x7, z1, z3, z5, z7 } + * + * and after performing 8x8->16 bit long polynomial multiplication of + * each of the halves of the first vector with those of the second one, + * we obtain the following four vectors of 16-bit elements: + * + * a := { w0*x0, w0*x2, w0*x4, w0*x6 }, { y0*z0, y0*z2, y0*z4, y0*z6 } + * b := { w0*x1, w0*x3, w0*x5, w0*x7 }, { y0*z1, y0*z3, y0*z5, y0*z7 } + * c := { w1*x0, w1*x2, w1*x4, w1*x6 }, { y1*z0, y1*z2, y1*z4, y1*z6 } + * d := { w1*x1, w1*x3, w1*x5, w1*x7 }, { y1*z1, y1*z3, y1*z5, y1*z7 } + * + * Results b and c can be XORed together, as the vector elements have + * matching ranks. Then, the final XOR (*) can be pulled forward, and + * applied between the halves of each of the remaining three vectors, + * which are then shifted into place, and combined to produce two + * 80-bit results. + * + * (*) NOTE: the 16x64 bit polynomial multiply below is not equivalent + * to the 64x64 bit one above, but XOR'ing the outputs together will + * produce the expected result, and this is sufficient in the context of + * this algorithm. + */ + .macro pmull16x64_p8, a16, b64, c64 + ext t7.16b, \b64\().16b, \b64\().16b, #1 + tbl t5.16b, {\a16\().16b}, perm.16b + uzp1 t7.16b, \b64\().16b, t7.16b + bl __pmull_p8_16x64 + ext \b64\().16b, t4.16b, t4.16b, #15 + eor \c64\().16b, t8.16b, t5.16b .endm - .macro __pmull_pre_p8, bd - tbl bd1.16b, {\bd\().16b}, perm1.16b - tbl bd2.16b, {\bd\().16b}, perm2.16b - tbl bd3.16b, {\bd\().16b}, perm3.16b - tbl bd4.16b, {\bd\().16b}, perm4.16b - .endm - -SYM_FUNC_START_LOCAL(__pmull_p8_core) -.L__pmull_p8_core: - ext t4.8b, ad.8b, ad.8b, #1 // A1 - ext t5.8b, ad.8b, ad.8b, #2 // A2 - ext t6.8b, ad.8b, ad.8b, #3 // A3 - - pmull t4.8h, t4.8b, fold_consts.8b // F = A1*B - pmull t8.8h, ad.8b, bd1.8b // E = A*B1 - pmull t5.8h, t5.8b, fold_consts.8b // H = A2*B - pmull t7.8h, ad.8b, bd2.8b // G = A*B2 - pmull t6.8h, t6.8b, fold_consts.8b // J = A3*B - pmull t9.8h, ad.8b, bd3.8b // I = A*B3 - pmull t3.8h, ad.8b, bd4.8b // K = A*B4 - b 0f - -.L__pmull_p8_core2: - tbl t4.16b, {ad.16b}, perm1.16b // A1 - tbl t5.16b, {ad.16b}, perm2.16b // A2 - tbl t6.16b, {ad.16b}, perm3.16b // A3 - - pmull2 t4.8h, t4.16b, fold_consts.16b // F = A1*B - pmull2 t8.8h, ad.16b, bd1.16b // E = A*B1 - pmull2 t5.8h, t5.16b, fold_consts.16b // H = A2*B - pmull2 t7.8h, ad.16b, bd2.16b // G = A*B2 - pmull2 t6.8h, t6.16b, fold_consts.16b // J = A3*B - pmull2 t9.8h, ad.16b, bd3.16b // I = A*B3 - pmull2 t3.8h, ad.16b, bd4.16b // K = A*B4 - -0: eor t4.16b, t4.16b, t8.16b // L = E + F - eor t5.16b, t5.16b, t7.16b // M = G + H - eor t6.16b, t6.16b, t9.16b // N = I + J - - uzp1 t8.2d, t4.2d, t5.2d - uzp2 t4.2d, t4.2d, t5.2d - uzp1 t7.2d, t6.2d, t3.2d - uzp2 t6.2d, t6.2d, t3.2d - - // t4 = (L) (P0 + P1) << 8 - // t5 = (M) (P2 + P3) << 16 - eor t8.16b, t8.16b, t4.16b - and t4.16b, t4.16b, k32_48.16b - - // t6 = (N) (P4 + P5) << 24 - // t7 = (K) (P6 + P7) << 32 - eor t7.16b, t7.16b, t6.16b - and t6.16b, t6.16b, k00_16.16b - - eor t8.16b, t8.16b, t4.16b - eor t7.16b, t7.16b, t6.16b - - zip2 t5.2d, t8.2d, t4.2d - zip1 t4.2d, t8.2d, t4.2d - zip2 t3.2d, t7.2d, t6.2d - zip1 t6.2d, t7.2d, t6.2d - - ext t4.16b, t4.16b, t4.16b, #15 +SYM_FUNC_START_LOCAL(__pmull_p8_16x64) + ext t6.16b, t5.16b, t5.16b, #8 + + pmull t3.8h, t7.8b, t5.8b + pmull t4.8h, t7.8b, t6.8b + pmull2 t5.8h, t7.16b, t5.16b + pmull2 t6.8h, t7.16b, t6.16b + + ext t8.16b, t3.16b, t3.16b, #8 + eor t4.16b, t4.16b, t6.16b + ext t7.16b, t5.16b, t5.16b, #8 + ext t6.16b, t4.16b, t4.16b, #8 + eor t8.8b, t8.8b, t3.8b + eor t5.8b, t5.8b, t7.8b + eor t4.8b, t4.8b, t6.8b ext t5.16b, t5.16b, t5.16b, #14 - ext t6.16b, t6.16b, t6.16b, #13 - ext t3.16b, t3.16b, t3.16b, #12 - - eor t4.16b, t4.16b, t5.16b - eor t6.16b, t6.16b, t3.16b ret -SYM_FUNC_END(__pmull_p8_core) +SYM_FUNC_END(__pmull_p8_16x64) - .macro __pmull_p8, rq, ad, bd, i - .ifnc \bd, fold_consts - .err - .endif - mov ad.16b, \ad\().16b - .ifb \i - pmull \rq\().8h, \ad\().8b, \bd\().8b // D = A*B - .else - pmull2 \rq\().8h, \ad\().16b, \bd\().16b // D = A*B - .endif - - bl .L__pmull_p8_core\i - - eor \rq\().16b, \rq\().16b, t4.16b - eor \rq\().16b, \rq\().16b, t6.16b - .endm // Fold reg1, reg2 into the next 32 data bytes, storing the result back // into reg1, reg2. .macro fold_32_bytes, p, reg1, reg2 ldp q11, q12, [buf], #0x20 - __pmull_\p v8, \reg1, fold_consts, 2 - __pmull_\p \reg1, \reg1, fold_consts + pmull16x64_\p fold_consts, \reg1, v8 CPU_LE( rev64 v11.16b, v11.16b ) CPU_LE( rev64 v12.16b, v12.16b ) - __pmull_\p v9, \reg2, fold_consts, 2 - __pmull_\p \reg2, \reg2, fold_consts + pmull16x64_\p fold_consts, \reg2, v9 CPU_LE( ext v11.16b, v11.16b, v11.16b, #8 ) CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 ) @@ -238,26 +197,15 @@ CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 ) // Fold src_reg into dst_reg, optionally loading the next fold constants .macro fold_16_bytes, p, src_reg, dst_reg, load_next_consts - __pmull_\p v8, \src_reg, fold_consts - __pmull_\p \src_reg, \src_reg, fold_consts, 2 + pmull16x64_\p fold_consts, \src_reg, v8 .ifnb \load_next_consts ld1 {fold_consts.2d}, [fold_consts_ptr], #16 - __pmull_pre_\p fold_consts .endif eor \dst_reg\().16b, \dst_reg\().16b, v8.16b eor \dst_reg\().16b, \dst_reg\().16b, \src_reg\().16b .endm - .macro __pmull_p64, rd, rn, rm, n - .ifb \n - pmull \rd\().1q, \rn\().1d, \rm\().1d - .else - pmull2 \rd\().1q, \rn\().2d, \rm\().2d - .endif - .endm - .macro crc_t10dif_pmull, p - __pmull_init_\p // For sizes less than 256 bytes, we can't fold 128 bytes at a time. cmp len, #256 @@ -296,7 +244,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // Load the constants for folding across 128 bytes. ld1 {fold_consts.2d}, [fold_consts_ptr] - __pmull_pre_\p fold_consts // Subtract 128 for the 128 data bytes just consumed. Subtract another // 128 to simplify the termination condition of the following loop. @@ -318,7 +265,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // Fold across 64 bytes. add fold_consts_ptr, fold_consts_ptr, #16 ld1 {fold_consts.2d}, [fold_consts_ptr], #16 - __pmull_pre_\p fold_consts fold_16_bytes \p, v0, v4 fold_16_bytes \p, v1, v5 fold_16_bytes \p, v2, v6 @@ -339,8 +285,7 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // into them, storing the result back into v7. b.lt .Lfold_16_bytes_loop_done_\@ .Lfold_16_bytes_loop_\@: - __pmull_\p v8, v7, fold_consts - __pmull_\p v7, v7, fold_consts, 2 + pmull16x64_\p fold_consts, v7, v8 eor v7.16b, v7.16b, v8.16b ldr q0, [buf], #16 CPU_LE( rev64 v0.16b, v0.16b ) @@ -387,51 +332,10 @@ CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 ) bsl v2.16b, v1.16b, v0.16b // Fold the first chunk into the second chunk, storing the result in v7. - __pmull_\p v0, v3, fold_consts - __pmull_\p v7, v3, fold_consts, 2 - eor v7.16b, v7.16b, v0.16b + pmull16x64_\p fold_consts, v3, v0 + eor v7.16b, v3.16b, v0.16b eor v7.16b, v7.16b, v2.16b - -.Lreduce_final_16_bytes_\@: - // Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC. - - movi v2.16b, #0 // init zero register - - // Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'. - ld1 {fold_consts.2d}, [fold_consts_ptr], #16 - __pmull_pre_\p fold_consts - - // Fold the high 64 bits into the low 64 bits, while also multiplying by - // x^64. This produces a 128-bit value congruent to x^64 * M(x) and - // whose low 48 bits are 0. - ext v0.16b, v2.16b, v7.16b, #8 - __pmull_\p v7, v7, fold_consts, 2 // high bits * x^48 * (x^80 mod G(x)) - eor v0.16b, v0.16b, v7.16b // + low bits * x^64 - - // Fold the high 32 bits into the low 96 bits. This produces a 96-bit - // value congruent to x^64 * M(x) and whose low 48 bits are 0. - ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits - mov v0.s[3], v2.s[0] // zero high 32 bits - __pmull_\p v1, v1, fold_consts // high 32 bits * x^48 * (x^48 mod G(x)) - eor v0.16b, v0.16b, v1.16b // + low bits - - // Load G(x) and floor(x^48 / G(x)). - ld1 {fold_consts.2d}, [fold_consts_ptr] - __pmull_pre_\p fold_consts - - // Use Barrett reduction to compute the final CRC value. - __pmull_\p v1, v0, fold_consts, 2 // high 32 bits * floor(x^48 / G(x)) - ushr v1.2d, v1.2d, #32 // /= x^32 - __pmull_\p v1, v1, fold_consts // *= G(x) - ushr v0.2d, v0.2d, #48 - eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits - // Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0. - - umov w0, v0.h[0] - .ifc \p, p8 - frame_pop - .endif - ret + b .Lreduce_final_16_bytes_\@ .Lless_than_256_bytes_\@: // Checksumming a buffer of length 16...255 bytes @@ -450,7 +354,6 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // Load the fold-across-16-bytes constants. ld1 {fold_consts.2d}, [fold_consts_ptr], #16 - __pmull_pre_\p fold_consts cmp len, #16 b.eq .Lreduce_final_16_bytes_\@ // len == 16 @@ -458,6 +361,8 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) b.ge .Lfold_16_bytes_loop_\@ // 32 <= len <= 255 add len, len, #16 b .Lhandle_partial_segment_\@ // 17 <= len <= 31 + +.Lreduce_final_16_bytes_\@: .endm // @@ -467,7 +372,22 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // SYM_FUNC_START(crc_t10dif_pmull_p8) frame_push 1 + + // Compose { 0,0,0,0, 8,8,8,8, 1,1,1,1, 9,9,9,9 } + movi perm.4h, #8, lsl #8 + orr perm.2s, #1, lsl #16 + orr perm.2s, #1, lsl #24 + zip1 perm.16b, perm.16b, perm.16b + zip1 perm.16b, perm.16b, perm.16b + crc_t10dif_pmull p8 + +CPU_LE( rev64 v7.16b, v7.16b ) +CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) + str q7, [x3] + + frame_pop + ret SYM_FUNC_END(crc_t10dif_pmull_p8) .align 5 @@ -478,6 +398,41 @@ SYM_FUNC_END(crc_t10dif_pmull_p8) // SYM_FUNC_START(crc_t10dif_pmull_p64) crc_t10dif_pmull p64 + + // Reduce the 128-bit value M(x), stored in v7, to the final 16-bit CRC. + + movi v2.16b, #0 // init zero register + + // Load 'x^48 * (x^48 mod G(x))' and 'x^48 * (x^80 mod G(x))'. + ld1 {fold_consts.2d}, [fold_consts_ptr], #16 + + // Fold the high 64 bits into the low 64 bits, while also multiplying by + // x^64. This produces a 128-bit value congruent to x^64 * M(x) and + // whose low 48 bits are 0. + ext v0.16b, v2.16b, v7.16b, #8 + pmull2 v7.1q, v7.2d, fold_consts.2d // high bits * x^48 * (x^80 mod G(x)) + eor v0.16b, v0.16b, v7.16b // + low bits * x^64 + + // Fold the high 32 bits into the low 96 bits. This produces a 96-bit + // value congruent to x^64 * M(x) and whose low 48 bits are 0. + ext v1.16b, v0.16b, v2.16b, #12 // extract high 32 bits + mov v0.s[3], v2.s[0] // zero high 32 bits + pmull v1.1q, v1.1d, fold_consts.1d // high 32 bits * x^48 * (x^48 mod G(x)) + eor v0.16b, v0.16b, v1.16b // + low bits + + // Load G(x) and floor(x^48 / G(x)). + ld1 {fold_consts.2d}, [fold_consts_ptr] + + // Use Barrett reduction to compute the final CRC value. + pmull2 v1.1q, v0.2d, fold_consts.2d // high 32 bits * floor(x^48 / G(x)) + ushr v1.2d, v1.2d, #32 // /= x^32 + pmull v1.1q, v1.1d, fold_consts.1d // *= G(x) + ushr v0.2d, v0.2d, #48 + eor v0.16b, v0.16b, v1.16b // + low 16 nonzero bits + // Final CRC value (x^16 * M(x)) mod G(x) is in low 16 bits of v0. + + umov w0, v0.h[0] + ret SYM_FUNC_END(crc_t10dif_pmull_p64) .section ".rodata", "a" diff --git a/arch/arm64/crypto/crct10dif-ce-glue.c b/arch/arm64/crypto/crct10dif-ce-glue.c index 606d25c559ed..08bcbd884395 100644 --- a/arch/arm64/crypto/crct10dif-ce-glue.c +++ b/arch/arm64/crypto/crct10dif-ce-glue.c @@ -20,7 +20,8 @@ #define CRC_T10DIF_PMULL_CHUNK_SIZE 16U -asmlinkage u16 crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len); +asmlinkage void crc_t10dif_pmull_p8(u16 init_crc, const u8 *buf, size_t len, + u8 out[16]); asmlinkage u16 crc_t10dif_pmull_p64(u16 init_crc, const u8 *buf, size_t len); static int crct10dif_init(struct shash_desc *desc) @@ -34,25 +35,21 @@ static int crct10dif_init(struct shash_desc *desc) static int crct10dif_update_pmull_p8(struct shash_desc *desc, const u8 *data, unsigned int length) { - u16 *crc = shash_desc_ctx(desc); - - if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) { - do { - unsigned int chunk = length; - - if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE) - chunk = SZ_4K; - - kernel_neon_begin(); - *crc = crc_t10dif_pmull_p8(*crc, data, chunk); - kernel_neon_end(); - data += chunk; - length -= chunk; - } while (length); - } else { - *crc = crc_t10dif_generic(*crc, data, length); + u16 *crcp = shash_desc_ctx(desc); + u16 crc = *crcp; + u8 buf[16]; + + if (length > CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) { + kernel_neon_begin(); + crc_t10dif_pmull_p8(crc, data, length, buf); + kernel_neon_end(); + + crc = 0; + data = buf; + length = sizeof(buf); } + *crcp = crc_t10dif_generic(crc, data, length); return 0; } @@ -62,18 +59,9 @@ static int crct10dif_update_pmull_p64(struct shash_desc *desc, const u8 *data, u16 *crc = shash_desc_ctx(desc); if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) { - do { - unsigned int chunk = length; - - if (chunk > SZ_4K + CRC_T10DIF_PMULL_CHUNK_SIZE) - chunk = SZ_4K; - - kernel_neon_begin(); - *crc = crc_t10dif_pmull_p64(*crc, data, chunk); - kernel_neon_end(); - data += chunk; - length -= chunk; - } while (length); + kernel_neon_begin(); + *crc = crc_t10dif_pmull_p64(*crc, data, length); + kernel_neon_end(); } else { *crc = crc_t10dif_generic(*crc, data, length); } diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c index 97331b454ea8..da7b7ec1a664 100644 --- a/arch/arm64/crypto/ghash-ce-glue.c +++ b/arch/arm64/crypto/ghash-ce-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/aes.h> #include <crypto/gcm.h> #include <crypto/algapi.h> diff --git a/arch/arm64/crypto/poly1305-armv8.pl b/arch/arm64/crypto/poly1305-armv8.pl index cbc980fb02e3..22c9069c0650 100644 --- a/arch/arm64/crypto/poly1305-armv8.pl +++ b/arch/arm64/crypto/poly1305-armv8.pl @@ -473,7 +473,8 @@ poly1305_blocks_neon: subs $len,$len,#64 ldp x9,x13,[$inp,#48] add $in2,$inp,#96 - adr $zeros,.Lzeros + adrp $zeros,.Lzeros + add $zeros,$zeros,#:lo12:.Lzeros lsl $padbit,$padbit,#24 add x15,$ctx,#48 @@ -885,10 +886,13 @@ poly1305_blocks_neon: ret .size poly1305_blocks_neon,.-poly1305_blocks_neon +.pushsection .rodata .align 5 .Lzeros: .long 0,0,0,0,0,0,0,0 .asciz "Poly1305 for ARMv8, CRYPTOGAMS by \@dot-asm" +.popsection + .align 2 #if !defined(__KERNEL__) && !defined(_WIN64) .comm OPENSSL_armcap_P,4,4 diff --git a/arch/arm64/crypto/poly1305-glue.c b/arch/arm64/crypto/poly1305-glue.c index 9c4bfd62e789..18883ea438f3 100644 --- a/arch/arm64/crypto/poly1305-glue.c +++ b/arch/arm64/crypto/poly1305-glue.c @@ -8,7 +8,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/algapi.h> #include <crypto/internal/hash.h> #include <crypto/internal/poly1305.h> diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c index 1dd93e1fcb39..cbd14f208f83 100644 --- a/arch/arm64/crypto/sha1-ce-glue.c +++ b/arch/arm64/crypto/sha1-ce-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sha1.h> diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c index 0a44d2e7ee1f..6b4866a88ded 100644 --- a/arch/arm64/crypto/sha2-ce-glue.c +++ b/arch/arm64/crypto/sha2-ce-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sha2.h> diff --git a/arch/arm64/crypto/sha3-ce-glue.c b/arch/arm64/crypto/sha3-ce-glue.c index 250e1377c481..5662c3ac49e9 100644 --- a/arch/arm64/crypto/sha3-ce-glue.c +++ b/arch/arm64/crypto/sha3-ce-glue.c @@ -12,7 +12,7 @@ #include <asm/hwcap.h> #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sha3.h> diff --git a/arch/arm64/crypto/sha512-ce-glue.c b/arch/arm64/crypto/sha512-ce-glue.c index f3431fc62315..071f64293227 100644 --- a/arch/arm64/crypto/sha512-ce-glue.c +++ b/arch/arm64/crypto/sha512-ce-glue.c @@ -11,7 +11,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sha2.h> diff --git a/arch/arm64/crypto/sm3-ce-glue.c b/arch/arm64/crypto/sm3-ce-glue.c index 54bf6ebcfffb..1a71788c4cda 100644 --- a/arch/arm64/crypto/sm3-ce-glue.c +++ b/arch/arm64/crypto/sm3-ce-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sm3.h> diff --git a/arch/arm64/crypto/sm3-neon-glue.c b/arch/arm64/crypto/sm3-neon-glue.c index 7182ee683f14..8dd71ce79b69 100644 --- a/arch/arm64/crypto/sm3-neon-glue.c +++ b/arch/arm64/crypto/sm3-neon-glue.c @@ -7,7 +7,7 @@ #include <asm/neon.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/sm3.h> diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 7d7d97ad3cd5..4e350df9a02d 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -9,6 +9,7 @@ syscall-y += unistd_compat_32.h generic-y += early_ioremap.h generic-y += mcs_spinlock.h +generic-y += mmzone.h generic-y += qrwlock.h generic-y += qspinlock.h generic-y += parport.h diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h index d328f549b1a6..c8c77f9e36d6 100644 --- a/arch/arm64/include/asm/alternative-macros.h +++ b/arch/arm64/include/asm/alternative-macros.h @@ -230,7 +230,11 @@ alternative_has_cap_likely(const unsigned long cpucap) return false; asm goto( +#ifdef BUILD_VDSO + ALTERNATIVE("b %l[l_no]", "nop", %[cpucap]) +#else ALTERNATIVE_CB("b %l[l_no]", %[cpucap], alt_cb_patch_nops) +#endif : : [cpucap] "i" (cpucap) : diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h index a4697a0b6835..8a777dec8d88 100644 --- a/arch/arm64/include/asm/arm_pmuv3.h +++ b/arch/arm64/include/asm/arm_pmuv3.h @@ -33,6 +33,14 @@ static inline void write_pmevtypern(int n, unsigned long val) PMEVN_SWITCH(n, WRITE_PMEVTYPERN); } +#define RETURN_READ_PMEVTYPERN(n) \ + return read_sysreg(pmevtyper##n##_el0) +static inline unsigned long read_pmevtypern(int n) +{ + PMEVN_SWITCH(n, RETURN_READ_PMEVTYPERN); + return 0; +} + static inline unsigned long read_pmmir(void) { return read_cpuid(PMMIR_EL1); @@ -46,6 +54,14 @@ static inline u32 read_pmuver(void) ID_AA64DFR0_EL1_PMUVer_SHIFT); } +static inline bool pmuv3_has_icntr(void) +{ + u64 dfr1 = read_sysreg(id_aa64dfr1_el1); + + return !!cpuid_feature_extract_unsigned_field(dfr1, + ID_AA64DFR1_EL1_PMICNTR_SHIFT); +} + static inline void write_pmcr(u64 val) { write_sysreg(val, pmcr_el0); @@ -71,22 +87,32 @@ static inline u64 read_pmccntr(void) return read_sysreg(pmccntr_el0); } -static inline void write_pmcntenset(u32 val) +static inline void write_pmicntr(u64 val) +{ + write_sysreg_s(val, SYS_PMICNTR_EL0); +} + +static inline u64 read_pmicntr(void) +{ + return read_sysreg_s(SYS_PMICNTR_EL0); +} + +static inline void write_pmcntenset(u64 val) { write_sysreg(val, pmcntenset_el0); } -static inline void write_pmcntenclr(u32 val) +static inline void write_pmcntenclr(u64 val) { write_sysreg(val, pmcntenclr_el0); } -static inline void write_pmintenset(u32 val) +static inline void write_pmintenset(u64 val) { write_sysreg(val, pmintenset_el1); } -static inline void write_pmintenclr(u32 val) +static inline void write_pmintenclr(u64 val) { write_sysreg(val, pmintenclr_el1); } @@ -96,12 +122,27 @@ static inline void write_pmccfiltr(u64 val) write_sysreg(val, pmccfiltr_el0); } -static inline void write_pmovsclr(u32 val) +static inline u64 read_pmccfiltr(void) +{ + return read_sysreg(pmccfiltr_el0); +} + +static inline void write_pmicfiltr(u64 val) +{ + write_sysreg_s(val, SYS_PMICFILTR_EL0); +} + +static inline u64 read_pmicfiltr(void) +{ + return read_sysreg_s(SYS_PMICFILTR_EL0); +} + +static inline void write_pmovsclr(u64 val) { write_sysreg(val, pmovsclr_el0); } -static inline u32 read_pmovsclr(void) +static inline u64 read_pmovsclr(void) { return read_sysreg(pmovsclr_el0); } @@ -111,6 +152,11 @@ static inline void write_pmuserenr(u32 val) write_sysreg(val, pmuserenr_el0); } +static inline void write_pmuacr(u64 val) +{ + write_sysreg_s(val, SYS_PMUACR_EL1); +} + static inline u64 read_pmceid0(void) { return read_sysreg(pmceid0_el0); @@ -137,4 +183,9 @@ static inline bool is_pmuv3p5(int pmuver) return pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P5; } +static inline bool is_pmuv3p9(int pmuver) +{ + return pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P9; +} + #endif diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index bc0b0d75acef..3d8d534a7a77 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -249,13 +249,6 @@ alternative_endif .endm /* - * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) - */ - .macro vma_vm_mm, rd, rn - ldr \rd, [\rn, #VMA_VM_MM] - .endm - -/* * read_ctr - read CTR_EL0. If the system has mismatched register fields, * provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val */ diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index a6e5b07b64fd..a08a1212ffbb 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -42,6 +42,8 @@ cpucap_is_possible(const unsigned int cap) return IS_ENABLED(CONFIG_ARM64_BTI); case ARM64_HAS_TLB_RANGE: return IS_ENABLED(CONFIG_ARM64_TLB_RANGE); + case ARM64_HAS_S1POE: + return IS_ENABLED(CONFIG_ARM64_POE); case ARM64_UNMAP_KERNEL_AT_EL0: return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0); case ARM64_WORKAROUND_843419: diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 558434267271..3d63c20ccefc 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -12,7 +12,7 @@ #include <asm/hwcap.h> #include <asm/sysreg.h> -#define MAX_CPU_FEATURES 128 +#define MAX_CPU_FEATURES 192 #define cpu_feature(x) KERNEL_HWCAP_ ## x #define ARM64_SW_FEATURE_OVERRIDE_NOKASLR 0 @@ -438,6 +438,7 @@ void cpu_set_feature(unsigned int num); bool cpu_have_feature(unsigned int num); unsigned long cpu_get_elf_hwcap(void); unsigned long cpu_get_elf_hwcap2(void); +unsigned long cpu_get_elf_hwcap3(void); #define cpu_set_named_feature(name) cpu_set_feature(cpu_feature(name)) #define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name)) @@ -832,6 +833,23 @@ static inline bool system_supports_lpa2(void) return cpus_have_final_cap(ARM64_HAS_LPA2); } +static inline bool system_supports_poe(void) +{ + return alternative_has_cap_unlikely(ARM64_HAS_S1POE); +} + +static inline bool system_supports_gcs(void) +{ + return IS_ENABLED(CONFIG_ARM64_GCS) && + alternative_has_cap_unlikely(ARM64_HAS_GCS); +} + +static inline bool system_supports_haft(void) +{ + return IS_ENABLED(CONFIG_ARM64_HAFT) && + cpus_have_final_cap(ARM64_HAFT); +} + int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); bool try_emulate_mrs(struct pt_regs *regs, u32 isn); diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 5fd7caea4419..488f8e751349 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -94,6 +94,7 @@ #define ARM_CPU_PART_NEOVERSE_V3 0xD84 #define ARM_CPU_PART_CORTEX_X925 0xD85 #define ARM_CPU_PART_CORTEX_A725 0xD87 +#define ARM_CPU_PART_NEOVERSE_N3 0xD8E #define APM_CPU_PART_XGENE 0x000 #define APM_CPU_VAR_POTENZA 0x00 @@ -143,6 +144,7 @@ #define APPLE_CPU_PART_M2_AVALANCHE_MAX 0x039 #define AMPERE_CPU_PART_AMPERE1 0xAC3 +#define AMPERE_CPU_PART_AMPERE1A 0xAC4 #define MICROSOFT_CPU_PART_AZURE_COBALT_100 0xD49 /* Based on r0p0 of ARM Neoverse N2 */ @@ -175,6 +177,7 @@ #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) #define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) #define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) +#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) @@ -212,6 +215,7 @@ #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1) +#define MIDR_AMPERE1A MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1A) #define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100) /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h index 55f57dfa8e2f..fbb5c99eb2f9 100644 --- a/arch/arm64/include/asm/daifflags.h +++ b/arch/arm64/include/asm/daifflags.h @@ -132,7 +132,7 @@ static inline void local_daif_inherit(struct pt_regs *regs) trace_hardirqs_on(); if (system_uses_irq_prio_masking()) - gic_write_pmr(regs->pmr_save); + gic_write_pmr(regs->pmr); /* * We can't use local_daif_restore(regs->pstate) here as diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index 13d437bcbf58..8f6ba31b8658 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -105,6 +105,7 @@ void kernel_enable_single_step(struct pt_regs *regs); void kernel_disable_single_step(void); int kernel_active_single_step(void); void kernel_rewind_single_step(struct pt_regs *regs); +void kernel_fastforward_single_step(struct pt_regs *regs); #ifdef CONFIG_HAVE_HW_BREAKPOINT int reinstall_suspended_bps(struct pt_regs *regs); diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index fd87c4b8f984..27086a81eae3 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -27,6 +27,14 @@ ubfx x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 cbz x0, .Lskip_hcrx_\@ mov_q x0, HCRX_HOST_FLAGS + + /* Enable GCS if supported */ + mrs_s x1, SYS_ID_AA64PFR1_EL1 + ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 + cbz x1, .Lset_hcrx_\@ + orr x0, x0, #HCRX_EL2_GCSEn + +.Lset_hcrx_\@: msr_s SYS_HCRX_EL2, x0 .Lskip_hcrx_\@: .endm @@ -165,32 +173,50 @@ mrs x1, id_aa64dfr0_el1 ubfx x1, x1, #ID_AA64DFR0_EL1_PMSVer_SHIFT, #4 cmp x1, #3 - b.lt .Lset_debug_fgt_\@ + b.lt .Lskip_spe_fgt_\@ /* Disable PMSNEVFR_EL1 read and write traps */ orr x0, x0, #(1 << 62) -.Lset_debug_fgt_\@: +.Lskip_spe_fgt_\@: msr_s SYS_HDFGRTR_EL2, x0 msr_s SYS_HDFGWTR_EL2, x0 mov x0, xzr mrs x1, id_aa64pfr1_el1 ubfx x1, x1, #ID_AA64PFR1_EL1_SME_SHIFT, #4 - cbz x1, .Lset_pie_fgt_\@ + cbz x1, .Lskip_debug_fgt_\@ /* Disable nVHE traps of TPIDR2 and SMPRI */ orr x0, x0, #HFGxTR_EL2_nSMPRI_EL1_MASK orr x0, x0, #HFGxTR_EL2_nTPIDR2_EL0_MASK -.Lset_pie_fgt_\@: +.Lskip_debug_fgt_\@: mrs_s x1, SYS_ID_AA64MMFR3_EL1 ubfx x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4 - cbz x1, .Lset_fgt_\@ + cbz x1, .Lskip_pie_fgt_\@ /* Disable trapping of PIR_EL1 / PIRE0_EL1 */ orr x0, x0, #HFGxTR_EL2_nPIR_EL1 orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1 +.Lskip_pie_fgt_\@: + mrs_s x1, SYS_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_S1POE_SHIFT, #4 + cbz x1, .Lskip_poe_fgt_\@ + + /* Disable trapping of POR_EL0 */ + orr x0, x0, #HFGxTR_EL2_nPOR_EL0 + +.Lskip_poe_fgt_\@: + /* GCS depends on PIE so we don't check it if PIE is absent */ + mrs_s x1, SYS_ID_AA64PFR1_EL1 + ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 + cbz x1, .Lset_fgt_\@ + + /* Disable traps of access to GCS registers at EL0 and EL1 */ + orr x0, x0, #HFGxTR_EL2_nGCS_EL1_MASK + orr x0, x0, #HFGxTR_EL2_nGCS_EL0_MASK + .Lset_fgt_\@: msr_s SYS_HFGRTR_EL2, x0 msr_s SYS_HFGWTR_EL2, x0 @@ -198,12 +224,26 @@ mrs x1, id_aa64pfr0_el1 // AMU traps UNDEF without AMU ubfx x1, x1, #ID_AA64PFR0_EL1_AMU_SHIFT, #4 - cbz x1, .Lskip_fgt_\@ + cbz x1, .Lskip_amu_fgt_\@ msr_s SYS_HAFGRTR_EL2, xzr + +.Lskip_amu_fgt_\@: + .Lskip_fgt_\@: .endm +.macro __init_el2_gcs + mrs_s x1, SYS_ID_AA64PFR1_EL1 + ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 + cbz x1, .Lskip_gcs_\@ + + /* Ensure GCS is not enabled when we start trying to do BLs */ + msr_s SYS_GCSCR_EL1, xzr + msr_s SYS_GCSCRE0_EL1, xzr +.Lskip_gcs_\@: +.endm + .macro __init_el2_nvhe_prepare_eret mov x0, #INIT_PSTATE_EL1 msr spsr_el2, x0 @@ -229,6 +269,7 @@ __init_el2_nvhe_idregs __init_el2_cptr __init_el2_fgt + __init_el2_gcs .endm #ifndef __KVM_NVHE_HYPERVISOR__ diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 56c148890daf..d1b1a33f9a8b 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -10,63 +10,64 @@ #include <asm/memory.h> #include <asm/sysreg.h> -#define ESR_ELx_EC_UNKNOWN (0x00) -#define ESR_ELx_EC_WFx (0x01) +#define ESR_ELx_EC_UNKNOWN UL(0x00) +#define ESR_ELx_EC_WFx UL(0x01) /* Unallocated EC: 0x02 */ -#define ESR_ELx_EC_CP15_32 (0x03) -#define ESR_ELx_EC_CP15_64 (0x04) -#define ESR_ELx_EC_CP14_MR (0x05) -#define ESR_ELx_EC_CP14_LS (0x06) -#define ESR_ELx_EC_FP_ASIMD (0x07) -#define ESR_ELx_EC_CP10_ID (0x08) /* EL2 only */ -#define ESR_ELx_EC_PAC (0x09) /* EL2 and above */ +#define ESR_ELx_EC_CP15_32 UL(0x03) +#define ESR_ELx_EC_CP15_64 UL(0x04) +#define ESR_ELx_EC_CP14_MR UL(0x05) +#define ESR_ELx_EC_CP14_LS UL(0x06) +#define ESR_ELx_EC_FP_ASIMD UL(0x07) +#define ESR_ELx_EC_CP10_ID UL(0x08) /* EL2 only */ +#define ESR_ELx_EC_PAC UL(0x09) /* EL2 and above */ /* Unallocated EC: 0x0A - 0x0B */ -#define ESR_ELx_EC_CP14_64 (0x0C) -#define ESR_ELx_EC_BTI (0x0D) -#define ESR_ELx_EC_ILL (0x0E) +#define ESR_ELx_EC_CP14_64 UL(0x0C) +#define ESR_ELx_EC_BTI UL(0x0D) +#define ESR_ELx_EC_ILL UL(0x0E) /* Unallocated EC: 0x0F - 0x10 */ -#define ESR_ELx_EC_SVC32 (0x11) -#define ESR_ELx_EC_HVC32 (0x12) /* EL2 only */ -#define ESR_ELx_EC_SMC32 (0x13) /* EL2 and above */ +#define ESR_ELx_EC_SVC32 UL(0x11) +#define ESR_ELx_EC_HVC32 UL(0x12) /* EL2 only */ +#define ESR_ELx_EC_SMC32 UL(0x13) /* EL2 and above */ /* Unallocated EC: 0x14 */ -#define ESR_ELx_EC_SVC64 (0x15) -#define ESR_ELx_EC_HVC64 (0x16) /* EL2 and above */ -#define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */ -#define ESR_ELx_EC_SYS64 (0x18) -#define ESR_ELx_EC_SVE (0x19) -#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */ +#define ESR_ELx_EC_SVC64 UL(0x15) +#define ESR_ELx_EC_HVC64 UL(0x16) /* EL2 and above */ +#define ESR_ELx_EC_SMC64 UL(0x17) /* EL2 and above */ +#define ESR_ELx_EC_SYS64 UL(0x18) +#define ESR_ELx_EC_SVE UL(0x19) +#define ESR_ELx_EC_ERET UL(0x1a) /* EL2 only */ /* Unallocated EC: 0x1B */ -#define ESR_ELx_EC_FPAC (0x1C) /* EL1 and above */ -#define ESR_ELx_EC_SME (0x1D) +#define ESR_ELx_EC_FPAC UL(0x1C) /* EL1 and above */ +#define ESR_ELx_EC_SME UL(0x1D) /* Unallocated EC: 0x1E */ -#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */ -#define ESR_ELx_EC_IABT_LOW (0x20) -#define ESR_ELx_EC_IABT_CUR (0x21) -#define ESR_ELx_EC_PC_ALIGN (0x22) +#define ESR_ELx_EC_IMP_DEF UL(0x1f) /* EL3 only */ +#define ESR_ELx_EC_IABT_LOW UL(0x20) +#define ESR_ELx_EC_IABT_CUR UL(0x21) +#define ESR_ELx_EC_PC_ALIGN UL(0x22) /* Unallocated EC: 0x23 */ -#define ESR_ELx_EC_DABT_LOW (0x24) -#define ESR_ELx_EC_DABT_CUR (0x25) -#define ESR_ELx_EC_SP_ALIGN (0x26) -#define ESR_ELx_EC_MOPS (0x27) -#define ESR_ELx_EC_FP_EXC32 (0x28) +#define ESR_ELx_EC_DABT_LOW UL(0x24) +#define ESR_ELx_EC_DABT_CUR UL(0x25) +#define ESR_ELx_EC_SP_ALIGN UL(0x26) +#define ESR_ELx_EC_MOPS UL(0x27) +#define ESR_ELx_EC_FP_EXC32 UL(0x28) /* Unallocated EC: 0x29 - 0x2B */ -#define ESR_ELx_EC_FP_EXC64 (0x2C) -/* Unallocated EC: 0x2D - 0x2E */ -#define ESR_ELx_EC_SERROR (0x2F) -#define ESR_ELx_EC_BREAKPT_LOW (0x30) -#define ESR_ELx_EC_BREAKPT_CUR (0x31) -#define ESR_ELx_EC_SOFTSTP_LOW (0x32) -#define ESR_ELx_EC_SOFTSTP_CUR (0x33) -#define ESR_ELx_EC_WATCHPT_LOW (0x34) -#define ESR_ELx_EC_WATCHPT_CUR (0x35) +#define ESR_ELx_EC_FP_EXC64 UL(0x2C) +#define ESR_ELx_EC_GCS UL(0x2D) +/* Unallocated EC: 0x2E */ +#define ESR_ELx_EC_SERROR UL(0x2F) +#define ESR_ELx_EC_BREAKPT_LOW UL(0x30) +#define ESR_ELx_EC_BREAKPT_CUR UL(0x31) +#define ESR_ELx_EC_SOFTSTP_LOW UL(0x32) +#define ESR_ELx_EC_SOFTSTP_CUR UL(0x33) +#define ESR_ELx_EC_WATCHPT_LOW UL(0x34) +#define ESR_ELx_EC_WATCHPT_CUR UL(0x35) /* Unallocated EC: 0x36 - 0x37 */ -#define ESR_ELx_EC_BKPT32 (0x38) +#define ESR_ELx_EC_BKPT32 UL(0x38) /* Unallocated EC: 0x39 */ -#define ESR_ELx_EC_VECTOR32 (0x3A) /* EL2 only */ +#define ESR_ELx_EC_VECTOR32 UL(0x3A) /* EL2 only */ /* Unallocated EC: 0x3B */ -#define ESR_ELx_EC_BRK64 (0x3C) +#define ESR_ELx_EC_BRK64 UL(0x3C) /* Unallocated EC: 0x3D - 0x3F */ -#define ESR_ELx_EC_MAX (0x3F) +#define ESR_ELx_EC_MAX UL(0x3F) #define ESR_ELx_EC_SHIFT (26) #define ESR_ELx_EC_WIDTH (6) @@ -122,8 +123,8 @@ #define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n)) /* Status codes for individual page table levels */ -#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + n) -#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + n) +#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + (n)) +#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + (n)) #define ESR_ELx_FSC_FAULT_nL (0x2C) #define ESR_ELx_FSC_FAULT_L(n) (((n) < 0 ? ESR_ELx_FSC_FAULT_nL : \ @@ -161,6 +162,7 @@ /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_FSC_ADDRSZ (0x00) +#define ESR_ELx_FSC_ADDRSZ_L(n) (ESR_ELx_FSC_ADDRSZ + (n)) #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) #define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT) @@ -385,6 +387,31 @@ #define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5) #define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0) +/* ISS field definitions for GCS */ +#define ESR_ELx_ExType_SHIFT (20) +#define ESR_ELx_ExType_MASK GENMASK(23, 20) +#define ESR_ELx_Raddr_SHIFT (10) +#define ESR_ELx_Raddr_MASK GENMASK(14, 10) +#define ESR_ELx_Rn_SHIFT (5) +#define ESR_ELx_Rn_MASK GENMASK(9, 5) +#define ESR_ELx_Rvalue_SHIFT 5 +#define ESR_ELx_Rvalue_MASK GENMASK(9, 5) +#define ESR_ELx_IT_SHIFT (0) +#define ESR_ELx_IT_MASK GENMASK(4, 0) + +#define ESR_ELx_ExType_DATA_CHECK 0 +#define ESR_ELx_ExType_EXLOCK 1 +#define ESR_ELx_ExType_STR 2 + +#define ESR_ELx_IT_RET 0 +#define ESR_ELx_IT_GCSPOPM 1 +#define ESR_ELx_IT_RET_KEYA 2 +#define ESR_ELx_IT_RET_KEYB 3 +#define ESR_ELx_IT_GCSSS1 4 +#define ESR_ELx_IT_GCSSS2 5 +#define ESR_ELx_IT_GCSPOPCX 6 +#define ESR_ELx_IT_GCSPOPX 7 + #ifndef __ASSEMBLY__ #include <asm/types.h> diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index f296662590c7..d48fc16584cd 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -57,6 +57,8 @@ void do_el0_undef(struct pt_regs *regs, unsigned long esr); void do_el1_undef(struct pt_regs *regs, unsigned long esr); void do_el0_bti(struct pt_regs *regs); void do_el1_bti(struct pt_regs *regs, unsigned long esr); +void do_el0_gcs(struct pt_regs *regs, unsigned long esr); +void do_el1_gcs(struct pt_regs *regs, unsigned long esr); void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr, struct pt_regs *regs); void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs); @@ -73,6 +75,7 @@ void do_el0_svc_compat(struct pt_regs *regs); void do_el0_fpac(struct pt_regs *regs, unsigned long esr); void do_el1_fpac(struct pt_regs *regs, unsigned long esr); void do_el0_mops(struct pt_regs *regs, unsigned long esr); +void do_el1_mops(struct pt_regs *regs, unsigned long esr); void do_serror(struct pt_regs *regs, unsigned long esr); void do_signal(struct pt_regs *regs); diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index bc69ac368d73..f2a84efc3618 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -155,8 +155,6 @@ extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused); extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused); extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused); -extern u64 read_smcr_features(void); - /* * Helpers to translate bit indices in sve_vq_map to VQ values (and * vice versa). This allows find_next_bit() to be used to find the diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h index dc9cf0bd2a4c..5ccff4de7f09 100644 --- a/arch/arm64/include/asm/ftrace.h +++ b/arch/arm64/include/asm/ftrace.h @@ -54,8 +54,11 @@ extern void return_to_handler(void); unsigned long ftrace_call_adjust(unsigned long addr); #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS +#define HAVE_ARCH_FTRACE_REGS struct dyn_ftrace; struct ftrace_ops; +struct ftrace_regs; +#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs)) #define arch_ftrace_get_regs(regs) NULL @@ -63,7 +66,7 @@ struct ftrace_ops; * Note: sizeof(struct ftrace_regs) must be a multiple of 16 to ensure correct * stack alignment */ -struct ftrace_regs { +struct __arch_ftrace_regs { /* x0 - x8 */ unsigned long regs[9]; @@ -83,47 +86,47 @@ struct ftrace_regs { static __always_inline unsigned long ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs) { - return fregs->pc; + return arch_ftrace_regs(fregs)->pc; } static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long pc) { - fregs->pc = pc; + arch_ftrace_regs(fregs)->pc = pc; } static __always_inline unsigned long ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs) { - return fregs->sp; + return arch_ftrace_regs(fregs)->sp; } static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n) { if (n < 8) - return fregs->regs[n]; + return arch_ftrace_regs(fregs)->regs[n]; return 0; } static __always_inline unsigned long ftrace_regs_get_return_value(const struct ftrace_regs *fregs) { - return fregs->regs[0]; + return arch_ftrace_regs(fregs)->regs[0]; } static __always_inline void ftrace_regs_set_return_value(struct ftrace_regs *fregs, unsigned long ret) { - fregs->regs[0] = ret; + arch_ftrace_regs(fregs)->regs[0] = ret; } static __always_inline void ftrace_override_function_with_return(struct ftrace_regs *fregs) { - fregs->pc = fregs->lr; + arch_ftrace_regs(fregs)->pc = arch_ftrace_regs(fregs)->lr; } int ftrace_regs_query_register_offset(const char *name); @@ -143,7 +146,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, * The ftrace trampoline will return to this address instead of the * instrumented function. */ - fregs->direct_tramp = addr; + arch_ftrace_regs(fregs)->direct_tramp = addr; } #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h new file mode 100644 index 000000000000..f50660603ecf --- /dev/null +++ b/arch/arm64/include/asm/gcs.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 ARM Ltd. + */ +#ifndef __ASM_GCS_H +#define __ASM_GCS_H + +#include <asm/types.h> +#include <asm/uaccess.h> + +struct kernel_clone_args; +struct ksignal; + +static inline void gcsb_dsync(void) +{ + asm volatile(".inst 0xd503227f" : : : "memory"); +} + +static inline void gcsstr(u64 *addr, u64 val) +{ + register u64 *_addr __asm__ ("x0") = addr; + register long _val __asm__ ("x1") = val; + + /* GCSSTTR x1, x0 */ + asm volatile( + ".inst 0xd91f1c01\n" + : + : "rZ" (_val), "r" (_addr) + : "memory"); +} + +static inline void gcsss1(u64 Xt) +{ + asm volatile ( + "sys #3, C7, C7, #2, %0\n" + : + : "rZ" (Xt) + : "memory"); +} + +static inline u64 gcsss2(void) +{ + u64 Xt; + + asm volatile( + "SYSL %0, #3, C7, C7, #3\n" + : "=r" (Xt) + : + : "memory"); + + return Xt; +} + +#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK \ + (PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH) + +#ifdef CONFIG_ARM64_GCS + +static inline bool task_gcs_el0_enabled(struct task_struct *task) +{ + return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE; +} + +void gcs_set_el0_mode(struct task_struct *task); +void gcs_free(struct task_struct *task); +void gcs_preserve_current_state(void); +unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, + const struct kernel_clone_args *args); + +static inline int gcs_check_locked(struct task_struct *task, + unsigned long new_val) +{ + unsigned long cur_val = task->thread.gcs_el0_mode; + + cur_val &= task->thread.gcs_el0_locked; + new_val &= task->thread.gcs_el0_locked; + + if (cur_val != new_val) + return -EBUSY; + + return 0; +} + +#else + +static inline bool task_gcs_el0_enabled(struct task_struct *task) +{ + return false; +} + +static inline void gcs_set_el0_mode(struct task_struct *task) { } +static inline void gcs_free(struct task_struct *task) { } +static inline void gcs_preserve_current_state(void) { } +static inline unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, + const struct kernel_clone_args *args) +{ + return -ENOTSUPP; +} +static inline int gcs_check_locked(struct task_struct *task, + unsigned long new_val) +{ + return 0; +} + +#endif + +#endif diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h index 293f880865e8..c6dff3e69539 100644 --- a/arch/arm64/include/asm/hugetlb.h +++ b/arch/arm64/include/asm/hugetlb.h @@ -11,6 +11,7 @@ #define __ASM_HUGETLB_H #include <asm/cacheflush.h> +#include <asm/mte.h> #include <asm/page.h> #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION @@ -21,6 +22,13 @@ extern bool arch_hugetlb_migration_supported(struct hstate *h); static inline void arch_clear_hugetlb_flags(struct folio *folio) { clear_bit(PG_dcache_clean, &folio->flags); + +#ifdef CONFIG_ARM64_MTE + if (system_supports_mte()) { + clear_bit(PG_mte_tagged, &folio->flags); + clear_bit(PG_mte_lock, &folio->flags); + } +#endif } #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index 4edd3b61df11..2b6c61c608e2 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -92,6 +92,7 @@ #define KERNEL_HWCAP_SB __khwcap_feature(SB) #define KERNEL_HWCAP_PACA __khwcap_feature(PACA) #define KERNEL_HWCAP_PACG __khwcap_feature(PACG) +#define KERNEL_HWCAP_GCS __khwcap_feature(GCS) #define __khwcap2_feature(x) (const_ilog2(HWCAP2_ ## x) + 64) #define KERNEL_HWCAP_DCPODP __khwcap2_feature(DCPODP) @@ -157,6 +158,9 @@ #define KERNEL_HWCAP_SME_SF8FMA __khwcap2_feature(SME_SF8FMA) #define KERNEL_HWCAP_SME_SF8DP4 __khwcap2_feature(SME_SF8DP4) #define KERNEL_HWCAP_SME_SF8DP2 __khwcap2_feature(SME_SF8DP2) +#define KERNEL_HWCAP_POE __khwcap2_feature(POE) + +#define __khwcap3_feature(x) (const_ilog2(HWCAP3_ ## x) + 128) /* * This yields a mask that user programs can use to figure out what @@ -164,11 +168,13 @@ */ #define ELF_HWCAP cpu_get_elf_hwcap() #define ELF_HWCAP2 cpu_get_elf_hwcap2() +#define ELF_HWCAP3 cpu_get_elf_hwcap3() #ifdef CONFIG_COMPAT #define COMPAT_ELF_HWCAP (compat_elf_hwcap) #define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2) -extern unsigned int compat_elf_hwcap, compat_elf_hwcap2; +#define COMPAT_ELF_HWCAP3 (compat_elf_hwcap3) +extern unsigned int compat_elf_hwcap, compat_elf_hwcap2, compat_elf_hwcap3; #endif enum { diff --git a/arch/arm64/include/asm/hypervisor.h b/arch/arm64/include/asm/hypervisor.h index 0ae427f352c8..409e239834d1 100644 --- a/arch/arm64/include/asm/hypervisor.h +++ b/arch/arm64/include/asm/hypervisor.h @@ -7,4 +7,15 @@ void kvm_init_hyp_services(void); bool kvm_arm_hyp_service_available(u32 func_id); +#ifdef CONFIG_ARM_PKVM_GUEST +void pkvm_init_hyp_services(void); +#else +static inline void pkvm_init_hyp_services(void) { }; +#endif + +static inline void kvm_arch_init_hyp_services(void) +{ + pkvm_init_hyp_services(); +}; + #endif diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 8c0a36f72d6f..e390c432f546 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -353,6 +353,7 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000) __AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000) __AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000) __AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000) +__AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400) __AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000) __AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000) __AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000) @@ -575,6 +576,11 @@ static __always_inline u32 aarch64_insn_gen_nop(void) return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP); } +static __always_inline bool aarch64_insn_is_nop(u32 insn) +{ + return insn == aarch64_insn_gen_nop(); +} + u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type); u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 41fd90895dfc..8688343b71f2 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -17,6 +17,7 @@ #include <asm/early_ioremap.h> #include <asm/alternative.h> #include <asm/cpufeature.h> +#include <asm/rsi.h> /* * Generic IO read/write. These perform native-endian accesses. @@ -271,6 +272,10 @@ __iowrite64_copy(void __iomem *to, const void *from, size_t count) * I/O memory mapping functions. */ +typedef int (*ioremap_prot_hook_t)(phys_addr_t phys_addr, size_t size, + pgprot_t *prot); +int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook); + #define ioremap_prot ioremap_prot #define _PAGE_IOREMAP PROT_DEVICE_nGnRE @@ -314,4 +319,11 @@ extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, unsigned long flags); #define arch_memremap_can_ram_remap arch_memremap_can_ram_remap +static inline bool arm64_is_protected_mmio(phys_addr_t phys_addr, size_t size) +{ + if (unlikely(is_realm_world())) + return __arm64_is_protected_mmio(phys_addr, size); + return false; +} + #endif /* __ASM_IO_H */ diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index bf05a77873a4..fd5a08450b12 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -26,7 +26,6 @@ #define SWAPPER_SKIP_LEVEL 0 #endif #define SWAPPER_BLOCK_SIZE (UL(1) << SWAPPER_BLOCK_SHIFT) -#define SWAPPER_TABLE_SHIFT (SWAPPER_BLOCK_SHIFT + PAGE_SHIFT - 3) #define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - SWAPPER_SKIP_LEVEL) #define INIT_IDMAP_PGTABLE_LEVELS (IDMAP_LEVELS - SWAPPER_SKIP_LEVEL) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index d81cc746e0eb..109a85ee6910 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -107,6 +107,7 @@ /* TCR_EL2 Registers bits */ #define TCR_EL2_DS (1UL << 32) #define TCR_EL2_RES1 ((1U << 31) | (1 << 23)) +#define TCR_EL2_HPD (1 << 24) #define TCR_EL2_TBI (1 << 20) #define TCR_EL2_PS_SHIFT 16 #define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 2181a11b9d92..67afac659231 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -10,6 +10,7 @@ #include <asm/hyp_image.h> #include <asm/insn.h> #include <asm/virt.h> +#include <asm/sysreg.h> #define ARM_EXIT_WITH_SERROR_BIT 31 #define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) @@ -177,6 +178,7 @@ struct kvm_nvhe_init_params { unsigned long hcr_el2; unsigned long vttbr; unsigned long vtcr; + unsigned long tmp; }; /* @@ -235,6 +237,9 @@ extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); extern int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding); extern void __kvm_timer_set_cntvoff(u64 cntvoff); +extern void __kvm_at_s1e01(struct kvm_vcpu *vcpu, u32 op, u64 vaddr); +extern void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr); +extern void __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr); extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); @@ -259,7 +264,7 @@ extern u64 __kvm_get_mdcr_el2(void); asm volatile( \ " mrs %1, spsr_el2\n" \ " mrs %2, elr_el2\n" \ - "1: at "at_op", %3\n" \ + "1: " __msr_s(at_op, "%3") "\n" \ " isb\n" \ " b 9f\n" \ "2: msr spsr_el2, %1\n" \ diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index a33f5996ca9f..bf64fed9820e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -51,6 +51,7 @@ #define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5) #define KVM_REQ_SUSPEND KVM_ARCH_REQ(6) #define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7) +#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8) #define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ KVM_DIRTY_LOG_INITIALLY_SET) @@ -212,6 +213,12 @@ struct kvm_s2_mmu { bool nested_stage2_enabled; /* + * true when this MMU needs to be unmapped before being used for a new + * purpose. + */ + bool pending_unmap; + + /* * 0: Nobody is currently using this, check vttbr for validity * >0: Somebody is actively using this. */ @@ -446,6 +453,12 @@ enum vcpu_sysreg { GCR_EL1, /* Tag Control Register */ TFSRE0_EL1, /* Tag Fault Status Register (EL0) */ + POR_EL0, /* Permission Overlay Register 0 (EL0) */ + + /* FP/SIMD/SVE */ + SVCR, + FPMR, + /* 32bit specific registers. */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ @@ -517,6 +530,8 @@ enum vcpu_sysreg { VNCR(PIR_EL1), /* Permission Indirection Register 1 (EL1) */ VNCR(PIRE0_EL1), /* Permission Indirection Register 0 (EL1) */ + VNCR(POR_EL1), /* Permission Overlay Register 1 (EL1) */ + VNCR(HFGRTR_EL2), VNCR(HFGWTR_EL2), VNCR(HFGITR_EL2), @@ -530,6 +545,8 @@ enum vcpu_sysreg { VNCR(CNTP_CVAL_EL0), VNCR(CNTP_CTL_EL0), + VNCR(ICH_HCR_EL2), + NR_SYS_REGS /* Nothing after this line! */ }; @@ -595,6 +612,16 @@ struct kvm_host_data { struct cpu_sve_state *sve_state; }; + union { + /* HYP VA pointer to the host storage for FPMR */ + u64 *fpmr_ptr; + /* + * Used by pKVM only, as it needs to provide storage + * for the host + */ + u64 fpmr; + }; + /* Ownership of the FP regs */ enum { FP_STATE_FREE, @@ -664,8 +691,6 @@ struct kvm_vcpu_arch { void *sve_state; enum fp_type fp_type; unsigned int sve_max_vl; - u64 svcr; - u64 fpmr; /* Stage 2 paging state used by the hardware on next switch */ struct kvm_s2_mmu *hw_mmu; @@ -1330,12 +1355,12 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu); #ifdef CONFIG_KVM -void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr); -void kvm_clr_pmu_events(u32 clr); +void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr); +void kvm_clr_pmu_events(u64 clr); bool kvm_set_pmuserenr(u64 val); #else -static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {} -static inline void kvm_clr_pmu_events(u32 clr) {} +static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) {} +static inline void kvm_clr_pmu_events(u64 clr) {} static inline bool kvm_set_pmuserenr(u64 val) { return false; @@ -1423,11 +1448,6 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val); sign_extend64(__val, id##_##fld##_WIDTH - 1); \ }) -#define expand_field_sign(id, fld, val) \ - (id##_##fld##_SIGNED ? \ - __expand_field_sign_signed(id, fld, val) : \ - __expand_field_sign_unsigned(id, fld, val)) - #define get_idreg_field_unsigned(kvm, id, fld) \ ({ \ u64 __val = kvm_read_vm_id_reg((kvm), SYS_##id); \ @@ -1443,20 +1463,26 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val); #define get_idreg_field_enum(kvm, id, fld) \ get_idreg_field_unsigned(kvm, id, fld) -#define get_idreg_field(kvm, id, fld) \ +#define kvm_cmp_feat_signed(kvm, id, fld, op, limit) \ + (get_idreg_field_signed((kvm), id, fld) op __expand_field_sign_signed(id, fld, limit)) + +#define kvm_cmp_feat_unsigned(kvm, id, fld, op, limit) \ + (get_idreg_field_unsigned((kvm), id, fld) op __expand_field_sign_unsigned(id, fld, limit)) + +#define kvm_cmp_feat(kvm, id, fld, op, limit) \ (id##_##fld##_SIGNED ? \ - get_idreg_field_signed(kvm, id, fld) : \ - get_idreg_field_unsigned(kvm, id, fld)) + kvm_cmp_feat_signed(kvm, id, fld, op, limit) : \ + kvm_cmp_feat_unsigned(kvm, id, fld, op, limit)) #define kvm_has_feat(kvm, id, fld, limit) \ - (get_idreg_field((kvm), id, fld) >= expand_field_sign(id, fld, limit)) + kvm_cmp_feat(kvm, id, fld, >=, limit) #define kvm_has_feat_enum(kvm, id, fld, val) \ - (get_idreg_field_unsigned((kvm), id, fld) == __expand_field_sign_unsigned(id, fld, val)) + kvm_cmp_feat_unsigned(kvm, id, fld, ==, val) #define kvm_has_feat_range(kvm, id, fld, min, max) \ - (get_idreg_field((kvm), id, fld) >= expand_field_sign(id, fld, min) && \ - get_idreg_field((kvm), id, fld) <= expand_field_sign(id, fld, max)) + (kvm_cmp_feat(kvm, id, fld, >=, min) && \ + kvm_cmp_feat(kvm, id, fld, <=, max)) /* Check for a given level of PAuth support */ #define kvm_has_pauth(k, l) \ @@ -1473,4 +1499,8 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val); (pa + pi + pa3) == 1; \ }) +#define kvm_has_fpmr(k) \ + (system_supports_fpmr() && \ + kvm_has_feat((k), ID_AA64PFR2_EL1, FPMR, IMP)) + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 216ca424bb16..66d93e320ec8 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -166,7 +166,8 @@ int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size, int create_hyp_stack(phys_addr_t phys_addr, unsigned long *haddr); void __init free_hyp_pgds(void); -void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size); +void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, + u64 size, bool may_block); void kvm_stage2_flush_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end); void kvm_stage2_wp_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end); @@ -352,5 +353,11 @@ static inline bool kvm_is_nested_s2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu) return &kvm->arch.mmu != mmu; } +#ifdef CONFIG_PTDUMP_STAGE2_DEBUGFS +void kvm_s2_ptdump_create_debugfs(struct kvm *kvm); +#else +static inline void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) {} +#endif /* CONFIG_PTDUMP_STAGE2_DEBUGFS */ + #endif /* __ASSEMBLY__ */ #endif /* __ARM64_KVM_MMU_H__ */ diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h index 5b06c31035a2..233e65522716 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -78,6 +78,8 @@ extern void kvm_s2_mmu_iterate_by_vmid(struct kvm *kvm, u16 vmid, extern void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu); extern void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu); +extern void check_nested_vcpu_requests(struct kvm_vcpu *vcpu); + struct kvm_s2_trans { phys_addr_t output; unsigned long block_size; @@ -85,7 +87,7 @@ struct kvm_s2_trans { bool readable; int level; u32 esr; - u64 upper_attr; + u64 desc; }; static inline phys_addr_t kvm_s2_trans_output(struct kvm_s2_trans *trans) @@ -115,7 +117,7 @@ static inline bool kvm_s2_trans_writable(struct kvm_s2_trans *trans) static inline bool kvm_s2_trans_executable(struct kvm_s2_trans *trans) { - return !(trans->upper_attr & BIT(54)); + return !(trans->desc & BIT(54)); } extern int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa, @@ -124,7 +126,7 @@ extern int kvm_s2_handle_perm_fault(struct kvm_vcpu *vcpu, struct kvm_s2_trans *trans); extern int kvm_inject_s2_fault(struct kvm_vcpu *vcpu, u64 esr_el2); extern void kvm_nested_s2_wp(struct kvm *kvm); -extern void kvm_nested_s2_unmap(struct kvm *kvm); +extern void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block); extern void kvm_nested_s2_flush(struct kvm *kvm); unsigned long compute_tlb_inval_range(struct kvm_s2_mmu *mmu, u64 val); @@ -205,4 +207,40 @@ static inline u64 kvm_encode_nested_level(struct kvm_s2_trans *trans) return FIELD_PREP(KVM_NV_GUEST_MAP_SZ, trans->level); } +/* Adjust alignment for the contiguous bit as per StageOA() */ +#define contiguous_bit_shift(d, wi, l) \ + ({ \ + u8 shift = 0; \ + \ + if ((d) & PTE_CONT) { \ + switch (BIT((wi)->pgshift)) { \ + case SZ_4K: \ + shift = 4; \ + break; \ + case SZ_16K: \ + shift = (l) == 2 ? 5 : 7; \ + break; \ + case SZ_64K: \ + shift = 5; \ + break; \ + } \ + } \ + \ + shift; \ + }) + +static inline unsigned int ps_to_output_size(unsigned int ps) +{ + switch (ps) { + case 0: return 32; + case 1: return 36; + case 2: return 40; + case 3: return 42; + case 4: return 44; + case 5: + default: + return 48; + } +} + #endif /* __ARM64_KVM_NESTED_H */ diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index 19278dfe7978..03f4c3d7839c 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -59,6 +59,48 @@ typedef u64 kvm_pte_t; #define KVM_PHYS_INVALID (-1ULL) +#define KVM_PTE_LEAF_ATTR_LO GENMASK(11, 2) + +#define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2) +#define KVM_PTE_LEAF_ATTR_LO_S1_AP GENMASK(7, 6) +#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO \ + ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 2 : 3; }) +#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW \ + ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 0 : 1; }) +#define KVM_PTE_LEAF_ATTR_LO_S1_SH GENMASK(9, 8) +#define KVM_PTE_LEAF_ATTR_LO_S1_SH_IS 3 +#define KVM_PTE_LEAF_ATTR_LO_S1_AF BIT(10) + +#define KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR GENMASK(5, 2) +#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R BIT(6) +#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W BIT(7) +#define KVM_PTE_LEAF_ATTR_LO_S2_SH GENMASK(9, 8) +#define KVM_PTE_LEAF_ATTR_LO_S2_SH_IS 3 +#define KVM_PTE_LEAF_ATTR_LO_S2_AF BIT(10) + +#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 50) + +#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55) + +#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54) + +#define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54) + +#define KVM_PTE_LEAF_ATTR_HI_S1_GP BIT(50) + +#define KVM_PTE_LEAF_ATTR_S2_PERMS (KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \ + KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \ + KVM_PTE_LEAF_ATTR_HI_S2_XN) + +#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2) +#define KVM_MAX_OWNER_ID 1 + +/* + * Used to indicate a pte for which a 'break-before-make' sequence is in + * progress. + */ +#define KVM_INVALID_PTE_LOCKED BIT(10) + static inline bool kvm_pte_valid(kvm_pte_t pte) { return pte & KVM_PTE_VALID; diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h new file mode 100644 index 000000000000..f8f78f622dd2 --- /dev/null +++ b/arch/arm64/include/asm/mem_encrypt.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_MEM_ENCRYPT_H +#define __ASM_MEM_ENCRYPT_H + +#include <asm/rsi.h> + +struct arm64_mem_crypt_ops { + int (*encrypt)(unsigned long addr, int numpages); + int (*decrypt)(unsigned long addr, int numpages); +}; + +int arm64_mem_crypt_ops_register(const struct arm64_mem_crypt_ops *ops); + +int set_memory_encrypted(unsigned long addr, int numpages); +int set_memory_decrypted(unsigned long addr, int numpages); + +int realm_register_memory_enc_ops(void); + +static inline bool force_dma_unencrypted(struct device *dev) +{ + return is_realm_world(); +} + +#endif /* __ASM_MEM_ENCRYPT_H */ diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 54fb014eba05..0480c61dbb4f 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -110,6 +110,8 @@ #define PAGE_END (_PAGE_END(VA_BITS_MIN)) #endif /* CONFIG_KASAN */ +#define PHYSMEM_END __pa(PAGE_END - 1) + #define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT) /* diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h index 5966ee4a6154..1d53022fc7e1 100644 --- a/arch/arm64/include/asm/mman.h +++ b/arch/arm64/include/asm/mman.h @@ -2,12 +2,16 @@ #ifndef __ASM_MMAN_H__ #define __ASM_MMAN_H__ +#include <uapi/asm/mman.h> + +#ifndef BUILD_VDSO #include <linux/compiler.h> +#include <linux/fs.h> +#include <linux/shmem_fs.h> #include <linux/types.h> -#include <uapi/asm/mman.h> static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot, - unsigned long pkey __always_unused) + unsigned long pkey) { unsigned long ret = 0; @@ -17,23 +21,36 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot, if (system_supports_mte() && (prot & PROT_MTE)) ret |= VM_MTE; +#ifdef CONFIG_ARCH_HAS_PKEYS + if (system_supports_poe()) { + ret |= pkey & BIT(0) ? VM_PKEY_BIT0 : 0; + ret |= pkey & BIT(1) ? VM_PKEY_BIT1 : 0; + ret |= pkey & BIT(2) ? VM_PKEY_BIT2 : 0; + } +#endif + return ret; } #define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey) -static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags) +static inline unsigned long arch_calc_vm_flag_bits(struct file *file, + unsigned long flags) { /* * Only allow MTE on anonymous mappings as these are guaranteed to be * backed by tags-capable memory. The vm_flags may be overridden by a * filesystem supporting MTE (RAM-based). */ - if (system_supports_mte() && (flags & MAP_ANONYMOUS)) - return VM_MTE_ALLOWED; + if (system_supports_mte()) { + if (flags & (MAP_ANONYMOUS | MAP_HUGETLB)) + return VM_MTE_ALLOWED; + if (shmem_file(file)) + return VM_MTE_ALLOWED; + } return 0; } -#define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags) +#define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags) static inline bool arch_validate_prot(unsigned long prot, unsigned long addr __always_unused) @@ -52,12 +69,29 @@ static inline bool arch_validate_prot(unsigned long prot, static inline bool arch_validate_flags(unsigned long vm_flags) { - if (!system_supports_mte()) - return true; + if (system_supports_mte()) { + /* + * only allow VM_MTE if VM_MTE_ALLOWED has been set + * previously + */ + if ((vm_flags & VM_MTE) && !(vm_flags & VM_MTE_ALLOWED)) + return false; + } + + if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) { + /* An executable GCS isn't a good idea. */ + if (vm_flags & VM_EXEC) + return false; + + /* The memory management core should prevent this */ + VM_WARN_ON(vm_flags & VM_SHARED); + } + + return true; - /* only allow VM_MTE if VM_MTE_ALLOWED has been set previously */ - return !(vm_flags & VM_MTE) || (vm_flags & VM_MTE_ALLOWED); } #define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags) +#endif /* !BUILD_VDSO */ + #endif /* ! __ASM_MMAN_H__ */ diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 65977c7783c5..2ec96d91acc6 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -25,6 +25,7 @@ typedef struct { refcount_t pinned; void *vdso; unsigned long flags; + u8 pkey_allocation_map; } mm_context_t; /* @@ -63,7 +64,6 @@ static inline bool arm64_kernel_unmapped_at_el0(void) extern void arm64_memblock_init(void); extern void paging_init(void); extern void bootmem_init(void); -extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void create_mapping_noalloc(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index bd19f4c758b7..48b3d9553b67 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -15,12 +15,13 @@ #include <linux/sched/hotplug.h> #include <linux/mm_types.h> #include <linux/pgtable.h> +#include <linux/pkeys.h> #include <asm/cacheflush.h> #include <asm/cpufeature.h> #include <asm/daifflags.h> +#include <asm/gcs.h> #include <asm/proc-fns.h> -#include <asm-generic/mm_hooks.h> #include <asm/cputype.h> #include <asm/sysreg.h> #include <asm/tlbflush.h> @@ -175,9 +176,36 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) { atomic64_set(&mm->context.id, 0); refcount_set(&mm->context.pinned, 0); + + /* pkey 0 is the default, so always reserve it. */ + mm->context.pkey_allocation_map = BIT(0); + + return 0; +} + +static inline void arch_dup_pkeys(struct mm_struct *oldmm, + struct mm_struct *mm) +{ + /* Duplicate the oldmm pkey state in mm: */ + mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map; +} + +static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) +{ + arch_dup_pkeys(oldmm, mm); + return 0; } +static inline void arch_exit_mmap(struct mm_struct *mm) +{ +} + +static inline void arch_unmap(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ +} + #ifdef CONFIG_ARM64_SW_TTBR0_PAN static inline void update_saved_ttbr0(struct task_struct *tsk, struct mm_struct *mm) @@ -267,6 +295,31 @@ static inline unsigned long mm_untag_mask(struct mm_struct *mm) return -1UL >> 8; } +/* + * Only enforce protection keys on the current process, because there is no + * user context to access POR_EL0 for another address space. + */ +static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, + bool write, bool execute, bool foreign) +{ + if (!system_supports_poe()) + return true; + + /* allow access if the VMA is not one from this process */ + if (foreign || vma_is_foreign(vma)) + return true; + + return por_el0_allows_pkey(vma_pkey(vma), write, execute); +} + +#define deactivate_mm deactivate_mm +static inline void deactivate_mm(struct task_struct *tsk, + struct mm_struct *mm) +{ + gcs_free(tsk); +} + + #include <asm-generic/mmu_context.h> #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm64/include/asm/mmzone.h b/arch/arm64/include/asm/mmzone.h deleted file mode 100644 index fa17e01d9ab2..000000000000 --- a/arch/arm64/include/asm/mmzone.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_MMZONE_H -#define __ASM_MMZONE_H - -#ifdef CONFIG_NUMA - -#include <asm/numa.h> - -extern struct pglist_data *node_data[]; -#define NODE_DATA(nid) (node_data[(nid)]) - -#endif /* CONFIG_NUMA */ -#endif /* __ASM_MMZONE_H */ diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h index 0f84518632b4..6567df8ec8ca 100644 --- a/arch/arm64/include/asm/mte.h +++ b/arch/arm64/include/asm/mte.h @@ -41,6 +41,8 @@ void mte_free_tag_storage(char *storage); static inline void set_page_mte_tagged(struct page *page) { + VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page))); + /* * Ensure that the tags written prior to this function are visible * before the page flags update. @@ -53,6 +55,8 @@ static inline bool page_mte_tagged(struct page *page) { bool ret = test_bit(PG_mte_tagged, &page->flags); + VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page))); + /* * If the page is tagged, ensure ordering with a likely subsequent * read of the tags. @@ -76,6 +80,8 @@ static inline bool page_mte_tagged(struct page *page) */ static inline bool try_page_mte_tagging(struct page *page) { + VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page))); + if (!test_and_set_bit(PG_mte_lock, &page->flags)) return true; @@ -157,6 +163,67 @@ static inline int mte_ptrace_copy_tags(struct task_struct *child, #endif /* CONFIG_ARM64_MTE */ +#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_ARM64_MTE) +static inline void folio_set_hugetlb_mte_tagged(struct folio *folio) +{ + VM_WARN_ON_ONCE(!folio_test_hugetlb(folio)); + + /* + * Ensure that the tags written prior to this function are visible + * before the folio flags update. + */ + smp_wmb(); + set_bit(PG_mte_tagged, &folio->flags); + +} + +static inline bool folio_test_hugetlb_mte_tagged(struct folio *folio) +{ + bool ret = test_bit(PG_mte_tagged, &folio->flags); + + VM_WARN_ON_ONCE(!folio_test_hugetlb(folio)); + + /* + * If the folio is tagged, ensure ordering with a likely subsequent + * read of the tags. + */ + if (ret) + smp_rmb(); + return ret; +} + +static inline bool folio_try_hugetlb_mte_tagging(struct folio *folio) +{ + VM_WARN_ON_ONCE(!folio_test_hugetlb(folio)); + + if (!test_and_set_bit(PG_mte_lock, &folio->flags)) + return true; + + /* + * The tags are either being initialised or may have been initialised + * already. Check if the PG_mte_tagged flag has been set or wait + * otherwise. + */ + smp_cond_load_acquire(&folio->flags, VAL & (1UL << PG_mte_tagged)); + + return false; +} +#else +static inline void folio_set_hugetlb_mte_tagged(struct folio *folio) +{ +} + +static inline bool folio_test_hugetlb_mte_tagged(struct folio *folio) +{ + return false; +} + +static inline bool folio_try_hugetlb_mte_tagging(struct folio *folio) +{ + return false; +} +#endif + static inline void mte_disable_tco_entry(struct task_struct *task) { if (!system_supports_mte()) diff --git a/arch/arm64/include/asm/page-def.h b/arch/arm64/include/asm/page-def.h index 792e9fe881dc..d402e08442ee 100644 --- a/arch/arm64/include/asm/page-def.h +++ b/arch/arm64/include/asm/page-def.h @@ -10,9 +10,6 @@ #include <linux/const.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #endif /* __ASM_PAGE_DEF_H */ diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index eb7071c9eb34..ee45b4e77347 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -10,10 +10,6 @@ #include <asm/ptrace.h> #ifdef CONFIG_PERF_EVENTS -struct pt_regs; -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); -extern unsigned long perf_misc_flags(struct pt_regs *regs); -#define perf_misc_flags(regs) perf_misc_flags(regs) #define perf_arch_bpf_user_pt_regs(regs) ®s->user_regs #endif diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h index 8ff5f2a2579e..e75422864d1b 100644 --- a/arch/arm64/include/asm/pgalloc.h +++ b/arch/arm64/include/asm/pgalloc.h @@ -28,7 +28,7 @@ static inline void __pud_populate(pud_t *pudp, phys_addr_t pmdp, pudval_t prot) static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp) { - pudval_t pudval = PUD_TYPE_TABLE; + pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_AF; pudval |= (mm == &init_mm) ? PUD_TABLE_UXN : PUD_TABLE_PXN; __pud_populate(pudp, __pa(pmdp), pudval); @@ -50,7 +50,7 @@ static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot) static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp) { - p4dval_t p4dval = P4D_TYPE_TABLE; + p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_AF; p4dval |= (mm == &init_mm) ? P4D_TABLE_UXN : P4D_TABLE_PXN; __p4d_populate(p4dp, __pa(pudp), p4dval); @@ -79,7 +79,7 @@ static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot) static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp) { - pgdval_t pgdval = PGD_TYPE_TABLE; + pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_AF; pgdval |= (mm == &init_mm) ? PGD_TABLE_UXN : PGD_TABLE_PXN; __pgd_populate(pgdp, __pa(p4dp), pgdval); @@ -127,14 +127,16 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) { VM_BUG_ON(mm && mm != &init_mm); - __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN); + __pmd_populate(pmdp, __pa(ptep), + PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_UXN); } static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) { VM_BUG_ON(mm == &init_mm); - __pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE | PMD_TABLE_PXN); + __pmd_populate(pmdp, page_to_phys(ptep), + PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_PXN); } #endif diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index 1f60aa1bc750..c78a988cca93 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -99,6 +99,7 @@ #define PGD_TYPE_TABLE (_AT(pgdval_t, 3) << 0) #define PGD_TABLE_BIT (_AT(pgdval_t, 1) << 1) #define PGD_TYPE_MASK (_AT(pgdval_t, 3) << 0) +#define PGD_TABLE_AF (_AT(pgdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */ #define PGD_TABLE_PXN (_AT(pgdval_t, 1) << 59) #define PGD_TABLE_UXN (_AT(pgdval_t, 1) << 60) @@ -110,6 +111,7 @@ #define P4D_TYPE_MASK (_AT(p4dval_t, 3) << 0) #define P4D_TYPE_SECT (_AT(p4dval_t, 1) << 0) #define P4D_SECT_RDONLY (_AT(p4dval_t, 1) << 7) /* AP[2] */ +#define P4D_TABLE_AF (_AT(p4dval_t, 1) << 10) /* Ignored if no FEAT_HAFT */ #define P4D_TABLE_PXN (_AT(p4dval_t, 1) << 59) #define P4D_TABLE_UXN (_AT(p4dval_t, 1) << 60) @@ -121,6 +123,7 @@ #define PUD_TYPE_MASK (_AT(pudval_t, 3) << 0) #define PUD_TYPE_SECT (_AT(pudval_t, 1) << 0) #define PUD_SECT_RDONLY (_AT(pudval_t, 1) << 7) /* AP[2] */ +#define PUD_TABLE_AF (_AT(pudval_t, 1) << 10) /* Ignored if no FEAT_HAFT */ #define PUD_TABLE_PXN (_AT(pudval_t, 1) << 59) #define PUD_TABLE_UXN (_AT(pudval_t, 1) << 60) @@ -131,11 +134,11 @@ #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) #define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) +#define PMD_TABLE_AF (_AT(pmdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */ /* * Section */ -#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) #define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */ #define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */ #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) @@ -200,11 +203,26 @@ #define PTE_PI_IDX_3 54 /* UXN */ /* + * POIndex[2:0] encoding (Permission Overlay Extension) + */ +#define PTE_PO_IDX_0 (_AT(pteval_t, 1) << 60) +#define PTE_PO_IDX_1 (_AT(pteval_t, 1) << 61) +#define PTE_PO_IDX_2 (_AT(pteval_t, 1) << 62) + +#define PTE_PO_IDX_MASK GENMASK_ULL(62, 60) + + +/* * Memory Attribute override for Stage-2 (MemAttr[3:0]) */ #define PTE_S2_MEMATTR(t) (_AT(pteval_t, (t)) << 2) /* + * Hierarchical permission for Stage-1 tables + */ +#define S1_TABLE_AP (_AT(pmdval_t, 3) << 61) + +/* * Highest possible physical address supported. */ #define PHYS_MASK_SHIFT (CONFIG_ARM64_PA_BITS) @@ -298,6 +316,10 @@ #define TCR_TBI1 (UL(1) << 38) #define TCR_HA (UL(1) << 39) #define TCR_HD (UL(1) << 40) +#define TCR_HPD0_SHIFT 41 +#define TCR_HPD0 (UL(1) << TCR_HPD0_SHIFT) +#define TCR_HPD1_SHIFT 42 +#define TCR_HPD1 (UL(1) << TCR_HPD1_SHIFT) #define TCR_TBID0 (UL(1) << 51) #define TCR_TBID1 (UL(1) << 52) #define TCR_NFD0 (UL(1) << 53) diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index b11cfb9fdd37..9f9cf13bbd95 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -35,7 +35,6 @@ #endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */ #define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_MAYBE_NG | PTE_MAYBE_SHARED | PTE_AF) #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_MAYBE_NG | PMD_MAYBE_SHARED | PMD_SECT_AF) @@ -68,8 +67,12 @@ #include <asm/cpufeature.h> #include <asm/pgtable-types.h> +#include <asm/rsi.h> extern bool arm64_use_ng_mappings; +extern unsigned long prot_ns_shared; + +#define PROT_NS_SHARED (is_realm_world() ? prot_ns_shared : 0) #define PTE_MAYBE_NG (arm64_use_ng_mappings ? PTE_NG : 0) #define PMD_MAYBE_NG (arm64_use_ng_mappings ? PMD_SECT_NG : 0) @@ -144,22 +147,32 @@ static inline bool __pure lpa2_is_enabled(void) /* 6: PTE_PXN | PTE_WRITE */ /* 7: PAGE_SHARED_EXEC PTE_PXN | PTE_WRITE | PTE_USER */ /* 8: PAGE_KERNEL_ROX PTE_UXN */ -/* 9: PTE_UXN | PTE_USER */ +/* 9: PAGE_GCS_RO PTE_UXN | PTE_USER */ /* a: PAGE_KERNEL_EXEC PTE_UXN | PTE_WRITE */ -/* b: PTE_UXN | PTE_WRITE | PTE_USER */ +/* b: PAGE_GCS PTE_UXN | PTE_WRITE | PTE_USER */ /* c: PAGE_KERNEL_RO PTE_UXN | PTE_PXN */ /* d: PAGE_READONLY PTE_UXN | PTE_PXN | PTE_USER */ /* e: PAGE_KERNEL PTE_UXN | PTE_PXN | PTE_WRITE */ /* f: PAGE_SHARED PTE_UXN | PTE_PXN | PTE_WRITE | PTE_USER */ +#define _PAGE_GCS (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_WRITE | PTE_USER) +#define _PAGE_GCS_RO (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_USER) + +#define PAGE_GCS __pgprot(_PAGE_GCS) +#define PAGE_GCS_RO __pgprot(_PAGE_GCS_RO) + #define PIE_E0 ( \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS), PIE_GCS) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO), PIE_R) | \ PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_X_O) | \ - PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX) | \ - PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX) | \ - PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R) | \ - PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW)) + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW_O)) #define PIE_E1 ( \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS), PIE_NONE_O) | \ + PIRx_ELx_PERM(pte_pi_index(_PAGE_GCS_RO), PIE_NONE_O) | \ PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_NONE_O) | \ PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_R) | \ PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RW) | \ diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 7a4f5604be3f..6986345b537a 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -34,6 +34,7 @@ #include <asm/cmpxchg.h> #include <asm/fixmap.h> +#include <asm/por.h> #include <linux/mmdebug.h> #include <linux/mm_types.h> #include <linux/sched.h> @@ -149,6 +150,24 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys) #define pte_accessible(mm, pte) \ (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte)) +static inline bool por_el0_allows_pkey(u8 pkey, bool write, bool execute) +{ + u64 por; + + if (!system_supports_poe()) + return true; + + por = read_sysreg_s(SYS_POR_EL0); + + if (write) + return por_elx_allows_write(por, pkey); + + if (execute) + return por_elx_allows_exec(por, pkey); + + return por_elx_allows_read(por, pkey); +} + /* * p??_access_permitted() is true for valid user mappings (PTE_USER * bit set, subject to the write permission check). For execute-only @@ -156,8 +175,11 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys) * not set) must return false. PROT_NONE mappings do not have the * PTE_VALID bit set. */ -#define pte_access_permitted(pte, write) \ +#define pte_access_permitted_no_overlay(pte, write) \ (((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) && (!(write) || pte_write(pte))) +#define pte_access_permitted(pte, write) \ + (pte_access_permitted_no_overlay(pte, write) && \ + por_el0_allows_pkey(FIELD_GET(PTE_PO_IDX_MASK, pte_val(pte)), write, false)) #define pmd_access_permitted(pmd, write) \ (pte_access_permitted(pmd_pte(pmd), (write))) #define pud_access_permitted(pud, write) \ @@ -243,8 +265,7 @@ static inline pte_t pte_mkspecial(pte_t pte) static inline pte_t pte_mkcont(pte_t pte) { - pte = set_pte_bit(pte, __pgprot(PTE_CONT)); - return set_pte_bit(pte, __pgprot(PTE_TYPE_PAGE)); + return set_pte_bit(pte, __pgprot(PTE_CONT)); } static inline pte_t pte_mknoncont(pte_t pte) @@ -316,7 +337,7 @@ static inline pte_t __ptep_get(pte_t *ptep) } extern void __sync_icache_dcache(pte_t pteval); -bool pgattr_change_is_safe(u64 old, u64 new); +bool pgattr_change_is_safe(pteval_t old, pteval_t new); /* * PTE bits configuration in the presence of hardware Dirty Bit Management @@ -373,10 +394,11 @@ static inline void __sync_cache_and_tags(pte_t pte, unsigned int nr_pages) /* * If the PTE would provide user space access to the tags associated * with it then ensure that the MTE tags are synchronised. Although - * pte_access_permitted() returns false for exec only mappings, they - * don't expose tags (instruction fetches don't check tags). + * pte_access_permitted_no_overlay() returns false for exec only + * mappings, they don't expose tags (instruction fetches don't check + * tags). */ - if (system_supports_mte() && pte_access_permitted(pte, false) && + if (system_supports_mte() && pte_access_permitted_no_overlay(pte, false) && !pte_special(pte) && pte_tagged(pte)) mte_sync_tags(pte, nr_pages); } @@ -384,6 +406,7 @@ static inline void __sync_cache_and_tags(pte_t pte, unsigned int nr_pages) /* * Select all bits except the pfn */ +#define pte_pgprot pte_pgprot static inline pgprot_t pte_pgprot(pte_t pte) { unsigned long pfn = pte_pfn(pte); @@ -415,11 +438,6 @@ static inline void __set_ptes(struct mm_struct *mm, } /* - * Huge pte definitions. - */ -#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) - -/* * Hugetlb definitions. */ #define HUGE_MAX_HSTATE 4 @@ -577,6 +595,14 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) return pte_pmd(set_pte_bit(pmd_pte(pmd), __pgprot(PTE_DEVMAP))); } +#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP +#define pmd_special(pte) (!!((pmd_val(pte) & PTE_SPECIAL))) +static inline pmd_t pmd_mkspecial(pmd_t pmd) +{ + return set_pmd_bit(pmd, __pgprot(PTE_SPECIAL)); +} +#endif + #define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd)) #define __phys_to_pmd_val(phys) __phys_to_pte_val(phys) #define pmd_pfn(pmd) ((__pmd_to_phys(pmd) & PMD_MASK) >> PAGE_SHIFT) @@ -594,6 +620,27 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT) #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP +#define pud_special(pte) pte_special(pud_pte(pud)) +#define pud_mkspecial(pte) pte_pud(pte_mkspecial(pud_pte(pud))) +#endif + +#define pmd_pgprot pmd_pgprot +static inline pgprot_t pmd_pgprot(pmd_t pmd) +{ + unsigned long pfn = pmd_pfn(pmd); + + return __pgprot(pmd_val(pfn_pmd(pfn, __pgprot(0))) ^ pmd_val(pmd)); +} + +#define pud_pgprot pud_pgprot +static inline pgprot_t pud_pgprot(pud_t pud) +{ + unsigned long pfn = pud_pfn(pud); + + return __pgprot(pud_val(pfn_pud(pfn, __pgprot(0))) ^ pud_val(pud)); +} + static inline void __set_pte_at(struct mm_struct *mm, unsigned long __always_unused addr, pte_t *ptep, pte_t pte, unsigned int nr) @@ -631,6 +678,11 @@ static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, #define pgprot_nx(prot) \ __pgprot_modify(prot, PTE_MAYBE_GP, PTE_PXN) +#define pgprot_decrypted(prot) \ + __pgprot_modify(prot, PROT_NS_SHARED, PROT_NS_SHARED) +#define pgprot_encrypted(prot) \ + __pgprot_modify(prot, PROT_NS_SHARED, 0) + /* * Mark the prot value as uncacheable and unbufferable. */ @@ -874,6 +926,9 @@ static inline phys_addr_t p4d_page_paddr(p4d_t p4d) static inline pud_t *p4d_to_folded_pud(p4d_t *p4dp, unsigned long addr) { + /* Ensure that 'p4dp' indexes a page table according to 'addr' */ + VM_BUG_ON(((addr >> P4D_SHIFT) ^ ((u64)p4dp >> 3)) % PTRS_PER_P4D); + return (pud_t *)PTR_ALIGN_DOWN(p4dp, PAGE_SIZE) + pud_index(addr); } @@ -998,6 +1053,9 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd) static inline p4d_t *pgd_to_folded_p4d(pgd_t *pgdp, unsigned long addr) { + /* Ensure that 'pgdp' indexes a page table according to 'addr' */ + VM_BUG_ON(((addr >> PGDIR_SHIFT) ^ ((u64)pgdp >> 3)) % PTRS_PER_PGD); + return (p4d_t *)PTR_ALIGN_DOWN(pgdp, PAGE_SIZE) + p4d_index(addr); } @@ -1103,7 +1161,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) */ const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | PTE_PRESENT_INVALID | PTE_VALID | PTE_WRITE | - PTE_GP | PTE_ATTRINDX_MASK; + PTE_GP | PTE_ATTRINDX_MASK | PTE_PO_IDX_MASK; + /* preserve the hardware dirty information */ if (pte_hw_dirty(pte)) pte = set_pte_bit(pte, __pgprot(PTE_DIRTY)); @@ -1205,15 +1264,17 @@ static inline int __ptep_clear_flush_young(struct vm_area_struct *vma, return young; } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) { + /* Operation applies to PMD table entry only if FEAT_HAFT is enabled */ + VM_WARN_ON(pmd_table(READ_ONCE(*pmdp)) && !system_supports_haft()); return __ptep_test_and_clear_young(vma, address, (pte_t *)pmdp); } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */ static inline pte_t __ptep_get_and_clear(struct mm_struct *mm, unsigned long address, pte_t *ptep) @@ -1448,6 +1509,10 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, */ #define arch_has_hw_pte_young cpu_has_hw_af +#ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG +#define arch_has_hw_nonleaf_pmd_young system_supports_haft +#endif + /* * Experimentally, it's cheap to set the access flag in hardware and we * benefit from prefaulting mappings as 'old' to start with. diff --git a/arch/arm64/include/asm/pkeys.h b/arch/arm64/include/asm/pkeys.h new file mode 100644 index 000000000000..0ca5f83ce148 --- /dev/null +++ b/arch/arm64/include/asm/pkeys.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Arm Ltd. + * + * Based on arch/x86/include/asm/pkeys.h + */ + +#ifndef _ASM_ARM64_PKEYS_H +#define _ASM_ARM64_PKEYS_H + +#define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2) + +#define arch_max_pkey() 8 + +int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, + unsigned long init_val); + +static inline bool arch_pkeys_enabled(void) +{ + return system_supports_poe(); +} + +static inline int vma_pkey(struct vm_area_struct *vma) +{ + return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT; +} + +static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma, + int prot, int pkey) +{ + if (pkey != -1) + return pkey; + + return vma_pkey(vma); +} + +static inline int execute_only_pkey(struct mm_struct *mm) +{ + // Execute-only mappings are handled by EPAN/FEAT_PAN3. + return -1; +} + +#define mm_pkey_allocation_map(mm) (mm)->context.pkey_allocation_map +#define mm_set_pkey_allocated(mm, pkey) do { \ + mm_pkey_allocation_map(mm) |= (1U << pkey); \ +} while (0) +#define mm_set_pkey_free(mm, pkey) do { \ + mm_pkey_allocation_map(mm) &= ~(1U << pkey); \ +} while (0) + +static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) +{ + /* + * "Allocated" pkeys are those that have been returned + * from pkey_alloc() or pkey 0 which is allocated + * implicitly when the mm is created. + */ + if (pkey < 0 || pkey >= arch_max_pkey()) + return false; + + return mm_pkey_allocation_map(mm) & (1U << pkey); +} + +/* + * Returns a positive, 3-bit key on success, or -1 on failure. + */ +static inline int mm_pkey_alloc(struct mm_struct *mm) +{ + /* + * Note: this is the one and only place we make sure + * that the pkey is valid as far as the hardware is + * concerned. The rest of the kernel trusts that + * only good, valid pkeys come out of here. + */ + u8 all_pkeys_mask = GENMASK(arch_max_pkey() - 1, 0); + int ret; + + if (!arch_pkeys_enabled()) + return -1; + + /* + * Are we out of pkeys? We must handle this specially + * because ffz() behavior is undefined if there are no + * zeros. + */ + if (mm_pkey_allocation_map(mm) == all_pkeys_mask) + return -1; + + ret = ffz(mm_pkey_allocation_map(mm)); + + mm_set_pkey_allocated(mm, ret); + + return ret; +} + +static inline int mm_pkey_free(struct mm_struct *mm, int pkey) +{ + if (!mm_pkey_is_allocated(mm, pkey)) + return -EINVAL; + + mm_set_pkey_free(mm, pkey); + + return 0; +} + +#endif /* _ASM_ARM64_PKEYS_H */ diff --git a/arch/arm64/include/asm/por.h b/arch/arm64/include/asm/por.h new file mode 100644 index 000000000000..e06e9f473675 --- /dev/null +++ b/arch/arm64/include/asm/por.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Arm Ltd. + */ + +#ifndef _ASM_ARM64_POR_H +#define _ASM_ARM64_POR_H + +#define POR_BITS_PER_PKEY 4 +#define POR_ELx_IDX(por_elx, idx) (((por_elx) >> ((idx) * POR_BITS_PER_PKEY)) & 0xf) + +static inline bool por_elx_allows_read(u64 por, u8 pkey) +{ + u8 perm = POR_ELx_IDX(por, pkey); + + return perm & POE_R; +} + +static inline bool por_elx_allows_write(u64 por, u8 pkey) +{ + u8 perm = POR_ELx_IDX(por, pkey); + + return perm & POE_W; +} + +static inline bool por_elx_allows_exec(u64 por, u8 pkey) +{ + u8 perm = POR_ELx_IDX(por, pkey); + + return perm & POE_X; +} + +#endif /* _ASM_ARM64_POR_H */ diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h index 006946745352..d49368886309 100644 --- a/arch/arm64/include/asm/probes.h +++ b/arch/arm64/include/asm/probes.h @@ -9,21 +9,18 @@ #include <asm/insn.h> -typedef u32 probe_opcode_t; typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); -/* architecture specific copy of original instruction */ struct arch_probe_insn { - probe_opcode_t *insn; - pstate_check_t *pstate_cc; probes_handler_t *handler; - /* restore address after step xol */ - unsigned long restore; }; #ifdef CONFIG_KPROBES -typedef u32 kprobe_opcode_t; +typedef __le32 kprobe_opcode_t; struct arch_specific_insn { struct arch_probe_insn api; + kprobe_opcode_t *xol_insn; + /* restore address after step xol */ + unsigned long xol_restore; }; #endif diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index f77371232d8c..1bf1a3b16e88 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -184,6 +184,14 @@ struct thread_struct { u64 sctlr_user; u64 svcr; u64 tpidr2_el0; + u64 por_el0; +#ifdef CONFIG_ARM64_GCS + unsigned int gcs_el0_mode; + unsigned int gcs_el0_locked; + u64 gcspr_el0; + u64 gcs_base; + u64 gcs_size; +#endif }; static inline unsigned int thread_get_vl(struct thread_struct *thread, @@ -284,22 +292,44 @@ void tls_preserve_current_state(void); .fpsimd_cpu = NR_CPUS, \ } -static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) +static inline void start_thread_common(struct pt_regs *regs, unsigned long pc, + unsigned long pstate) { - s32 previous_syscall = regs->syscallno; - memset(regs, 0, sizeof(*regs)); - regs->syscallno = previous_syscall; - regs->pc = pc; + /* + * Ensure all GPRs are zeroed, and initialize PC + PSTATE. + * The SP (or compat SP) will be initialized later. + */ + regs->user_regs = (struct user_pt_regs) { + .pc = pc, + .pstate = pstate, + }; + /* + * To allow the syscalls:sys_exit_execve tracepoint we need to preserve + * syscallno, but do not need orig_x0 or the original GPRs. + */ + regs->orig_x0 = 0; + + /* + * An exec from a kernel thread won't have an existing PMR value. + */ if (system_uses_irq_prio_masking()) - regs->pmr_save = GIC_PRIO_IRQON; + regs->pmr = GIC_PRIO_IRQON; + + /* + * The pt_regs::stackframe field must remain valid throughout this + * function as a stacktrace can be taken at any time. Any user or + * kernel task should have a valid final frame. + */ + WARN_ON_ONCE(regs->stackframe.record.fp != 0); + WARN_ON_ONCE(regs->stackframe.record.lr != 0); + WARN_ON_ONCE(regs->stackframe.type != FRAME_META_TYPE_FINAL); } static inline void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - start_thread_common(regs, pc); - regs->pstate = PSR_MODE_EL0t; + start_thread_common(regs, pc, PSR_MODE_EL0t); spectre_v4_enable_task_mitigation(current); regs->sp = sp; } @@ -308,15 +338,13 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc, static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - start_thread_common(regs, pc); - regs->pstate = PSR_AA32_MODE_USR; + unsigned long pstate = PSR_AA32_MODE_USR; if (pc & 1) - regs->pstate |= PSR_AA32_T_BIT; - -#ifdef __AARCH64EB__ - regs->pstate |= PSR_AA32_E_BIT; -#endif + pstate |= PSR_AA32_T_BIT; + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + pstate |= PSR_AA32_E_BIT; + start_thread_common(regs, pc, pstate); spectre_v4_enable_task_mitigation(current); regs->compat_sp = sp; } @@ -402,5 +430,10 @@ long get_tagged_addr_ctrl(struct task_struct *task); #define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current) #endif +int get_tsc_mode(unsigned long adr); +int set_tsc_mode(unsigned int val); +#define GET_TSC_CTL(adr) get_tsc_mode((adr)) +#define SET_TSC_CTL(val) set_tsc_mode((val)) + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PROCESSOR_H */ diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index 5b1701c76d1c..6cf4aae05219 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/arch/arm64/include/asm/ptdump.h @@ -5,6 +5,8 @@ #ifndef __ASM_PTDUMP_H #define __ASM_PTDUMP_H +#include <linux/ptdump.h> + #ifdef CONFIG_PTDUMP_CORE #include <linux/mm_types.h> @@ -21,14 +23,53 @@ struct ptdump_info { unsigned long base_addr; }; +struct ptdump_prot_bits { + u64 mask; + u64 val; + const char *set; + const char *clear; +}; + +struct ptdump_pg_level { + const struct ptdump_prot_bits *bits; + char name[4]; + int num; + u64 mask; +}; + +/* + * The page dumper groups page table entries of the same type into a single + * description. It uses pg_state to track the range information while + * iterating over the pte entries. When the continuity is broken it then + * dumps out a description of the range. + */ +struct ptdump_pg_state { + struct ptdump_state ptdump; + struct ptdump_pg_level *pg_level; + struct seq_file *seq; + const struct addr_marker *marker; + const struct mm_struct *mm; + unsigned long start_address; + int level; + u64 current_prot; + bool check_wx; + unsigned long wx_pages; + unsigned long uxn_pages; +}; + void ptdump_walk(struct seq_file *s, struct ptdump_info *info); +void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, + u64 val); #ifdef CONFIG_PTDUMP_DEBUGFS #define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64 void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name); #else static inline void ptdump_debugfs_register(struct ptdump_info *info, const char *name) { } -#endif +#endif /* CONFIG_PTDUMP_DEBUGFS */ +#else +static inline void note_page(struct ptdump_state *pt_st, unsigned long addr, + int level, u64 val) { } #endif /* CONFIG_PTDUMP_CORE */ #endif /* __ASM_PTDUMP_H */ diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index 0abe975d68a8..47ff8654c5ec 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -98,6 +98,8 @@ #include <linux/bug.h> #include <linux/types.h> +#include <asm/stacktrace/frame.h> + /* sizeof(struct user) for AArch32 */ #define COMPAT_USER_SZ 296 @@ -149,8 +151,7 @@ static inline unsigned long pstate_to_compat_psr(const unsigned long pstate) /* * This struct defines the way the registers are stored on the stack during an - * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for - * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs. + * exception. struct user_pt_regs must form a prefix of struct pt_regs. */ struct pt_regs { union { @@ -163,23 +164,20 @@ struct pt_regs { }; }; u64 orig_x0; -#ifdef __AARCH64EB__ - u32 unused2; - s32 syscallno; -#else s32 syscallno; - u32 unused2; -#endif + u32 pmr; + u64 sdei_ttbr1; - /* Only valid when ARM64_HAS_GIC_PRIO_MASKING is enabled. */ - u64 pmr_save; - u64 stackframe[2]; + struct frame_record_meta stackframe; /* Only valid for some EL1 exceptions. */ u64 lockdep_hardirqs; u64 exit_rcu; }; +/* For correct stack alignment, pt_regs has to be a multiple of 16 bytes. */ +static_assert(IS_ALIGNED(sizeof(struct pt_regs), 16)); + static inline bool in_syscall(struct pt_regs const *regs) { return regs->syscallno != NO_SYSCALL; @@ -213,7 +211,7 @@ static inline void forget_syscall(struct pt_regs *regs) #define irqs_priority_unmasked(regs) \ (system_uses_irq_prio_masking() ? \ - (regs)->pmr_save == GIC_PRIO_IRQON : \ + (regs)->pmr == GIC_PRIO_IRQON : \ true) #define interrupts_enabled(regs) \ diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h new file mode 100644 index 000000000000..188cbb9b23f5 --- /dev/null +++ b/arch/arm64/include/asm/rsi.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 ARM Ltd. + */ + +#ifndef __ASM_RSI_H_ +#define __ASM_RSI_H_ + +#include <linux/errno.h> +#include <linux/jump_label.h> +#include <asm/rsi_cmds.h> + +DECLARE_STATIC_KEY_FALSE(rsi_present); + +void __init arm64_rsi_init(void); + +bool __arm64_is_protected_mmio(phys_addr_t base, size_t size); + +static inline bool is_realm_world(void) +{ + return static_branch_unlikely(&rsi_present); +} + +static inline int rsi_set_memory_range(phys_addr_t start, phys_addr_t end, + enum ripas state, unsigned long flags) +{ + unsigned long ret; + phys_addr_t top; + + while (start != end) { + ret = rsi_set_addr_range_state(start, end, state, flags, &top); + if (ret || top < start || top > end) + return -EINVAL; + start = top; + } + + return 0; +} + +/* + * Convert the specified range to RAM. Do not use this if you rely on the + * contents of a page that may already be in RAM state. + */ +static inline int rsi_set_memory_range_protected(phys_addr_t start, + phys_addr_t end) +{ + return rsi_set_memory_range(start, end, RSI_RIPAS_RAM, + RSI_CHANGE_DESTROYED); +} + +/* + * Convert the specified range to RAM. Do not convert any pages that may have + * been DESTROYED, without our permission. + */ +static inline int rsi_set_memory_range_protected_safe(phys_addr_t start, + phys_addr_t end) +{ + return rsi_set_memory_range(start, end, RSI_RIPAS_RAM, + RSI_NO_CHANGE_DESTROYED); +} + +static inline int rsi_set_memory_range_shared(phys_addr_t start, + phys_addr_t end) +{ + return rsi_set_memory_range(start, end, RSI_RIPAS_EMPTY, + RSI_CHANGE_DESTROYED); +} +#endif /* __ASM_RSI_H_ */ diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h new file mode 100644 index 000000000000..e6a211001bd3 --- /dev/null +++ b/arch/arm64/include/asm/rsi_cmds.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 ARM Ltd. + */ + +#ifndef __ASM_RSI_CMDS_H +#define __ASM_RSI_CMDS_H + +#include <linux/arm-smccc.h> + +#include <asm/rsi_smc.h> + +#define RSI_GRANULE_SHIFT 12 +#define RSI_GRANULE_SIZE (_AC(1, UL) << RSI_GRANULE_SHIFT) + +enum ripas { + RSI_RIPAS_EMPTY = 0, + RSI_RIPAS_RAM = 1, + RSI_RIPAS_DESTROYED = 2, + RSI_RIPAS_DEV = 3, +}; + +static inline unsigned long rsi_request_version(unsigned long req, + unsigned long *out_lower, + unsigned long *out_higher) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_ABI_VERSION, req, 0, 0, 0, 0, 0, 0, &res); + + if (out_lower) + *out_lower = res.a1; + if (out_higher) + *out_higher = res.a2; + + return res.a0; +} + +static inline unsigned long rsi_get_realm_config(struct realm_config *cfg) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_REALM_CONFIG, virt_to_phys(cfg), + 0, 0, 0, 0, 0, 0, &res); + return res.a0; +} + +static inline unsigned long rsi_ipa_state_get(phys_addr_t start, + phys_addr_t end, + enum ripas *state, + phys_addr_t *top) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_IPA_STATE_GET, + start, end, 0, 0, 0, 0, 0, + &res); + + if (res.a0 == RSI_SUCCESS) { + if (top) + *top = res.a1; + if (state) + *state = res.a2; + } + + return res.a0; +} + +static inline long rsi_set_addr_range_state(phys_addr_t start, + phys_addr_t end, + enum ripas state, + unsigned long flags, + phys_addr_t *top) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state, + flags, 0, 0, 0, &res); + + if (top) + *top = res.a1; + + if (res.a2 != RSI_ACCEPT) + return -EPERM; + + return res.a0; +} + +/** + * rsi_attestation_token_init - Initialise the operation to retrieve an + * attestation token. + * + * @challenge: The challenge data to be used in the attestation token + * generation. + * @size: Size of the challenge data in bytes. + * + * Initialises the attestation token generation and returns an upper bound + * on the attestation token size that can be used to allocate an adequate + * buffer. The caller is expected to subsequently call + * rsi_attestation_token_continue() to retrieve the attestation token data on + * the same CPU. + * + * Returns: + * On success, returns the upper limit of the attestation report size. + * Otherwise, -EINVAL + */ +static inline long +rsi_attestation_token_init(const u8 *challenge, unsigned long size) +{ + struct arm_smccc_1_2_regs regs = { 0 }; + + /* The challenge must be at least 32bytes and at most 64bytes */ + if (!challenge || size < 32 || size > 64) + return -EINVAL; + + regs.a0 = SMC_RSI_ATTESTATION_TOKEN_INIT; + memcpy(®s.a1, challenge, size); + arm_smccc_1_2_smc(®s, ®s); + + if (regs.a0 == RSI_SUCCESS) + return regs.a1; + + return -EINVAL; +} + +/** + * rsi_attestation_token_continue - Continue the operation to retrieve an + * attestation token. + * + * @granule: {I}PA of the Granule to which the token will be written. + * @offset: Offset within Granule to start of buffer in bytes. + * @size: The size of the buffer. + * @len: The number of bytes written to the buffer. + * + * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The caller + * is expected to call rsi_attestation_token_init() before calling this + * function to retrieve the attestation token. + * + * Return: + * * %RSI_SUCCESS - Attestation token retrieved successfully. + * * %RSI_INCOMPLETE - Token generation is not complete. + * * %RSI_ERROR_INPUT - A parameter was not valid. + * * %RSI_ERROR_STATE - Attestation not in progress. + */ +static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule, + unsigned long offset, + unsigned long size, + unsigned long *len) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE, + granule, offset, size, 0, &res); + + if (len) + *len = res.a1; + return res.a0; +} + +#endif /* __ASM_RSI_CMDS_H */ diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h new file mode 100644 index 000000000000..6cb070eca9e9 --- /dev/null +++ b/arch/arm64/include/asm/rsi_smc.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 ARM Ltd. + */ + +#ifndef __ASM_RSI_SMC_H_ +#define __ASM_RSI_SMC_H_ + +#include <linux/arm-smccc.h> + +/* + * This file describes the Realm Services Interface (RSI) Application Binary + * Interface (ABI) for SMC calls made from within the Realm to the RMM and + * serviced by the RMM. + */ + +/* + * The major version number of the RSI implementation. This is increased when + * the binary format or semantics of the SMC calls change. + */ +#define RSI_ABI_VERSION_MAJOR UL(1) + +/* + * The minor version number of the RSI implementation. This is increased when + * a bug is fixed, or a feature is added without breaking binary compatibility. + */ +#define RSI_ABI_VERSION_MINOR UL(0) + +#define RSI_ABI_VERSION ((RSI_ABI_VERSION_MAJOR << 16) | \ + RSI_ABI_VERSION_MINOR) + +#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16) +#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF) + +#define RSI_SUCCESS UL(0) +#define RSI_ERROR_INPUT UL(1) +#define RSI_ERROR_STATE UL(2) +#define RSI_INCOMPLETE UL(3) +#define RSI_ERROR_UNKNOWN UL(4) + +#define SMC_RSI_FID(n) ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD, \ + n) + +/* + * Returns RSI version. + * + * arg1 == Requested interface revision + * ret0 == Status / error + * ret1 == Lower implemented interface revision + * ret2 == Higher implemented interface revision + */ +#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190) + +/* + * Read feature register. + * + * arg1 == Feature register index + * ret0 == Status / error + * ret1 == Feature register value + */ +#define SMC_RSI_FEATURES SMC_RSI_FID(0x191) + +/* + * Read measurement for the current Realm. + * + * arg1 == Index, which measurements slot to read + * ret0 == Status / error + * ret1 == Measurement value, bytes: 0 - 7 + * ret2 == Measurement value, bytes: 8 - 15 + * ret3 == Measurement value, bytes: 16 - 23 + * ret4 == Measurement value, bytes: 24 - 31 + * ret5 == Measurement value, bytes: 32 - 39 + * ret6 == Measurement value, bytes: 40 - 47 + * ret7 == Measurement value, bytes: 48 - 55 + * ret8 == Measurement value, bytes: 56 - 63 + */ +#define SMC_RSI_MEASUREMENT_READ SMC_RSI_FID(0x192) + +/* + * Extend Realm Extensible Measurement (REM) value. + * + * arg1 == Index, which measurements slot to extend + * arg2 == Size of realm measurement in bytes, max 64 bytes + * arg3 == Measurement value, bytes: 0 - 7 + * arg4 == Measurement value, bytes: 8 - 15 + * arg5 == Measurement value, bytes: 16 - 23 + * arg6 == Measurement value, bytes: 24 - 31 + * arg7 == Measurement value, bytes: 32 - 39 + * arg8 == Measurement value, bytes: 40 - 47 + * arg9 == Measurement value, bytes: 48 - 55 + * arg10 == Measurement value, bytes: 56 - 63 + * ret0 == Status / error + */ +#define SMC_RSI_MEASUREMENT_EXTEND SMC_RSI_FID(0x193) + +/* + * Initialize the operation to retrieve an attestation token. + * + * arg1 == Challenge value, bytes: 0 - 7 + * arg2 == Challenge value, bytes: 8 - 15 + * arg3 == Challenge value, bytes: 16 - 23 + * arg4 == Challenge value, bytes: 24 - 31 + * arg5 == Challenge value, bytes: 32 - 39 + * arg6 == Challenge value, bytes: 40 - 47 + * arg7 == Challenge value, bytes: 48 - 55 + * arg8 == Challenge value, bytes: 56 - 63 + * ret0 == Status / error + * ret1 == Upper bound of token size in bytes + */ +#define SMC_RSI_ATTESTATION_TOKEN_INIT SMC_RSI_FID(0x194) + +/* + * Continue the operation to retrieve an attestation token. + * + * arg1 == The IPA of token buffer + * arg2 == Offset within the granule of the token buffer + * arg3 == Size of the granule buffer + * ret0 == Status / error + * ret1 == Length of token bytes copied to the granule buffer + */ +#define SMC_RSI_ATTESTATION_TOKEN_CONTINUE SMC_RSI_FID(0x195) + +#ifndef __ASSEMBLY__ + +struct realm_config { + union { + struct { + unsigned long ipa_bits; /* Width of IPA in bits */ + unsigned long hash_algo; /* Hash algorithm */ + }; + u8 pad[0x200]; + }; + union { + u8 rpv[64]; /* Realm Personalization Value */ + u8 pad2[0xe00]; + }; + /* + * The RMM requires the configuration structure to be aligned to a 4k + * boundary, ensure this happens by aligning this structure. + */ +} __aligned(0x1000); + +#endif /* __ASSEMBLY__ */ + +/* + * Read configuration for the current Realm. + * + * arg1 == struct realm_config addr + * ret0 == Status / error + */ +#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(0x196) + +/* + * Request RIPAS of a target IPA range to be changed to a specified value. + * + * arg1 == Base IPA address of target region + * arg2 == Top of the region + * arg3 == RIPAS value + * arg4 == flags + * ret0 == Status / error + * ret1 == Top of modified IPA range + * ret2 == Whether the Host accepted or rejected the request + */ +#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(0x197) + +#define RSI_NO_CHANGE_DESTROYED UL(0) +#define RSI_CHANGE_DESTROYED UL(1) + +#define RSI_ACCEPT UL(0) +#define RSI_REJECT UL(1) + +/* + * Get RIPAS of a target IPA range. + * + * arg1 == Base IPA of target region + * arg2 == End of target IPA region + * ret0 == Status / error + * ret1 == Top of IPA region which has the reported RIPAS value + * ret2 == RIPAS value + */ +#define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198) + +/* + * Make a Host call. + * + * arg1 == IPA of host call structure + * ret0 == Status / error + */ +#define SMC_RSI_HOST_CALL SMC_RSI_FID(0x199) + +#endif /* __ASM_RSI_SMC_H_ */ diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h index 2e010ea76be2..a76f9b387a26 100644 --- a/arch/arm64/include/asm/scs.h +++ b/arch/arm64/include/asm/scs.h @@ -46,8 +46,14 @@ static inline void dynamic_scs_init(void) static inline void dynamic_scs_init(void) {} #endif +enum { + EDYNSCS_INVALID_CIE_HEADER = 1, + EDYNSCS_INVALID_CIE_SDATA_SIZE = 2, + EDYNSCS_INVALID_FDE_AUGM_DATA_SIZE = 3, + EDYNSCS_INVALID_CFA_OPCODE = 4, +}; + int __pi_scs_patch(const u8 eh_frame[], int size); -asmlinkage void __pi_scs_patch_vmlinux(void); #endif /* __ASSEMBLY __ */ diff --git a/arch/arm64/include/asm/set_memory.h b/arch/arm64/include/asm/set_memory.h index 0f740b781187..37774c793006 100644 --- a/arch/arm64/include/asm/set_memory.h +++ b/arch/arm64/include/asm/set_memory.h @@ -3,6 +3,7 @@ #ifndef _ASM_ARM64_SET_MEMORY_H #define _ASM_ARM64_SET_MEMORY_H +#include <asm/mem_encrypt.h> #include <asm-generic/set_memory.h> bool can_set_direct_map(void); @@ -14,4 +15,7 @@ int set_direct_map_invalid_noflush(struct page *page); int set_direct_map_default_noflush(struct page *page); bool kernel_page_present(struct page *page); +int set_memory_encrypted(unsigned long addr, int numpages); +int set_memory_decrypted(unsigned long addr, int numpages); + #endif /* _ASM_ARM64_SET_MEMORY_H */ diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h index f63dc654e545..821a8fdd31af 100644 --- a/arch/arm64/include/asm/stacktrace/common.h +++ b/arch/arm64/include/asm/stacktrace/common.h @@ -60,13 +60,27 @@ static inline void unwind_init_common(struct unwind_state *state) state->stack = stackinfo_get_unknown(); } -static struct stack_info *unwind_find_next_stack(const struct unwind_state *state, - unsigned long sp, - unsigned long size) +/** + * unwind_find_stack() - Find the accessible stack which entirely contains an + * object. + * + * @state: the current unwind state. + * @sp: the base address of the object. + * @size: the size of the object. + * + * Return: a pointer to the relevant stack_info if found; NULL otherwise. + */ +static struct stack_info *unwind_find_stack(struct unwind_state *state, + unsigned long sp, + unsigned long size) { - for (int i = 0; i < state->nr_stacks; i++) { - struct stack_info *info = &state->stacks[i]; + struct stack_info *info = &state->stack; + if (stackinfo_on_stack(info, sp, size)) + return info; + + for (int i = 0; i < state->nr_stacks; i++) { + info = &state->stacks[i]; if (stackinfo_on_stack(info, sp, size)) return info; } @@ -75,36 +89,31 @@ static struct stack_info *unwind_find_next_stack(const struct unwind_state *stat } /** - * unwind_consume_stack() - Check if an object is on an accessible stack, - * updating stack boundaries so that future unwind steps cannot consume this - * object again. + * unwind_consume_stack() - Update stack boundaries so that future unwind steps + * cannot consume this object again. * * @state: the current unwind state. + * @info: the stack_info of the stack containing the object. * @sp: the base address of the object. * @size: the size of the object. * * Return: 0 upon success, an error code otherwise. */ -static inline int unwind_consume_stack(struct unwind_state *state, - unsigned long sp, - unsigned long size) +static inline void unwind_consume_stack(struct unwind_state *state, + struct stack_info *info, + unsigned long sp, + unsigned long size) { - struct stack_info *next; - - if (stackinfo_on_stack(&state->stack, sp, size)) - goto found; - - next = unwind_find_next_stack(state, sp, size); - if (!next) - return -EINVAL; + struct stack_info tmp; /* * Stack transitions are strictly one-way, and once we've * transitioned from one stack to another, it's never valid to * unwind back to the old stack. * - * Remove the current stack from the list of stacks so that it cannot - * be found on a subsequent transition. + * Destroy the old stack info so that it cannot be found upon a + * subsequent transition. If the stack has not changed, we'll + * immediately restore the current stack info. * * Note that stacks can nest in several valid orders, e.g. * @@ -115,16 +124,15 @@ static inline int unwind_consume_stack(struct unwind_state *state, * ... so we do not check the specific order of stack * transitions. */ - state->stack = *next; - *next = stackinfo_get_unknown(); + tmp = *info; + *info = stackinfo_get_unknown(); + state->stack = tmp; -found: /* * Future unwind steps can only consume stack above this frame record. * Update the current stack to start immediately above it. */ state->stack.low = sp + size; - return 0; } /** @@ -137,21 +145,25 @@ found: static inline int unwind_next_frame_record(struct unwind_state *state) { + struct stack_info *info; + struct frame_record *record; unsigned long fp = state->fp; - int err; if (fp & 0x7) return -EINVAL; - err = unwind_consume_stack(state, fp, 16); - if (err) - return err; + info = unwind_find_stack(state, fp, sizeof(*record)); + if (!info) + return -EINVAL; + + unwind_consume_stack(state, info, fp, sizeof(*record)); /* * Record this frame record's values. */ - state->fp = READ_ONCE(*(unsigned long *)(fp)); - state->pc = READ_ONCE(*(unsigned long *)(fp + 8)); + record = (struct frame_record *)fp; + state->fp = READ_ONCE(record->fp); + state->pc = READ_ONCE(record->lr); return 0; } diff --git a/arch/arm64/include/asm/stacktrace/frame.h b/arch/arm64/include/asm/stacktrace/frame.h new file mode 100644 index 000000000000..0ee0f6ba0fd8 --- /dev/null +++ b/arch/arm64/include/asm/stacktrace/frame.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_STACKTRACE_FRAME_H +#define __ASM_STACKTRACE_FRAME_H + +/* + * - FRAME_META_TYPE_NONE + * + * This value is reserved. + * + * - FRAME_META_TYPE_FINAL + * + * The record is the last entry on the stack. + * Unwinding should terminate successfully. + * + * - FRAME_META_TYPE_PT_REGS + * + * The record is embedded within a struct pt_regs, recording the registers at + * an arbitrary point in time. + * Unwinding should consume pt_regs::pc, followed by pt_regs::lr. + * + * Note: all other values are reserved and should result in unwinding + * terminating with an error. + */ +#define FRAME_META_TYPE_NONE 0 +#define FRAME_META_TYPE_FINAL 1 +#define FRAME_META_TYPE_PT_REGS 2 + +#ifndef __ASSEMBLY__ +/* + * A standard AAPCS64 frame record. + */ +struct frame_record { + u64 fp; + u64 lr; +}; + +/* + * A metadata frame record indicating a special unwind. + * The record::{fp,lr} fields must be zero to indicate the presence of + * metadata. + */ +struct frame_record_meta { + struct frame_record record; + u64 type; +}; +#endif /* __ASSEMBLY */ + +#endif /* __ASM_STACKTRACE_FRAME_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 4a9ea103817e..9c98ff448bd9 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -109,6 +109,9 @@ #define set_pstate_ssbs(x) asm volatile(SET_PSTATE_SSBS(x)) #define set_pstate_dit(x) asm volatile(SET_PSTATE_DIT(x)) +/* Register-based PAN access, for save/restore purposes */ +#define SYS_PSTATE_PAN sys_reg(3, 0, 4, 2, 3) + #define __SYS_BARRIER_INSN(CRm, op2, Rt) \ __emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f)) @@ -325,7 +328,25 @@ #define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0) #define SYS_PAR_EL1_F BIT(0) +/* When PAR_EL1.F == 1 */ #define SYS_PAR_EL1_FST GENMASK(6, 1) +#define SYS_PAR_EL1_PTW BIT(8) +#define SYS_PAR_EL1_S BIT(9) +#define SYS_PAR_EL1_AssuredOnly BIT(12) +#define SYS_PAR_EL1_TopLevel BIT(13) +#define SYS_PAR_EL1_Overlay BIT(14) +#define SYS_PAR_EL1_DirtyBit BIT(15) +#define SYS_PAR_EL1_F1_IMPDEF GENMASK_ULL(63, 48) +#define SYS_PAR_EL1_F1_RES0 (BIT(7) | BIT(10) | GENMASK_ULL(47, 16)) +#define SYS_PAR_EL1_RES1 BIT(11) +/* When PAR_EL1.F == 0 */ +#define SYS_PAR_EL1_SH GENMASK_ULL(8, 7) +#define SYS_PAR_EL1_NS BIT(9) +#define SYS_PAR_EL1_F0_IMPDEF BIT(10) +#define SYS_PAR_EL1_NSE BIT(11) +#define SYS_PAR_EL1_PA GENMASK_ULL(51, 12) +#define SYS_PAR_EL1_ATTR GENMASK_ULL(63, 56) +#define SYS_PAR_EL1_F0_RES0 (GENMASK_ULL(6, 1) | GENMASK_ULL(55, 52)) /*** Statistical Profiling Extension ***/ #define PMSEVFR_EL1_RES0_IMP \ @@ -403,7 +424,6 @@ #define SYS_PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2) #define SYS_PMOVSCLR_EL0 sys_reg(3, 3, 9, 12, 3) #define SYS_PMSWINC_EL0 sys_reg(3, 3, 9, 12, 4) -#define SYS_PMSELR_EL0 sys_reg(3, 3, 9, 12, 5) #define SYS_PMCEID0_EL0 sys_reg(3, 3, 9, 12, 6) #define SYS_PMCEID1_EL0 sys_reg(3, 3, 9, 12, 7) #define SYS_PMCCNTR_EL0 sys_reg(3, 3, 9, 13, 0) @@ -652,6 +672,7 @@ #define OP_AT_S12E1W sys_insn(AT_Op0, 4, AT_CRn, 8, 5) #define OP_AT_S12E0R sys_insn(AT_Op0, 4, AT_CRn, 8, 6) #define OP_AT_S12E0W sys_insn(AT_Op0, 4, AT_CRn, 8, 7) +#define OP_AT_S1E2A sys_insn(AT_Op0, 4, AT_CRn, 9, 2) /* TLBI instructions */ #define TLBI_Op0 1 @@ -1077,6 +1098,29 @@ #define POE_RXW UL(0x7) #define POE_MASK UL(0xf) +/* Initial value for Permission Overlay Extension for EL0 */ +#define POR_EL0_INIT POE_RXW + +/* + * Definitions for Guarded Control Stack + */ + +#define GCS_CAP_ADDR_MASK GENMASK(63, 12) +#define GCS_CAP_ADDR_SHIFT 12 +#define GCS_CAP_ADDR_WIDTH 52 +#define GCS_CAP_ADDR(x) FIELD_GET(GCS_CAP_ADDR_MASK, x) + +#define GCS_CAP_TOKEN_MASK GENMASK(11, 0) +#define GCS_CAP_TOKEN_SHIFT 0 +#define GCS_CAP_TOKEN_WIDTH 12 +#define GCS_CAP_TOKEN(x) FIELD_GET(GCS_CAP_TOKEN_MASK, x) + +#define GCS_CAP_VALID_TOKEN 0x1 +#define GCS_CAP_IN_PROGRESS_TOKEN 0x5 + +#define GCS_CAP(x) ((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \ + GCS_CAP_VALID_TOKEN) + #define ARM64_FEATURE_FIELD_BITS 4 /* Defined for compatibility only, do not add new users. */ diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index e72a3bf9e563..1114c1c3300a 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -81,6 +81,7 @@ void arch_setup_new_exec(void); #define TIF_SME 27 /* SME in use */ #define TIF_SME_VL_INHERIT 28 /* Inherit SME vl_onexec across exec */ #define TIF_KERNEL_FPSTATE 29 /* Task is in a kernel mode FPSIMD section */ +#define TIF_TSC_SIGSEGV 30 /* SIGSEGV on counter-timer access */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) @@ -97,6 +98,7 @@ void arch_setup_new_exec(void); #define _TIF_SVE (1 << TIF_SVE) #define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT) #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) +#define _TIF_TSC_SIGSEGV (1 << TIF_TSC_SIGSEGV) #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \ diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 95fbc8c05607..bc94e036a26b 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -431,6 +431,23 @@ do { \ #define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \ __flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false, kvm_lpa2_is_enabled()); +static inline bool __flush_tlb_range_limit_excess(unsigned long start, + unsigned long end, unsigned long pages, unsigned long stride) +{ + /* + * When the system does not support TLB range based flush + * operation, (MAX_DVM_OPS - 1) pages can be handled. But + * with TLB range based operation, MAX_TLBI_RANGE_PAGES + * pages can be handled. + */ + if ((!system_supports_tlb_range() && + (end - start) >= (MAX_DVM_OPS * stride)) || + pages > MAX_TLBI_RANGE_PAGES) + return true; + + return false; +} + static inline void __flush_tlb_range_nosync(struct vm_area_struct *vma, unsigned long start, unsigned long end, unsigned long stride, bool last_level, @@ -442,15 +459,7 @@ static inline void __flush_tlb_range_nosync(struct vm_area_struct *vma, end = round_up(end, stride); pages = (end - start) >> PAGE_SHIFT; - /* - * When not uses TLB range ops, we can handle up to - * (MAX_DVM_OPS - 1) pages; - * When uses TLB range ops, we can handle up to - * MAX_TLBI_RANGE_PAGES pages. - */ - if ((!system_supports_tlb_range() && - (end - start) >= (MAX_DVM_OPS * stride)) || - pages > MAX_TLBI_RANGE_PAGES) { + if (__flush_tlb_range_limit_excess(start, end, pages, stride)) { flush_tlb_mm(vma->vm_mm); return; } @@ -492,19 +501,21 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - unsigned long addr; + const unsigned long stride = PAGE_SIZE; + unsigned long pages; - if ((end - start) > (MAX_DVM_OPS * PAGE_SIZE)) { + start = round_down(start, stride); + end = round_up(end, stride); + pages = (end - start) >> PAGE_SHIFT; + + if (__flush_tlb_range_limit_excess(start, end, pages, stride)) { flush_tlb_all(); return; } - start = __TLBI_VADDR(start, 0); - end = __TLBI_VADDR(end, 0); - dsb(ishst); - for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) - __tlbi(vaale1is, addr); + __flush_tlb_range_op(vaale1is, start, pages, stride, 0, + TLBI_TTL_UNKNOWN, false, lpa2_is_enabled()); dsb(ish); isb(); } diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 0f6ef432fb84..341174bf9106 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -5,6 +5,7 @@ #include <linux/cpumask.h> #ifdef CONFIG_NUMA +#include <asm/numa.h> struct pci_bus; int pcibus_to_node(struct pci_bus *bus); @@ -25,10 +26,6 @@ void update_freq_counters_refs(void); #define arch_scale_freq_invariant topology_scale_freq_invariant #define arch_scale_freq_ref topology_get_freq_ref -#ifdef CONFIG_ACPI_CPPC_LIB -#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc -#endif - /* Replace task scheduler's default cpu-invariant accounting */ #define arch_scale_cpu_capacity topology_get_cpu_scale diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index eefe766d6161..d780d1bd2eac 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -25,6 +25,7 @@ try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn) void force_signal_inject(int signal, int code, unsigned long address, unsigned long err); void arm64_notify_segfault(unsigned long addr); void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str); +void arm64_force_sig_fault_pkey(unsigned long far, const char *str, int pkey); void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str); void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str); diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 1aa4ecb73429..5b91803201ef 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -502,4 +502,44 @@ static inline size_t probe_subpage_writeable(const char __user *uaddr, #endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */ +#ifdef CONFIG_ARM64_GCS + +static inline int gcssttr(unsigned long __user *addr, unsigned long val) +{ + register unsigned long __user *_addr __asm__ ("x0") = addr; + register unsigned long _val __asm__ ("x1") = val; + int err = 0; + + /* GCSSTTR x1, x0 */ + asm volatile( + "1: .inst 0xd91f1c01\n" + "2: \n" + _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %w0) + : "+r" (err) + : "rZ" (_val), "r" (_addr) + : "memory"); + + return err; +} + +static inline void put_user_gcs(unsigned long val, unsigned long __user *addr, + int *err) +{ + int ret; + + if (!access_ok((char __user *)addr, sizeof(u64))) { + *err = -EFAULT; + return; + } + + uaccess_ttbr0_enable(); + ret = gcssttr(addr, val); + if (ret != 0) + *err = ret; + uaccess_ttbr0_disable(); +} + + +#endif /* CONFIG_ARM64_GCS */ + #endif /* __ASM_UACCESS_H */ diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h index 2b09495499c6..014b02897f8e 100644 --- a/arch/arm64/include/asm/uprobes.h +++ b/arch/arm64/include/asm/uprobes.h @@ -10,11 +10,9 @@ #include <asm/insn.h> #include <asm/probes.h> -#define MAX_UINSN_BYTES AARCH64_INSN_SIZE - #define UPROBE_SWBP_INSN cpu_to_le32(BRK64_OPCODE_UPROBES) #define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE -#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES +#define UPROBE_XOL_SLOT_BYTES AARCH64_INSN_SIZE typedef __le32 uprobe_opcode_t; @@ -23,8 +21,8 @@ struct arch_uprobe_task { struct arch_uprobe { union { - u8 insn[MAX_UINSN_BYTES]; - u8 ixol[MAX_UINSN_BYTES]; + __le32 insn; + __le32 ixol; }; struct arch_probe_insn api; bool simulate; diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h index 4305995c8f82..3e3c3fdb1842 100644 --- a/arch/arm64/include/asm/vdso.h +++ b/arch/arm64/include/asm/vdso.h @@ -5,13 +5,6 @@ #ifndef __ASM_VDSO_H #define __ASM_VDSO_H -/* - * Default link address for the vDSO. - * Since we randomise the VDSO mapping, there's little point in trying - * to prelink this. - */ -#define VDSO_LBASE 0x0 - #define __VVAR_PAGES 2 #ifndef __ASSEMBLY__ @@ -20,7 +13,7 @@ #define VDSO_SYMBOL(base, name) \ ({ \ - (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ + (void *)(vdso_offset_##name + (unsigned long)(base)); \ }) extern char vdso_start[], vdso_end[]; diff --git a/arch/arm64/include/asm/vdso/getrandom.h b/arch/arm64/include/asm/vdso/getrandom.h new file mode 100644 index 000000000000..342f807e2044 --- /dev/null +++ b/arch/arm64/include/asm/vdso/getrandom.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_VDSO_GETRANDOM_H +#define __ASM_VDSO_GETRANDOM_H + +#ifndef __ASSEMBLY__ + +#include <asm/unistd.h> +#include <asm/vdso/vsyscall.h> +#include <vdso/datapage.h> + +/** + * getrandom_syscall - Invoke the getrandom() syscall. + * @buffer: Destination buffer to fill with random bytes. + * @len: Size of @buffer in bytes. + * @flags: Zero or more GRND_* flags. + * Returns: The number of random bytes written to @buffer, or a negative value indicating an error. + */ +static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, unsigned int _flags) +{ + register void *buffer asm ("x0") = _buffer; + register size_t len asm ("x1") = _len; + register unsigned int flags asm ("x2") = _flags; + register long ret asm ("x0"); + register long nr asm ("x8") = __NR_getrandom; + + asm volatile( + " svc #0\n" + : "=r" (ret) + : "r" (buffer), "r" (len), "r" (flags), "r" (nr) + : "memory"); + + return ret; +} + +static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) +{ + /* + * The RNG data is in the real VVAR data page, but if a task belongs to a time namespace + * then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_ + * PAGE_OFFSET points to the real VVAR page. + */ + if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS) + return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * (1UL << CONFIG_PAGE_SHIFT); + return &_vdso_rng_data; +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_VDSO_GETRANDOM_H */ diff --git a/arch/arm64/include/asm/vdso/vsyscall.h b/arch/arm64/include/asm/vdso/vsyscall.h index f94b1457c117..eea51946d45a 100644 --- a/arch/arm64/include/asm/vdso/vsyscall.h +++ b/arch/arm64/include/asm/vdso/vsyscall.h @@ -2,11 +2,18 @@ #ifndef __ASM_VDSO_VSYSCALL_H #define __ASM_VDSO_VSYSCALL_H +#define __VDSO_RND_DATA_OFFSET 480 + #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> +enum vvar_pages { + VVAR_DATA_PAGE_OFFSET, + VVAR_TIMENS_PAGE_OFFSET, + VVAR_NR_PAGES, +}; + #define VDSO_PRECISION_MASK ~(0xFF00ULL<<48) extern struct vdso_data *vdso_data; @@ -22,7 +29,14 @@ struct vdso_data *__arm64_get_k_vdso_data(void) #define __arch_get_k_vdso_data __arm64_get_k_vdso_data static __always_inline -void __arm64_update_vsyscall(struct vdso_data *vdata, struct timekeeper *tk) +struct vdso_rng_data *__arm64_get_k_vdso_rnd_data(void) +{ + return (void *)vdso_data + __VDSO_RND_DATA_OFFSET; +} +#define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data + +static __always_inline +void __arm64_update_vsyscall(struct vdso_data *vdata) { vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK; vdata[CS_RAW].mask = VDSO_PRECISION_MASK; diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm/vncr_mapping.h index df2c47c55972..06f8ec0906a6 100644 --- a/arch/arm64/include/asm/vncr_mapping.h +++ b/arch/arm64/include/asm/vncr_mapping.h @@ -52,6 +52,7 @@ #define VNCR_PIRE0_EL1 0x290 #define VNCR_PIRE0_EL2 0x298 #define VNCR_PIR_EL1 0x2A0 +#define VNCR_POR_EL1 0x2A8 #define VNCR_ICH_LR0_EL2 0x400 #define VNCR_ICH_LR1_EL2 0x408 #define VNCR_ICH_LR2_EL2 0x410 diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h index 285610e626f5..48d46b768eae 100644 --- a/arch/arm64/include/uapi/asm/hwcap.h +++ b/arch/arm64/include/uapi/asm/hwcap.h @@ -21,7 +21,7 @@ * HWCAP flags - for AT_HWCAP * * Bits 62 and 63 are reserved for use by libc. - * Bits 32-61 are unallocated for potential use by libc. + * Bits 33-61 are unallocated for potential use by libc. */ #define HWCAP_FP (1 << 0) #define HWCAP_ASIMD (1 << 1) @@ -55,6 +55,7 @@ #define HWCAP_SB (1 << 29) #define HWCAP_PACA (1 << 30) #define HWCAP_PACG (1UL << 31) +#define HWCAP_GCS (1UL << 32) /* * HWCAP2 flags - for AT_HWCAP2 @@ -122,5 +123,10 @@ #define HWCAP2_SME_SF8FMA (1UL << 60) #define HWCAP2_SME_SF8DP4 (1UL << 61) #define HWCAP2_SME_SF8DP2 (1UL << 62) +#define HWCAP2_POE (1UL << 63) + +/* + * HWCAP3 flags - for AT_HWCAP3 + */ #endif /* _UAPI__ASM_HWCAP_H */ diff --git a/arch/arm64/include/uapi/asm/mman.h b/arch/arm64/include/uapi/asm/mman.h index 1e6482a838e1..e7e0c8216243 100644 --- a/arch/arm64/include/uapi/asm/mman.h +++ b/arch/arm64/include/uapi/asm/mman.h @@ -7,4 +7,13 @@ #define PROT_BTI 0x10 /* BTI guarded page */ #define PROT_MTE 0x20 /* Normal Tagged mapping */ +/* Override any generic PKEY permission defines */ +#define PKEY_DISABLE_EXECUTE 0x4 +#define PKEY_DISABLE_READ 0x8 +#undef PKEY_ACCESS_MASK +#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\ + PKEY_DISABLE_WRITE |\ + PKEY_DISABLE_READ |\ + PKEY_DISABLE_EXECUTE) + #endif /* ! _UAPI__ASM_MMAN_H */ diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h index 7fa2f7036aa7..0f39ba4f3efd 100644 --- a/arch/arm64/include/uapi/asm/ptrace.h +++ b/arch/arm64/include/uapi/asm/ptrace.h @@ -324,6 +324,14 @@ struct user_za_header { #define ZA_PT_SIZE(vq) \ (ZA_PT_ZA_OFFSET + ZA_PT_ZA_SIZE(vq)) +/* GCS state (NT_ARM_GCS) */ + +struct user_gcs { + __u64 features_enabled; + __u64 features_locked; + __u64 gcspr_el0; +}; + #endif /* __ASSEMBLY__ */ #endif /* _UAPI__ASM_PTRACE_H */ diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h index 8a45b7a411e0..d42f7a92238b 100644 --- a/arch/arm64/include/uapi/asm/sigcontext.h +++ b/arch/arm64/include/uapi/asm/sigcontext.h @@ -98,6 +98,13 @@ struct esr_context { __u64 esr; }; +#define POE_MAGIC 0x504f4530 + +struct poe_context { + struct _aarch64_ctx head; + __u64 por_el0; +}; + /* * extra_context: describes extra space in the signal frame for * additional structures that don't fit in sigcontext.__reserved[]. @@ -176,6 +183,15 @@ struct zt_context { __u16 __reserved[3]; }; +#define GCS_MAGIC 0x47435300 + +struct gcs_context { + struct _aarch64_ctx head; + __u64 gcspr; + __u64 features_enabled; + __u64 reserved; +}; + #endif /* !__ASSEMBLY__ */ #include <asm/sve_context.h> @@ -320,10 +336,10 @@ struct zt_context { ((sizeof(struct za_context) + (__SVE_VQ_BYTES - 1)) \ / __SVE_VQ_BYTES * __SVE_VQ_BYTES) -#define ZA_SIG_REGS_SIZE(vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES)) +#define ZA_SIG_REGS_SIZE(vq) (((vq) * __SVE_VQ_BYTES) * ((vq) * __SVE_VQ_BYTES)) #define ZA_SIG_ZAV_OFFSET(vq, n) (ZA_SIG_REGS_OFFSET + \ - (SVE_SIG_ZREG_SIZE(vq) * n)) + (SVE_SIG_ZREG_SIZE(vq) * (n))) #define ZA_SIG_CONTEXT_SIZE(vq) \ (ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq)) @@ -334,7 +350,7 @@ struct zt_context { #define ZT_SIG_REGS_OFFSET sizeof(struct zt_context) -#define ZT_SIG_REGS_SIZE(n) (ZT_SIG_REG_BYTES * n) +#define ZT_SIG_REGS_SIZE(n) (ZT_SIG_REG_BYTES * (n)) #define ZT_SIG_CONTEXT_SIZE(n) \ (sizeof(struct zt_context) + ZT_SIG_REGS_SIZE(n)) diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 2b112f3b7510..71c29a2a2f19 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -33,7 +33,8 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ return_address.o cpuinfo.o cpu_errata.o \ cpufeature.o alternative.o cacheinfo.o \ smp.o smp_spin_table.o topology.o smccc-call.o \ - syscall.o proton-pack.o idle.o patching.o pi/ + syscall.o proton-pack.o idle.o patching.o pi/ \ + rsi.o obj-$(CONFIG_COMPAT) += sys32.o signal32.o \ sys_compat.o diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 27de1dddb0ab..29bf85dacffe 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -12,15 +12,12 @@ #include <linux/ftrace.h> #include <linux/kexec.h> #include <linux/mm.h> -#include <linux/dma-mapping.h> #include <linux/kvm_host.h> -#include <linux/preempt.h> #include <linux/suspend.h> #include <asm/cpufeature.h> #include <asm/fixmap.h> #include <asm/thread_info.h> #include <asm/memory.h> -#include <asm/signal32.h> #include <asm/smp_plat.h> #include <asm/suspend.h> #include <linux/kbuild.h> @@ -28,8 +25,6 @@ int main(void) { - DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); - BLANK(); DEFINE(TSK_TI_CPU, offsetof(struct task_struct, thread_info.cpu)); DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count)); @@ -79,45 +74,27 @@ int main(void) DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate)); DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno)); DEFINE(S_SDEI_TTBR1, offsetof(struct pt_regs, sdei_ttbr1)); - DEFINE(S_PMR_SAVE, offsetof(struct pt_regs, pmr_save)); + DEFINE(S_PMR, offsetof(struct pt_regs, pmr)); DEFINE(S_STACKFRAME, offsetof(struct pt_regs, stackframe)); + DEFINE(S_STACKFRAME_TYPE, offsetof(struct pt_regs, stackframe.type)); DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs)); BLANK(); #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS - DEFINE(FREGS_X0, offsetof(struct ftrace_regs, regs[0])); - DEFINE(FREGS_X2, offsetof(struct ftrace_regs, regs[2])); - DEFINE(FREGS_X4, offsetof(struct ftrace_regs, regs[4])); - DEFINE(FREGS_X6, offsetof(struct ftrace_regs, regs[6])); - DEFINE(FREGS_X8, offsetof(struct ftrace_regs, regs[8])); - DEFINE(FREGS_FP, offsetof(struct ftrace_regs, fp)); - DEFINE(FREGS_LR, offsetof(struct ftrace_regs, lr)); - DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp)); - DEFINE(FREGS_PC, offsetof(struct ftrace_regs, pc)); + DEFINE(FREGS_X0, offsetof(struct __arch_ftrace_regs, regs[0])); + DEFINE(FREGS_X2, offsetof(struct __arch_ftrace_regs, regs[2])); + DEFINE(FREGS_X4, offsetof(struct __arch_ftrace_regs, regs[4])); + DEFINE(FREGS_X6, offsetof(struct __arch_ftrace_regs, regs[6])); + DEFINE(FREGS_X8, offsetof(struct __arch_ftrace_regs, regs[8])); + DEFINE(FREGS_FP, offsetof(struct __arch_ftrace_regs, fp)); + DEFINE(FREGS_LR, offsetof(struct __arch_ftrace_regs, lr)); + DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp)); + DEFINE(FREGS_PC, offsetof(struct __arch_ftrace_regs, pc)); #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS - DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct ftrace_regs, direct_tramp)); -#endif - DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs)); - BLANK(); + DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct __arch_ftrace_regs, direct_tramp)); #endif -#ifdef CONFIG_COMPAT - DEFINE(COMPAT_SIGFRAME_REGS_OFFSET, offsetof(struct compat_sigframe, uc.uc_mcontext.arm_r0)); - DEFINE(COMPAT_RT_SIGFRAME_REGS_OFFSET, offsetof(struct compat_rt_sigframe, sig.uc.uc_mcontext.arm_r0)); + DEFINE(FREGS_SIZE, sizeof(struct __arch_ftrace_regs)); BLANK(); #endif - DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter)); - BLANK(); - DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); - DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); - BLANK(); - DEFINE(VM_EXEC, VM_EXEC); - BLANK(); - DEFINE(PAGE_SZ, PAGE_SIZE); - BLANK(); - DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); - DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); - BLANK(); - DEFINE(PREEMPT_DISABLE_OFFSET, PREEMPT_DISABLE_OFFSET); - BLANK(); DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task)); BLANK(); DEFINE(FTR_OVR_VAL_OFFSET, offsetof(struct arm64_ftr_override, val)); @@ -146,6 +123,7 @@ int main(void) DEFINE(NVHE_INIT_HCR_EL2, offsetof(struct kvm_nvhe_init_params, hcr_el2)); DEFINE(NVHE_INIT_VTTBR, offsetof(struct kvm_nvhe_init_params, vttbr)); DEFINE(NVHE_INIT_VTCR, offsetof(struct kvm_nvhe_init_params, vtcr)); + DEFINE(NVHE_INIT_TMP, offsetof(struct kvm_nvhe_init_params, tmp)); #endif #ifdef CONFIG_CPU_PM DEFINE(CPU_CTX_SP, offsetof(struct cpu_suspend_ctx, sp)); diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f6b6b4507357..a78f247029ae 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -439,6 +439,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A715), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), @@ -447,8 +448,10 @@ static const struct midr_range erratum_spec_ssbs_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), MIDR_ALL_VERSIONS(MIDR_CORTEX_X4), MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), + MIDR_ALL_VERSIONS(MIDR_MICROSOFT_AZURE_COBALT_100), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N3), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), @@ -456,6 +459,14 @@ static const struct midr_range erratum_spec_ssbs_list[] = { }; #endif +#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 +static const struct midr_range erratum_ac03_cpu_38_list[] = { + MIDR_ALL_VERSIONS(MIDR_AMPERE1), + MIDR_ALL_VERSIONS(MIDR_AMPERE1A), + {}, +}; +#endif + const struct arm64_cpu_capabilities arm64_errata[] = { #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE { @@ -772,7 +783,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .desc = "AmpereOne erratum AC03_CPU_38", .capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38, - ERRATA_MIDR_ALL_VERSIONS(MIDR_AMPERE1), + ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_38_list), }, #endif { diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 646ecd3069fd..351aa825ec40 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -103,6 +103,7 @@ static DECLARE_BITMAP(elf_hwcap, MAX_CPU_FEATURES) __read_mostly; COMPAT_HWCAP_LPAE) unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; unsigned int compat_elf_hwcap2 __read_mostly; +unsigned int compat_elf_hwcap3 __read_mostly; #endif DECLARE_BITMAP(system_cpucaps, ARM64_NCAPS); @@ -228,6 +229,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = { }; static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_XS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_I8MM_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_DGH_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_EL1_BF16_SHIFT, 4, 0), @@ -291,6 +293,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { }; static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = { + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_GCS), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_GCS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SME), FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_SME_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_MPAM_frac_SHIFT, 4, 0), @@ -466,6 +470,8 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { }; static const struct arm64_ftr_bits ftr_id_aa64mmfr3[] = { + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_POE), + FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_S1POE_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_S1PIE_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_TCRX_SHIFT, 4, 0), ARM64_FTR_END, @@ -2348,6 +2354,22 @@ static void cpu_enable_mops(const struct arm64_cpu_capabilities *__unused) sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_MSCEn); } +#ifdef CONFIG_ARM64_POE +static void cpu_enable_poe(const struct arm64_cpu_capabilities *__unused) +{ + sysreg_clear_set(REG_TCR2_EL1, 0, TCR2_EL1x_E0POE); + sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_E0POE); +} +#endif + +#ifdef CONFIG_ARM64_GCS +static void cpu_enable_gcs(const struct arm64_cpu_capabilities *__unused) +{ + /* GCSPR_EL0 is always readable */ + write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1); +} +#endif + /* Internal helper functions to match cpu capability type */ static bool cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap) @@ -2581,6 +2603,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = { ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, DBM) }, #endif +#ifdef CONFIG_ARM64_HAFT + { + .desc = "Hardware managed Access Flag for Table Descriptors", + /* + * Contrary to the page/block access flag, the table access flag + * cannot be emulated in software (no access fault will occur). + * Therefore this should be used only if it's supported system + * wide. + */ + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .capability = ARM64_HAFT, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, HAFT) + }, +#endif { .desc = "CRC32 instructions", .capability = ARM64_HAS_CRC32, @@ -2870,6 +2907,26 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = has_nv1, ARM64_CPUID_FIELDS_NEG(ID_AA64MMFR4_EL1, E2H0, NI_NV1) }, +#ifdef CONFIG_ARM64_POE + { + .desc = "Stage-1 Permission Overlay Extension (S1POE)", + .capability = ARM64_HAS_S1POE, + .type = ARM64_CPUCAP_BOOT_CPU_FEATURE, + .matches = has_cpuid_feature, + .cpu_enable = cpu_enable_poe, + ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, S1POE, IMP) + }, +#endif +#ifdef CONFIG_ARM64_GCS + { + .desc = "Guarded Control Stack (GCS)", + .capability = ARM64_HAS_GCS, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .cpu_enable = cpu_enable_gcs, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP) + }, +#endif {}, }; @@ -2986,6 +3043,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(ID_AA64ZFR0_EL1, F32MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF32MM), HWCAP_CAP(ID_AA64ZFR0_EL1, F64MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF64MM), #endif +#ifdef CONFIG_ARM64_GCS + HWCAP_CAP(ID_AA64PFR1_EL1, GCS, IMP, CAP_HWCAP, KERNEL_HWCAP_GCS), +#endif HWCAP_CAP(ID_AA64PFR1_EL1, SSBS, SSBS2, CAP_HWCAP, KERNEL_HWCAP_SSBS), #ifdef CONFIG_ARM64_BTI HWCAP_CAP(ID_AA64PFR1_EL1, BT, IMP, CAP_HWCAP, KERNEL_HWCAP_BTI), @@ -3034,6 +3094,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP2), HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), +#ifdef CONFIG_ARM64_POE + HWCAP_CAP(ID_AA64MMFR3_EL1, S1POE, IMP, CAP_HWCAP, KERNEL_HWCAP_POE), +#endif {}, }; @@ -3476,6 +3539,11 @@ unsigned long cpu_get_elf_hwcap2(void) return elf_hwcap[1]; } +unsigned long cpu_get_elf_hwcap3(void) +{ + return elf_hwcap[2]; +} + static void __init setup_boot_cpu_capabilities(void) { /* diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 09eeaa24d456..f2f92c6b1c85 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -80,6 +80,7 @@ static const char *const hwcap_str[] = { [KERNEL_HWCAP_SB] = "sb", [KERNEL_HWCAP_PACA] = "paca", [KERNEL_HWCAP_PACG] = "pacg", + [KERNEL_HWCAP_GCS] = "gcs", [KERNEL_HWCAP_DCPODP] = "dcpodp", [KERNEL_HWCAP_SVE2] = "sve2", [KERNEL_HWCAP_SVEAES] = "sveaes", @@ -143,6 +144,7 @@ static const char *const hwcap_str[] = { [KERNEL_HWCAP_SME_SF8FMA] = "smesf8fma", [KERNEL_HWCAP_SME_SF8DP4] = "smesf8dp4", [KERNEL_HWCAP_SME_SF8DP2] = "smesf8dp2", + [KERNEL_HWCAP_POE] = "poe", }; #ifdef CONFIG_COMPAT @@ -280,7 +282,7 @@ const struct seq_operations cpuinfo_op = { }; -static struct kobj_type cpuregs_kobj_type = { +static const struct kobj_type cpuregs_kobj_type = { .sysfs_ops = &kobj_sysfs_ops, }; diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 024a7b245056..58f047de3e1c 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -303,7 +303,6 @@ static int call_break_hook(struct pt_regs *regs, unsigned long esr) { struct break_hook *hook; struct list_head *list; - int (*fn)(struct pt_regs *regs, unsigned long esr) = NULL; list = user_mode(regs) ? &user_break_hook : &kernel_break_hook; @@ -313,10 +312,10 @@ static int call_break_hook(struct pt_regs *regs, unsigned long esr) */ list_for_each_entry_rcu(hook, list, node) { if ((esr_brk_comment(esr) & ~hook->mask) == hook->imm) - fn = hook->fn; + return hook->fn(regs, esr); } - return fn ? fn(regs, esr) : DBG_HOOK_ERROR; + return DBG_HOOK_ERROR; } NOKPROBE_SYMBOL(call_break_hook); @@ -441,6 +440,11 @@ void kernel_rewind_single_step(struct pt_regs *regs) set_regs_spsr_ss(regs); } +void kernel_fastforward_single_step(struct pt_regs *regs) +{ + clear_regs_spsr_ss(regs); +} + /* ptrace API */ void user_enable_single_step(struct task_struct *task) { diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 712718aed5dd..1d25d8899dbf 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -34,8 +34,16 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md) u64 attr = md->attribute; u32 type = md->type; - if (type == EFI_MEMORY_MAPPED_IO) - return PROT_DEVICE_nGnRE; + if (type == EFI_MEMORY_MAPPED_IO) { + pgprot_t prot = __pgprot(PROT_DEVICE_nGnRE); + + if (arm64_is_protected_mmio(md->phys_addr, + md->num_pages << EFI_PAGE_SHIFT)) + prot = pgprot_encrypted(prot); + else + prot = pgprot_decrypted(prot); + return pgprot_val(prot); + } if (region_is_misaligned(md)) { static bool __initdata code_is_misaligned; diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index b77a15955f28..b260ddc4d3e9 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -103,7 +103,7 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs) static __always_inline void __enter_from_user_mode(void) { lockdep_hardirqs_off(CALLER_ADDR0); - CT_WARN_ON(ct_state() != CONTEXT_USER); + CT_WARN_ON(ct_state() != CT_STATE_USER); user_exit_irqoff(); trace_hardirqs_off_finish(); mte_disable_tco_entry(current); @@ -463,6 +463,24 @@ static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr) exit_to_kernel_mode(regs); } +static void noinstr el1_gcs(struct pt_regs *regs, unsigned long esr) +{ + enter_from_kernel_mode(regs); + local_daif_inherit(regs); + do_el1_gcs(regs, esr); + local_daif_mask(); + exit_to_kernel_mode(regs); +} + +static void noinstr el1_mops(struct pt_regs *regs, unsigned long esr) +{ + enter_from_kernel_mode(regs); + local_daif_inherit(regs); + do_el1_mops(regs, esr); + local_daif_mask(); + exit_to_kernel_mode(regs); +} + static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr) { unsigned long far = read_sysreg(far_el1); @@ -505,6 +523,12 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs) case ESR_ELx_EC_BTI: el1_bti(regs, esr); break; + case ESR_ELx_EC_GCS: + el1_gcs(regs, esr); + break; + case ESR_ELx_EC_MOPS: + el1_mops(regs, esr); + break; case ESR_ELx_EC_BREAKPT_CUR: case ESR_ELx_EC_SOFTSTP_CUR: case ESR_ELx_EC_WATCHPT_CUR: @@ -684,6 +708,14 @@ static void noinstr el0_mops(struct pt_regs *regs, unsigned long esr) exit_to_user_mode(regs); } +static void noinstr el0_gcs(struct pt_regs *regs, unsigned long esr) +{ + enter_from_user_mode(regs); + local_daif_restore(DAIF_PROCCTX); + do_el0_gcs(regs, esr); + exit_to_user_mode(regs); +} + static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr) { enter_from_user_mode(regs); @@ -766,6 +798,9 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs) case ESR_ELx_EC_MOPS: el0_mops(regs, esr); break; + case ESR_ELx_EC_GCS: + el0_gcs(regs, esr); + break; case ESR_ELx_EC_BREAKPT_LOW: case ESR_ELx_EC_SOFTSTP_LOW: case ESR_ELx_EC_WATCHPT_LOW: diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 7ef0e127b149..5ae2a34b50bd 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -25,6 +25,7 @@ #include <asm/processor.h> #include <asm/ptrace.h> #include <asm/scs.h> +#include <asm/stacktrace/frame.h> #include <asm/thread_info.h> #include <asm/asm-uaccess.h> #include <asm/unistd.h> @@ -284,15 +285,16 @@ alternative_else_nop_endif stp lr, x21, [sp, #S_LR] /* - * For exceptions from EL0, create a final frame record. - * For exceptions from EL1, create a synthetic frame record so the - * interrupted code shows up in the backtrace. + * Create a metadata frame record. The unwinder will use this to + * identify and unwind exception boundaries. */ - .if \el == 0 stp xzr, xzr, [sp, #S_STACKFRAME] + .if \el == 0 + mov x0, #FRAME_META_TYPE_FINAL .else - stp x29, x22, [sp, #S_STACKFRAME] + mov x0, #FRAME_META_TYPE_PT_REGS .endif + str x0, [sp, #S_STACKFRAME_TYPE] add x29, sp, #S_STACKFRAME #ifdef CONFIG_ARM64_SW_TTBR0_PAN @@ -315,7 +317,7 @@ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING alternative_else_nop_endif mrs_s x20, SYS_ICC_PMR_EL1 - str x20, [sp, #S_PMR_SAVE] + str w20, [sp, #S_PMR] mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET msr_s SYS_ICC_PMR_EL1, x20 @@ -342,7 +344,7 @@ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING b .Lskip_pmr_restore\@ alternative_else_nop_endif - ldr x20, [sp, #S_PMR_SAVE] + ldr w20, [sp, #S_PMR] msr_s SYS_ICC_PMR_EL1, x20 /* Ensure priority change is seen by redistributor */ diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 77006df20a75..8c4c1a2186cc 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -386,7 +386,7 @@ static void task_fpsimd_load(void) * fpsimd_save_user_state() or memory corruption, we * should always record an explicit format * when we save. We always at least have the - * memory allocated for FPSMID registers so + * memory allocated for FPSIMD registers so * try that and hope for the best. */ WARN_ON_ONCE(1); @@ -1367,6 +1367,7 @@ static void sve_init_regs(void) } else { fpsimd_to_sve(current); current->thread.fp_type = FP_STATE_SVE; + fpsimd_flush_task_state(current); } } diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c index a650f5e11fc5..b2d947175cbe 100644 --- a/arch/arm64/kernel/ftrace.c +++ b/arch/arm64/kernel/ftrace.c @@ -23,10 +23,10 @@ struct fregs_offset { int offset; }; -#define FREGS_OFFSET(n, field) \ -{ \ - .name = n, \ - .offset = offsetof(struct ftrace_regs, field), \ +#define FREGS_OFFSET(n, field) \ +{ \ + .name = n, \ + .offset = offsetof(struct __arch_ftrace_regs, field), \ } static const struct fregs_offset fregs_offsets[] = { @@ -481,7 +481,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent, void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - prepare_ftrace_return(ip, &fregs->lr, fregs->fp); + prepare_ftrace_return(ip, &arch_ftrace_regs(fregs)->lr, arch_ftrace_regs(fregs)->fp); } #else /* diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index cb68adcabe07..5ab1970ee543 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -32,6 +32,7 @@ #include <asm/scs.h> #include <asm/smp.h> #include <asm/sysreg.h> +#include <asm/stacktrace/frame.h> #include <asm/thread_info.h> #include <asm/virt.h> @@ -199,6 +200,8 @@ SYM_CODE_END(preserve_boot_args) sub sp, sp, #PT_REGS_SIZE stp xzr, xzr, [sp, #S_STACKFRAME] + mov \tmp1, #FRAME_META_TYPE_FINAL + str \tmp1, [sp, #S_STACKFRAME_TYPE] add x29, sp, #S_STACKFRAME scs_load_current diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 02870beb271e..18749e9a6c2d 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -266,9 +266,15 @@ static int swsusp_mte_save_tags(void) max_zone_pfn = zone_end_pfn(zone); for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) { struct page *page = pfn_to_online_page(pfn); + struct folio *folio; if (!page) continue; + folio = page_folio(page); + + if (folio_test_hugetlb(folio) && + !folio_test_hugetlb_mte_tagged(folio)) + continue; if (!page_mte_tagged(page)) continue; @@ -407,7 +413,7 @@ int swsusp_arch_resume(void) void *, phys_addr_t, phys_addr_t); struct trans_pgd_info trans_info = { .trans_alloc_page = hibernate_page_alloc, - .trans_alloc_arg = (void *)GFP_ATOMIC, + .trans_alloc_arg = (__force void *)GFP_ATOMIC, }; /* diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 36b25af56324..06bb680bfe97 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -462,14 +462,20 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { const Elf_Shdr *s; + int ret; + s = find_section(hdr, sechdrs, ".altinstructions"); if (s) apply_alternatives_module((void *)s->sh_addr, s->sh_size); if (scs_is_dynamic()) { s = find_section(hdr, sechdrs, ".init.eh_frame"); - if (s) - __pi_scs_patch((void *)s->sh_addr, s->sh_size); + if (s) { + ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size); + if (ret) + pr_err("module %s: error occurred during dynamic SCS patching (%d)\n", + me->name, ret); + } } return module_init_ftrace_plt(hdr, sechdrs, me); diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c index 6174671be7c1..2fbfd27ff5f2 100644 --- a/arch/arm64/kernel/mte.c +++ b/arch/arm64/kernel/mte.c @@ -38,7 +38,24 @@ EXPORT_SYMBOL_GPL(mte_async_or_asymm_mode); void mte_sync_tags(pte_t pte, unsigned int nr_pages) { struct page *page = pte_page(pte); - unsigned int i; + struct folio *folio = page_folio(page); + unsigned long i; + + if (folio_test_hugetlb(folio)) { + unsigned long nr = folio_nr_pages(folio); + + /* Hugetlb MTE flags are set for head page only */ + if (folio_try_hugetlb_mte_tagging(folio)) { + for (i = 0; i < nr; i++, page++) + mte_clear_page_tags(page_address(page)); + folio_set_hugetlb_mte_tagged(folio); + } + + /* ensure the tags are visible before the PTE is set */ + smp_wmb(); + + return; + } /* if PG_mte_tagged is set, tags have already been initialised */ for (i = 0; i < nr_pages; i++, page++) { @@ -410,6 +427,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, void *maddr; struct page *page = get_user_page_vma_remote(mm, addr, gup_flags, &vma); + struct folio *folio; if (IS_ERR(page)) { err = PTR_ERR(page); @@ -428,7 +446,12 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr, put_page(page); break; } - WARN_ON_ONCE(!page_mte_tagged(page)); + + folio = page_folio(page); + if (folio_test_hugetlb(folio)) + WARN_ON_ONCE(!folio_test_hugetlb_mte_tagged(folio)); + else + WARN_ON_ONCE(!page_mte_tagged(page)); /* limit access to the end of the page */ offset = offset_in_page(addr); diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index f872c57e9909..fd9a7bed83ce 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -6,28 +6,7 @@ * Copyright (C) 2014 ARM Ltd. */ -#include <linux/acpi.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/mm.h> #include <linux/pci.h> -#include <linux/pci-acpi.h> -#include <linux/pci-ecam.h> -#include <linux/slab.h> - -#ifdef CONFIG_ACPI -/* - * Try to assign the IRQ number when probing a new device - */ -int pcibios_alloc_irq(struct pci_dev *dev) -{ - if (!acpi_disabled) - acpi_pci_irq_enable(dev); - - return 0; -} -#endif /* * raw_pci_read/write - Platform-specific PCI config space access. @@ -61,173 +40,3 @@ int pcibus_to_node(struct pci_bus *bus) EXPORT_SYMBOL(pcibus_to_node); #endif - -#ifdef CONFIG_ACPI - -struct acpi_pci_generic_root_info { - struct acpi_pci_root_info common; - struct pci_config_window *cfg; /* config space mapping */ -}; - -int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) -{ - struct pci_config_window *cfg = bus->sysdata; - struct acpi_device *adev = to_acpi_device(cfg->parent); - struct acpi_pci_root *root = acpi_driver_data(adev); - - return root->segment; -} - -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - struct pci_config_window *cfg; - struct acpi_device *adev; - struct device *bus_dev; - - if (acpi_disabled) - return 0; - - cfg = bridge->bus->sysdata; - - /* - * On Hyper-V there is no corresponding ACPI device for a root bridge, - * therefore ->parent is set as NULL by the driver. And set 'adev' as - * NULL in this case because there is no proper ACPI device. - */ - if (!cfg->parent) - adev = NULL; - else - adev = to_acpi_device(cfg->parent); - - bus_dev = &bridge->bus->dev; - - ACPI_COMPANION_SET(&bridge->dev, adev); - set_dev_node(bus_dev, acpi_get_node(acpi_device_handle(adev))); - - return 0; -} - -static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci) -{ - struct resource_entry *entry, *tmp; - int status; - - status = acpi_pci_probe_root_resources(ci); - resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { - if (!(entry->res->flags & IORESOURCE_WINDOW)) - resource_list_destroy_entry(entry); - } - return status; -} - -/* - * Lookup the bus range for the domain in MCFG, and set up config space - * mapping. - */ -static struct pci_config_window * -pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) -{ - struct device *dev = &root->device->dev; - struct resource *bus_res = &root->secondary; - u16 seg = root->segment; - const struct pci_ecam_ops *ecam_ops; - struct resource cfgres; - struct acpi_device *adev; - struct pci_config_window *cfg; - int ret; - - ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops); - if (ret) { - dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res); - return NULL; - } - - adev = acpi_resource_consumer(&cfgres); - if (adev) - dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres, - dev_name(&adev->dev)); - else - dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n", - &cfgres); - - cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops); - if (IS_ERR(cfg)) { - dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res, - PTR_ERR(cfg)); - return NULL; - } - - return cfg; -} - -/* release_info: free resources allocated by init_info */ -static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) -{ - struct acpi_pci_generic_root_info *ri; - - ri = container_of(ci, struct acpi_pci_generic_root_info, common); - pci_ecam_free(ri->cfg); - kfree(ci->ops); - kfree(ri); -} - -/* Interface called from ACPI code to setup PCI host controller */ -struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) -{ - struct acpi_pci_generic_root_info *ri; - struct pci_bus *bus, *child; - struct acpi_pci_root_ops *root_ops; - struct pci_host_bridge *host; - - ri = kzalloc(sizeof(*ri), GFP_KERNEL); - if (!ri) - return NULL; - - root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL); - if (!root_ops) { - kfree(ri); - return NULL; - } - - ri->cfg = pci_acpi_setup_ecam_mapping(root); - if (!ri->cfg) { - kfree(ri); - kfree(root_ops); - return NULL; - } - - root_ops->release_info = pci_acpi_generic_release_info; - root_ops->prepare_resources = pci_acpi_root_prepare_resources; - root_ops->pci_ops = (struct pci_ops *)&ri->cfg->ops->pci_ops; - bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg); - if (!bus) - return NULL; - - /* If we must preserve the resource configuration, claim now */ - host = pci_find_host_bridge(bus); - if (host->preserve_config) - pci_bus_claim_resources(bus); - - /* - * Assign whatever was left unassigned. If we didn't claim above, - * this will reassign everything. - */ - pci_assign_unassigned_root_bus_resources(bus); - - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child); - - return bus; -} - -void pcibios_add_bus(struct pci_bus *bus) -{ - acpi_pci_add_bus(bus); -} - -void pcibios_remove_bus(struct pci_bus *bus) -{ - acpi_pci_remove_bus(bus); -} - -#endif diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c index e8ed5673f481..9b7f26b128b5 100644 --- a/arch/arm64/kernel/perf_callchain.c +++ b/arch/arm64/kernel/perf_callchain.c @@ -38,31 +38,3 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, arch_stack_walk(callchain_trace, entry, current, regs); } - -unsigned long perf_instruction_pointer(struct pt_regs *regs) -{ - if (perf_guest_state()) - return perf_guest_get_ip(); - - return instruction_pointer(regs); -} - -unsigned long perf_misc_flags(struct pt_regs *regs) -{ - unsigned int guest_state = perf_guest_state(); - int misc = 0; - - if (guest_state) { - if (guest_state & PERF_GUEST_USER) - misc |= PERF_RECORD_MISC_GUEST_USER; - else - misc |= PERF_RECORD_MISC_GUEST_KERNEL; - } else { - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - } - - return misc; -} diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c index 29d4b6244a6f..22159251eb3a 100644 --- a/arch/arm64/kernel/pi/idreg-override.c +++ b/arch/arm64/kernel/pi/idreg-override.c @@ -38,6 +38,15 @@ struct ftr_set_desc { #define FIELD(n, s, f) { .name = n, .shift = s, .width = 4, .filter = f } +static const struct ftr_set_desc mmfr0 __prel64_initconst = { + .name = "id_aa64mmfr0", + .override = &id_aa64mmfr0_override, + .fields = { + FIELD("ecv", ID_AA64MMFR0_EL1_ECV_SHIFT, NULL), + {} + }, +}; + static bool __init mmfr1_vh_filter(u64 val) { /* @@ -133,6 +142,7 @@ static const struct ftr_set_desc pfr1 __prel64_initconst = { .override = &id_aa64pfr1_override, .fields = { FIELD("bt", ID_AA64PFR1_EL1_BT_SHIFT, NULL ), + FIELD("gcs", ID_AA64PFR1_EL1_GCS_SHIFT, NULL), FIELD("mte", ID_AA64PFR1_EL1_MTE_SHIFT, NULL), FIELD("sme", ID_AA64PFR1_EL1_SME_SHIFT, pfr1_sme_filter), {} @@ -196,6 +206,7 @@ static const struct ftr_set_desc sw_features __prel64_initconst = { static const PREL64(const struct ftr_set_desc, reg) regs[] __prel64_initconst = { + { &mmfr0 }, { &mmfr1 }, { &mmfr2 }, { &pfr0 }, @@ -215,6 +226,7 @@ static const struct { { "arm64.nosve", "id_aa64pfr0.sve=0" }, { "arm64.nosme", "id_aa64pfr1.sme=0" }, { "arm64.nobti", "id_aa64pfr1.bt=0" }, + { "arm64.nogcs", "id_aa64pfr1.gcs=0" }, { "arm64.nopauth", "id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 " "id_aa64isar1.api=0 id_aa64isar1.apa=0 " diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c index 5410b2cac590..2b69e3beeef8 100644 --- a/arch/arm64/kernel/pi/map_range.c +++ b/arch/arm64/kernel/pi/map_range.c @@ -30,7 +30,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot, int level, pte_t *tbl, bool may_use_cont, u64 va_offset) { u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX; - u64 protval = pgprot_val(prot) & ~PTE_TYPE_MASK; + pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK; int lshift = (3 - level) * (PAGE_SHIFT - 3); u64 lmask = (PAGE_SIZE << lshift) - 1; diff --git a/arch/arm64/kernel/pi/patch-scs.c b/arch/arm64/kernel/pi/patch-scs.c index 49d8b40e61bc..55d0cd64ef71 100644 --- a/arch/arm64/kernel/pi/patch-scs.c +++ b/arch/arm64/kernel/pi/patch-scs.c @@ -50,6 +50,10 @@ bool dynamic_scs_is_enabled; #define DW_CFA_GNU_negative_offset_extended 0x2f #define DW_CFA_hi_user 0x3f +#define DW_EH_PE_sdata4 0x0b +#define DW_EH_PE_sdata8 0x0c +#define DW_EH_PE_pcrel 0x10 + enum { PACIASP = 0xd503233f, AUTIASP = 0xd50323bf, @@ -120,7 +124,12 @@ struct eh_frame { union { struct { // CIE u8 version; - u8 augmentation_string[]; + u8 augmentation_string[3]; + u8 code_alignment_factor; + u8 data_alignment_factor; + u8 return_address_register; + u8 augmentation_data_size; + u8 fde_pointer_format; }; struct { // FDE @@ -128,29 +137,38 @@ struct eh_frame { s32 range; u8 opcodes[]; }; + + struct { // FDE + s64 initial_loc64; + s64 range64; + u8 opcodes64[]; + }; }; }; static int scs_handle_fde_frame(const struct eh_frame *frame, - bool fde_has_augmentation_data, int code_alignment_factor, + bool use_sdata8, bool dry_run) { int size = frame->size - offsetof(struct eh_frame, opcodes) + 4; u64 loc = (u64)offset_to_ptr(&frame->initial_loc); const u8 *opcode = frame->opcodes; + int l; - if (fde_has_augmentation_data) { - int l; + if (use_sdata8) { + loc = (u64)&frame->initial_loc64 + frame->initial_loc64; + opcode = frame->opcodes64; + size -= 8; + } - // assume single byte uleb128_t - if (WARN_ON(*opcode & BIT(7))) - return -ENOEXEC; + // assume single byte uleb128_t for augmentation data size + if (*opcode & BIT(7)) + return EDYNSCS_INVALID_FDE_AUGM_DATA_SIZE; - l = *opcode++; - opcode += l; - size -= l + 1; - } + l = *opcode++; + opcode += l; + size -= l + 1; /* * Starting from 'loc', apply the CFA opcodes that advance the location @@ -201,7 +219,7 @@ static int scs_handle_fde_frame(const struct eh_frame *frame, break; default: - return -ENOEXEC; + return EDYNSCS_INVALID_CFA_OPCODE; } } return 0; @@ -209,12 +227,12 @@ static int scs_handle_fde_frame(const struct eh_frame *frame, int scs_patch(const u8 eh_frame[], int size) { + int code_alignment_factor = 1; + bool fde_use_sdata8 = false; const u8 *p = eh_frame; while (size > 4) { const struct eh_frame *frame = (const void *)p; - bool fde_has_augmentation_data = true; - int code_alignment_factor = 1; int ret; if (frame->size == 0 || @@ -223,28 +241,47 @@ int scs_patch(const u8 eh_frame[], int size) break; if (frame->cie_id_or_pointer == 0) { - const u8 *p = frame->augmentation_string; - - /* a 'z' in the augmentation string must come first */ - fde_has_augmentation_data = *p == 'z'; + /* + * Require presence of augmentation data (z) with a + * specifier for the size of the FDE initial_loc and + * range fields (R), and nothing else. + */ + if (strcmp(frame->augmentation_string, "zR")) + return EDYNSCS_INVALID_CIE_HEADER; /* * The code alignment factor is a uleb128 encoded field * but given that the only sensible values are 1 or 4, - * there is no point in decoding the whole thing. + * there is no point in decoding the whole thing. Also + * sanity check the size of the data alignment factor + * field, and the values of the return address register + * and augmentation data size fields. */ - p += strlen(p) + 1; - if (!WARN_ON(*p & BIT(7))) - code_alignment_factor = *p; + if ((frame->code_alignment_factor & BIT(7)) || + (frame->data_alignment_factor & BIT(7)) || + frame->return_address_register != 30 || + frame->augmentation_data_size != 1) + return EDYNSCS_INVALID_CIE_HEADER; + + code_alignment_factor = frame->code_alignment_factor; + + switch (frame->fde_pointer_format) { + case DW_EH_PE_pcrel | DW_EH_PE_sdata4: + fde_use_sdata8 = false; + break; + case DW_EH_PE_pcrel | DW_EH_PE_sdata8: + fde_use_sdata8 = true; + break; + default: + return EDYNSCS_INVALID_CIE_SDATA_SIZE; + } } else { - ret = scs_handle_fde_frame(frame, - fde_has_augmentation_data, - code_alignment_factor, - true); + ret = scs_handle_fde_frame(frame, code_alignment_factor, + fde_use_sdata8, true); if (ret) return ret; - scs_handle_fde_frame(frame, fde_has_augmentation_data, - code_alignment_factor, false); + scs_handle_fde_frame(frame, code_alignment_factor, + fde_use_sdata8, false); } p += sizeof(frame->size) + frame->size; diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c index 968d5fffe233..6438bf62e753 100644 --- a/arch/arm64/kernel/probes/decode-insn.c +++ b/arch/arm64/kernel/probes/decode-insn.c @@ -58,10 +58,13 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn) * Instructions which load PC relative literals are not going to work * when executed from an XOL slot. Instructions doing an exclusive * load/store are not going to complete successfully when single-step - * exception handling happens in the middle of the sequence. + * exception handling happens in the middle of the sequence. Memory + * copy/set instructions require that all three instructions be placed + * consecutively in memory. */ if (aarch64_insn_uses_literal(insn) || - aarch64_insn_is_exclusive(insn)) + aarch64_insn_is_exclusive(insn) || + aarch64_insn_is_mops(insn)) return false; return true; @@ -73,9 +76,18 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn) * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. */ enum probe_insn __kprobes -arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api) +arm_probe_decode_insn(u32 insn, struct arch_probe_insn *api) { /* + * While 'nop' instruction can execute in the out-of-line slot, + * simulating them in breakpoint handling offers better performance. + */ + if (aarch64_insn_is_nop(insn)) { + api->handler = simulate_nop; + return INSN_GOOD_NO_SLOT; + } + + /* * Instructions reading or modifying the PC won't work from the XOL * slot. */ @@ -99,10 +111,6 @@ arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api) aarch64_insn_is_blr(insn) || aarch64_insn_is_ret(insn)) { api->handler = simulate_br_blr_ret; - } else if (aarch64_insn_is_ldr_lit(insn)) { - api->handler = simulate_ldr_literal; - } else if (aarch64_insn_is_ldrsw_lit(insn)) { - api->handler = simulate_ldrsw_literal; } else { /* * Instruction cannot be stepped out-of-line and we don't @@ -137,9 +145,20 @@ enum probe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi) { enum probe_insn decoded; - probe_opcode_t insn = le32_to_cpu(*addr); - probe_opcode_t *scan_end = NULL; + u32 insn = le32_to_cpu(*addr); + kprobe_opcode_t *scan_end = NULL; unsigned long size = 0, offset = 0; + struct arch_probe_insn *api = &asi->api; + + if (aarch64_insn_is_ldr_lit(insn)) { + api->handler = simulate_ldr_literal; + decoded = INSN_GOOD_NO_SLOT; + } else if (aarch64_insn_is_ldrsw_lit(insn)) { + api->handler = simulate_ldrsw_literal; + decoded = INSN_GOOD_NO_SLOT; + } else { + decoded = arm_probe_decode_insn(insn, &asi->api); + } /* * If there's a symbol defined in front of and near enough to @@ -157,7 +176,6 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi) else scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; } - decoded = arm_probe_decode_insn(insn, &asi->api); if (decoded != INSN_REJECTED && scan_end) if (is_probed_address_atomic(addr - 1, scan_end)) diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h index 8b758c5a2062..0e4195de8206 100644 --- a/arch/arm64/kernel/probes/decode-insn.h +++ b/arch/arm64/kernel/probes/decode-insn.h @@ -28,6 +28,6 @@ enum probe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi); #endif enum probe_insn __kprobes -arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *asi); +arm_probe_decode_insn(u32 insn, struct arch_probe_insn *asi); #endif /* _ARM_KERNEL_KPROBES_ARM64_H */ diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index 4268678d0e86..48d88e07611d 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -43,7 +43,7 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *); static void __kprobes arch_prepare_ss_slot(struct kprobe *p) { - kprobe_opcode_t *addr = p->ainsn.api.insn; + kprobe_opcode_t *addr = p->ainsn.xol_insn; /* * Prepare insn slot, Mark Rutland points out it depends on a coupe of @@ -64,20 +64,20 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p) * the BRK exception handler, so it is unnecessary to generate * Contex-Synchronization-Event via ISB again. */ - aarch64_insn_patch_text_nosync(addr, p->opcode); + aarch64_insn_patch_text_nosync(addr, le32_to_cpu(p->opcode)); aarch64_insn_patch_text_nosync(addr + 1, BRK64_OPCODE_KPROBES_SS); /* * Needs restoring of return address after stepping xol. */ - p->ainsn.api.restore = (unsigned long) p->addr + + p->ainsn.xol_restore = (unsigned long) p->addr + sizeof(kprobe_opcode_t); } static void __kprobes arch_prepare_simulate(struct kprobe *p) { /* This instructions is not executed xol. No need to adjust the PC */ - p->ainsn.api.restore = 0; + p->ainsn.xol_restore = 0; } static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) @@ -85,7 +85,7 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (p->ainsn.api.handler) - p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs); + p->ainsn.api.handler(le32_to_cpu(p->opcode), (long)p->addr, regs); /* single step simulated, now go for post processing */ post_kprobe_handler(p, kcb, regs); @@ -99,7 +99,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) return -EINVAL; /* copy instruction */ - p->opcode = le32_to_cpu(*p->addr); + p->opcode = *p->addr; if (search_exception_tables(probe_addr)) return -EINVAL; @@ -110,18 +110,18 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) return -EINVAL; case INSN_GOOD_NO_SLOT: /* insn need simulation */ - p->ainsn.api.insn = NULL; + p->ainsn.xol_insn = NULL; break; case INSN_GOOD: /* instruction uses slot */ - p->ainsn.api.insn = get_insn_slot(); - if (!p->ainsn.api.insn) + p->ainsn.xol_insn = get_insn_slot(); + if (!p->ainsn.xol_insn) return -ENOMEM; break; } /* prepare the instruction */ - if (p->ainsn.api.insn) + if (p->ainsn.xol_insn) arch_prepare_ss_slot(p); else arch_prepare_simulate(p); @@ -142,15 +142,16 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) void __kprobes arch_disarm_kprobe(struct kprobe *p) { void *addr = p->addr; + u32 insn = le32_to_cpu(p->opcode); - aarch64_insn_patch_text(&addr, &p->opcode, 1); + aarch64_insn_patch_text(&addr, &insn, 1); } void __kprobes arch_remove_kprobe(struct kprobe *p) { - if (p->ainsn.api.insn) { - free_insn_slot(p->ainsn.api.insn, 0); - p->ainsn.api.insn = NULL; + if (p->ainsn.xol_insn) { + free_insn_slot(p->ainsn.xol_insn, 0); + p->ainsn.xol_insn = NULL; } } @@ -205,9 +206,9 @@ static void __kprobes setup_singlestep(struct kprobe *p, } - if (p->ainsn.api.insn) { + if (p->ainsn.xol_insn) { /* prepare for single stepping */ - slot = (unsigned long)p->ainsn.api.insn; + slot = (unsigned long)p->ainsn.xol_insn; kprobes_save_local_irqflag(kcb, regs); instruction_pointer_set(regs, slot); @@ -245,8 +246,8 @@ static void __kprobes post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs) { /* return addr restore if non-branching insn */ - if (cur->ainsn.api.restore != 0) - instruction_pointer_set(regs, cur->ainsn.api.restore); + if (cur->ainsn.xol_restore != 0) + instruction_pointer_set(regs, cur->ainsn.xol_restore); /* restore back original saved kprobe variables and continue */ if (kcb->kprobe_status == KPROBE_REENTER) { @@ -348,7 +349,7 @@ kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr) struct kprobe *cur = kprobe_running(); if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) && - ((unsigned long)&cur->ainsn.api.insn[1] == addr)) { + ((unsigned long)&cur->ainsn.xol_insn[1] == addr)) { kprobes_restore_local_irqflag(kcb, regs); post_kprobe_handler(cur, kcb, regs); diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c index 22d0b3252476..4c6d2d712fbd 100644 --- a/arch/arm64/kernel/probes/simulate-insn.c +++ b/arch/arm64/kernel/probes/simulate-insn.c @@ -171,17 +171,15 @@ simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs) void __kprobes simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) { - u64 *load_addr; + unsigned long load_addr; int xn = opcode & 0x1f; - int disp; - disp = ldr_displacement(opcode); - load_addr = (u64 *) (addr + disp); + load_addr = addr + ldr_displacement(opcode); if (opcode & (1 << 30)) /* x0-x30 */ - set_x_reg(regs, xn, *load_addr); + set_x_reg(regs, xn, READ_ONCE(*(u64 *)load_addr)); else /* w0-w30 */ - set_w_reg(regs, xn, *load_addr); + set_w_reg(regs, xn, READ_ONCE(*(u32 *)load_addr)); instruction_pointer_set(regs, instruction_pointer(regs) + 4); } @@ -189,14 +187,18 @@ simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) void __kprobes simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs) { - s32 *load_addr; + unsigned long load_addr; int xn = opcode & 0x1f; - int disp; - disp = ldr_displacement(opcode); - load_addr = (s32 *) (addr + disp); + load_addr = addr + ldr_displacement(opcode); - set_x_reg(regs, xn, *load_addr); + set_x_reg(regs, xn, READ_ONCE(*(s32 *)load_addr)); instruction_pointer_set(regs, instruction_pointer(regs) + 4); } + +void __kprobes +simulate_nop(u32 opcode, long addr, struct pt_regs *regs) +{ + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); +} diff --git a/arch/arm64/kernel/probes/simulate-insn.h b/arch/arm64/kernel/probes/simulate-insn.h index e065dc92218e..efb2803ec943 100644 --- a/arch/arm64/kernel/probes/simulate-insn.h +++ b/arch/arm64/kernel/probes/simulate-insn.h @@ -16,5 +16,6 @@ void simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs); void simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs); void simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs); void simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs); +void simulate_nop(u32 opcode, long addr, struct pt_regs *regs); #endif /* _ARM_KERNEL_KPROBES_SIMULATE_INSN_H */ diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c index d49aef2657cd..cb3d05af36e3 100644 --- a/arch/arm64/kernel/probes/uprobes.c +++ b/arch/arm64/kernel/probes/uprobes.c @@ -17,12 +17,20 @@ void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, void *xol_page_kaddr = kmap_atomic(page); void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); + /* + * Initial cache maintenance of the xol page done via set_pte_at(). + * Subsequent CMOs only needed if the xol slot changes. + */ + if (!memcmp(dst, src, len)) + goto done; + /* Initialize the slot */ memcpy(dst, src, len); /* flush caches (dcache/icache) */ sync_icache_aliases((unsigned long)dst, (unsigned long)dst + len); +done: kunmap_atomic(xol_page_kaddr); } @@ -34,7 +42,7 @@ unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) { - probe_opcode_t insn; + u32 insn; /* TODO: Currently we do not support AARCH32 instruction probing */ if (mm->context.flags & MMCF_AARCH32) @@ -42,7 +50,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) return -EINVAL; - insn = *(probe_opcode_t *)(&auprobe->insn[0]); + insn = le32_to_cpu(auprobe->insn); switch (arm_probe_decode_insn(insn, &auprobe->api)) { case INSN_REJECTED: @@ -102,13 +110,13 @@ bool arch_uprobe_xol_was_trapped(struct task_struct *t) bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { - probe_opcode_t insn; + u32 insn; unsigned long addr; if (!auprobe->simulate) return false; - insn = *(probe_opcode_t *)(&auprobe->insn[0]); + insn = le32_to_cpu(auprobe->insn); addr = instruction_pointer(regs); if (auprobe->api.handler) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 4ae31b7af6c3..2968a33bb3bc 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -43,11 +43,13 @@ #include <linux/stacktrace.h> #include <asm/alternative.h> +#include <asm/arch_timer.h> #include <asm/compat.h> #include <asm/cpufeature.h> #include <asm/cacheflush.h> #include <asm/exec.h> #include <asm/fpsimd.h> +#include <asm/gcs.h> #include <asm/mmu_context.h> #include <asm/mte.h> #include <asm/processor.h> @@ -226,7 +228,7 @@ void __show_regs(struct pt_regs *regs) printk("sp : %016llx\n", sp); if (system_uses_irq_prio_masking()) - printk("pmr_save: %08llx\n", regs->pmr_save); + printk("pmr: %08x\n", regs->pmr); i = top_reg; @@ -271,17 +273,73 @@ static void flush_tagged_addr_state(void) clear_thread_flag(TIF_TAGGED_ADDR); } +static void flush_poe(void) +{ + if (!system_supports_poe()) + return; + + write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0); +} + +#ifdef CONFIG_ARM64_GCS + +static void flush_gcs(void) +{ + if (!system_supports_gcs()) + return; + + gcs_free(current); + current->thread.gcs_el0_mode = 0; + write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1); + write_sysreg_s(0, SYS_GCSPR_EL0); +} + +static int copy_thread_gcs(struct task_struct *p, + const struct kernel_clone_args *args) +{ + unsigned long gcs; + + if (!system_supports_gcs()) + return 0; + + p->thread.gcs_base = 0; + p->thread.gcs_size = 0; + + gcs = gcs_alloc_thread_stack(p, args); + if (IS_ERR_VALUE(gcs)) + return PTR_ERR((void *)gcs); + + p->thread.gcs_el0_mode = current->thread.gcs_el0_mode; + p->thread.gcs_el0_locked = current->thread.gcs_el0_locked; + + return 0; +} + +#else + +static void flush_gcs(void) { } +static int copy_thread_gcs(struct task_struct *p, + const struct kernel_clone_args *args) +{ + return 0; +} + +#endif + void flush_thread(void) { fpsimd_flush_thread(); tls_thread_flush(); flush_ptrace_hw_breakpoint(current); flush_tagged_addr_state(); + flush_poe(); + flush_gcs(); } void arch_release_task_struct(struct task_struct *tsk) { fpsimd_release_task(tsk); + gcs_free(tsk); } int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) @@ -345,6 +403,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) unsigned long stack_start = args->stack; unsigned long tls = args->tls; struct pt_regs *childregs = task_pt_regs(p); + int ret; memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); @@ -371,6 +430,9 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) if (system_supports_tpidr2()) p->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0); + if (system_supports_poe()) + p->thread.por_el0 = read_sysreg_s(SYS_POR_EL0); + if (stack_start) { if (is_compat_thread(task_thread_info(p))) childregs->compat_sp = stack_start; @@ -386,6 +448,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) p->thread.uw.tp_value = tls; p->thread.tpidr2_el0 = 0; } + + ret = copy_thread_gcs(p, args); + if (ret != 0) + return ret; } else { /* * A kthread has no context to ERET to, so ensure any buggy @@ -396,9 +462,13 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) */ memset(childregs, 0, sizeof(struct pt_regs)); childregs->pstate = PSR_MODE_EL1h | PSR_IL_BIT; + childregs->stackframe.type = FRAME_META_TYPE_FINAL; p->thread.cpu_context.x19 = (unsigned long)args->fn; p->thread.cpu_context.x20 = (unsigned long)args->fn_arg; + + if (system_supports_poe()) + p->thread.por_el0 = POR_EL0_INIT; } p->thread.cpu_context.pc = (unsigned long)ret_from_fork; p->thread.cpu_context.sp = (unsigned long)childregs; @@ -406,7 +476,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) * For the benefit of the unwinder, set up childregs->stackframe * as the final frame for the new task. */ - p->thread.cpu_context.fp = (unsigned long)childregs->stackframe; + p->thread.cpu_context.fp = (unsigned long)&childregs->stackframe; ptrace_hw_copy_thread(p); @@ -426,7 +496,7 @@ static void tls_thread_switch(struct task_struct *next) if (is_compat_thread(task_thread_info(next))) write_sysreg(next->thread.uw.tp_value, tpidrro_el0); - else if (!arm64_kernel_unmapped_at_el0()) + else write_sysreg(0, tpidrro_el0); write_sysreg(*task_user_tls(next), tpidr_el0); @@ -471,28 +541,104 @@ static void entry_task_switch(struct task_struct *next) __this_cpu_write(__entry_task, next); } +#ifdef CONFIG_ARM64_GCS + +void gcs_preserve_current_state(void) +{ + current->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); +} + +static void gcs_thread_switch(struct task_struct *next) +{ + if (!system_supports_gcs()) + return; + + /* GCSPR_EL0 is always readable */ + gcs_preserve_current_state(); + write_sysreg_s(next->thread.gcspr_el0, SYS_GCSPR_EL0); + + if (current->thread.gcs_el0_mode != next->thread.gcs_el0_mode) + gcs_set_el0_mode(next); + + /* + * Ensure that GCS memory effects of the 'prev' thread are + * ordered before other memory accesses with release semantics + * (or preceded by a DMB) on the current PE. In addition, any + * memory accesses with acquire semantics (or succeeded by a + * DMB) are ordered before GCS memory effects of the 'next' + * thread. This will ensure that the GCS memory effects are + * visible to other PEs in case of migration. + */ + if (task_gcs_el0_enabled(current) || task_gcs_el0_enabled(next)) + gcsb_dsync(); +} + +#else + +static void gcs_thread_switch(struct task_struct *next) +{ +} + +#endif + /* - * ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT. - * Ensure access is disabled when switching to a 32bit task, ensure - * access is enabled when switching to a 64bit task. + * Handle sysreg updates for ARM erratum 1418040 which affects the 32bit view of + * CNTVCT, various other errata which require trapping all CNTVCT{,_EL0} + * accesses and prctl(PR_SET_TSC). Ensure access is disabled iff a workaround is + * required or PR_TSC_SIGSEGV is set. */ -static void erratum_1418040_thread_switch(struct task_struct *next) +static void update_cntkctl_el1(struct task_struct *next) { - if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) || - !this_cpu_has_cap(ARM64_WORKAROUND_1418040)) - return; + struct thread_info *ti = task_thread_info(next); - if (is_compat_thread(task_thread_info(next))) + if (test_ti_thread_flag(ti, TIF_TSC_SIGSEGV) || + has_erratum_handler(read_cntvct_el0) || + (IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) && + this_cpu_has_cap(ARM64_WORKAROUND_1418040) && + is_compat_thread(ti))) sysreg_clear_set(cntkctl_el1, ARCH_TIMER_USR_VCT_ACCESS_EN, 0); else sysreg_clear_set(cntkctl_el1, 0, ARCH_TIMER_USR_VCT_ACCESS_EN); } -static void erratum_1418040_new_exec(void) +static void cntkctl_thread_switch(struct task_struct *prev, + struct task_struct *next) +{ + if ((read_ti_thread_flags(task_thread_info(prev)) & + (_TIF_32BIT | _TIF_TSC_SIGSEGV)) != + (read_ti_thread_flags(task_thread_info(next)) & + (_TIF_32BIT | _TIF_TSC_SIGSEGV))) + update_cntkctl_el1(next); +} + +static int do_set_tsc_mode(unsigned int val) { + bool tsc_sigsegv; + + if (val == PR_TSC_SIGSEGV) + tsc_sigsegv = true; + else if (val == PR_TSC_ENABLE) + tsc_sigsegv = false; + else + return -EINVAL; + preempt_disable(); - erratum_1418040_thread_switch(current); + update_thread_flag(TIF_TSC_SIGSEGV, tsc_sigsegv); + update_cntkctl_el1(current); preempt_enable(); + + return 0; +} + +static void permission_overlay_switch(struct task_struct *next) +{ + if (!system_supports_poe()) + return; + + current->thread.por_el0 = read_sysreg_s(SYS_POR_EL0); + if (current->thread.por_el0 != next->thread.por_el0) { + write_sysreg_s(next->thread.por_el0, SYS_POR_EL0); + } } /* @@ -528,8 +674,10 @@ struct task_struct *__switch_to(struct task_struct *prev, contextidr_thread_switch(next); entry_task_switch(next); ssbs_thread_switch(next); - erratum_1418040_thread_switch(next); + cntkctl_thread_switch(prev, next); ptrauth_thread_switch_user(next); + permission_overlay_switch(next); + gcs_thread_switch(next); /* * Complete any pending TLB or cache maintenance on this CPU in case @@ -645,7 +793,7 @@ void arch_setup_new_exec(void) current->mm->context.flags = mmflags; ptrauth_thread_init_user(); mte_thread_init_user(); - erratum_1418040_new_exec(); + do_set_tsc_mode(PR_TSC_ENABLE); if (task_spec_ssb_noexec(current)) { arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS, @@ -754,3 +902,26 @@ int arch_elf_adjust_prot(int prot, const struct arch_elf_state *state, return prot; } #endif + +int get_tsc_mode(unsigned long adr) +{ + unsigned int val; + + if (is_compat_task()) + return -EINVAL; + + if (test_thread_flag(TIF_TSC_SIGSEGV)) + val = PR_TSC_SIGSEGV; + else + val = PR_TSC_ENABLE; + + return put_user(val, (unsigned int __user *)adr); +} + +int set_tsc_mode(unsigned int val) +{ + if (is_compat_task()) + return -EINVAL; + + return do_set_tsc_mode(val); +} diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 0d022599eb61..e4437f62a2cd 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -34,6 +34,7 @@ #include <asm/cpufeature.h> #include <asm/debug-monitors.h> #include <asm/fpsimd.h> +#include <asm/gcs.h> #include <asm/mte.h> #include <asm/pointer_auth.h> #include <asm/stacktrace.h> @@ -898,7 +899,11 @@ static int sve_set_common(struct task_struct *target, if (ret) goto out; - /* Actual VL set may be less than the user asked for: */ + /* + * Actual VL set may be different from what the user asked + * for, or we may have configured the _ONEXEC VL not the + * current VL: + */ vq = sve_vq_from_vl(task_get_vl(target, type)); /* Enter/exit streaming mode */ @@ -1125,7 +1130,11 @@ static int za_set(struct task_struct *target, if (ret) goto out; - /* Actual VL set may be less than the user asked for: */ + /* + * Actual VL set may be different from what the user asked + * for, or we may have configured the _ONEXEC rather than + * current VL: + */ vq = sve_vq_from_vl(task_get_sme_vl(target)); /* Ensure there is some SVE storage for streaming mode */ @@ -1440,6 +1449,85 @@ static int tagged_addr_ctrl_set(struct task_struct *target, const struct } #endif +#ifdef CONFIG_ARM64_POE +static int poe_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + if (!system_supports_poe()) + return -EINVAL; + + return membuf_write(&to, &target->thread.por_el0, + sizeof(target->thread.por_el0)); +} + +static int poe_set(struct task_struct *target, const struct + user_regset *regset, unsigned int pos, + unsigned int count, const void *kbuf, const + void __user *ubuf) +{ + int ret; + long ctrl; + + if (!system_supports_poe()) + return -EINVAL; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1); + if (ret) + return ret; + + target->thread.por_el0 = ctrl; + + return 0; +} +#endif + +#ifdef CONFIG_ARM64_GCS +static int gcs_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + struct user_gcs user_gcs; + + if (!system_supports_gcs()) + return -EINVAL; + + if (target == current) + gcs_preserve_current_state(); + + user_gcs.features_enabled = target->thread.gcs_el0_mode; + user_gcs.features_locked = target->thread.gcs_el0_locked; + user_gcs.gcspr_el0 = target->thread.gcspr_el0; + + return membuf_write(&to, &user_gcs, sizeof(user_gcs)); +} + +static int gcs_set(struct task_struct *target, const struct + user_regset *regset, unsigned int pos, + unsigned int count, const void *kbuf, const + void __user *ubuf) +{ + int ret; + struct user_gcs user_gcs; + + if (!system_supports_gcs()) + return -EINVAL; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_gcs, 0, -1); + if (ret) + return ret; + + if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK) + return -EINVAL; + + target->thread.gcs_el0_mode = user_gcs.features_enabled; + target->thread.gcs_el0_locked = user_gcs.features_locked; + target->thread.gcspr_el0 = user_gcs.gcspr_el0; + + return 0; +} +#endif + enum aarch64_regset { REGSET_GPR, REGSET_FPR, @@ -1469,6 +1557,12 @@ enum aarch64_regset { #ifdef CONFIG_ARM64_TAGGED_ADDR_ABI REGSET_TAGGED_ADDR_CTRL, #endif +#ifdef CONFIG_ARM64_POE + REGSET_POE, +#endif +#ifdef CONFIG_ARM64_GCS + REGSET_GCS, +#endif }; static const struct user_regset aarch64_regsets[] = { @@ -1628,6 +1722,26 @@ static const struct user_regset aarch64_regsets[] = { .set = tagged_addr_ctrl_set, }, #endif +#ifdef CONFIG_ARM64_POE + [REGSET_POE] = { + .core_note_type = NT_ARM_POE, + .n = 1, + .size = sizeof(long), + .align = sizeof(long), + .regset_get = poe_get, + .set = poe_set, + }, +#endif +#ifdef CONFIG_ARM64_GCS + [REGSET_GCS] = { + .core_note_type = NT_ARM_GCS, + .n = sizeof(struct user_gcs) / sizeof(u64), + .size = sizeof(u64), + .align = sizeof(u64), + .regset_get = gcs_get, + .set = gcs_set, + }, +#endif }; static const struct user_regset_view user_aarch64_view = { diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c new file mode 100644 index 000000000000..3031f25c32ef --- /dev/null +++ b/arch/arm64/kernel/rsi.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 ARM Ltd. + */ + +#include <linux/jump_label.h> +#include <linux/memblock.h> +#include <linux/psci.h> +#include <linux/swiotlb.h> +#include <linux/cc_platform.h> + +#include <asm/io.h> +#include <asm/mem_encrypt.h> +#include <asm/rsi.h> + +static struct realm_config config; + +unsigned long prot_ns_shared; +EXPORT_SYMBOL(prot_ns_shared); + +DEFINE_STATIC_KEY_FALSE_RO(rsi_present); +EXPORT_SYMBOL(rsi_present); + +bool cc_platform_has(enum cc_attr attr) +{ + switch (attr) { + case CC_ATTR_MEM_ENCRYPT: + return is_realm_world(); + default: + return false; + } +} +EXPORT_SYMBOL_GPL(cc_platform_has); + +static bool rsi_version_matches(void) +{ + unsigned long ver_lower, ver_higher; + unsigned long ret = rsi_request_version(RSI_ABI_VERSION, + &ver_lower, + &ver_higher); + + if (ret == SMCCC_RET_NOT_SUPPORTED) + return false; + + if (ret != RSI_SUCCESS) { + pr_err("RME: RMM doesn't support RSI version %lu.%lu. Supported range: %lu.%lu-%lu.%lu\n", + RSI_ABI_VERSION_MAJOR, RSI_ABI_VERSION_MINOR, + RSI_ABI_VERSION_GET_MAJOR(ver_lower), + RSI_ABI_VERSION_GET_MINOR(ver_lower), + RSI_ABI_VERSION_GET_MAJOR(ver_higher), + RSI_ABI_VERSION_GET_MINOR(ver_higher)); + return false; + } + + pr_info("RME: Using RSI version %lu.%lu\n", + RSI_ABI_VERSION_GET_MAJOR(ver_lower), + RSI_ABI_VERSION_GET_MINOR(ver_lower)); + + return true; +} + +static void __init arm64_rsi_setup_memory(void) +{ + u64 i; + phys_addr_t start, end; + + /* + * Iterate over the available memory ranges and convert the state to + * protected memory. We should take extra care to ensure that we DO NOT + * permit any "DESTROYED" pages to be converted to "RAM". + * + * panic() is used because if the attempt to switch the memory to + * protected has failed here, then future accesses to the memory are + * simply going to be reflected as a SEA (Synchronous External Abort) + * which we can't handle. Bailing out early prevents the guest limping + * on and dying later. + */ + for_each_mem_range(i, &start, &end) { + if (rsi_set_memory_range_protected_safe(start, end)) { + panic("Failed to set memory range to protected: %pa-%pa", + &start, &end); + } + } +} + +bool __arm64_is_protected_mmio(phys_addr_t base, size_t size) +{ + enum ripas ripas; + phys_addr_t end, top; + + /* Overflow ? */ + if (WARN_ON(base + size <= base)) + return false; + + end = ALIGN(base + size, RSI_GRANULE_SIZE); + base = ALIGN_DOWN(base, RSI_GRANULE_SIZE); + + while (base < end) { + if (WARN_ON(rsi_ipa_state_get(base, end, &ripas, &top))) + break; + if (WARN_ON(top <= base)) + break; + if (ripas != RSI_RIPAS_DEV) + break; + base = top; + } + + return base >= end; +} +EXPORT_SYMBOL(__arm64_is_protected_mmio); + +static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot) +{ + if (__arm64_is_protected_mmio(phys, size)) + *prot = pgprot_encrypted(*prot); + else + *prot = pgprot_decrypted(*prot); + + return 0; +} + +void __init arm64_rsi_init(void) +{ + if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC) + return; + if (!rsi_version_matches()) + return; + if (WARN_ON(rsi_get_realm_config(&config))) + return; + prot_ns_shared = BIT(config.ipa_bits - 1); + + if (arm64_ioremap_prot_hook_register(realm_ioremap_hook)) + return; + + if (realm_register_memory_enc_ops()) + return; + + arm64_rsi_setup_memory(); + + static_branch_enable(&rsi_present); +} + diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index b22d28ec8028..4f613e8e0745 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -43,6 +43,7 @@ #include <asm/cpu_ops.h> #include <asm/kasan.h> #include <asm/numa.h> +#include <asm/rsi.h> #include <asm/scs.h> #include <asm/sections.h> #include <asm/setup.h> @@ -175,7 +176,11 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) if (dt_virt) memblock_reserve(dt_phys, size); - if (!dt_virt || !early_init_dt_scan(dt_virt)) { + /* + * dt_virt is a fixmap address, hence __pa(dt_virt) can't be used. + * Pass dt_phys directly. + */ + if (!early_init_dt_scan(dt_virt, dt_phys)) { pr_crit("\n" "Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n" "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" @@ -351,6 +356,8 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) else psci_acpi_init(); + arm64_rsi_init(); + init_bootcpu_ops(); smp_init_cpus(); smp_build_mpidr_hash(); diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 4a77f4976e11..14ac6fdb872b 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -19,12 +19,14 @@ #include <linux/ratelimit.h> #include <linux/rseq.h> #include <linux/syscalls.h> +#include <linux/pkeys.h> #include <asm/daifflags.h> #include <asm/debug-monitors.h> #include <asm/elf.h> #include <asm/exception.h> #include <asm/cacheflush.h> +#include <asm/gcs.h> #include <asm/ucontext.h> #include <asm/unistd.h> #include <asm/fpsimd.h> @@ -34,6 +36,15 @@ #include <asm/traps.h> #include <asm/vdso.h> +#ifdef CONFIG_ARM64_GCS +#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK) + +static bool gcs_signal_cap_valid(u64 addr, u64 val) +{ + return val == GCS_SIGNAL_CAP(addr); +} +#endif + /* * Do a signal return; undo the signal stack. These are aligned to 128-bit. */ @@ -42,11 +53,6 @@ struct rt_sigframe { struct ucontext uc; }; -struct frame_record { - u64 fp; - u64 lr; -}; - struct rt_sigframe_user_layout { struct rt_sigframe __user *sigframe; struct frame_record __user *next_frame; @@ -56,19 +62,73 @@ struct rt_sigframe_user_layout { unsigned long fpsimd_offset; unsigned long esr_offset; + unsigned long gcs_offset; unsigned long sve_offset; unsigned long tpidr2_offset; unsigned long za_offset; unsigned long zt_offset; unsigned long fpmr_offset; + unsigned long poe_offset; unsigned long extra_offset; unsigned long end_offset; }; -#define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16) +/* + * Holds any EL0-controlled state that influences unprivileged memory accesses. + * This includes both accesses done in userspace and uaccess done in the kernel. + * + * This state needs to be carefully managed to ensure that it doesn't cause + * uaccess to fail when setting up the signal frame, and the signal handler + * itself also expects a well-defined state when entered. + */ +struct user_access_state { + u64 por_el0; +}; + #define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16) #define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16) +/* + * Save the user access state into ua_state and reset it to disable any + * restrictions. + */ +static void save_reset_user_access_state(struct user_access_state *ua_state) +{ + if (system_supports_poe()) { + u64 por_enable_all = 0; + + for (int pkey = 0; pkey < arch_max_pkey(); pkey++) + por_enable_all |= POE_RXW << (pkey * POR_BITS_PER_PKEY); + + ua_state->por_el0 = read_sysreg_s(SYS_POR_EL0); + write_sysreg_s(por_enable_all, SYS_POR_EL0); + /* Ensure that any subsequent uaccess observes the updated value */ + isb(); + } +} + +/* + * Set the user access state for invoking the signal handler. + * + * No uaccess should be done after that function is called. + */ +static void set_handler_user_access_state(void) +{ + if (system_supports_poe()) + write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0); +} + +/* + * Restore the user access state to the values saved in ua_state. + * + * No uaccess should be done after that function is called. + */ +static void restore_user_access_state(const struct user_access_state *ua_state) +{ + if (system_supports_poe()) + write_sysreg_s(ua_state->por_el0, SYS_POR_EL0); +} + static void init_user_layout(struct rt_sigframe_user_layout *user) { const size_t reserved_size = @@ -185,6 +245,10 @@ struct user_ctxs { u32 zt_size; struct fpmr_context __user *fpmr; u32 fpmr_size; + struct poe_context __user *poe; + u32 poe_size; + struct gcs_context __user *gcs; + u32 gcs_size; }; static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) @@ -258,6 +322,34 @@ static int restore_fpmr_context(struct user_ctxs *user) return err; } +static int preserve_poe_context(struct poe_context __user *ctx, + const struct user_access_state *ua_state) +{ + int err = 0; + + __put_user_error(POE_MAGIC, &ctx->head.magic, err); + __put_user_error(sizeof(*ctx), &ctx->head.size, err); + __put_user_error(ua_state->por_el0, &ctx->por_el0, err); + + return err; +} + +static int restore_poe_context(struct user_ctxs *user, + struct user_access_state *ua_state) +{ + u64 por_el0; + int err = 0; + + if (user->poe_size != sizeof(*user->poe)) + return -EINVAL; + + __get_user_error(por_el0, &(user->poe->por_el0), err); + if (!err) + ua_state->por_el0 = por_el0; + + return err; +} + #ifdef CONFIG_ARM64_SVE static int preserve_sve_context(struct sve_context __user *ctx) @@ -604,6 +696,82 @@ extern int restore_zt_context(struct user_ctxs *user); #endif /* ! CONFIG_ARM64_SME */ +#ifdef CONFIG_ARM64_GCS + +static int preserve_gcs_context(struct gcs_context __user *ctx) +{ + int err = 0; + u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0); + + /* + * If GCS is enabled we will add a cap token to the frame, + * include it in the GCSPR_EL0 we report to support stack + * switching via sigreturn if GCS is enabled. We do not allow + * enabling via sigreturn so the token is only relevant for + * threads with GCS enabled. + */ + if (task_gcs_el0_enabled(current)) + gcspr -= 8; + + __put_user_error(GCS_MAGIC, &ctx->head.magic, err); + __put_user_error(sizeof(*ctx), &ctx->head.size, err); + __put_user_error(gcspr, &ctx->gcspr, err); + __put_user_error(0, &ctx->reserved, err); + __put_user_error(current->thread.gcs_el0_mode, + &ctx->features_enabled, err); + + return err; +} + +static int restore_gcs_context(struct user_ctxs *user) +{ + u64 gcspr, enabled; + int err = 0; + + if (user->gcs_size != sizeof(*user->gcs)) + return -EINVAL; + + __get_user_error(gcspr, &user->gcs->gcspr, err); + __get_user_error(enabled, &user->gcs->features_enabled, err); + if (err) + return err; + + /* Don't allow unknown modes */ + if (enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK) + return -EINVAL; + + err = gcs_check_locked(current, enabled); + if (err != 0) + return err; + + /* Don't allow enabling */ + if (!task_gcs_el0_enabled(current) && + (enabled & PR_SHADOW_STACK_ENABLE)) + return -EINVAL; + + /* If we are disabling disable everything */ + if (!(enabled & PR_SHADOW_STACK_ENABLE)) + enabled = 0; + + current->thread.gcs_el0_mode = enabled; + + /* + * We let userspace set GCSPR_EL0 to anything here, we will + * validate later in gcs_restore_signal(). + */ + write_sysreg_s(gcspr, SYS_GCSPR_EL0); + + return 0; +} + +#else /* ! CONFIG_ARM64_GCS */ + +/* Turn any non-optimised out attempts to use these into a link error: */ +extern int preserve_gcs_context(void __user *ctx); +extern int restore_gcs_context(struct user_ctxs *user); + +#endif /* ! CONFIG_ARM64_GCS */ + static int parse_user_sigframe(struct user_ctxs *user, struct rt_sigframe __user *sf) { @@ -621,6 +789,8 @@ static int parse_user_sigframe(struct user_ctxs *user, user->za = NULL; user->zt = NULL; user->fpmr = NULL; + user->poe = NULL; + user->gcs = NULL; if (!IS_ALIGNED((unsigned long)base, 16)) goto invalid; @@ -671,6 +841,17 @@ static int parse_user_sigframe(struct user_ctxs *user, /* ignore */ break; + case POE_MAGIC: + if (!system_supports_poe()) + goto invalid; + + if (user->poe) + goto invalid; + + user->poe = (struct poe_context __user *)head; + user->poe_size = size; + break; + case SVE_MAGIC: if (!system_supports_sve() && !system_supports_sme()) goto invalid; @@ -726,6 +907,17 @@ static int parse_user_sigframe(struct user_ctxs *user, user->fpmr_size = size; break; + case GCS_MAGIC: + if (!system_supports_gcs()) + goto invalid; + + if (user->gcs) + goto invalid; + + user->gcs = (struct gcs_context __user *)head; + user->gcs_size = size; + break; + case EXTRA_MAGIC: if (have_extra_context) goto invalid; @@ -809,7 +1001,8 @@ invalid: } static int restore_sigframe(struct pt_regs *regs, - struct rt_sigframe __user *sf) + struct rt_sigframe __user *sf, + struct user_access_state *ua_state) { sigset_t set; int i, err; @@ -845,6 +1038,9 @@ static int restore_sigframe(struct pt_regs *regs, err = restore_fpsimd_context(&user); } + if (err == 0 && system_supports_gcs() && user.gcs) + err = restore_gcs_context(&user); + if (err == 0 && system_supports_tpidr2() && user.tpidr2) err = restore_tpidr2_context(&user); @@ -857,13 +1053,69 @@ static int restore_sigframe(struct pt_regs *regs, if (err == 0 && system_supports_sme2() && user.zt) err = restore_zt_context(&user); + if (err == 0 && system_supports_poe() && user.poe) + err = restore_poe_context(&user, ua_state); + return err; } +#ifdef CONFIG_ARM64_GCS +static int gcs_restore_signal(void) +{ + unsigned long __user *gcspr_el0; + u64 cap; + int ret; + + if (!system_supports_gcs()) + return 0; + + if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE)) + return 0; + + gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0); + + /* + * Ensure that any changes to the GCS done via GCS operations + * are visible to the normal reads we do to validate the + * token. + */ + gcsb_dsync(); + + /* + * GCSPR_EL0 should be pointing at a capped GCS, read the cap. + * We don't enforce that this is in a GCS page, if it is not + * then faults will be generated on GCS operations - the main + * concern is to protect GCS pages. + */ + ret = copy_from_user(&cap, gcspr_el0, sizeof(cap)); + if (ret) + return -EFAULT; + + /* + * Check that the cap is the actual GCS before replacing it. + */ + if (!gcs_signal_cap_valid((u64)gcspr_el0, cap)) + return -EINVAL; + + /* Invalidate the token to prevent reuse */ + put_user_gcs(0, (__user void*)gcspr_el0, &ret); + if (ret != 0) + return -EFAULT; + + write_sysreg_s(gcspr_el0 + 1, SYS_GCSPR_EL0); + + return 0; +} + +#else +static int gcs_restore_signal(void) { return 0; } +#endif + SYSCALL_DEFINE0(rt_sigreturn) { struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame; + struct user_access_state ua_state; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; @@ -880,12 +1132,17 @@ SYSCALL_DEFINE0(rt_sigreturn) if (!access_ok(frame, sizeof (*frame))) goto badframe; - if (restore_sigframe(regs, frame)) + if (restore_sigframe(regs, frame, &ua_state)) + goto badframe; + + if (gcs_restore_signal()) goto badframe; if (restore_altstack(&frame->uc.uc_stack)) goto badframe; + restore_user_access_state(&ua_state); + return regs->regs[0]; badframe: @@ -920,6 +1177,15 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, return err; } +#ifdef CONFIG_ARM64_GCS + if (system_supports_gcs() && (add_all || current->thread.gcspr_el0)) { + err = sigframe_alloc(user, &user->gcs_offset, + sizeof(struct gcs_context)); + if (err) + return err; + } +#endif + if (system_supports_sve() || system_supports_sme()) { unsigned int vq = 0; @@ -980,11 +1246,19 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, return err; } + if (system_supports_poe()) { + err = sigframe_alloc(user, &user->poe_offset, + sizeof(struct poe_context)); + if (err) + return err; + } + return sigframe_alloc_end(user); } static int setup_sigframe(struct rt_sigframe_user_layout *user, - struct pt_regs *regs, sigset_t *set) + struct pt_regs *regs, sigset_t *set, + const struct user_access_state *ua_state) { int i, err = 0; struct rt_sigframe __user *sf = user->sigframe; @@ -1020,6 +1294,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, __put_user_error(current->thread.fault_code, &esr_ctx->esr, err); } + if (system_supports_gcs() && err == 0 && user->gcs_offset) { + struct gcs_context __user *gcs_ctx = + apply_user_offset(user, user->gcs_offset); + err |= preserve_gcs_context(gcs_ctx); + } + /* Scalable Vector Extension state (including streaming), if present */ if ((system_supports_sve() || system_supports_sme()) && err == 0 && user->sve_offset) { @@ -1042,6 +1322,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, err |= preserve_fpmr_context(fpmr_ctx); } + if (system_supports_poe() && err == 0) { + struct poe_context __user *poe_ctx = + apply_user_offset(user, user->poe_offset); + + err |= preserve_poe_context(poe_ctx, ua_state); + } + /* ZA state if present */ if (system_supports_sme() && err == 0 && user->za_offset) { struct za_context __user *za_ctx = @@ -1130,7 +1417,48 @@ static int get_sigframe(struct rt_sigframe_user_layout *user, return 0; } -static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, +#ifdef CONFIG_ARM64_GCS + +static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig) +{ + unsigned long __user *gcspr_el0; + int ret = 0; + + if (!system_supports_gcs()) + return 0; + + if (!task_gcs_el0_enabled(current)) + return 0; + + /* + * We are entering a signal handler, current register state is + * active. + */ + gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0); + + /* + * Push a cap and the GCS entry for the trampoline onto the GCS. + */ + put_user_gcs((unsigned long)sigtramp, gcspr_el0 - 2, &ret); + put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 1), gcspr_el0 - 1, &ret); + if (ret != 0) + return ret; + + gcspr_el0 -= 2; + write_sysreg_s((unsigned long)gcspr_el0, SYS_GCSPR_EL0); + + return 0; +} +#else + +static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig) +{ + return 0; +} + +#endif + +static int setup_return(struct pt_regs *regs, struct ksignal *ksig, struct rt_sigframe_user_layout *user, int usig) { __sigrestore_t sigtramp; @@ -1138,7 +1466,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, regs->regs[0] = usig; regs->sp = (unsigned long)user->sigframe; regs->regs[29] = (unsigned long)&user->next_frame->fp; - regs->pc = (unsigned long)ka->sa.sa_handler; + regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* * Signal delivery is a (wacky) indirect function call in @@ -1178,12 +1506,14 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, sme_smstop(); } - if (ka->sa.sa_flags & SA_RESTORER) - sigtramp = ka->sa.sa_restorer; + if (ksig->ka.sa.sa_flags & SA_RESTORER) + sigtramp = ksig->ka.sa.sa_restorer; else sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); regs->regs[30] = (unsigned long)sigtramp; + + return gcs_signal_entry(sigtramp, ksig); } static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, @@ -1191,6 +1521,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, { struct rt_sigframe_user_layout user; struct rt_sigframe __user *frame; + struct user_access_state ua_state; int err = 0; fpsimd_signal_preserve_current_state(); @@ -1198,15 +1529,16 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, if (get_sigframe(&user, ksig, regs)) return 1; + save_reset_user_access_state(&ua_state); frame = user.sigframe; __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(NULL, &frame->uc.uc_link, err); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); - err |= setup_sigframe(&user, regs, set); + err |= setup_sigframe(&user, regs, set, &ua_state); if (err == 0) { - setup_return(regs, &ksig->ka, &user, usig); + err = setup_return(regs, ksig, &user, usig); if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, &ksig->info); regs->regs[1] = (unsigned long)&frame->info; @@ -1214,6 +1546,11 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, } } + if (err == 0) + set_handler_user_access_state(); + else + restore_user_access_state(&ua_state); + return err; } diff --git a/arch/arm64/kernel/smccc-call.S b/arch/arm64/kernel/smccc-call.S index 487381164ff6..2def9d0dd3dd 100644 --- a/arch/arm64/kernel/smccc-call.S +++ b/arch/arm64/kernel/smccc-call.S @@ -7,48 +7,19 @@ #include <asm/asm-offsets.h> #include <asm/assembler.h> -#include <asm/thread_info.h> - -/* - * If we have SMCCC v1.3 and (as is likely) no SVE state in - * the registers then set the SMCCC hint bit to say there's no - * need to preserve it. Do this by directly adjusting the SMCCC - * function value which is already stored in x0 ready to be called. - */ -SYM_FUNC_START(__arm_smccc_sve_check) - - ldr_l x16, smccc_has_sve_hint - cbz x16, 2f - - get_current_task x16 - ldr x16, [x16, #TSK_TI_FLAGS] - tbnz x16, #TIF_FOREIGN_FPSTATE, 1f // Any live FP state? - tbnz x16, #TIF_SVE, 2f // Does that state include SVE? - -1: orr x0, x0, ARM_SMCCC_1_3_SVE_HINT - -2: ret -SYM_FUNC_END(__arm_smccc_sve_check) -EXPORT_SYMBOL(__arm_smccc_sve_check) .macro SMCCC instr - stp x29, x30, [sp, #-16]! - mov x29, sp -alternative_if ARM64_SVE - bl __arm_smccc_sve_check -alternative_else_nop_endif \instr #0 - ldr x4, [sp, #16] + ldr x4, [sp] stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] - ldr x4, [sp, #24] + ldr x4, [sp, #8] cbz x4, 1f /* no quirk structure */ ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS] cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6 b.ne 1f str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS] -1: ldp x29, x30, [sp], #16 - ret +1: ret .endm /* diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index f01f0fd7b7fe..3b3f6b56e733 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -68,7 +68,7 @@ enum ipi_msg_type { IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CPU_STOP, - IPI_CPU_CRASH_STOP, + IPI_CPU_STOP_NMI, IPI_TIMER, IPI_IRQ_WORK, NR_IPI, @@ -85,6 +85,8 @@ static int ipi_irq_base __ro_after_init; static int nr_ipi __ro_after_init = NR_IPI; static struct irq_desc *ipi_desc[MAX_IPI] __ro_after_init; +static bool crash_stop; + static void ipi_setup(int cpu); #ifdef CONFIG_HOTPLUG_CPU @@ -823,7 +825,7 @@ static const char *ipi_types[MAX_IPI] __tracepoint_string = { [IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_CALL_FUNC] = "Function call interrupts", [IPI_CPU_STOP] = "CPU stop interrupts", - [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", + [IPI_CPU_STOP_NMI] = "CPU stop NMIs", [IPI_TIMER] = "Timer broadcast interrupts", [IPI_IRQ_WORK] = "IRQ work interrupts", [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", @@ -867,9 +869,9 @@ void arch_irq_work_raise(void) } #endif -static void __noreturn local_cpu_stop(void) +static void __noreturn local_cpu_stop(unsigned int cpu) { - set_cpu_online(smp_processor_id(), false); + set_cpu_online(cpu, false); local_daif_mask(); sdei_mask_local_cpu(); @@ -883,21 +885,26 @@ static void __noreturn local_cpu_stop(void) */ void __noreturn panic_smp_self_stop(void) { - local_cpu_stop(); + local_cpu_stop(smp_processor_id()); } -#ifdef CONFIG_KEXEC_CORE -static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0); -#endif - static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) { #ifdef CONFIG_KEXEC_CORE + /* + * Use local_daif_mask() instead of local_irq_disable() to make sure + * that pseudo-NMIs are disabled. The "crash stop" code starts with + * an IRQ and falls back to NMI (which might be pseudo). If the IRQ + * finally goes through right as we're timing out then the NMI could + * interrupt us. It's better to prevent the NMI and let the IRQ + * finish since the pt_regs will be better. + */ + local_daif_mask(); + crash_save_cpu(regs, cpu); - atomic_dec(&waiting_for_crash_ipi); + set_cpu_online(cpu, false); - local_irq_disable(); sdei_mask_local_cpu(); if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) @@ -962,14 +969,12 @@ static void do_handle_IPI(int ipinr) break; case IPI_CPU_STOP: - local_cpu_stop(); - break; - - case IPI_CPU_CRASH_STOP: - if (IS_ENABLED(CONFIG_KEXEC_CORE)) { + case IPI_CPU_STOP_NMI: + if (IS_ENABLED(CONFIG_KEXEC_CORE) && crash_stop) { ipi_cpu_crash_stop(cpu, get_irq_regs()); - unreachable(); + } else { + local_cpu_stop(cpu); } break; @@ -1024,8 +1029,7 @@ static bool ipi_should_be_nmi(enum ipi_msg_type ipi) return false; switch (ipi) { - case IPI_CPU_STOP: - case IPI_CPU_CRASH_STOP: + case IPI_CPU_STOP_NMI: case IPI_CPU_BACKTRACE: case IPI_KGDB_ROUNDUP: return true; @@ -1138,79 +1142,109 @@ static inline unsigned int num_other_online_cpus(void) void smp_send_stop(void) { + static unsigned long stop_in_progress; + cpumask_t mask; unsigned long timeout; - if (num_other_online_cpus()) { - cpumask_t mask; + /* + * If this cpu is the only one alive at this point in time, online or + * not, there are no stop messages to be sent around, so just back out. + */ + if (num_other_online_cpus() == 0) + goto skip_ipi; - cpumask_copy(&mask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &mask); + /* Only proceed if this is the first CPU to reach this code */ + if (test_and_set_bit(0, &stop_in_progress)) + return; - if (system_state <= SYSTEM_RUNNING) - pr_crit("SMP: stopping secondary CPUs\n"); - smp_cross_call(&mask, IPI_CPU_STOP); - } + /* + * Send an IPI to all currently online CPUs except the CPU running + * this code. + * + * NOTE: we don't do anything here to prevent other CPUs from coming + * online after we snapshot `cpu_online_mask`. Ideally, the calling code + * should do something to prevent other CPUs from coming up. This code + * can be called in the panic path and thus it doesn't seem wise to + * grab the CPU hotplug mutex ourselves. Worst case: + * - If a CPU comes online as we're running, we'll likely notice it + * during the 1 second wait below and then we'll catch it when we try + * with an NMI (assuming NMIs are enabled) since we re-snapshot the + * mask before sending an NMI. + * - If we leave the function and see that CPUs are still online we'll + * at least print a warning. Especially without NMIs this function + * isn't foolproof anyway so calling code will just have to accept + * the fact that there could be cases where a CPU can't be stopped. + */ + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); - /* Wait up to one second for other CPUs to stop */ + if (system_state <= SYSTEM_RUNNING) + pr_crit("SMP: stopping secondary CPUs\n"); + + /* + * Start with a normal IPI and wait up to one second for other CPUs to + * stop. We do this first because it gives other processors a chance + * to exit critical sections / drop locks and makes the rest of the + * stop process (especially console flush) more robust. + */ + smp_cross_call(&mask, IPI_CPU_STOP); timeout = USEC_PER_SEC; while (num_other_online_cpus() && timeout--) udelay(1); - if (num_other_online_cpus()) + /* + * If CPUs are still online, try an NMI. There's no excuse for this to + * be slow, so we only give them an extra 10 ms to respond. + */ + if (num_other_online_cpus() && ipi_should_be_nmi(IPI_CPU_STOP_NMI)) { + smp_rmb(); + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); + + pr_info("SMP: retry stop with NMI for CPUs %*pbl\n", + cpumask_pr_args(&mask)); + + smp_cross_call(&mask, IPI_CPU_STOP_NMI); + timeout = USEC_PER_MSEC * 10; + while (num_other_online_cpus() && timeout--) + udelay(1); + } + + if (num_other_online_cpus()) { + smp_rmb(); + cpumask_copy(&mask, cpu_online_mask); + cpumask_clear_cpu(smp_processor_id(), &mask); + pr_warn("SMP: failed to stop secondary CPUs %*pbl\n", - cpumask_pr_args(cpu_online_mask)); + cpumask_pr_args(&mask)); + } +skip_ipi: sdei_mask_local_cpu(); } #ifdef CONFIG_KEXEC_CORE void crash_smp_send_stop(void) { - static int cpus_stopped; - cpumask_t mask; - unsigned long timeout; - /* * This function can be called twice in panic path, but obviously * we execute this only once. + * + * We use this same boolean to tell whether the IPI we send was a + * stop or a "crash stop". */ - if (cpus_stopped) + if (crash_stop) return; + crash_stop = 1; - cpus_stopped = 1; + smp_send_stop(); - /* - * If this cpu is the only one alive at this point in time, online or - * not, there are no stop messages to be sent around, so just back out. - */ - if (num_other_online_cpus() == 0) - goto skip_ipi; - - cpumask_copy(&mask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &mask); - - atomic_set(&waiting_for_crash_ipi, num_other_online_cpus()); - - pr_crit("SMP: stopping secondary CPUs\n"); - smp_cross_call(&mask, IPI_CPU_CRASH_STOP); - - /* Wait up to one second for other CPUs to stop */ - timeout = USEC_PER_SEC; - while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--) - udelay(1); - - if (atomic_read(&waiting_for_crash_ipi) > 0) - pr_warn("SMP: failed to stop secondary CPUs %*pbl\n", - cpumask_pr_args(&mask)); - -skip_ipi: - sdei_mask_local_cpu(); sdei_handler_abort(); } bool smp_crash_stop_failed(void) { - return (atomic_read(&waiting_for_crash_ipi) > 0); + return num_other_online_cpus() != 0; } #endif diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index 6b3258860377..caef85462acb 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -20,11 +20,29 @@ #include <asm/stack_pointer.h> #include <asm/stacktrace.h> +enum kunwind_source { + KUNWIND_SOURCE_UNKNOWN, + KUNWIND_SOURCE_FRAME, + KUNWIND_SOURCE_CALLER, + KUNWIND_SOURCE_TASK, + KUNWIND_SOURCE_REGS_PC, + KUNWIND_SOURCE_REGS_LR, +}; + +union unwind_flags { + unsigned long all; + struct { + unsigned long fgraph : 1, + kretprobe : 1; + }; +}; + /* * Kernel unwind state * * @common: Common unwind state. * @task: The task being unwound. + * @graph_idx: Used by ftrace_graph_ret_addr() for optimized stack unwinding. * @kr_cur: When KRETPROBES is selected, holds the kretprobe instance * associated with the most recently encountered replacement lr * value. @@ -32,9 +50,13 @@ struct kunwind_state { struct unwind_state common; struct task_struct *task; + int graph_idx; #ifdef CONFIG_KRETPROBES struct llist_node *kr_cur; #endif + enum kunwind_source source; + union unwind_flags flags; + struct pt_regs *regs; }; static __always_inline void @@ -43,6 +65,9 @@ kunwind_init(struct kunwind_state *state, { unwind_init_common(&state->common); state->task = task; + state->source = KUNWIND_SOURCE_UNKNOWN; + state->flags.all = 0; + state->regs = NULL; } /* @@ -58,8 +83,10 @@ kunwind_init_from_regs(struct kunwind_state *state, { kunwind_init(state, current); + state->regs = regs; state->common.fp = regs->regs[29]; state->common.pc = regs->pc; + state->source = KUNWIND_SOURCE_REGS_PC; } /* @@ -77,6 +104,7 @@ kunwind_init_from_caller(struct kunwind_state *state) state->common.fp = (unsigned long)__builtin_frame_address(1); state->common.pc = (unsigned long)__builtin_return_address(0); + state->source = KUNWIND_SOURCE_CALLER; } /* @@ -97,6 +125,7 @@ kunwind_init_from_task(struct kunwind_state *state, state->common.fp = thread_saved_fp(task); state->common.pc = thread_saved_pc(task); + state->source = KUNWIND_SOURCE_TASK; } static __always_inline int @@ -106,12 +135,13 @@ kunwind_recover_return_address(struct kunwind_state *state) if (state->task->ret_stack && (state->common.pc == (unsigned long)return_to_handler)) { unsigned long orig_pc; - orig_pc = ftrace_graph_ret_addr(state->task, NULL, + orig_pc = ftrace_graph_ret_addr(state->task, &state->graph_idx, state->common.pc, (void *)state->common.fp); if (WARN_ON_ONCE(state->common.pc == orig_pc)) return -EINVAL; state->common.pc = orig_pc; + state->flags.fgraph = 1; } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ @@ -122,12 +152,110 @@ kunwind_recover_return_address(struct kunwind_state *state) (void *)state->common.fp, &state->kr_cur); state->common.pc = orig_pc; + state->flags.kretprobe = 1; } #endif /* CONFIG_KRETPROBES */ return 0; } +static __always_inline +int kunwind_next_regs_pc(struct kunwind_state *state) +{ + struct stack_info *info; + unsigned long fp = state->common.fp; + struct pt_regs *regs; + + regs = container_of((u64 *)fp, struct pt_regs, stackframe.record.fp); + + info = unwind_find_stack(&state->common, (unsigned long)regs, sizeof(*regs)); + if (!info) + return -EINVAL; + + unwind_consume_stack(&state->common, info, (unsigned long)regs, + sizeof(*regs)); + + state->regs = regs; + state->common.pc = regs->pc; + state->common.fp = regs->regs[29]; + state->source = KUNWIND_SOURCE_REGS_PC; + return 0; +} + +static __always_inline int +kunwind_next_regs_lr(struct kunwind_state *state) +{ + /* + * The stack for the regs was consumed by kunwind_next_regs_pc(), so we + * cannot consume that again here, but we know the regs are safe to + * access. + */ + state->common.pc = state->regs->regs[30]; + state->common.fp = state->regs->regs[29]; + state->regs = NULL; + state->source = KUNWIND_SOURCE_REGS_LR; + + return 0; +} + +static __always_inline int +kunwind_next_frame_record_meta(struct kunwind_state *state) +{ + struct task_struct *tsk = state->task; + unsigned long fp = state->common.fp; + struct frame_record_meta *meta; + struct stack_info *info; + + info = unwind_find_stack(&state->common, fp, sizeof(*meta)); + if (!info) + return -EINVAL; + + meta = (struct frame_record_meta *)fp; + switch (READ_ONCE(meta->type)) { + case FRAME_META_TYPE_FINAL: + if (meta == &task_pt_regs(tsk)->stackframe) + return -ENOENT; + WARN_ON_ONCE(1); + return -EINVAL; + case FRAME_META_TYPE_PT_REGS: + return kunwind_next_regs_pc(state); + default: + WARN_ON_ONCE(1); + return -EINVAL; + } +} + +static __always_inline int +kunwind_next_frame_record(struct kunwind_state *state) +{ + unsigned long fp = state->common.fp; + struct frame_record *record; + struct stack_info *info; + unsigned long new_fp, new_pc; + + if (fp & 0x7) + return -EINVAL; + + info = unwind_find_stack(&state->common, fp, sizeof(*record)); + if (!info) + return -EINVAL; + + record = (struct frame_record *)fp; + new_fp = READ_ONCE(record->fp); + new_pc = READ_ONCE(record->lr); + + if (!new_fp && !new_pc) + return kunwind_next_frame_record_meta(state); + + unwind_consume_stack(&state->common, info, fp, sizeof(*record)); + + state->common.fp = new_fp; + state->common.pc = new_pc; + state->source = KUNWIND_SOURCE_FRAME; + + return 0; +} + /* * Unwind from one frame record (A) to the next frame record (B). * @@ -138,15 +266,24 @@ kunwind_recover_return_address(struct kunwind_state *state) static __always_inline int kunwind_next(struct kunwind_state *state) { - struct task_struct *tsk = state->task; - unsigned long fp = state->common.fp; int err; - /* Final frame; nothing to unwind */ - if (fp == (unsigned long)task_pt_regs(tsk)->stackframe) - return -ENOENT; + state->flags.all = 0; + + switch (state->source) { + case KUNWIND_SOURCE_FRAME: + case KUNWIND_SOURCE_CALLER: + case KUNWIND_SOURCE_TASK: + case KUNWIND_SOURCE_REGS_LR: + err = kunwind_next_frame_record(state); + break; + case KUNWIND_SOURCE_REGS_PC: + err = kunwind_next_regs_lr(state); + break; + default: + err = -EINVAL; + } - err = unwind_next_frame_record(&state->common); if (err) return err; @@ -292,10 +429,33 @@ noinline noinstr void arch_bpf_stack_walk(bool (*consume_entry)(void *cookie, u6 kunwind_stack_walk(arch_bpf_unwind_consume_entry, &data, current, NULL); } -static bool dump_backtrace_entry(void *arg, unsigned long where) +static const char *state_source_string(const struct kunwind_state *state) { + switch (state->source) { + case KUNWIND_SOURCE_FRAME: return NULL; + case KUNWIND_SOURCE_CALLER: return "C"; + case KUNWIND_SOURCE_TASK: return "T"; + case KUNWIND_SOURCE_REGS_PC: return "P"; + case KUNWIND_SOURCE_REGS_LR: return "L"; + default: return "U"; + } +} + +static bool dump_backtrace_entry(const struct kunwind_state *state, void *arg) +{ + const char *source = state_source_string(state); + union unwind_flags flags = state->flags; + bool has_info = source || flags.all; char *loglvl = arg; - printk("%s %pSb\n", loglvl, (void *)where); + + printk("%s %pSb%s%s%s%s%s\n", loglvl, + (void *)state->common.pc, + has_info ? " (" : "", + source ? source : "", + flags.fgraph ? "F" : "", + flags.kretprobe ? "K" : "", + has_info ? ")" : ""); + return true; } @@ -314,7 +474,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk, return; printk("%sCall trace:\n", loglvl); - arch_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs); + kunwind_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs); put_task_stack(tsk); } diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 9e22683aa921..ee318f6df647 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -273,6 +273,12 @@ void arm64_force_sig_fault(int signo, int code, unsigned long far, force_sig_fault(signo, code, (void __user *)far); } +void arm64_force_sig_fault_pkey(unsigned long far, const char *str, int pkey) +{ + arm64_show_signal(SIGSEGV, str); + force_sig_pkuerr((void __user *)far, pkey); +} + void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str) { @@ -500,6 +506,16 @@ void do_el1_bti(struct pt_regs *regs, unsigned long esr) die("Oops - BTI", regs, esr); } +void do_el0_gcs(struct pt_regs *regs, unsigned long esr) +{ + force_signal_inject(SIGSEGV, SEGV_CPERR, regs->pc, 0); +} + +void do_el1_gcs(struct pt_regs *regs, unsigned long esr) +{ + die("Oops - GCS", regs, esr); +} + void do_el0_fpac(struct pt_regs *regs, unsigned long esr) { force_signal_inject(SIGILL, ILL_ILLOPN, regs->pc, esr); @@ -525,6 +541,13 @@ void do_el0_mops(struct pt_regs *regs, unsigned long esr) user_fastforward_single_step(current); } +void do_el1_mops(struct pt_regs *regs, unsigned long esr) +{ + arm64_mops_reset_regs(®s->user_regs, esr); + + kernel_fastforward_single_step(regs); +} + #define __user_cache_maint(insn, address, res) \ if (address >= TASK_SIZE_MAX) { \ res = -EFAULT; \ @@ -601,18 +624,26 @@ static void ctr_read_handler(unsigned long esr, struct pt_regs *regs) static void cntvct_read_handler(unsigned long esr, struct pt_regs *regs) { - int rt = ESR_ELx_SYS64_ISS_RT(esr); + if (test_thread_flag(TIF_TSC_SIGSEGV)) { + force_sig(SIGSEGV); + } else { + int rt = ESR_ELx_SYS64_ISS_RT(esr); - pt_regs_write_reg(regs, rt, arch_timer_read_counter()); - arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + pt_regs_write_reg(regs, rt, arch_timer_read_counter()); + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } } static void cntfrq_read_handler(unsigned long esr, struct pt_regs *regs) { - int rt = ESR_ELx_SYS64_ISS_RT(esr); + if (test_thread_flag(TIF_TSC_SIGSEGV)) { + force_sig(SIGSEGV); + } else { + int rt = ESR_ELx_SYS64_ISS_RT(esr); - pt_regs_write_reg(regs, rt, arch_timer_get_rate()); - arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + pt_regs_write_reg(regs, rt, arch_timer_get_rate()); + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } } static void mrs_handler(unsigned long esr, struct pt_regs *regs) @@ -838,6 +869,7 @@ static const char *esr_class_str[] = { [ESR_ELx_EC_MOPS] = "MOPS", [ESR_ELx_EC_FP_EXC32] = "FP (AArch32)", [ESR_ELx_EC_FP_EXC64] = "FP (AArch64)", + [ESR_ELx_EC_GCS] = "Guarded Control Stack", [ESR_ELx_EC_SERROR] = "SError", [ESR_ELx_EC_BREAKPT_LOW] = "Breakpoint (lower EL)", [ESR_ELx_EC_BREAKPT_CUR] = "Breakpoint (current EL)", diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 89b6e7840002..e8ed8e5b713b 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -19,7 +19,6 @@ #include <linux/signal.h> #include <linux/slab.h> #include <linux/time_namespace.h> -#include <linux/timekeeper_internal.h> #include <linux/vmalloc.h> #include <vdso/datapage.h> #include <vdso/helpers.h> @@ -34,19 +33,11 @@ enum vdso_abi { VDSO_ABI_AA32, }; -enum vvar_pages { - VVAR_DATA_PAGE_OFFSET, - VVAR_TIMENS_PAGE_OFFSET, - VVAR_NR_PAGES, -}; - struct vdso_abi_info { const char *name; const char *vdso_code_start; const char *vdso_code_end; unsigned long vdso_pages; - /* Data Mapping */ - struct vm_special_mapping *dm; /* Code Mapping */ struct vm_special_mapping *cm; }; @@ -119,6 +110,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page) return (struct vdso_data *)(vvar_page); } +static const struct vm_special_mapping vvar_map; + /* * The vvar mapping contains data for a specific time namespace, so when a task * changes namespace we must unmap its vvar data for the old namespace. @@ -135,12 +128,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) mmap_read_lock(mm); for_each_vma(vmi, vma) { - if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA64].dm)) + if (vma_is_special_mapping(vma, &vvar_map)) zap_vma_pages(vma); -#ifdef CONFIG_COMPAT_VDSO - if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA32].dm)) - zap_vma_pages(vma); -#endif } mmap_read_unlock(mm); @@ -182,6 +171,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, return vmf_insert_pfn(vma, vmf->address, pfn); } +static const struct vm_special_mapping vvar_map = { + .name = "[vvar]", + .fault = vvar_fault, +}; + static int __setup_additional_pages(enum vdso_abi abi, struct mm_struct *mm, struct linux_binprm *bprm, @@ -205,7 +199,7 @@ static int __setup_additional_pages(enum vdso_abi abi, ret = _install_special_mapping(mm, vdso_base, VVAR_NR_PAGES * PAGE_SIZE, VM_READ|VM_MAYREAD|VM_PFNMAP, - vdso_info[abi].dm); + &vvar_map); if (IS_ERR(ret)) goto up_fail; @@ -235,7 +229,6 @@ up_fail: enum aarch32_map { AA32_MAP_VECTORS, /* kuser helpers */ AA32_MAP_SIGPAGE, - AA32_MAP_VVAR, AA32_MAP_VDSO, }; @@ -260,10 +253,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = { .pages = &aarch32_sig_page, .mremap = aarch32_sigpage_mremap, }, - [AA32_MAP_VVAR] = { - .name = "[vvar]", - .fault = vvar_fault, - }, [AA32_MAP_VDSO] = { .name = "[vdso]", .mremap = vdso_mremap, @@ -313,7 +302,6 @@ static int __init __aarch32_alloc_vdso_pages(void) if (!IS_ENABLED(CONFIG_COMPAT_VDSO)) return 0; - vdso_info[VDSO_ABI_AA32].dm = &aarch32_vdso_maps[AA32_MAP_VVAR]; vdso_info[VDSO_ABI_AA32].cm = &aarch32_vdso_maps[AA32_MAP_VDSO]; return __vdso_init(VDSO_ABI_AA32); @@ -408,26 +396,14 @@ out: } #endif /* CONFIG_COMPAT */ -enum aarch64_map { - AA64_MAP_VVAR, - AA64_MAP_VDSO, -}; - -static struct vm_special_mapping aarch64_vdso_maps[] __ro_after_init = { - [AA64_MAP_VVAR] = { - .name = "[vvar]", - .fault = vvar_fault, - }, - [AA64_MAP_VDSO] = { - .name = "[vdso]", - .mremap = vdso_mremap, - }, +static struct vm_special_mapping aarch64_vdso_map __ro_after_init = { + .name = "[vdso]", + .mremap = vdso_mremap, }; static int __init vdso_init(void) { - vdso_info[VDSO_ABI_AA64].dm = &aarch64_vdso_maps[AA64_MAP_VVAR]; - vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_maps[AA64_MAP_VDSO]; + vdso_info[VDSO_ABI_AA64].cm = &aarch64_vdso_map; return __vdso_init(VDSO_ABI_AA64); } diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile index d11da6461278..35685c036044 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -9,7 +9,7 @@ # Include the generic Makefile to check the built vdso. include $(srctree)/lib/vdso/Makefile -obj-vdso := vgettimeofday.o note.o sigreturn.o +obj-vdso := vgettimeofday.o note.o sigreturn.o vgetrandom.o vgetrandom-chacha.o # Build rules targets := $(obj-vdso) vdso.so vdso.so.dbg @@ -34,19 +34,28 @@ ccflags-y := -fno-common -fno-builtin -fno-stack-protector -ffixed-x18 ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO # -Wmissing-prototypes and -Wmissing-declarations are removed from -# the CFLAGS of vgettimeofday.c to make possible to build the -# kernel with CONFIG_WERROR enabled. -CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \ - $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) \ - $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \ - -Wmissing-prototypes -Wmissing-declarations +# the CFLAGS to make possible to build the kernel with CONFIG_WERROR enabled. +CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \ + $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) \ + $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \ + -Wmissing-prototypes -Wmissing-declarations -CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -fasynchronous-unwind-tables +CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables + +CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO) +CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO) + +CFLAGS_vgettimeofday.o = $(CC_FLAGS_ADD_VDSO) +CFLAGS_vgetrandom.o = $(CC_FLAGS_ADD_VDSO) ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) endif +ifneq ($(c-getrandom-y),) + CFLAGS_vgetrandom.o += -include $(c-getrandom-y) +endif + targets += vdso.lds CPPFLAGS_vdso.lds += -P -C -U$(ARCH) diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S index 45354f2ddf70..4ec32e86a8da 100644 --- a/arch/arm64/kernel/vdso/vdso.lds.S +++ b/arch/arm64/kernel/vdso/vdso.lds.S @@ -11,7 +11,9 @@ #include <linux/const.h> #include <asm/page.h> #include <asm/vdso.h> +#include <asm/vdso/vsyscall.h> #include <asm-generic/vmlinux.lds.h> +#include <vdso/datapage.h> OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64") OUTPUT_ARCH(aarch64) @@ -19,10 +21,11 @@ OUTPUT_ARCH(aarch64) SECTIONS { PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE); + PROVIDE(_vdso_rng_data = _vdso_data + __VDSO_RND_DATA_OFFSET); #ifdef CONFIG_TIME_NS PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); #endif - . = VDSO_LBASE + SIZEOF_HEADERS; + . = SIZEOF_HEADERS; .hash : { *(.hash) } :text .gnu.hash : { *(.gnu.hash) } @@ -102,6 +105,7 @@ VERSION __kernel_gettimeofday; __kernel_clock_gettime; __kernel_clock_getres; + __kernel_getrandom; local: *; }; } diff --git a/arch/arm64/kernel/vdso/vgetrandom-chacha.S b/arch/arm64/kernel/vdso/vgetrandom-chacha.S new file mode 100644 index 000000000000..67890b445309 --- /dev/null +++ b/arch/arm64/kernel/vdso/vgetrandom-chacha.S @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/linkage.h> +#include <asm/cache.h> +#include <asm/assembler.h> + + .text + +#define state0 v0 +#define state1 v1 +#define state2 v2 +#define state3 v3 +#define copy0 v4 +#define copy0_q q4 +#define copy1 v5 +#define copy2 v6 +#define copy3 v7 +#define copy3_d d7 +#define one_d d16 +#define one_q q16 +#define one_v v16 +#define tmp v17 +#define rot8 v18 + +/* + * ARM64 ChaCha20 implementation meant for vDSO. Produces a given positive + * number of blocks of output with nonce 0, taking an input key and 8-bytes + * counter. Importantly does not spill to the stack. + * + * This implementation avoids d8-d15 because they are callee-save in user + * space. + * + * void __arch_chacha20_blocks_nostack(uint8_t *dst_bytes, + * const uint8_t *key, + * uint32_t *counter, + * size_t nblocks) + * + * x0: output bytes + * x1: 32-byte key input + * x2: 8-byte counter input/output + * x3: number of 64-byte block to write to output + */ +SYM_FUNC_START(__arch_chacha20_blocks_nostack) + + /* copy0 = "expand 32-byte k" */ + mov_q x8, 0x3320646e61707865 + mov_q x9, 0x6b20657479622d32 + mov copy0.d[0], x8 + mov copy0.d[1], x9 + + /* copy1,copy2 = key */ + ld1 { copy1.4s, copy2.4s }, [x1] + /* copy3 = counter || zero nonce */ + ld1 { copy3.2s }, [x2] + + movi one_v.2s, #1 + uzp1 one_v.4s, one_v.4s, one_v.4s + +.Lblock: + /* copy state to auxiliary vectors for the final add after the permute. */ + mov state0.16b, copy0.16b + mov state1.16b, copy1.16b + mov state2.16b, copy2.16b + mov state3.16b, copy3.16b + + mov w4, 20 +.Lpermute: + /* + * Permute one 64-byte block where the state matrix is stored in the four NEON + * registers state0-state3. It performs matrix operations on four words in parallel, + * but requires shuffling to rearrange the words after each round. + */ + +.Ldoubleround: + /* state0 += state1, state3 = rotl32(state3 ^ state0, 16) */ + add state0.4s, state0.4s, state1.4s + eor state3.16b, state3.16b, state0.16b + rev32 state3.8h, state3.8h + + /* state2 += state3, state1 = rotl32(state1 ^ state2, 12) */ + add state2.4s, state2.4s, state3.4s + eor tmp.16b, state1.16b, state2.16b + shl state1.4s, tmp.4s, #12 + sri state1.4s, tmp.4s, #20 + + /* state0 += state1, state3 = rotl32(state3 ^ state0, 8) */ + add state0.4s, state0.4s, state1.4s + eor tmp.16b, state3.16b, state0.16b + shl state3.4s, tmp.4s, #8 + sri state3.4s, tmp.4s, #24 + + /* state2 += state3, state1 = rotl32(state1 ^ state2, 7) */ + add state2.4s, state2.4s, state3.4s + eor tmp.16b, state1.16b, state2.16b + shl state1.4s, tmp.4s, #7 + sri state1.4s, tmp.4s, #25 + + /* state1[0,1,2,3] = state1[1,2,3,0] */ + ext state1.16b, state1.16b, state1.16b, #4 + /* state2[0,1,2,3] = state2[2,3,0,1] */ + ext state2.16b, state2.16b, state2.16b, #8 + /* state3[0,1,2,3] = state3[1,2,3,0] */ + ext state3.16b, state3.16b, state3.16b, #12 + + /* state0 += state1, state3 = rotl32(state3 ^ state0, 16) */ + add state0.4s, state0.4s, state1.4s + eor state3.16b, state3.16b, state0.16b + rev32 state3.8h, state3.8h + + /* state2 += state3, state1 = rotl32(state1 ^ state2, 12) */ + add state2.4s, state2.4s, state3.4s + eor tmp.16b, state1.16b, state2.16b + shl state1.4s, tmp.4s, #12 + sri state1.4s, tmp.4s, #20 + + /* state0 += state1, state3 = rotl32(state3 ^ state0, 8) */ + add state0.4s, state0.4s, state1.4s + eor tmp.16b, state3.16b, state0.16b + shl state3.4s, tmp.4s, #8 + sri state3.4s, tmp.4s, #24 + + /* state2 += state3, state1 = rotl32(state1 ^ state2, 7) */ + add state2.4s, state2.4s, state3.4s + eor tmp.16b, state1.16b, state2.16b + shl state1.4s, tmp.4s, #7 + sri state1.4s, tmp.4s, #25 + + /* state1[0,1,2,3] = state1[3,0,1,2] */ + ext state1.16b, state1.16b, state1.16b, #12 + /* state2[0,1,2,3] = state2[2,3,0,1] */ + ext state2.16b, state2.16b, state2.16b, #8 + /* state3[0,1,2,3] = state3[1,2,3,0] */ + ext state3.16b, state3.16b, state3.16b, #4 + + subs w4, w4, #2 + b.ne .Ldoubleround + + /* output0 = state0 + state0 */ + add state0.4s, state0.4s, copy0.4s + /* output1 = state1 + state1 */ + add state1.4s, state1.4s, copy1.4s + /* output2 = state2 + state2 */ + add state2.4s, state2.4s, copy2.4s + /* output2 = state3 + state3 */ + add state3.4s, state3.4s, copy3.4s + st1 { state0.16b - state3.16b }, [x0] + + /* + * ++copy3.counter, the 'add' clears the upper half of the SIMD register + * which is the expected behaviour here. + */ + add copy3_d, copy3_d, one_d + + /* output += 64, --nblocks */ + add x0, x0, 64 + subs x3, x3, #1 + b.ne .Lblock + + /* counter = copy3.counter */ + st1 { copy3.2s }, [x2] + + /* Zero out the potentially sensitive regs, in case nothing uses these again. */ + movi state0.16b, #0 + movi state1.16b, #0 + movi state2.16b, #0 + movi state3.16b, #0 + movi copy1.16b, #0 + movi copy2.16b, #0 + ret +SYM_FUNC_END(__arch_chacha20_blocks_nostack) + +emit_aarch64_feature_1_and diff --git a/arch/arm64/kernel/vdso/vgetrandom.c b/arch/arm64/kernel/vdso/vgetrandom.c new file mode 100644 index 000000000000..832fe195292b --- /dev/null +++ b/arch/arm64/kernel/vdso/vgetrandom.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <uapi/asm-generic/errno.h> + +typeof(__cvdso_getrandom) __kernel_getrandom; + +ssize_t __kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len) +{ + if (alternative_has_cap_likely(ARM64_HAS_FPSIMD)) + return __cvdso_getrandom(buffer, len, flags, opaque_state, opaque_len); + + if (unlikely(opaque_len == ~0UL && !buffer && !len && !flags)) + return -ENOSYS; + return getrandom_syscall(buffer, len, flags); +} diff --git a/arch/arm64/kernel/vdso32/vdso.lds.S b/arch/arm64/kernel/vdso32/vdso.lds.S index 8d95d7d35057..732702a187e9 100644 --- a/arch/arm64/kernel/vdso32/vdso.lds.S +++ b/arch/arm64/kernel/vdso32/vdso.lds.S @@ -22,7 +22,7 @@ SECTIONS #ifdef CONFIG_TIME_NS PROVIDE_HIDDEN(_timens_data = _vdso_data + PAGE_SIZE); #endif - . = VDSO_LBASE + SIZEOF_HEADERS; + . = SIZEOF_HEADERS; .hash : { *(.hash) } :text .gnu.hash : { *(.gnu.hash) } diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 55a8e310ea12..f84c71f04d9e 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -264,8 +264,7 @@ SECTIONS EXIT_DATA } - RUNTIME_CONST(shift, d_hash_shift) - RUNTIME_CONST(ptr, dentry_hashtable) + RUNTIME_CONST_VARIABLES PERCPU_SECTION(L1_CACHE_BYTES) HYPERVISOR_PERCPU_SECTION @@ -288,6 +287,9 @@ SECTIONS __initdata_end = .; __init_end = .; + .data.rel.ro : { *(.data.rel.ro) } + ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") + _data = .; _sdata = .; RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) @@ -344,9 +346,6 @@ SECTIONS *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt) } ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!") - - .data.rel.ro : { *(.data.rel.ro) } - ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!") } #include "image-vars.h" diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 8304eb342be9..ead632ad01b4 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -66,4 +66,21 @@ config PROTECTED_NVHE_STACKTRACE If unsure, or not using protected nVHE (pKVM), say N. +config PTDUMP_STAGE2_DEBUGFS + bool "Present the stage-2 pagetables to debugfs" + depends on KVM + depends on DEBUG_KERNEL + depends on DEBUG_FS + depends on GENERIC_PTDUMP + select PTDUMP_CORE + default n + help + Say Y here if you want to show the stage-2 kernel pagetables + layout in a debugfs file. This information is only useful for kernel developers + who are working in architecture specific areas of the kernel. + It is probably not a good idea to enable this feature in a production + kernel. + + If in doubt, say N. + endif # VIRTUALIZATION diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 86a629aaf0a1..3cf7adb2b503 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -17,7 +17,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ inject_fault.o va_layout.o handle_exit.o \ guest.o debug.o reset.o sys_regs.o stacktrace.o \ vgic-sys-reg-v3.o fpsimd.o pkvm.o \ - arch_timer.o trng.o vmid.o emulate-nested.o nested.o \ + arch_timer.o trng.o vmid.o emulate-nested.o nested.o at.o \ vgic/vgic.o vgic/vgic-init.o \ vgic/vgic-irqfd.o vgic/vgic-v2.o \ vgic/vgic-v3.o vgic/vgic-v4.o \ @@ -27,6 +27,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o +kvm-$(CONFIG_PTDUMP_STAGE2_DEBUGFS) += ptdump.o always-y := hyp_constants.h hyp-constants.s diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 9bef7638342e..48cafb65d6ac 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -46,6 +46,8 @@ #include <kvm/arm_pmu.h> #include <kvm/arm_psci.h> +#include "sys_regs.h" + static enum kvm_mode kvm_mode = KVM_MODE_DEFAULT; enum kvm_wfx_trap_policy { @@ -228,6 +230,7 @@ vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) void kvm_arch_create_vm_debugfs(struct kvm *kvm) { kvm_sys_regs_create_debugfs(kvm); + kvm_s2_ptdump_create_debugfs(kvm); } static void kvm_destroy_mpidr_data(struct kvm *kvm) @@ -821,15 +824,13 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu) return ret; } - if (vcpu_has_nv(vcpu)) { - ret = kvm_init_nv_sysregs(vcpu->kvm); - if (ret) - return ret; - } + ret = kvm_finalize_sys_regs(vcpu); + if (ret) + return ret; /* - * This needs to happen after NV has imposed its own restrictions on - * the feature set + * This needs to happen after any restriction has been applied + * to the feature set. */ kvm_calculate_traps(vcpu); @@ -996,6 +997,9 @@ static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu) static int check_vcpu_requests(struct kvm_vcpu *vcpu) { if (kvm_request_pending(vcpu)) { + if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu)) + return -EIO; + if (kvm_check_request(KVM_REQ_SLEEP, vcpu)) kvm_vcpu_sleep(vcpu); @@ -1030,6 +1034,8 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu) if (kvm_dirty_ring_check_request(vcpu)) return 0; + + check_nested_vcpu_requests(vcpu); } return 1; @@ -2163,7 +2169,7 @@ static void cpu_hyp_uninit(void *discard) } } -int kvm_arch_hardware_enable(void) +int kvm_arch_enable_virtualization_cpu(void) { /* * Most calls to this function are made with migration @@ -2183,7 +2189,7 @@ int kvm_arch_hardware_enable(void) return 0; } -void kvm_arch_hardware_disable(void) +void kvm_arch_disable_virtualization_cpu(void) { kvm_timer_cpu_down(); kvm_vgic_cpu_down(); @@ -2379,7 +2385,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits) /* * The stub hypercalls are now disabled, so set our local flag to - * prevent a later re-init attempt in kvm_arch_hardware_enable(). + * prevent a later re-init attempt in kvm_arch_enable_virtualization_cpu(). */ __this_cpu_write(kvm_hyp_initialized, 1); preempt_enable(); diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c new file mode 100644 index 000000000000..39f0e87a340e --- /dev/null +++ b/arch/arm64/kvm/at.c @@ -0,0 +1,1101 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017 - Linaro Ltd + * Author: Jintack Lim <jintack.lim@linaro.org> + */ + +#include <linux/kvm_host.h> + +#include <asm/esr.h> +#include <asm/kvm_hyp.h> +#include <asm/kvm_mmu.h> + +enum trans_regime { + TR_EL10, + TR_EL20, + TR_EL2, +}; + +struct s1_walk_info { + u64 baddr; + enum trans_regime regime; + unsigned int max_oa_bits; + unsigned int pgshift; + unsigned int txsz; + int sl; + bool hpd; + bool be; + bool s2; +}; + +struct s1_walk_result { + union { + struct { + u64 desc; + u64 pa; + s8 level; + u8 APTable; + bool UXNTable; + bool PXNTable; + }; + struct { + u8 fst; + bool ptw; + bool s2; + }; + }; + bool failed; +}; + +static void fail_s1_walk(struct s1_walk_result *wr, u8 fst, bool ptw, bool s2) +{ + wr->fst = fst; + wr->ptw = ptw; + wr->s2 = s2; + wr->failed = true; +} + +#define S1_MMU_DISABLED (-127) + +static int get_ia_size(struct s1_walk_info *wi) +{ + return 64 - wi->txsz; +} + +/* Return true if the IPA is out of the OA range */ +static bool check_output_size(u64 ipa, struct s1_walk_info *wi) +{ + return wi->max_oa_bits < 48 && (ipa & GENMASK_ULL(47, wi->max_oa_bits)); +} + +/* Return the translation regime that applies to an AT instruction */ +static enum trans_regime compute_translation_regime(struct kvm_vcpu *vcpu, u32 op) +{ + /* + * We only get here from guest EL2, so the translation + * regime AT applies to is solely defined by {E2H,TGE}. + */ + switch (op) { + case OP_AT_S1E2R: + case OP_AT_S1E2W: + case OP_AT_S1E2A: + return vcpu_el2_e2h_is_set(vcpu) ? TR_EL20 : TR_EL2; + break; + default: + return (vcpu_el2_e2h_is_set(vcpu) && + vcpu_el2_tge_is_set(vcpu)) ? TR_EL20 : TR_EL10; + } +} + +static int setup_s1_walk(struct kvm_vcpu *vcpu, u32 op, struct s1_walk_info *wi, + struct s1_walk_result *wr, u64 va) +{ + u64 hcr, sctlr, tcr, tg, ps, ia_bits, ttbr; + unsigned int stride, x; + bool va55, tbi, lva, as_el0; + + hcr = __vcpu_sys_reg(vcpu, HCR_EL2); + + wi->regime = compute_translation_regime(vcpu, op); + as_el0 = (op == OP_AT_S1E0R || op == OP_AT_S1E0W); + + va55 = va & BIT(55); + + if (wi->regime == TR_EL2 && va55) + goto addrsz; + + wi->s2 = wi->regime == TR_EL10 && (hcr & (HCR_VM | HCR_DC)); + + switch (wi->regime) { + case TR_EL10: + sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1); + tcr = vcpu_read_sys_reg(vcpu, TCR_EL1); + ttbr = (va55 ? + vcpu_read_sys_reg(vcpu, TTBR1_EL1) : + vcpu_read_sys_reg(vcpu, TTBR0_EL1)); + break; + case TR_EL2: + case TR_EL20: + sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL2); + tcr = vcpu_read_sys_reg(vcpu, TCR_EL2); + ttbr = (va55 ? + vcpu_read_sys_reg(vcpu, TTBR1_EL2) : + vcpu_read_sys_reg(vcpu, TTBR0_EL2)); + break; + default: + BUG(); + } + + tbi = (wi->regime == TR_EL2 ? + FIELD_GET(TCR_EL2_TBI, tcr) : + (va55 ? + FIELD_GET(TCR_TBI1, tcr) : + FIELD_GET(TCR_TBI0, tcr))); + + if (!tbi && (u64)sign_extend64(va, 55) != va) + goto addrsz; + + va = (u64)sign_extend64(va, 55); + + /* Let's put the MMU disabled case aside immediately */ + switch (wi->regime) { + case TR_EL10: + /* + * If dealing with the EL1&0 translation regime, 3 things + * can disable the S1 translation: + * + * - HCR_EL2.DC = 1 + * - HCR_EL2.{E2H,TGE} = {0,1} + * - SCTLR_EL1.M = 0 + * + * The TGE part is interesting. If we have decided that this + * is EL1&0, then it means that either {E2H,TGE} == {1,0} or + * {0,x}, and we only need to test for TGE == 1. + */ + if (hcr & (HCR_DC | HCR_TGE)) { + wr->level = S1_MMU_DISABLED; + break; + } + fallthrough; + case TR_EL2: + case TR_EL20: + if (!(sctlr & SCTLR_ELx_M)) + wr->level = S1_MMU_DISABLED; + break; + } + + if (wr->level == S1_MMU_DISABLED) { + if (va >= BIT(kvm_get_pa_bits(vcpu->kvm))) + goto addrsz; + + wr->pa = va; + return 0; + } + + wi->be = sctlr & SCTLR_ELx_EE; + + wi->hpd = kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, HPDS, IMP); + wi->hpd &= (wi->regime == TR_EL2 ? + FIELD_GET(TCR_EL2_HPD, tcr) : + (va55 ? + FIELD_GET(TCR_HPD1, tcr) : + FIELD_GET(TCR_HPD0, tcr))); + + /* Someone was silly enough to encode TG0/TG1 differently */ + if (va55) { + wi->txsz = FIELD_GET(TCR_T1SZ_MASK, tcr); + tg = FIELD_GET(TCR_TG1_MASK, tcr); + + switch (tg << TCR_TG1_SHIFT) { + case TCR_TG1_4K: + wi->pgshift = 12; break; + case TCR_TG1_16K: + wi->pgshift = 14; break; + case TCR_TG1_64K: + default: /* IMPDEF: treat any other value as 64k */ + wi->pgshift = 16; break; + } + } else { + wi->txsz = FIELD_GET(TCR_T0SZ_MASK, tcr); + tg = FIELD_GET(TCR_TG0_MASK, tcr); + + switch (tg << TCR_TG0_SHIFT) { + case TCR_TG0_4K: + wi->pgshift = 12; break; + case TCR_TG0_16K: + wi->pgshift = 14; break; + case TCR_TG0_64K: + default: /* IMPDEF: treat any other value as 64k */ + wi->pgshift = 16; break; + } + } + + /* R_PLCGL, R_YXNYW */ + if (!kvm_has_feat_enum(vcpu->kvm, ID_AA64MMFR2_EL1, ST, 48_47)) { + if (wi->txsz > 39) + goto transfault_l0; + } else { + if (wi->txsz > 48 || (BIT(wi->pgshift) == SZ_64K && wi->txsz > 47)) + goto transfault_l0; + } + + /* R_GTJBY, R_SXWGM */ + switch (BIT(wi->pgshift)) { + case SZ_4K: + lva = kvm_has_feat(vcpu->kvm, ID_AA64MMFR0_EL1, TGRAN4, 52_BIT); + lva &= tcr & (wi->regime == TR_EL2 ? TCR_EL2_DS : TCR_DS); + break; + case SZ_16K: + lva = kvm_has_feat(vcpu->kvm, ID_AA64MMFR0_EL1, TGRAN16, 52_BIT); + lva &= tcr & (wi->regime == TR_EL2 ? TCR_EL2_DS : TCR_DS); + break; + case SZ_64K: + lva = kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, VARange, 52); + break; + } + + if ((lva && wi->txsz < 12) || (!lva && wi->txsz < 16)) + goto transfault_l0; + + ia_bits = get_ia_size(wi); + + /* R_YYVYV, I_THCZK */ + if ((!va55 && va > GENMASK(ia_bits - 1, 0)) || + (va55 && va < GENMASK(63, ia_bits))) + goto transfault_l0; + + /* I_ZFSYQ */ + if (wi->regime != TR_EL2 && + (tcr & (va55 ? TCR_EPD1_MASK : TCR_EPD0_MASK))) + goto transfault_l0; + + /* R_BNDVG and following statements */ + if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, E0PD, IMP) && + as_el0 && (tcr & (va55 ? TCR_E0PD1 : TCR_E0PD0))) + goto transfault_l0; + + /* AArch64.S1StartLevel() */ + stride = wi->pgshift - 3; + wi->sl = 3 - (((ia_bits - 1) - wi->pgshift) / stride); + + ps = (wi->regime == TR_EL2 ? + FIELD_GET(TCR_EL2_PS_MASK, tcr) : FIELD_GET(TCR_IPS_MASK, tcr)); + + wi->max_oa_bits = min(get_kvm_ipa_limit(), ps_to_output_size(ps)); + + /* Compute minimal alignment */ + x = 3 + ia_bits - ((3 - wi->sl) * stride + wi->pgshift); + + wi->baddr = ttbr & TTBRx_EL1_BADDR; + + /* R_VPBBF */ + if (check_output_size(wi->baddr, wi)) + goto addrsz; + + wi->baddr &= GENMASK_ULL(wi->max_oa_bits - 1, x); + + return 0; + +addrsz: /* Address Size Fault level 0 */ + fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(0), false, false); + return -EFAULT; + +transfault_l0: /* Translation Fault level 0 */ + fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(0), false, false); + return -EFAULT; +} + +static int walk_s1(struct kvm_vcpu *vcpu, struct s1_walk_info *wi, + struct s1_walk_result *wr, u64 va) +{ + u64 va_top, va_bottom, baddr, desc; + int level, stride, ret; + + level = wi->sl; + stride = wi->pgshift - 3; + baddr = wi->baddr; + + va_top = get_ia_size(wi) - 1; + + while (1) { + u64 index, ipa; + + va_bottom = (3 - level) * stride + wi->pgshift; + index = (va & GENMASK_ULL(va_top, va_bottom)) >> (va_bottom - 3); + + ipa = baddr | index; + + if (wi->s2) { + struct kvm_s2_trans s2_trans = {}; + + ret = kvm_walk_nested_s2(vcpu, ipa, &s2_trans); + if (ret) { + fail_s1_walk(wr, + (s2_trans.esr & ~ESR_ELx_FSC_LEVEL) | level, + true, true); + return ret; + } + + if (!kvm_s2_trans_readable(&s2_trans)) { + fail_s1_walk(wr, ESR_ELx_FSC_PERM_L(level), + true, true); + + return -EPERM; + } + + ipa = kvm_s2_trans_output(&s2_trans); + } + + ret = kvm_read_guest(vcpu->kvm, ipa, &desc, sizeof(desc)); + if (ret) { + fail_s1_walk(wr, ESR_ELx_FSC_SEA_TTW(level), + true, false); + return ret; + } + + if (wi->be) + desc = be64_to_cpu((__force __be64)desc); + else + desc = le64_to_cpu((__force __le64)desc); + + /* Invalid descriptor */ + if (!(desc & BIT(0))) + goto transfault; + + /* Block mapping, check validity down the line */ + if (!(desc & BIT(1))) + break; + + /* Page mapping */ + if (level == 3) + break; + + /* Table handling */ + if (!wi->hpd) { + wr->APTable |= FIELD_GET(S1_TABLE_AP, desc); + wr->UXNTable |= FIELD_GET(PMD_TABLE_UXN, desc); + wr->PXNTable |= FIELD_GET(PMD_TABLE_PXN, desc); + } + + baddr = desc & GENMASK_ULL(47, wi->pgshift); + + /* Check for out-of-range OA */ + if (check_output_size(baddr, wi)) + goto addrsz; + + /* Prepare for next round */ + va_top = va_bottom - 1; + level++; + } + + /* Block mapping, check the validity of the level */ + if (!(desc & BIT(1))) { + bool valid_block = false; + + switch (BIT(wi->pgshift)) { + case SZ_4K: + valid_block = level == 1 || level == 2; + break; + case SZ_16K: + case SZ_64K: + valid_block = level == 2; + break; + } + + if (!valid_block) + goto transfault; + } + + if (check_output_size(desc & GENMASK(47, va_bottom), wi)) + goto addrsz; + + va_bottom += contiguous_bit_shift(desc, wi, level); + + wr->failed = false; + wr->level = level; + wr->desc = desc; + wr->pa = desc & GENMASK(47, va_bottom); + wr->pa |= va & GENMASK_ULL(va_bottom - 1, 0); + + return 0; + +addrsz: + fail_s1_walk(wr, ESR_ELx_FSC_ADDRSZ_L(level), true, false); + return -EINVAL; +transfault: + fail_s1_walk(wr, ESR_ELx_FSC_FAULT_L(level), true, false); + return -ENOENT; +} + +struct mmu_config { + u64 ttbr0; + u64 ttbr1; + u64 tcr; + u64 mair; + u64 sctlr; + u64 vttbr; + u64 vtcr; + u64 hcr; +}; + +static void __mmu_config_save(struct mmu_config *config) +{ + config->ttbr0 = read_sysreg_el1(SYS_TTBR0); + config->ttbr1 = read_sysreg_el1(SYS_TTBR1); + config->tcr = read_sysreg_el1(SYS_TCR); + config->mair = read_sysreg_el1(SYS_MAIR); + config->sctlr = read_sysreg_el1(SYS_SCTLR); + config->vttbr = read_sysreg(vttbr_el2); + config->vtcr = read_sysreg(vtcr_el2); + config->hcr = read_sysreg(hcr_el2); +} + +static void __mmu_config_restore(struct mmu_config *config) +{ + write_sysreg(config->hcr, hcr_el2); + + /* + * ARM errata 1165522 and 1530923 require TGE to be 1 before + * we update the guest state. + */ + asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); + + write_sysreg_el1(config->ttbr0, SYS_TTBR0); + write_sysreg_el1(config->ttbr1, SYS_TTBR1); + write_sysreg_el1(config->tcr, SYS_TCR); + write_sysreg_el1(config->mair, SYS_MAIR); + write_sysreg_el1(config->sctlr, SYS_SCTLR); + write_sysreg(config->vttbr, vttbr_el2); + write_sysreg(config->vtcr, vtcr_el2); +} + +static bool at_s1e1p_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + u64 host_pan; + bool fail; + + host_pan = read_sysreg_s(SYS_PSTATE_PAN); + write_sysreg_s(*vcpu_cpsr(vcpu) & PSTATE_PAN, SYS_PSTATE_PAN); + + switch (op) { + case OP_AT_S1E1RP: + fail = __kvm_at(OP_AT_S1E1RP, vaddr); + break; + case OP_AT_S1E1WP: + fail = __kvm_at(OP_AT_S1E1WP, vaddr); + break; + } + + write_sysreg_s(host_pan, SYS_PSTATE_PAN); + + return fail; +} + +#define MEMATTR(ic, oc) (MEMATTR_##oc << 4 | MEMATTR_##ic) +#define MEMATTR_NC 0b0100 +#define MEMATTR_Wt 0b1000 +#define MEMATTR_Wb 0b1100 +#define MEMATTR_WbRaWa 0b1111 + +#define MEMATTR_IS_DEVICE(m) (((m) & GENMASK(7, 4)) == 0) + +static u8 s2_memattr_to_attr(u8 memattr) +{ + memattr &= 0b1111; + + switch (memattr) { + case 0b0000: + case 0b0001: + case 0b0010: + case 0b0011: + return memattr << 2; + case 0b0100: + return MEMATTR(Wb, Wb); + case 0b0101: + return MEMATTR(NC, NC); + case 0b0110: + return MEMATTR(Wt, NC); + case 0b0111: + return MEMATTR(Wb, NC); + case 0b1000: + /* Reserved, assume NC */ + return MEMATTR(NC, NC); + case 0b1001: + return MEMATTR(NC, Wt); + case 0b1010: + return MEMATTR(Wt, Wt); + case 0b1011: + return MEMATTR(Wb, Wt); + case 0b1100: + /* Reserved, assume NC */ + return MEMATTR(NC, NC); + case 0b1101: + return MEMATTR(NC, Wb); + case 0b1110: + return MEMATTR(Wt, Wb); + case 0b1111: + return MEMATTR(Wb, Wb); + default: + unreachable(); + } +} + +static u8 combine_s1_s2_attr(u8 s1, u8 s2) +{ + bool transient; + u8 final = 0; + + /* Upgrade transient s1 to non-transient to simplify things */ + switch (s1) { + case 0b0001 ... 0b0011: /* Normal, Write-Through Transient */ + transient = true; + s1 = MEMATTR_Wt | (s1 & GENMASK(1,0)); + break; + case 0b0101 ... 0b0111: /* Normal, Write-Back Transient */ + transient = true; + s1 = MEMATTR_Wb | (s1 & GENMASK(1,0)); + break; + default: + transient = false; + } + + /* S2CombineS1AttrHints() */ + if ((s1 & GENMASK(3, 2)) == MEMATTR_NC || + (s2 & GENMASK(3, 2)) == MEMATTR_NC) + final = MEMATTR_NC; + else if ((s1 & GENMASK(3, 2)) == MEMATTR_Wt || + (s2 & GENMASK(3, 2)) == MEMATTR_Wt) + final = MEMATTR_Wt; + else + final = MEMATTR_Wb; + + if (final != MEMATTR_NC) { + /* Inherit RaWa hints form S1 */ + if (transient) { + switch (s1 & GENMASK(3, 2)) { + case MEMATTR_Wt: + final = 0; + break; + case MEMATTR_Wb: + final = MEMATTR_NC; + break; + } + } + + final |= s1 & GENMASK(1, 0); + } + + return final; +} + +#define ATTR_NSH 0b00 +#define ATTR_RSV 0b01 +#define ATTR_OSH 0b10 +#define ATTR_ISH 0b11 + +static u8 compute_sh(u8 attr, u64 desc) +{ + u8 sh; + + /* Any form of device, as well as NC has SH[1:0]=0b10 */ + if (MEMATTR_IS_DEVICE(attr) || attr == MEMATTR(NC, NC)) + return ATTR_OSH; + + sh = FIELD_GET(PTE_SHARED, desc); + if (sh == ATTR_RSV) /* Reserved, mapped to NSH */ + sh = ATTR_NSH; + + return sh; +} + +static u8 combine_sh(u8 s1_sh, u8 s2_sh) +{ + if (s1_sh == ATTR_OSH || s2_sh == ATTR_OSH) + return ATTR_OSH; + if (s1_sh == ATTR_ISH || s2_sh == ATTR_ISH) + return ATTR_ISH; + + return ATTR_NSH; +} + +static u64 compute_par_s12(struct kvm_vcpu *vcpu, u64 s1_par, + struct kvm_s2_trans *tr) +{ + u8 s1_parattr, s2_memattr, final_attr; + u64 par; + + /* If S2 has failed to translate, report the damage */ + if (tr->esr) { + par = SYS_PAR_EL1_RES1; + par |= SYS_PAR_EL1_F; + par |= SYS_PAR_EL1_S; + par |= FIELD_PREP(SYS_PAR_EL1_FST, tr->esr); + return par; + } + + s1_parattr = FIELD_GET(SYS_PAR_EL1_ATTR, s1_par); + s2_memattr = FIELD_GET(GENMASK(5, 2), tr->desc); + + if (__vcpu_sys_reg(vcpu, HCR_EL2) & HCR_FWB) { + if (!kvm_has_feat(vcpu->kvm, ID_AA64PFR2_EL1, MTEPERM, IMP)) + s2_memattr &= ~BIT(3); + + /* Combination of R_VRJSW and R_RHWZM */ + switch (s2_memattr) { + case 0b0101: + if (MEMATTR_IS_DEVICE(s1_parattr)) + final_attr = s1_parattr; + else + final_attr = MEMATTR(NC, NC); + break; + case 0b0110: + case 0b1110: + final_attr = MEMATTR(WbRaWa, WbRaWa); + break; + case 0b0111: + case 0b1111: + /* Preserve S1 attribute */ + final_attr = s1_parattr; + break; + case 0b0100: + case 0b1100: + case 0b1101: + /* Reserved, do something non-silly */ + final_attr = s1_parattr; + break; + default: + /* MemAttr[2]=0, Device from S2 */ + final_attr = s2_memattr & GENMASK(1,0) << 2; + } + } else { + /* Combination of R_HMNDG, R_TNHFM and R_GQFSF */ + u8 s2_parattr = s2_memattr_to_attr(s2_memattr); + + if (MEMATTR_IS_DEVICE(s1_parattr) || + MEMATTR_IS_DEVICE(s2_parattr)) { + final_attr = min(s1_parattr, s2_parattr); + } else { + /* At this stage, this is memory vs memory */ + final_attr = combine_s1_s2_attr(s1_parattr & 0xf, + s2_parattr & 0xf); + final_attr |= combine_s1_s2_attr(s1_parattr >> 4, + s2_parattr >> 4) << 4; + } + } + + if ((__vcpu_sys_reg(vcpu, HCR_EL2) & HCR_CD) && + !MEMATTR_IS_DEVICE(final_attr)) + final_attr = MEMATTR(NC, NC); + + par = FIELD_PREP(SYS_PAR_EL1_ATTR, final_attr); + par |= tr->output & GENMASK(47, 12); + par |= FIELD_PREP(SYS_PAR_EL1_SH, + combine_sh(FIELD_GET(SYS_PAR_EL1_SH, s1_par), + compute_sh(final_attr, tr->desc))); + + return par; +} + +static u64 compute_par_s1(struct kvm_vcpu *vcpu, struct s1_walk_result *wr, + enum trans_regime regime) +{ + u64 par; + + if (wr->failed) { + par = SYS_PAR_EL1_RES1; + par |= SYS_PAR_EL1_F; + par |= FIELD_PREP(SYS_PAR_EL1_FST, wr->fst); + par |= wr->ptw ? SYS_PAR_EL1_PTW : 0; + par |= wr->s2 ? SYS_PAR_EL1_S : 0; + } else if (wr->level == S1_MMU_DISABLED) { + /* MMU off or HCR_EL2.DC == 1 */ + par = SYS_PAR_EL1_NSE; + par |= wr->pa & GENMASK_ULL(47, 12); + + if (regime == TR_EL10 && + (__vcpu_sys_reg(vcpu, HCR_EL2) & HCR_DC)) { + par |= FIELD_PREP(SYS_PAR_EL1_ATTR, + MEMATTR(WbRaWa, WbRaWa)); + par |= FIELD_PREP(SYS_PAR_EL1_SH, ATTR_NSH); + } else { + par |= FIELD_PREP(SYS_PAR_EL1_ATTR, 0); /* nGnRnE */ + par |= FIELD_PREP(SYS_PAR_EL1_SH, ATTR_OSH); + } + } else { + u64 mair, sctlr; + u8 sh; + + par = SYS_PAR_EL1_NSE; + + mair = (regime == TR_EL10 ? + vcpu_read_sys_reg(vcpu, MAIR_EL1) : + vcpu_read_sys_reg(vcpu, MAIR_EL2)); + + mair >>= FIELD_GET(PTE_ATTRINDX_MASK, wr->desc) * 8; + mair &= 0xff; + + sctlr = (regime == TR_EL10 ? + vcpu_read_sys_reg(vcpu, SCTLR_EL1) : + vcpu_read_sys_reg(vcpu, SCTLR_EL2)); + + /* Force NC for memory if SCTLR_ELx.C is clear */ + if (!(sctlr & SCTLR_EL1_C) && !MEMATTR_IS_DEVICE(mair)) + mair = MEMATTR(NC, NC); + + par |= FIELD_PREP(SYS_PAR_EL1_ATTR, mair); + par |= wr->pa & GENMASK_ULL(47, 12); + + sh = compute_sh(mair, wr->desc); + par |= FIELD_PREP(SYS_PAR_EL1_SH, sh); + } + + return par; +} + +static bool pan3_enabled(struct kvm_vcpu *vcpu, enum trans_regime regime) +{ + u64 sctlr; + + if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, PAN, PAN3)) + return false; + + if (regime == TR_EL10) + sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1); + else + sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL2); + + return sctlr & SCTLR_EL1_EPAN; +} + +static u64 handle_at_slow(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + bool perm_fail, ur, uw, ux, pr, pw, px; + struct s1_walk_result wr = {}; + struct s1_walk_info wi = {}; + int ret, idx; + + ret = setup_s1_walk(vcpu, op, &wi, &wr, vaddr); + if (ret) + goto compute_par; + + if (wr.level == S1_MMU_DISABLED) + goto compute_par; + + idx = srcu_read_lock(&vcpu->kvm->srcu); + + ret = walk_s1(vcpu, &wi, &wr, vaddr); + + srcu_read_unlock(&vcpu->kvm->srcu, idx); + + if (ret) + goto compute_par; + + /* FIXME: revisit when adding indirect permission support */ + /* AArch64.S1DirectBasePermissions() */ + if (wi.regime != TR_EL2) { + switch (FIELD_GET(PTE_USER | PTE_RDONLY, wr.desc)) { + case 0b00: + pr = pw = true; + ur = uw = false; + break; + case 0b01: + pr = pw = ur = uw = true; + break; + case 0b10: + pr = true; + pw = ur = uw = false; + break; + case 0b11: + pr = ur = true; + pw = uw = false; + break; + } + + switch (wr.APTable) { + case 0b00: + break; + case 0b01: + ur = uw = false; + break; + case 0b10: + pw = uw = false; + break; + case 0b11: + pw = ur = uw = false; + break; + } + + /* We don't use px for anything yet, but hey... */ + px = !((wr.desc & PTE_PXN) || wr.PXNTable || uw); + ux = !((wr.desc & PTE_UXN) || wr.UXNTable); + + if (op == OP_AT_S1E1RP || op == OP_AT_S1E1WP) { + bool pan; + + pan = *vcpu_cpsr(vcpu) & PSR_PAN_BIT; + pan &= ur || uw || (pan3_enabled(vcpu, wi.regime) && ux); + pw &= !pan; + pr &= !pan; + } + } else { + ur = uw = ux = false; + + if (!(wr.desc & PTE_RDONLY)) { + pr = pw = true; + } else { + pr = true; + pw = false; + } + + if (wr.APTable & BIT(1)) + pw = false; + + /* XN maps to UXN */ + px = !((wr.desc & PTE_UXN) || wr.UXNTable); + } + + perm_fail = false; + + switch (op) { + case OP_AT_S1E1RP: + case OP_AT_S1E1R: + case OP_AT_S1E2R: + perm_fail = !pr; + break; + case OP_AT_S1E1WP: + case OP_AT_S1E1W: + case OP_AT_S1E2W: + perm_fail = !pw; + break; + case OP_AT_S1E0R: + perm_fail = !ur; + break; + case OP_AT_S1E0W: + perm_fail = !uw; + break; + case OP_AT_S1E1A: + case OP_AT_S1E2A: + break; + default: + BUG(); + } + + if (perm_fail) + fail_s1_walk(&wr, ESR_ELx_FSC_PERM_L(wr.level), false, false); + +compute_par: + return compute_par_s1(vcpu, &wr, wi.regime); +} + +/* + * Return the PAR_EL1 value as the result of a valid translation. + * + * If the translation is unsuccessful, the value may only contain + * PAR_EL1.F, and cannot be taken at face value. It isn't an + * indication of the translation having failed, only that the fast + * path did not succeed, *unless* it indicates a S1 permission fault. + */ +static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + struct mmu_config config; + struct kvm_s2_mmu *mmu; + bool fail; + u64 par; + + par = SYS_PAR_EL1_F; + + /* + * We've trapped, so everything is live on the CPU. As we will + * be switching contexts behind everybody's back, disable + * interrupts while holding the mmu lock. + */ + guard(write_lock_irqsave)(&vcpu->kvm->mmu_lock); + + /* + * If HCR_EL2.{E2H,TGE} == {1,1}, the MMU context is already + * the right one (as we trapped from vEL2). If not, save the + * full MMU context. + */ + if (vcpu_el2_e2h_is_set(vcpu) && vcpu_el2_tge_is_set(vcpu)) + goto skip_mmu_switch; + + /* + * Obtaining the S2 MMU for a L2 is horribly racy, and we may not + * find it (recycled by another vcpu, for example). When this + * happens, admit defeat immediately and use the SW (slow) path. + */ + mmu = lookup_s2_mmu(vcpu); + if (!mmu) + return par; + + __mmu_config_save(&config); + + write_sysreg_el1(vcpu_read_sys_reg(vcpu, TTBR0_EL1), SYS_TTBR0); + write_sysreg_el1(vcpu_read_sys_reg(vcpu, TTBR1_EL1), SYS_TTBR1); + write_sysreg_el1(vcpu_read_sys_reg(vcpu, TCR_EL1), SYS_TCR); + write_sysreg_el1(vcpu_read_sys_reg(vcpu, MAIR_EL1), SYS_MAIR); + write_sysreg_el1(vcpu_read_sys_reg(vcpu, SCTLR_EL1), SYS_SCTLR); + __load_stage2(mmu, mmu->arch); + +skip_mmu_switch: + /* Clear TGE, enable S2 translation, we're rolling */ + write_sysreg((config.hcr & ~HCR_TGE) | HCR_VM, hcr_el2); + isb(); + + switch (op) { + case OP_AT_S1E1RP: + case OP_AT_S1E1WP: + fail = at_s1e1p_fast(vcpu, op, vaddr); + break; + case OP_AT_S1E1R: + fail = __kvm_at(OP_AT_S1E1R, vaddr); + break; + case OP_AT_S1E1W: + fail = __kvm_at(OP_AT_S1E1W, vaddr); + break; + case OP_AT_S1E0R: + fail = __kvm_at(OP_AT_S1E0R, vaddr); + break; + case OP_AT_S1E0W: + fail = __kvm_at(OP_AT_S1E0W, vaddr); + break; + case OP_AT_S1E1A: + fail = __kvm_at(OP_AT_S1E1A, vaddr); + break; + default: + WARN_ON_ONCE(1); + fail = true; + break; + } + + if (!fail) + par = read_sysreg_par(); + + if (!(vcpu_el2_e2h_is_set(vcpu) && vcpu_el2_tge_is_set(vcpu))) + __mmu_config_restore(&config); + + return par; +} + +static bool par_check_s1_perm_fault(u64 par) +{ + u8 fst = FIELD_GET(SYS_PAR_EL1_FST, par); + + return ((fst & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_PERM && + !(par & SYS_PAR_EL1_S)); +} + +void __kvm_at_s1e01(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + u64 par = __kvm_at_s1e01_fast(vcpu, op, vaddr); + + /* + * If PAR_EL1 reports that AT failed on a S1 permission fault, we + * know for sure that the PTW was able to walk the S1 tables and + * there's nothing else to do. + * + * If AT failed for any other reason, then we must walk the guest S1 + * to emulate the instruction. + */ + if ((par & SYS_PAR_EL1_F) && !par_check_s1_perm_fault(par)) + par = handle_at_slow(vcpu, op, vaddr); + + vcpu_write_sys_reg(vcpu, par, PAR_EL1); +} + +void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + u64 par; + + /* + * We've trapped, so everything is live on the CPU. As we will be + * switching context behind everybody's back, disable interrupts... + */ + scoped_guard(write_lock_irqsave, &vcpu->kvm->mmu_lock) { + struct kvm_s2_mmu *mmu; + u64 val, hcr; + bool fail; + + mmu = &vcpu->kvm->arch.mmu; + + val = hcr = read_sysreg(hcr_el2); + val &= ~HCR_TGE; + val |= HCR_VM; + + if (!vcpu_el2_e2h_is_set(vcpu)) + val |= HCR_NV | HCR_NV1; + + write_sysreg(val, hcr_el2); + isb(); + + par = SYS_PAR_EL1_F; + + switch (op) { + case OP_AT_S1E2R: + fail = __kvm_at(OP_AT_S1E1R, vaddr); + break; + case OP_AT_S1E2W: + fail = __kvm_at(OP_AT_S1E1W, vaddr); + break; + case OP_AT_S1E2A: + fail = __kvm_at(OP_AT_S1E1A, vaddr); + break; + default: + WARN_ON_ONCE(1); + fail = true; + } + + isb(); + + if (!fail) + par = read_sysreg_par(); + + write_sysreg(hcr, hcr_el2); + isb(); + } + + /* We failed the translation, let's replay it in slow motion */ + if ((par & SYS_PAR_EL1_F) && !par_check_s1_perm_fault(par)) + par = handle_at_slow(vcpu, op, vaddr); + + vcpu_write_sys_reg(vcpu, par, PAR_EL1); +} + +void __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) +{ + struct kvm_s2_trans out = {}; + u64 ipa, par; + bool write; + int ret; + + /* Do the stage-1 translation */ + switch (op) { + case OP_AT_S12E1R: + op = OP_AT_S1E1R; + write = false; + break; + case OP_AT_S12E1W: + op = OP_AT_S1E1W; + write = true; + break; + case OP_AT_S12E0R: + op = OP_AT_S1E0R; + write = false; + break; + case OP_AT_S12E0W: + op = OP_AT_S1E0W; + write = true; + break; + default: + WARN_ON_ONCE(1); + return; + } + + __kvm_at_s1e01(vcpu, op, vaddr); + par = vcpu_read_sys_reg(vcpu, PAR_EL1); + if (par & SYS_PAR_EL1_F) + return; + + /* + * If we only have a single stage of translation (E2H=0 or + * TGE=1), exit early. Same thing if {VM,DC}=={0,0}. + */ + if (!vcpu_el2_e2h_is_set(vcpu) || vcpu_el2_tge_is_set(vcpu) || + !(vcpu_read_sys_reg(vcpu, HCR_EL2) & (HCR_VM | HCR_DC))) + return; + + /* Do the stage-2 translation */ + ipa = (par & GENMASK_ULL(47, 12)) | (vaddr & GENMASK_ULL(11, 0)); + out.esr = 0; + ret = kvm_walk_nested_s2(vcpu, ipa, &out); + if (ret < 0) + return; + + /* Check the access permission */ + if (!out.esr && + ((!write && !out.readable) || (write && !out.writable))) + out.esr = ESR_ELx_FSC_PERM_L(out.level & 0x3); + + par = compute_par_s12(vcpu, par, &out); + vcpu_write_sys_reg(vcpu, par, PAR_EL1); +} diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c index 05166eccea0a..05b6435d02a9 100644 --- a/arch/arm64/kvm/emulate-nested.c +++ b/arch/arm64/kvm/emulate-nested.c @@ -83,14 +83,20 @@ enum cgt_group_id { CGT_CPTR_TAM, CGT_CPTR_TCPAC, + CGT_HCRX_EnFPM, CGT_HCRX_TCR2En, + CGT_ICH_HCR_TC, + CGT_ICH_HCR_TALL0, + CGT_ICH_HCR_TALL1, + CGT_ICH_HCR_TDIR, + /* * Anything after this point is a combination of coarse trap * controls, which must all be evaluated to decide what to do. */ __MULTIPLE_CONTROL_BITS__, - CGT_HCR_IMO_FMO = __MULTIPLE_CONTROL_BITS__, + CGT_HCR_IMO_FMO_ICH_HCR_TC = __MULTIPLE_CONTROL_BITS__, CGT_HCR_TID2_TID4, CGT_HCR_TTLB_TTLBIS, CGT_HCR_TTLB_TTLBOS, @@ -105,6 +111,8 @@ enum cgt_group_id { CGT_MDCR_TDE_TDRA, CGT_MDCR_TDCC_TDE_TDA, + CGT_ICH_HCR_TC_TDIR, + /* * Anything after this point requires a callback evaluating a * complex trap condition. Ugly stuff. @@ -372,12 +380,42 @@ static const struct trap_bits coarse_trap_bits[] = { .mask = CPTR_EL2_TCPAC, .behaviour = BEHAVE_FORWARD_ANY, }, + [CGT_HCRX_EnFPM] = { + .index = HCRX_EL2, + .value = 0, + .mask = HCRX_EL2_EnFPM, + .behaviour = BEHAVE_FORWARD_ANY, + }, [CGT_HCRX_TCR2En] = { .index = HCRX_EL2, .value = 0, .mask = HCRX_EL2_TCR2En, .behaviour = BEHAVE_FORWARD_ANY, }, + [CGT_ICH_HCR_TC] = { + .index = ICH_HCR_EL2, + .value = ICH_HCR_TC, + .mask = ICH_HCR_TC, + .behaviour = BEHAVE_FORWARD_ANY, + }, + [CGT_ICH_HCR_TALL0] = { + .index = ICH_HCR_EL2, + .value = ICH_HCR_TALL0, + .mask = ICH_HCR_TALL0, + .behaviour = BEHAVE_FORWARD_ANY, + }, + [CGT_ICH_HCR_TALL1] = { + .index = ICH_HCR_EL2, + .value = ICH_HCR_TALL1, + .mask = ICH_HCR_TALL1, + .behaviour = BEHAVE_FORWARD_ANY, + }, + [CGT_ICH_HCR_TDIR] = { + .index = ICH_HCR_EL2, + .value = ICH_HCR_TDIR, + .mask = ICH_HCR_TDIR, + .behaviour = BEHAVE_FORWARD_ANY, + }, }; #define MCB(id, ...) \ @@ -387,7 +425,6 @@ static const struct trap_bits coarse_trap_bits[] = { } static const enum cgt_group_id *coarse_control_combo[] = { - MCB(CGT_HCR_IMO_FMO, CGT_HCR_IMO, CGT_HCR_FMO), MCB(CGT_HCR_TID2_TID4, CGT_HCR_TID2, CGT_HCR_TID4), MCB(CGT_HCR_TTLB_TTLBIS, CGT_HCR_TTLB, CGT_HCR_TTLBIS), MCB(CGT_HCR_TTLB_TTLBOS, CGT_HCR_TTLB, CGT_HCR_TTLBOS), @@ -402,6 +439,9 @@ static const enum cgt_group_id *coarse_control_combo[] = { MCB(CGT_MDCR_TDE_TDOSA, CGT_MDCR_TDE, CGT_MDCR_TDOSA), MCB(CGT_MDCR_TDE_TDRA, CGT_MDCR_TDE, CGT_MDCR_TDRA), MCB(CGT_MDCR_TDCC_TDE_TDA, CGT_MDCR_TDCC, CGT_MDCR_TDE, CGT_MDCR_TDA), + + MCB(CGT_HCR_IMO_FMO_ICH_HCR_TC, CGT_HCR_IMO, CGT_HCR_FMO, CGT_ICH_HCR_TC), + MCB(CGT_ICH_HCR_TC_TDIR, CGT_ICH_HCR_TC, CGT_ICH_HCR_TDIR), }; typedef enum trap_behaviour (*complex_condition_check)(struct kvm_vcpu *); @@ -536,9 +576,9 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = { SR_TRAP(SYS_CSSELR_EL1, CGT_HCR_TID2_TID4), SR_RANGE_TRAP(SYS_ID_PFR0_EL1, sys_reg(3, 0, 0, 7, 7), CGT_HCR_TID3), - SR_TRAP(SYS_ICC_SGI0R_EL1, CGT_HCR_IMO_FMO), - SR_TRAP(SYS_ICC_ASGI1R_EL1, CGT_HCR_IMO_FMO), - SR_TRAP(SYS_ICC_SGI1R_EL1, CGT_HCR_IMO_FMO), + SR_TRAP(SYS_ICC_SGI0R_EL1, CGT_HCR_IMO_FMO_ICH_HCR_TC), + SR_TRAP(SYS_ICC_ASGI1R_EL1, CGT_HCR_IMO_FMO_ICH_HCR_TC), + SR_TRAP(SYS_ICC_SGI1R_EL1, CGT_HCR_IMO_FMO_ICH_HCR_TC), SR_RANGE_TRAP(sys_reg(3, 0, 11, 0, 0), sys_reg(3, 0, 11, 15, 7), CGT_HCR_TIDCP), SR_RANGE_TRAP(sys_reg(3, 1, 11, 0, 0), @@ -786,6 +826,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = { SR_TRAP(OP_AT_S12E1W, CGT_HCR_NV), SR_TRAP(OP_AT_S12E0R, CGT_HCR_NV), SR_TRAP(OP_AT_S12E0W, CGT_HCR_NV), + SR_TRAP(OP_AT_S1E2A, CGT_HCR_NV), SR_TRAP(OP_TLBI_IPAS2E1, CGT_HCR_NV), SR_TRAP(OP_TLBI_RIPAS2E1, CGT_HCR_NV), SR_TRAP(OP_TLBI_IPAS2LE1, CGT_HCR_NV), @@ -867,6 +908,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = { SR_TRAP(OP_AT_S1E0W, CGT_HCR_AT), SR_TRAP(OP_AT_S1E1RP, CGT_HCR_AT), SR_TRAP(OP_AT_S1E1WP, CGT_HCR_AT), + SR_TRAP(OP_AT_S1E1A, CGT_HCR_AT), SR_TRAP(SYS_ERXPFGF_EL1, CGT_HCR_nFIEN), SR_TRAP(SYS_ERXPFGCTL_EL1, CGT_HCR_nFIEN), SR_TRAP(SYS_ERXPFGCDN_EL1, CGT_HCR_nFIEN), @@ -1108,6 +1150,35 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = { SR_TRAP(SYS_CNTP_CTL_EL0, CGT_CNTHCTL_EL1PTEN), SR_TRAP(SYS_CNTPCT_EL0, CGT_CNTHCTL_EL1PCTEN), SR_TRAP(SYS_CNTPCTSS_EL0, CGT_CNTHCTL_EL1PCTEN), + SR_TRAP(SYS_FPMR, CGT_HCRX_EnFPM), + /* + * IMPDEF choice: + * We treat ICC_SRE_EL2.{SRE,Enable) and ICV_SRE_EL1.SRE as + * RAO/WI. We therefore never consider ICC_SRE_EL2.Enable for + * ICC_SRE_EL1 access, and always handle it locally. + */ + SR_TRAP(SYS_ICC_AP0R0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_AP0R1_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_AP0R2_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_AP0R3_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_AP1R0_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_AP1R1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_AP1R2_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_AP1R3_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_BPR0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_BPR1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_CTLR_EL1, CGT_ICH_HCR_TC), + SR_TRAP(SYS_ICC_DIR_EL1, CGT_ICH_HCR_TC_TDIR), + SR_TRAP(SYS_ICC_EOIR0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_EOIR1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_HPPIR0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_HPPIR1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_IAR0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_IAR1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_IGRPEN0_EL1, CGT_ICH_HCR_TALL0), + SR_TRAP(SYS_ICC_IGRPEN1_EL1, CGT_ICH_HCR_TALL1), + SR_TRAP(SYS_ICC_PMR_EL1, CGT_ICH_HCR_TC), + SR_TRAP(SYS_ICC_RPR_EL1, CGT_ICH_HCR_TC), }; static DEFINE_XARRAY(sr_forward_xa); diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index c53e5b14038d..ea5484ce1f3b 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -63,6 +63,7 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) */ *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED; *host_data_ptr(fpsimd_state) = kern_hyp_va(¤t->thread.uw.fpsimd_state); + *host_data_ptr(fpmr_ptr) = kern_hyp_va(¤t->thread.uw.fpmr); vcpu_clear_flag(vcpu, HOST_SVE_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) @@ -134,8 +135,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fp_state.sve_state = vcpu->arch.sve_state; fp_state.sve_vl = vcpu->arch.sve_max_vl; fp_state.sme_state = NULL; - fp_state.svcr = &vcpu->arch.svcr; - fp_state.fpmr = &vcpu->arch.fpmr; + fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR); + fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR); fp_state.fp_type = &vcpu->arch.fp_type; if (vcpu_has_sve(vcpu)) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 11098eb7eb44..e738a353b20e 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -1045,11 +1045,17 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, mutex_lock(&kvm->slots_lock); + if (write && atomic_read(&kvm->nr_memslots_dirty_logging)) { + ret = -EBUSY; + goto out; + } + while (length > 0) { kvm_pfn_t pfn = gfn_to_pfn_prot(kvm, gfn, write, NULL); void *maddr; unsigned long num_tags; struct page *page; + struct folio *folio; if (is_error_noslot_pfn(pfn)) { ret = -EFAULT; @@ -1059,13 +1065,17 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, page = pfn_to_online_page(pfn); if (!page) { /* Reject ZONE_DEVICE memory */ + kvm_release_pfn_clean(pfn); ret = -EFAULT; goto out; } + folio = page_folio(page); maddr = page_address(page); if (!write) { - if (page_mte_tagged(page)) + if ((folio_test_hugetlb(folio) && + folio_test_hugetlb_mte_tagged(folio)) || + page_mte_tagged(page)) num_tags = mte_copy_tags_to_user(tags, maddr, MTE_GRANULES_PER_PAGE); else @@ -1079,14 +1089,20 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, * __set_ptes() in the VMM but still overriding the * tags, hence ignoring the return value. */ - try_page_mte_tagging(page); + if (folio_test_hugetlb(folio)) + folio_try_hugetlb_mte_tagging(folio); + else + try_page_mte_tagging(page); num_tags = mte_copy_tags_from_user(maddr, tags, MTE_GRANULES_PER_PAGE); /* uaccess failed, don't leave stale tags */ if (num_tags != MTE_GRANULES_PER_PAGE) mte_clear_page_tags(maddr); - set_page_mte_tagged(page); + if (folio_test_hugetlb(folio)) + folio_set_hugetlb_mte_tagged(folio); + else + set_page_mte_tagged(page); kvm_release_pfn_dirty(pfn); } diff --git a/arch/arm64/kvm/hyp/include/hyp/fault.h b/arch/arm64/kvm/hyp/include/hyp/fault.h index 9e13c1bc2ad5..17df94570f03 100644 --- a/arch/arm64/kvm/hyp/include/hyp/fault.h +++ b/arch/arm64/kvm/hyp/include/hyp/fault.h @@ -14,6 +14,7 @@ static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar) { + int ret; u64 par, tmp; /* @@ -27,7 +28,9 @@ static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar) * saved the guest context yet, and we may return early... */ par = read_sysreg_par(); - if (!__kvm_at("s1e1r", far)) + ret = system_supports_poe() ? __kvm_at(OP_AT_S1E1A, far) : + __kvm_at(OP_AT_S1E1R, far); + if (!ret) tmp = read_sysreg_par(); else tmp = SYS_PAR_EL1_F; /* back to the guest */ diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 37ff87d782b6..5310fe1da616 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -338,7 +338,7 @@ static inline void __hyp_sve_save_host(void) struct cpu_sve_state *sve_state = *host_data_ptr(sve_state); sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR); - write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); + write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); __sve_save_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max_vl), &sve_state->fpsr, true); @@ -403,6 +403,9 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) else __fpsimd_restore_state(&vcpu->arch.ctxt.fp_regs); + if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) + write_sysreg_s(__vcpu_sys_reg(vcpu, FPMR), SYS_FPMR); + /* Skip restoring fpexc32 for AArch64 guests */ if (!(read_sysreg(hcr_el2) & HCR_RW)) write_sysreg(__vcpu_sys_reg(vcpu, FPEXC32_EL2), fpexc32_el2); diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index 4c0fdabaf8ae..1579a3c08a36 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -16,9 +16,15 @@ #include <asm/kvm_hyp.h> #include <asm/kvm_mmu.h> +static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt); + static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, MDSCR_EL1) = read_sysreg(mdscr_el1); + + // POR_EL0 can affect uaccess, so must be saved/restored early. + if (ctxt_has_s1poe(ctxt)) + ctxt_sys_reg(ctxt, POR_EL0) = read_sysreg_s(SYS_POR_EL0); } static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) @@ -66,6 +72,17 @@ static inline bool ctxt_has_tcrx(struct kvm_cpu_context *ctxt) return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, TCRX, IMP); } +static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu; + + if (!system_supports_poe()) + return false; + + vcpu = ctxt_to_vcpu(ctxt); + return kvm_has_feat(kern_hyp_va(vcpu->kvm), ID_AA64MMFR3_EL1, S1POE, IMP); +} + static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, SCTLR_EL1) = read_sysreg_el1(SYS_SCTLR); @@ -80,6 +97,9 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); } + + if (ctxt_has_s1poe(ctxt)) + ctxt_sys_reg(ctxt, POR_EL1) = read_sysreg_el1(SYS_POR); } ctxt_sys_reg(ctxt, ESR_EL1) = read_sysreg_el1(SYS_ESR); ctxt_sys_reg(ctxt, AFSR0_EL1) = read_sysreg_el1(SYS_AFSR0); @@ -120,6 +140,10 @@ static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) static inline void __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt_sys_reg(ctxt, MDSCR_EL1), mdscr_el1); + + // POR_EL0 can affect uaccess, so must be saved/restored early. + if (ctxt_has_s1poe(ctxt)) + write_sysreg_s(ctxt_sys_reg(ctxt, POR_EL0), SYS_POR_EL0); } static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) @@ -158,6 +182,9 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR); write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0); } + + if (ctxt_has_s1poe(ctxt)) + write_sysreg_el1(ctxt_sys_reg(ctxt, POR_EL1), SYS_POR); } write_sysreg_el1(ctxt_sys_reg(ctxt, ESR_EL1), SYS_ESR); write_sysreg_el1(ctxt_sys_reg(ctxt, AFSR0_EL1), SYS_AFSR0); diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c index e715c157c2c4..e433dfab882a 100644 --- a/arch/arm64/kvm/hyp/nvhe/ffa.c +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c @@ -426,9 +426,9 @@ out: return; } -static __always_inline void do_ffa_mem_xfer(const u64 func_id, - struct arm_smccc_res *res, - struct kvm_cpu_context *ctxt) +static void __do_ffa_mem_xfer(const u64 func_id, + struct arm_smccc_res *res, + struct kvm_cpu_context *ctxt) { DECLARE_REG(u32, len, ctxt, 1); DECLARE_REG(u32, fraglen, ctxt, 2); @@ -440,9 +440,6 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id, u32 offset, nr_ranges; int ret = 0; - BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE && - func_id != FFA_FN64_MEM_LEND); - if (addr_mbz || npages_mbz || fraglen > len || fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) { ret = FFA_RET_INVALID_PARAMETERS; @@ -461,6 +458,11 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id, goto out_unlock; } + if (len > ffa_desc_buf.len) { + ret = FFA_RET_NO_MEMORY; + goto out_unlock; + } + buf = hyp_buffers.tx; memcpy(buf, host_buffers.tx, fraglen); @@ -512,6 +514,13 @@ err_unshare: goto out_unlock; } +#define do_ffa_mem_xfer(fid, res, ctxt) \ + do { \ + BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \ + (fid) != FFA_FN64_MEM_LEND); \ + __do_ffa_mem_xfer((fid), (res), (ctxt)); \ + } while (0); + static void do_ffa_mem_reclaim(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt) { diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S index 07120b37da35..fc1866226067 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-init.S +++ b/arch/arm64/kvm/hyp/nvhe/hyp-init.S @@ -24,28 +24,25 @@ .align 11 SYM_CODE_START(__kvm_hyp_init) - ventry __invalid // Synchronous EL2t - ventry __invalid // IRQ EL2t - ventry __invalid // FIQ EL2t - ventry __invalid // Error EL2t + ventry . // Synchronous EL2t + ventry . // IRQ EL2t + ventry . // FIQ EL2t + ventry . // Error EL2t - ventry __invalid // Synchronous EL2h - ventry __invalid // IRQ EL2h - ventry __invalid // FIQ EL2h - ventry __invalid // Error EL2h + ventry . // Synchronous EL2h + ventry . // IRQ EL2h + ventry . // FIQ EL2h + ventry . // Error EL2h ventry __do_hyp_init // Synchronous 64-bit EL1 - ventry __invalid // IRQ 64-bit EL1 - ventry __invalid // FIQ 64-bit EL1 - ventry __invalid // Error 64-bit EL1 + ventry . // IRQ 64-bit EL1 + ventry . // FIQ 64-bit EL1 + ventry . // Error 64-bit EL1 - ventry __invalid // Synchronous 32-bit EL1 - ventry __invalid // IRQ 32-bit EL1 - ventry __invalid // FIQ 32-bit EL1 - ventry __invalid // Error 32-bit EL1 - -__invalid: - b . + ventry . // Synchronous 32-bit EL1 + ventry . // IRQ 32-bit EL1 + ventry . // FIQ 32-bit EL1 + ventry . // Error 32-bit EL1 /* * Only uses x0..x3 so as to not clobber callee-saved SMCCC registers. @@ -76,6 +73,13 @@ __do_hyp_init: eret SYM_CODE_END(__kvm_hyp_init) +SYM_CODE_START_LOCAL(__kvm_init_el2_state) + /* Initialize EL2 CPU state to sane values. */ + init_el2_state // Clobbers x0..x2 + finalise_el2_state + ret +SYM_CODE_END(__kvm_init_el2_state) + /* * Initialize the hypervisor in EL2. * @@ -102,9 +106,12 @@ SYM_CODE_START_LOCAL(___kvm_hyp_init) // TPIDR_EL2 is used to preserve x0 across the macro maze... isb msr tpidr_el2, x0 - init_el2_state - finalise_el2_state + str lr, [x0, #NVHE_INIT_TMP] + + bl __kvm_init_el2_state + mrs x0, tpidr_el2 + ldr lr, [x0, #NVHE_INIT_TMP] 1: ldr x1, [x0, #NVHE_INIT_TPIDR_EL2] @@ -130,7 +137,7 @@ alternative_else_nop_endif /* Invalidate the stale TLBs from Bootloader */ tlbi alle2 - tlbi vmalls12e1 + tlbi alle1 dsb sy mov_q x0, INIT_SCTLR_EL2_MMU_ON @@ -199,9 +206,8 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu) 2: msr SPsel, #1 // We want to use SP_EL{1,2} - /* Initialize EL2 CPU state to sane values. */ - init_el2_state // Clobbers x0..x2 - finalise_el2_state + bl __kvm_init_el2_state + __init_el2_nvhe_prepare_eret /* Enable MMU, set vectors and stack. */ diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index f43d845f3c4e..fefc89209f9e 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -33,7 +33,7 @@ static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) */ sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2); __sve_save_state(vcpu_sve_pffr(vcpu), &vcpu->arch.ctxt.fp_regs.fpsr, true); - write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); + write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); } static void __hyp_sve_restore_host(void) @@ -45,10 +45,11 @@ static void __hyp_sve_restore_host(void) * the host. The layout of the data when saving the sve state depends * on the VL, so use a consistent (i.e., the maximum) host VL. * - * Setting ZCR_EL2 to ZCR_ELx_LEN_MASK sets the effective length - * supported by the system (or limited at EL3). + * Note that this constrains the PE to the maximum shared VL + * that was discovered, if we wish to use larger VLs this will + * need to be revisited. */ - write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); + write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); __sve_restore_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max_vl), &sve_state->fpsr, true); @@ -62,6 +63,8 @@ static void fpsimd_sve_flush(void) static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) { + bool has_fpmr; + if (!guest_owns_fp_regs()) return; @@ -73,11 +76,18 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) else __fpsimd_save_state(&vcpu->arch.ctxt.fp_regs); + has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm)); + if (has_fpmr) + __vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR); + if (system_supports_sve()) __hyp_sve_restore_host(); else __fpsimd_restore_state(*host_data_ptr(fpsimd_state)); + if (has_fpmr) + write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR); + *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED; } @@ -479,7 +489,8 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) case ESR_ELx_EC_SVE: cpacr_clear_set(0, CPACR_ELx_ZEN); isb(); - sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); + sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, + SYS_ZCR_EL2); break; case ESR_ELx_EC_IABT_LOW: case ESR_ELx_EC_DABT_LOW: diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 187a5f4d56c0..077d4098548d 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -574,12 +574,14 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu, unlock: hyp_spin_unlock(&vm_table_lock); - if (ret) + if (ret) { unmap_donated_memory(hyp_vcpu, sizeof(*hyp_vcpu)); + return ret; + } hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu); - return ret; + return 0; } static void diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 8f5c56d5b1cd..cc69106734ca 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -197,6 +197,15 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) } else { __fpsimd_save_state(*host_data_ptr(fpsimd_state)); } + + if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) { + u64 val = read_sysreg_s(SYS_FPMR); + + if (unlikely(is_protected_kvm_enabled())) + *host_data_ptr(fpmr) = val; + else + **host_data_ptr(fpmr_ptr) = val; + } } static const exit_handler_fn hyp_exit_handlers[] = { diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c index ca3c09df8d7c..48da9ca9763f 100644 --- a/arch/arm64/kvm/hyp/nvhe/tlb.c +++ b/arch/arm64/kvm/hyp/nvhe/tlb.c @@ -132,10 +132,10 @@ static void exit_vmid_context(struct tlb_inv_context *cxt) else __load_host_stage2(); - if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { - /* Ensure write of the old VMID */ - isb(); + /* Ensure write of the old VMID */ + isb(); + if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { if (!(cxt->sctlr & SCTLR_ELx_M)) { write_sysreg_el1(cxt->sctlr, SYS_SCTLR); isb(); diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 9e2bbee77491..b11bcebac908 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -17,48 +17,6 @@ #define KVM_PTE_TYPE_PAGE 1 #define KVM_PTE_TYPE_TABLE 1 -#define KVM_PTE_LEAF_ATTR_LO GENMASK(11, 2) - -#define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2) -#define KVM_PTE_LEAF_ATTR_LO_S1_AP GENMASK(7, 6) -#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO \ - ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 2 : 3; }) -#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW \ - ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 0 : 1; }) -#define KVM_PTE_LEAF_ATTR_LO_S1_SH GENMASK(9, 8) -#define KVM_PTE_LEAF_ATTR_LO_S1_SH_IS 3 -#define KVM_PTE_LEAF_ATTR_LO_S1_AF BIT(10) - -#define KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR GENMASK(5, 2) -#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R BIT(6) -#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W BIT(7) -#define KVM_PTE_LEAF_ATTR_LO_S2_SH GENMASK(9, 8) -#define KVM_PTE_LEAF_ATTR_LO_S2_SH_IS 3 -#define KVM_PTE_LEAF_ATTR_LO_S2_AF BIT(10) - -#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 50) - -#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55) - -#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54) - -#define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54) - -#define KVM_PTE_LEAF_ATTR_HI_S1_GP BIT(50) - -#define KVM_PTE_LEAF_ATTR_S2_PERMS (KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \ - KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \ - KVM_PTE_LEAF_ATTR_HI_S2_XN) - -#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2) -#define KVM_MAX_OWNER_ID 1 - -/* - * Used to indicate a pte for which a 'break-before-make' sequence is in - * progress. - */ -#define KVM_INVALID_PTE_LOCKED BIT(10) - struct kvm_pgtable_walk_data { struct kvm_pgtable_walker *walker; @@ -1547,7 +1505,6 @@ static int stage2_split_walker(const struct kvm_pgtable_visit_ctx *ctx, */ new = kvm_init_table_pte(childp, mm_ops); stage2_make_pte(ctx, new); - dsb(ishst); return 0; } @@ -1559,8 +1516,11 @@ int kvm_pgtable_stage2_split(struct kvm_pgtable *pgt, u64 addr, u64 size, .flags = KVM_PGTABLE_WALK_LEAF, .arg = mc, }; + int ret; - return kvm_pgtable_walk(pgt, addr, size, &walker); + ret = kvm_pgtable_walk(pgt, addr, size, &walker); + dsb(ishst); + return ret; } int __kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 7b397fad26f2..18d4677002b1 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -268,8 +268,16 @@ void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) * starting to mess with the rest of the GIC, and VMCR_EL2 in * particular. This logic must be called before * __vgic_v3_restore_state(). + * + * However, if the vgic is disabled (ICH_HCR_EL2.EN==0), no GIC is + * provisioned at all. In order to prevent illegal accesses to the + * system registers to trap to EL1 (duh), force ICC_SRE_EL1.SRE to 1 + * so that the trap bits can take effect. Yes, we *loves* the GIC. */ - if (!cpu_if->vgic_sre) { + if (!(cpu_if->vgic_hcr & ICH_HCR_EN)) { + write_gicreg(ICC_SRE_EL1_SRE, ICC_SRE_EL1); + isb(); + } else if (!cpu_if->vgic_sre) { write_gicreg(0, ICC_SRE_EL1); isb(); write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2); @@ -288,8 +296,9 @@ void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) } /* - * Prevent the guest from touching the GIC system registers if - * SRE isn't enabled for GICv3 emulation. + * Prevent the guest from touching the ICC_SRE_EL1 system + * register. Note that this may not have any effect, as + * ICC_SRE_EL2.Enable being RAO/WI is a valid implementation. */ write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE, ICC_SRE_EL2); @@ -297,10 +306,11 @@ void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if) /* * If we need to trap system registers, we must write * ICH_HCR_EL2 anyway, even if no interrupts are being - * injected, + * injected. Note that this also applies if we don't expect + * any system register access (no vgic at all). */ if (static_branch_unlikely(&vgic_v3_cpuif_trap) || - cpu_if->its_vpe.its_vm) + cpu_if->its_vpe.its_vm || !cpu_if->vgic_sre) write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2); } @@ -326,7 +336,7 @@ void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if) * no interrupts were being injected, and we disable it again here. */ if (static_branch_unlikely(&vgic_v3_cpuif_trap) || - cpu_if->its_vpe.its_vm) + cpu_if->its_vpe.its_vm || !cpu_if->vgic_sre) write_gicreg(0, ICH_HCR_EL2); } @@ -1032,6 +1042,75 @@ static void __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt) write_gicreg(vmcr, ICH_VMCR_EL2); } +static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu, + u32 sysreg, bool is_read) +{ + u64 ich_hcr; + + if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu)) + return false; + + ich_hcr = __vcpu_sys_reg(vcpu, ICH_HCR_EL2); + + switch (sysreg) { + case SYS_ICC_IGRPEN0_EL1: + if (is_read && + (__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1)) + return true; + + if (!is_read && + (__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1)) + return true; + + fallthrough; + + case SYS_ICC_AP0Rn_EL1(0): + case SYS_ICC_AP0Rn_EL1(1): + case SYS_ICC_AP0Rn_EL1(2): + case SYS_ICC_AP0Rn_EL1(3): + case SYS_ICC_BPR0_EL1: + case SYS_ICC_EOIR0_EL1: + case SYS_ICC_HPPIR0_EL1: + case SYS_ICC_IAR0_EL1: + return ich_hcr & ICH_HCR_TALL0; + + case SYS_ICC_IGRPEN1_EL1: + if (is_read && + (__vcpu_sys_reg(vcpu, HFGRTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1)) + return true; + + if (!is_read && + (__vcpu_sys_reg(vcpu, HFGWTR_EL2) & HFGxTR_EL2_ICC_IGRPENn_EL1)) + return true; + + fallthrough; + + case SYS_ICC_AP1Rn_EL1(0): + case SYS_ICC_AP1Rn_EL1(1): + case SYS_ICC_AP1Rn_EL1(2): + case SYS_ICC_AP1Rn_EL1(3): + case SYS_ICC_BPR1_EL1: + case SYS_ICC_EOIR1_EL1: + case SYS_ICC_HPPIR1_EL1: + case SYS_ICC_IAR1_EL1: + return ich_hcr & ICH_HCR_TALL1; + + case SYS_ICC_DIR_EL1: + if (ich_hcr & ICH_HCR_TDIR) + return true; + + fallthrough; + + case SYS_ICC_RPR_EL1: + case SYS_ICC_CTLR_EL1: + case SYS_ICC_PMR_EL1: + return ich_hcr & ICH_HCR_TC; + + default: + return false; + } +} + int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) { int rt; @@ -1041,6 +1120,9 @@ int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) bool is_read; u32 sysreg; + if (kern_hyp_va(vcpu->kvm)->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3) + return 0; + esr = kvm_vcpu_get_esr(vcpu); if (vcpu_mode_is_32bit(vcpu)) { if (!kvm_condition_valid(vcpu)) { @@ -1055,6 +1137,9 @@ int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ; + if (__vgic_v3_check_trap_forwarding(vcpu, sysreg, is_read)) + return 0; + switch (sysreg) { case SYS_ICC_IAR0_EL1: case SYS_ICC_IAR1_EL1: diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 77010b76c150..80581b1c3995 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -312,6 +312,9 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code) static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) { __fpsimd_save_state(*host_data_ptr(fpsimd_state)); + + if (kvm_has_fpmr(vcpu->kvm)) + **host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR); } static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code) diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c index 5763d979d8ca..ee6573befb81 100644 --- a/arch/arm64/kvm/hypercalls.c +++ b/arch/arm64/kvm/hypercalls.c @@ -317,7 +317,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu) * to the guest, and hide SSBS so that the * guest stays protected. */ - if (cpus_have_final_cap(ARM64_SSBS)) + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP)) break; fallthrough; case SPECTRE_UNAFFECTED: @@ -428,7 +428,7 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) * Convert the workaround level into an easy-to-compare number, where higher * values mean better protection. */ -static int get_kernel_wa_level(u64 regid) +static int get_kernel_wa_level(struct kvm_vcpu *vcpu, u64 regid) { switch (regid) { case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: @@ -449,7 +449,7 @@ static int get_kernel_wa_level(u64 regid) * don't have any FW mitigation if SSBS is there at * all times. */ - if (cpus_have_final_cap(ARM64_SSBS)) + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP)) return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; fallthrough; case SPECTRE_UNAFFECTED: @@ -486,7 +486,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: - val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK; + val = get_kernel_wa_level(vcpu, reg->id) & KVM_REG_FEATURE_LEVEL_MASK; break; case KVM_REG_ARM_STD_BMAP: val = READ_ONCE(smccc_feat->std_bmap); @@ -588,7 +588,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) if (val & ~KVM_REG_FEATURE_LEVEL_MASK) return -EINVAL; - if (get_kernel_wa_level(reg->id) < val) + if (get_kernel_wa_level(vcpu, reg->id) < val) return -EINVAL; return 0; @@ -624,7 +624,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the * other way around. */ - if (get_kernel_wa_level(reg->id) < wa_level) + if (get_kernel_wa_level(vcpu, reg->id) < wa_level) return -EINVAL; return 0; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index a509b63bd4dd..56d9a7f414fe 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -328,9 +328,10 @@ static void __unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 may_block)); } -void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size) +void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, + u64 size, bool may_block) { - __unmap_stage2_range(mmu, start, size, true); + __unmap_stage2_range(mmu, start, size, may_block); } void kvm_stage2_flush_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end) @@ -1015,7 +1016,7 @@ static void stage2_unmap_memslot(struct kvm *kvm, if (!(vma->vm_flags & VM_PFNMAP)) { gpa_t gpa = addr + (vm_start - memslot->userspace_addr); - kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, vm_end - vm_start); + kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, vm_end - vm_start, true); } hva = vm_end; } while (hva < reg_end); @@ -1042,7 +1043,7 @@ void stage2_unmap_vm(struct kvm *kvm) kvm_for_each_memslot(memslot, bkt, slots) stage2_unmap_memslot(kvm, memslot); - kvm_nested_s2_unmap(kvm); + kvm_nested_s2_unmap(kvm, true); write_unlock(&kvm->mmu_lock); mmap_read_unlock(current->mm); @@ -1401,10 +1402,21 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn, { unsigned long i, nr_pages = size >> PAGE_SHIFT; struct page *page = pfn_to_page(pfn); + struct folio *folio = page_folio(page); if (!kvm_has_mte(kvm)) return; + if (folio_test_hugetlb(folio)) { + /* Hugetlb has MTE flags set on head page only */ + if (folio_try_hugetlb_mte_tagging(folio)) { + for (i = 0; i < nr_pages; i++, page++) + mte_clear_page_tags(page_address(page)); + folio_set_hugetlb_mte_tagged(folio); + } + return; + } + for (i = 0; i < nr_pages; i++, page++) { if (try_page_mte_tagging(page)) { mte_clear_page_tags(page_address(page)); @@ -1912,7 +1924,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) (range->end - range->start) << PAGE_SHIFT, range->may_block); - kvm_nested_s2_unmap(kvm); + kvm_nested_s2_unmap(kvm, range->may_block); return false; } @@ -2179,8 +2191,8 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm, phys_addr_t size = slot->npages << PAGE_SHIFT; write_lock(&kvm->mmu_lock); - kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, size); - kvm_nested_s2_unmap(kvm); + kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, size, true); + kvm_nested_s2_unmap(kvm, true); write_unlock(&kvm->mmu_lock); } diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index bab27f9d8cc6..c4b17d90fc49 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -62,7 +62,6 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu) */ num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU; tmp = kvrealloc(kvm->arch.nested_mmus, - size_mul(sizeof(*kvm->arch.nested_mmus), kvm->arch.nested_mmus_size), size_mul(sizeof(*kvm->arch.nested_mmus), num_mmus), GFP_KERNEL_ACCOUNT | __GFP_ZERO); if (!tmp) @@ -103,20 +102,6 @@ struct s2_walk_info { bool be; }; -static unsigned int ps_to_output_size(unsigned int ps) -{ - switch (ps) { - case 0: return 32; - case 1: return 36; - case 2: return 40; - case 3: return 42; - case 4: return 44; - case 5: - default: - return 48; - } -} - static u32 compute_fsc(int level, u32 fsc) { return fsc | (level & 0x3); @@ -256,7 +241,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa, /* Check for valid descriptor at this point */ if (!(desc & 1) || ((desc & 3) == 1 && level == 3)) { out->esr = compute_fsc(level, ESR_ELx_FSC_FAULT); - out->upper_attr = desc; + out->desc = desc; return 1; } @@ -266,7 +251,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa, if (check_output_size(wi, desc)) { out->esr = compute_fsc(level, ESR_ELx_FSC_ADDRSZ); - out->upper_attr = desc; + out->desc = desc; return 1; } @@ -278,27 +263,24 @@ static int walk_nested_s2_pgd(phys_addr_t ipa, if (level < first_block_level) { out->esr = compute_fsc(level, ESR_ELx_FSC_FAULT); - out->upper_attr = desc; + out->desc = desc; return 1; } - /* - * We don't use the contiguous bit in the stage-2 ptes, so skip check - * for misprogramming of the contiguous bit. - */ - if (check_output_size(wi, desc)) { out->esr = compute_fsc(level, ESR_ELx_FSC_ADDRSZ); - out->upper_attr = desc; + out->desc = desc; return 1; } if (!(desc & BIT(10))) { out->esr = compute_fsc(level, ESR_ELx_FSC_ACCESS); - out->upper_attr = desc; + out->desc = desc; return 1; } + addr_bottom += contiguous_bit_shift(desc, wi, level); + /* Calculate and return the result */ paddr = (desc & GENMASK_ULL(47, addr_bottom)) | (ipa & GENMASK_ULL(addr_bottom - 1, 0)); @@ -307,7 +289,7 @@ static int walk_nested_s2_pgd(phys_addr_t ipa, out->readable = desc & (0b01 << 6); out->writable = desc & (0b10 << 6); out->level = level; - out->upper_attr = desc & GENMASK_ULL(63, 52); + out->desc = desc; return 0; } @@ -650,9 +632,9 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm_vcpu *vcpu) /* Set the scene for the next search */ kvm->arch.nested_mmus_next = (i + 1) % kvm->arch.nested_mmus_size; - /* Clear the old state */ + /* Make sure we don't forget to do the laundry */ if (kvm_s2_mmu_valid(s2_mmu)) - kvm_stage2_unmap_range(s2_mmu, 0, kvm_phys_size(s2_mmu)); + s2_mmu->pending_unmap = true; /* * The virtual VMID (modulo CnP) will be used as a key when matching @@ -668,6 +650,16 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm_vcpu *vcpu) out: atomic_inc(&s2_mmu->refcnt); + + /* + * Set the vCPU request to perform an unmap, even if the pending unmap + * originates from another vCPU. This guarantees that the MMU has been + * completely unmapped before any vCPU actually uses it, and allows + * multiple vCPUs to lend a hand with completing the unmap. + */ + if (s2_mmu->pending_unmap) + kvm_make_request(KVM_REQ_NESTED_S2_UNMAP, vcpu); + return s2_mmu; } @@ -681,6 +673,13 @@ void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu) void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu) { + /* + * The vCPU kept its reference on the MMU after the last put, keep + * rolling with it. + */ + if (vcpu->arch.hw_mmu) + return; + if (is_hyp_ctxt(vcpu)) { vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu; } else { @@ -692,10 +691,18 @@ void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu) void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu) { - if (kvm_is_nested_s2_mmu(vcpu->kvm, vcpu->arch.hw_mmu)) { + /* + * Keep a reference on the associated stage-2 MMU if the vCPU is + * scheduling out and not in WFI emulation, suggesting it is likely to + * reuse the MMU sometime soon. + */ + if (vcpu->scheduled_out && !vcpu_get_flag(vcpu, IN_WFI)) + return; + + if (kvm_is_nested_s2_mmu(vcpu->kvm, vcpu->arch.hw_mmu)) atomic_dec(&vcpu->arch.hw_mmu->refcnt); - vcpu->arch.hw_mmu = NULL; - } + + vcpu->arch.hw_mmu = NULL; } /* @@ -748,7 +755,7 @@ void kvm_nested_s2_wp(struct kvm *kvm) } } -void kvm_nested_s2_unmap(struct kvm *kvm) +void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block) { int i; @@ -758,7 +765,7 @@ void kvm_nested_s2_unmap(struct kvm *kvm) struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i]; if (kvm_s2_mmu_valid(mmu)) - kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu)); + kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu), may_block); } } @@ -954,19 +961,16 @@ static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1) int kvm_init_nv_sysregs(struct kvm *kvm) { u64 res0, res1; - int ret = 0; - mutex_lock(&kvm->arch.config_lock); + lockdep_assert_held(&kvm->arch.config_lock); if (kvm->arch.sysreg_masks) - goto out; + return 0; kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)), GFP_KERNEL_ACCOUNT); - if (!kvm->arch.sysreg_masks) { - ret = -ENOMEM; - goto out; - } + if (!kvm->arch.sysreg_masks) + return -ENOMEM; limit_nv_id_regs(kvm); @@ -1195,8 +1199,27 @@ int kvm_init_nv_sysregs(struct kvm *kvm) if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, V1P1)) res0 |= ~(res0 | res1); set_sysreg_masks(kvm, HAFGRTR_EL2, res0, res1); -out: - mutex_unlock(&kvm->arch.config_lock); - return ret; + /* SCTLR_EL1 */ + res0 = SCTLR_EL1_RES0; + res1 = SCTLR_EL1_RES1; + if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN3)) + res0 |= SCTLR_EL1_EPAN; + set_sysreg_masks(kvm, SCTLR_EL1, res0, res1); + + return 0; +} + +void check_nested_vcpu_requests(struct kvm_vcpu *vcpu) +{ + if (kvm_check_request(KVM_REQ_NESTED_S2_UNMAP, vcpu)) { + struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu; + + write_lock(&vcpu->kvm->mmu_lock); + if (mmu->pending_unmap) { + kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu), true); + mmu->pending_unmap = false; + } + write_unlock(&vcpu->kvm->mmu_lock); + } } diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 82a2a003259c..ac36c438b8c1 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -233,7 +233,7 @@ void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) int i; struct kvm_pmu *pmu = &vcpu->arch.pmu; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) pmu->pmc[i].idx = i; } @@ -260,7 +260,7 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) { int i; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, i)); irq_work_sync(&vcpu->arch.pmu.overflow_work); } @@ -291,7 +291,7 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E) || !val) return; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) { struct kvm_pmc *pmc; if (!(val & BIT(i))) @@ -323,7 +323,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) if (!kvm_vcpu_has_pmu(vcpu) || !val) return; - for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { + for (i = 0; i < KVM_ARMV8_PMU_MAX_COUNTERS; i++) { struct kvm_pmc *pmc; if (!(val & BIT(i))) @@ -910,10 +910,10 @@ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm) struct arm_pmu *arm_pmu = kvm->arch.arm_pmu; /* - * The arm_pmu->num_events considers the cycle counter as well. - * Ignore that and return only the general-purpose counters. + * The arm_pmu->cntr_mask considers the fixed counter(s) as well. + * Ignore those and return only the general-purpose counters. */ - return arm_pmu->num_events - 1; + return bitmap_weight(arm_pmu->cntr_mask, ARMV8_PMU_MAX_GENERAL_COUNTERS); } static void kvm_arm_set_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu) diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c index 329819806096..0b3adf3e17b4 100644 --- a/arch/arm64/kvm/pmu.c +++ b/arch/arm64/kvm/pmu.c @@ -5,6 +5,8 @@ */ #include <linux/kvm_host.h> #include <linux/perf_event.h> +#include <linux/perf/arm_pmu.h> +#include <linux/perf/arm_pmuv3.h> static DEFINE_PER_CPU(struct kvm_pmu_events, kvm_pmu_events); @@ -35,7 +37,7 @@ struct kvm_pmu_events *kvm_get_pmu_events(void) * Add events to track that we may want to switch at guest entry/exit * time. */ -void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) +void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) { struct kvm_pmu_events *pmu = kvm_get_pmu_events(); @@ -51,7 +53,7 @@ void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) /* * Stop tracking events */ -void kvm_clr_pmu_events(u32 clr) +void kvm_clr_pmu_events(u64 clr) { struct kvm_pmu_events *pmu = kvm_get_pmu_events(); @@ -62,79 +64,32 @@ void kvm_clr_pmu_events(u32 clr) pmu->events_guest &= ~clr; } -#define PMEVTYPER_READ_CASE(idx) \ - case idx: \ - return read_sysreg(pmevtyper##idx##_el0) - -#define PMEVTYPER_WRITE_CASE(idx) \ - case idx: \ - write_sysreg(val, pmevtyper##idx##_el0); \ - break - -#define PMEVTYPER_CASES(readwrite) \ - PMEVTYPER_##readwrite##_CASE(0); \ - PMEVTYPER_##readwrite##_CASE(1); \ - PMEVTYPER_##readwrite##_CASE(2); \ - PMEVTYPER_##readwrite##_CASE(3); \ - PMEVTYPER_##readwrite##_CASE(4); \ - PMEVTYPER_##readwrite##_CASE(5); \ - PMEVTYPER_##readwrite##_CASE(6); \ - PMEVTYPER_##readwrite##_CASE(7); \ - PMEVTYPER_##readwrite##_CASE(8); \ - PMEVTYPER_##readwrite##_CASE(9); \ - PMEVTYPER_##readwrite##_CASE(10); \ - PMEVTYPER_##readwrite##_CASE(11); \ - PMEVTYPER_##readwrite##_CASE(12); \ - PMEVTYPER_##readwrite##_CASE(13); \ - PMEVTYPER_##readwrite##_CASE(14); \ - PMEVTYPER_##readwrite##_CASE(15); \ - PMEVTYPER_##readwrite##_CASE(16); \ - PMEVTYPER_##readwrite##_CASE(17); \ - PMEVTYPER_##readwrite##_CASE(18); \ - PMEVTYPER_##readwrite##_CASE(19); \ - PMEVTYPER_##readwrite##_CASE(20); \ - PMEVTYPER_##readwrite##_CASE(21); \ - PMEVTYPER_##readwrite##_CASE(22); \ - PMEVTYPER_##readwrite##_CASE(23); \ - PMEVTYPER_##readwrite##_CASE(24); \ - PMEVTYPER_##readwrite##_CASE(25); \ - PMEVTYPER_##readwrite##_CASE(26); \ - PMEVTYPER_##readwrite##_CASE(27); \ - PMEVTYPER_##readwrite##_CASE(28); \ - PMEVTYPER_##readwrite##_CASE(29); \ - PMEVTYPER_##readwrite##_CASE(30) - /* * Read a value direct from PMEVTYPER<idx> where idx is 0-30 - * or PMCCFILTR_EL0 where idx is ARMV8_PMU_CYCLE_IDX (31). + * or PMxCFILTR_EL0 where idx is 31-32. */ static u64 kvm_vcpu_pmu_read_evtype_direct(int idx) { - switch (idx) { - PMEVTYPER_CASES(READ); - case ARMV8_PMU_CYCLE_IDX: - return read_sysreg(pmccfiltr_el0); - default: - WARN_ON(1); - } + if (idx == ARMV8_PMU_CYCLE_IDX) + return read_pmccfiltr(); + else if (idx == ARMV8_PMU_INSTR_IDX) + return read_pmicfiltr(); - return 0; + return read_pmevtypern(idx); } /* * Write a value direct to PMEVTYPER<idx> where idx is 0-30 - * or PMCCFILTR_EL0 where idx is ARMV8_PMU_CYCLE_IDX (31). + * or PMxCFILTR_EL0 where idx is 31-32. */ static void kvm_vcpu_pmu_write_evtype_direct(int idx, u32 val) { - switch (idx) { - PMEVTYPER_CASES(WRITE); - case ARMV8_PMU_CYCLE_IDX: - write_sysreg(val, pmccfiltr_el0); - break; - default: - WARN_ON(1); - } + if (idx == ARMV8_PMU_CYCLE_IDX) + write_pmccfiltr(val); + else if (idx == ARMV8_PMU_INSTR_IDX) + write_pmicfiltr(val); + else + write_pmevtypern(idx, val); } /* @@ -145,7 +100,7 @@ static void kvm_vcpu_pmu_enable_el0(unsigned long events) u64 typer; u32 counter; - for_each_set_bit(counter, &events, 32) { + for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) { typer = kvm_vcpu_pmu_read_evtype_direct(counter); typer &= ~ARMV8_PMU_EXCLUDE_EL0; kvm_vcpu_pmu_write_evtype_direct(counter, typer); @@ -160,7 +115,7 @@ static void kvm_vcpu_pmu_disable_el0(unsigned long events) u64 typer; u32 counter; - for_each_set_bit(counter, &events, 32) { + for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) { typer = kvm_vcpu_pmu_read_evtype_direct(counter); typer |= ARMV8_PMU_EXCLUDE_EL0; kvm_vcpu_pmu_write_evtype_direct(counter, typer); @@ -176,7 +131,7 @@ static void kvm_vcpu_pmu_disable_el0(unsigned long events) void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) { struct kvm_pmu_events *pmu; - u32 events_guest, events_host; + u64 events_guest, events_host; if (!kvm_arm_support_pmu_v3() || !has_vhe()) return; @@ -197,7 +152,7 @@ void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) { struct kvm_pmu_events *pmu; - u32 events_guest, events_host; + u64 events_guest, events_host; if (!kvm_arm_support_pmu_v3() || !has_vhe()) return; diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c new file mode 100644 index 000000000000..e4a342e903e2 --- /dev/null +++ b/arch/arm64/kvm/ptdump.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Debug helper used to dump the stage-2 pagetables of the system and their + * associated permissions. + * + * Copyright (C) Google, 2024 + * Author: Sebastian Ene <sebastianene@google.com> + */ +#include <linux/debugfs.h> +#include <linux/kvm_host.h> +#include <linux/seq_file.h> + +#include <asm/kvm_mmu.h> +#include <asm/kvm_pgtable.h> +#include <asm/ptdump.h> + +#define MARKERS_LEN 2 +#define KVM_PGTABLE_MAX_LEVELS (KVM_PGTABLE_LAST_LEVEL + 1) + +struct kvm_ptdump_guest_state { + struct kvm *kvm; + struct ptdump_pg_state parser_state; + struct addr_marker ipa_marker[MARKERS_LEN]; + struct ptdump_pg_level level[KVM_PGTABLE_MAX_LEVELS]; + struct ptdump_range range[MARKERS_LEN]; +}; + +static const struct ptdump_prot_bits stage2_pte_bits[] = { + { + .mask = PTE_VALID, + .val = PTE_VALID, + .set = " ", + .clear = "F", + }, { + .mask = KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | PTE_VALID, + .val = KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | PTE_VALID, + .set = "R", + .clear = " ", + }, { + .mask = KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | PTE_VALID, + .val = KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | PTE_VALID, + .set = "W", + .clear = " ", + }, { + .mask = KVM_PTE_LEAF_ATTR_HI_S2_XN | PTE_VALID, + .val = PTE_VALID, + .set = " ", + .clear = "X", + }, { + .mask = KVM_PTE_LEAF_ATTR_LO_S2_AF | PTE_VALID, + .val = KVM_PTE_LEAF_ATTR_LO_S2_AF | PTE_VALID, + .set = "AF", + .clear = " ", + }, { + .mask = PTE_TABLE_BIT | PTE_VALID, + .val = PTE_VALID, + .set = "BLK", + .clear = " ", + }, +}; + +static int kvm_ptdump_visitor(const struct kvm_pgtable_visit_ctx *ctx, + enum kvm_pgtable_walk_flags visit) +{ + struct ptdump_pg_state *st = ctx->arg; + struct ptdump_state *pt_st = &st->ptdump; + + note_page(pt_st, ctx->addr, ctx->level, ctx->old); + + return 0; +} + +static int kvm_ptdump_build_levels(struct ptdump_pg_level *level, u32 start_lvl) +{ + u32 i; + u64 mask; + + if (WARN_ON_ONCE(start_lvl >= KVM_PGTABLE_LAST_LEVEL)) + return -EINVAL; + + mask = 0; + for (i = 0; i < ARRAY_SIZE(stage2_pte_bits); i++) + mask |= stage2_pte_bits[i].mask; + + for (i = start_lvl; i < KVM_PGTABLE_MAX_LEVELS; i++) { + snprintf(level[i].name, sizeof(level[i].name), "%u", i); + + level[i].num = ARRAY_SIZE(stage2_pte_bits); + level[i].bits = stage2_pte_bits; + level[i].mask = mask; + } + + return 0; +} + +static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm *kvm) +{ + struct kvm_ptdump_guest_state *st; + struct kvm_s2_mmu *mmu = &kvm->arch.mmu; + struct kvm_pgtable *pgtable = mmu->pgt; + int ret; + + st = kzalloc(sizeof(struct kvm_ptdump_guest_state), GFP_KERNEL_ACCOUNT); + if (!st) + return ERR_PTR(-ENOMEM); + + ret = kvm_ptdump_build_levels(&st->level[0], pgtable->start_level); + if (ret) { + kfree(st); + return ERR_PTR(ret); + } + + st->ipa_marker[0].name = "Guest IPA"; + st->ipa_marker[1].start_address = BIT(pgtable->ia_bits); + st->range[0].end = BIT(pgtable->ia_bits); + + st->kvm = kvm; + st->parser_state = (struct ptdump_pg_state) { + .marker = &st->ipa_marker[0], + .level = -1, + .pg_level = &st->level[0], + .ptdump.range = &st->range[0], + .start_address = 0, + }; + + return st; +} + +static int kvm_ptdump_guest_show(struct seq_file *m, void *unused) +{ + int ret; + struct kvm_ptdump_guest_state *st = m->private; + struct kvm *kvm = st->kvm; + struct kvm_s2_mmu *mmu = &kvm->arch.mmu; + struct ptdump_pg_state *parser_state = &st->parser_state; + struct kvm_pgtable_walker walker = (struct kvm_pgtable_walker) { + .cb = kvm_ptdump_visitor, + .arg = parser_state, + .flags = KVM_PGTABLE_WALK_LEAF, + }; + + parser_state->seq = m; + + write_lock(&kvm->mmu_lock); + ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker); + write_unlock(&kvm->mmu_lock); + + return ret; +} + +static int kvm_ptdump_guest_open(struct inode *m, struct file *file) +{ + struct kvm *kvm = m->i_private; + struct kvm_ptdump_guest_state *st; + int ret; + + if (!kvm_get_kvm_safe(kvm)) + return -ENOENT; + + st = kvm_ptdump_parser_create(kvm); + if (IS_ERR(st)) { + ret = PTR_ERR(st); + goto err_with_kvm_ref; + } + + ret = single_open(file, kvm_ptdump_guest_show, st); + if (!ret) + return 0; + + kfree(st); +err_with_kvm_ref: + kvm_put_kvm(kvm); + return ret; +} + +static int kvm_ptdump_guest_close(struct inode *m, struct file *file) +{ + struct kvm *kvm = m->i_private; + void *st = ((struct seq_file *)file->private_data)->private; + + kfree(st); + kvm_put_kvm(kvm); + + return single_release(m, file); +} + +static const struct file_operations kvm_ptdump_guest_fops = { + .open = kvm_ptdump_guest_open, + .read = seq_read, + .llseek = seq_lseek, + .release = kvm_ptdump_guest_close, +}; + +static int kvm_pgtable_range_show(struct seq_file *m, void *unused) +{ + struct kvm_pgtable *pgtable = m->private; + + seq_printf(m, "%2u\n", pgtable->ia_bits); + return 0; +} + +static int kvm_pgtable_levels_show(struct seq_file *m, void *unused) +{ + struct kvm_pgtable *pgtable = m->private; + + seq_printf(m, "%1d\n", KVM_PGTABLE_MAX_LEVELS - pgtable->start_level); + return 0; +} + +static int kvm_pgtable_debugfs_open(struct inode *m, struct file *file, + int (*show)(struct seq_file *, void *)) +{ + struct kvm *kvm = m->i_private; + struct kvm_pgtable *pgtable; + int ret; + + if (!kvm_get_kvm_safe(kvm)) + return -ENOENT; + + pgtable = kvm->arch.mmu.pgt; + + ret = single_open(file, show, pgtable); + if (ret < 0) + kvm_put_kvm(kvm); + return ret; +} + +static int kvm_pgtable_range_open(struct inode *m, struct file *file) +{ + return kvm_pgtable_debugfs_open(m, file, kvm_pgtable_range_show); +} + +static int kvm_pgtable_levels_open(struct inode *m, struct file *file) +{ + return kvm_pgtable_debugfs_open(m, file, kvm_pgtable_levels_show); +} + +static int kvm_pgtable_debugfs_close(struct inode *m, struct file *file) +{ + struct kvm *kvm = m->i_private; + + kvm_put_kvm(kvm); + return single_release(m, file); +} + +static const struct file_operations kvm_pgtable_range_fops = { + .open = kvm_pgtable_range_open, + .read = seq_read, + .llseek = seq_lseek, + .release = kvm_pgtable_debugfs_close, +}; + +static const struct file_operations kvm_pgtable_levels_fops = { + .open = kvm_pgtable_levels_open, + .read = seq_read, + .llseek = seq_lseek, + .release = kvm_pgtable_debugfs_close, +}; + +void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) +{ + debugfs_create_file("stage2_page_tables", 0400, kvm->debugfs_dentry, + kvm, &kvm_ptdump_guest_fops); + debugfs_create_file("ipa_range", 0400, kvm->debugfs_dentry, kvm, + &kvm_pgtable_range_fops); + debugfs_create_file("stage2_levels", 0400, kvm->debugfs_dentry, + kvm, &kvm_pgtable_levels_fops); +} diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 31e49da867ff..ff8c4e1b847e 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -18,6 +18,7 @@ #include <linux/printk.h> #include <linux/uaccess.h> +#include <asm/arm_pmuv3.h> #include <asm/cacheflush.h> #include <asm/cputype.h> #include <asm/debug-monitors.h> @@ -47,6 +48,13 @@ static u64 sys_reg_to_index(const struct sys_reg_desc *reg); static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 val); +static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + kvm_inject_undefined(vcpu); + return false; +} + static bool bad_trap(struct kvm_vcpu *vcpu, struct sys_reg_params *params, const struct sys_reg_desc *r, @@ -54,8 +62,7 @@ static bool bad_trap(struct kvm_vcpu *vcpu, { WARN_ONCE(1, "Unexpected %s\n", msg); print_sys_reg_instr(params); - kvm_inject_undefined(vcpu); - return false; + return undef_access(vcpu, params, r); } static bool read_from_write_only(struct kvm_vcpu *vcpu, @@ -346,10 +353,8 @@ static bool access_dcgsw(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - if (!kvm_has_mte(vcpu->kvm)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_has_mte(vcpu->kvm)) + return undef_access(vcpu, p, r); /* Treat MTE S/W ops as we treat the classic ones: with contempt */ return access_dcsw(vcpu, p, r); @@ -386,10 +391,8 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu, u64 val, mask, shift; if (reg_to_encoding(r) == SYS_TCR2_EL1 && - !kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) { - kvm_inject_undefined(vcpu); - return false; - } + !kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) + return undef_access(vcpu, p, r); BUG_ON(!p->is_write); @@ -436,10 +439,8 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu, { bool g1; - if (!kvm_has_gicv3(vcpu->kvm)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_has_gicv3(vcpu->kvm)) + return undef_access(vcpu, p, r); if (!p->is_write) return read_from_write_only(vcpu, p, r); @@ -484,6 +485,9 @@ static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { + if (!kvm_has_gicv3(vcpu->kvm)) + return undef_access(vcpu, p, r); + if (p->is_write) return ignore_write(vcpu, p); @@ -501,14 +505,6 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, return read_zero(vcpu, p); } -static bool trap_undef(struct kvm_vcpu *vcpu, - struct sys_reg_params *p, - const struct sys_reg_desc *r) -{ - kvm_inject_undefined(vcpu); - return false; -} - /* * ARMv8.1 mandates at least a trivial LORegion implementation, where all the * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0 @@ -521,10 +517,8 @@ static bool trap_loregion(struct kvm_vcpu *vcpu, { u32 sr = reg_to_encoding(r); - if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, LO, IMP)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR1_EL1, LO, IMP)) + return undef_access(vcpu, p, r); if (p->is_write && sr == SYS_LORID_EL1) return write_to_read_only(vcpu, p, r); @@ -893,7 +887,7 @@ static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= ARMV8_PMU_COUNTER_MASK; + __vcpu_sys_reg(vcpu, r->reg) &= PMSELR_EL0_SEL_MASK; return __vcpu_sys_reg(vcpu, r->reg); } @@ -985,7 +979,7 @@ static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, else /* return PMSELR.SEL field */ p->regval = __vcpu_sys_reg(vcpu, PMSELR_EL0) - & ARMV8_PMU_COUNTER_MASK; + & PMSELR_EL0_SEL_MASK; return true; } @@ -1053,8 +1047,8 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu, if (pmu_access_event_counter_el0_disabled(vcpu)) return false; - idx = __vcpu_sys_reg(vcpu, PMSELR_EL0) - & ARMV8_PMU_COUNTER_MASK; + idx = SYS_FIELD_GET(PMSELR_EL0, SEL, + __vcpu_sys_reg(vcpu, PMSELR_EL0)); } else if (r->Op2 == 0) { /* PMCCNTR_EL0 */ if (pmu_access_cycle_counter_el0_disabled(vcpu)) @@ -1104,7 +1098,7 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 1) { /* PMXEVTYPER_EL0 */ - idx = __vcpu_sys_reg(vcpu, PMSELR_EL0) & ARMV8_PMU_COUNTER_MASK; + idx = SYS_FIELD_GET(PMSELR_EL0, SEL, __vcpu_sys_reg(vcpu, PMSELR_EL0)); reg = PMEVTYPER0_EL0 + idx; } else if (r->CRn == 14 && (r->CRm & 12) == 12) { idx = ((r->CRm & 3) << 3) | (r->Op2 & 7); @@ -1257,10 +1251,8 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { if (p->is_write) { - if (!vcpu_mode_priv(vcpu)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!vcpu_mode_priv(vcpu)) + return undef_access(vcpu, p, r); __vcpu_sys_reg(vcpu, PMUSERENR_EL0) = p->regval & ARMV8_PMU_USERENR_MASK; @@ -1344,14 +1336,6 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, .reset = reset_pmevtyper, \ .access = access_pmu_evtyper, .reg = (PMEVTYPER0_EL0 + n), } -static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p, - const struct sys_reg_desc *r) -{ - kvm_inject_undefined(vcpu); - - return false; -} - /* Macro to expand the AMU counter and type registers*/ #define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), undef_access } #define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), undef_access } @@ -1410,8 +1394,7 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, break; default: print_sys_reg_msg(p, "%s", "Unhandled trapped timer register"); - kvm_inject_undefined(vcpu); - return false; + return undef_access(vcpu, p, r); } if (p->is_write) @@ -1544,6 +1527,18 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu, val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE); val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_DF2); + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR); + break; + case SYS_ID_AA64PFR2_EL1: + /* We only expose FPMR */ + val &= ID_AA64PFR2_EL1_FPMR; break; case SYS_ID_AA64ISAR1_EL1: if (!vcpu_has_ptrauth(vcpu)) @@ -1562,6 +1557,10 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu, case SYS_ID_AA64MMFR2_EL1: val &= ~ID_AA64MMFR2_EL1_CCIDX_MASK; break; + case SYS_ID_AA64MMFR3_EL1: + val &= ID_AA64MMFR3_EL1_TCRX | ID_AA64MMFR3_EL1_S1POE | + ID_AA64MMFR3_EL1_S1PIE; + break; case SYS_ID_MMFR4_EL1: val &= ~ARM64_FEATURE_MASK(ID_MMFR4_EL1_CCIDX); break; @@ -1675,6 +1674,24 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu, return REG_HIDDEN; } +static unsigned int sme_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SME, IMP)) + return 0; + + return REG_HIDDEN; +} + +static unsigned int fp8_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + if (kvm_has_fpmr(vcpu->kvm)) + return 0; + + return REG_HIDDEN; +} + static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { @@ -1977,7 +1994,7 @@ static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) * one cache line. */ if (kvm_has_mte(vcpu->kvm)) - clidr |= 2 << CLIDR_TTYPE_SHIFT(loc); + clidr |= 2ULL << CLIDR_TTYPE_SHIFT(loc); __vcpu_sys_reg(vcpu, r->reg) = clidr; @@ -2091,26 +2108,6 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu, #define EL2_REG_REDIR(name, rst, v) EL2_REG(name, bad_redir_trap, rst, v) /* - * EL{0,1}2 registers are the EL2 view on an EL0 or EL1 register when - * HCR_EL2.E2H==1, and only in the sysreg table for convenience of - * handling traps. Given that, they are always hidden from userspace. - */ -static unsigned int hidden_user_visibility(const struct kvm_vcpu *vcpu, - const struct sys_reg_desc *rd) -{ - return REG_HIDDEN_USER; -} - -#define EL12_REG(name, acc, rst, v) { \ - SYS_DESC(SYS_##name##_EL12), \ - .access = acc, \ - .reset = rst, \ - .reg = name##_EL1, \ - .val = v, \ - .visibility = hidden_user_visibility, \ -} - -/* * Since reset() callback and field val are not used for idregs, they will be * used for specific purposes for idregs. * The reset() would return KVM sanitised register value. The value would be the @@ -2217,6 +2214,18 @@ static bool access_spsr(struct kvm_vcpu *vcpu, return true; } +static bool access_cntkctl_el12(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + if (p->is_write) + __vcpu_sys_reg(vcpu, CNTKCTL_EL1) = p->regval; + else + p->regval = __vcpu_sys_reg(vcpu, CNTKCTL_EL1); + + return true; +} + static u64 reset_hcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 val = r->val; @@ -2261,6 +2270,15 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu, return true; } +static unsigned int s1poe_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S1POE, IMP)) + return 0; + + return REG_HIDDEN; +} + /* * Architected system registers. * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2 @@ -2307,7 +2325,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { // DBGDTR[TR]X_EL0 share the same encoding { SYS_DESC(SYS_DBGDTRTX_EL0), trap_raz_wi }, - { SYS_DESC(SYS_DBGVCR32_EL2), trap_undef, reset_val, DBGVCR32_EL2, 0 }, + { SYS_DESC(SYS_DBGVCR32_EL2), undef_access, reset_val, DBGVCR32_EL2, 0 }, { SYS_DESC(SYS_MPIDR_EL1), NULL, reset_mpidr, MPIDR_EL1 }, @@ -2365,16 +2383,27 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_AA64PFR0_EL1_MPAM | ID_AA64PFR0_EL1_SVE | ID_AA64PFR0_EL1_RAS | - ID_AA64PFR0_EL1_GIC | ID_AA64PFR0_EL1_AdvSIMD | ID_AA64PFR0_EL1_FP), }, - ID_SANITISED(ID_AA64PFR1_EL1), - ID_UNALLOCATED(4,2), + ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_PFAR | + ID_AA64PFR1_EL1_DF2 | + ID_AA64PFR1_EL1_MTEX | + ID_AA64PFR1_EL1_THE | + ID_AA64PFR1_EL1_GCS | + ID_AA64PFR1_EL1_MTE_frac | + ID_AA64PFR1_EL1_NMI | + ID_AA64PFR1_EL1_RNDR_trap | + ID_AA64PFR1_EL1_SME | + ID_AA64PFR1_EL1_RES0 | + ID_AA64PFR1_EL1_MPAM_frac | + ID_AA64PFR1_EL1_RAS_frac | + ID_AA64PFR1_EL1_MTE)), + ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR), ID_UNALLOCATED(4,3), ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), ID_HIDDEN(ID_AA64SMFR0_EL1), ID_UNALLOCATED(4,6), - ID_UNALLOCATED(4,7), + ID_WRITABLE(ID_AA64FPFR0_EL1, ~ID_AA64FPFR0_EL1_RES0), /* CRm=5 */ { SYS_DESC(SYS_ID_AA64DFR0_EL1), @@ -2382,7 +2411,21 @@ static const struct sys_reg_desc sys_reg_descs[] = { .get_user = get_id_reg, .set_user = set_id_aa64dfr0_el1, .reset = read_sanitised_id_aa64dfr0_el1, - .val = ID_AA64DFR0_EL1_PMUVer_MASK | + /* + * Prior to FEAT_Debugv8.9, the architecture defines context-aware + * breakpoints (CTX_CMPs) as the highest numbered breakpoints (BRPs). + * KVM does not trap + emulate the breakpoint registers, and as such + * cannot support a layout that misaligns with the underlying hardware. + * While it may be possible to describe a subset that aligns with + * hardware, just prevent changes to BRPs and CTX_CMPs altogether for + * simplicity. + * + * See DDI0487K.a, section D2.8.3 Breakpoint types and linking + * of breakpoints for more details. + */ + .val = ID_AA64DFR0_EL1_DoubleLock_MASK | + ID_AA64DFR0_EL1_WRPs_MASK | + ID_AA64DFR0_EL1_PMUVer_MASK | ID_AA64DFR0_EL1_DebugVer_MASK, }, ID_SANITISED(ID_AA64DFR1_EL1), ID_UNALLOCATED(5,2), @@ -2424,7 +2467,9 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_AA64MMFR2_EL1_IDS | ID_AA64MMFR2_EL1_NV | ID_AA64MMFR2_EL1_CCIDX)), - ID_SANITISED(ID_AA64MMFR3_EL1), + ID_WRITABLE(ID_AA64MMFR3_EL1, (ID_AA64MMFR3_EL1_TCRX | + ID_AA64MMFR3_EL1_S1PIE | + ID_AA64MMFR3_EL1_S1POE)), ID_SANITISED(ID_AA64MMFR4_EL1), ID_UNALLOCATED(7,5), ID_UNALLOCATED(7,6), @@ -2455,6 +2500,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_SPSR_EL1), access_spsr}, { SYS_DESC(SYS_ELR_EL1), access_elr}, + { SYS_DESC(SYS_ICC_PMR_EL1), undef_access }, + { SYS_DESC(SYS_AFSR0_EL1), access_vm_reg, reset_unknown, AFSR0_EL1 }, { SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 }, { SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 }, @@ -2498,6 +2545,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 }, { SYS_DESC(SYS_PIRE0_EL1), NULL, reset_unknown, PIRE0_EL1 }, { SYS_DESC(SYS_PIR_EL1), NULL, reset_unknown, PIR_EL1 }, + { SYS_DESC(SYS_POR_EL1), NULL, reset_unknown, POR_EL1, + .visibility = s1poe_visibility }, { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 }, { SYS_DESC(SYS_LORSA_EL1), trap_loregion }, @@ -2509,18 +2558,31 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_VBAR_EL1), access_rw, reset_val, VBAR_EL1, 0 }, { SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 }, - { SYS_DESC(SYS_ICC_IAR0_EL1), write_to_read_only }, - { SYS_DESC(SYS_ICC_EOIR0_EL1), read_from_write_only }, - { SYS_DESC(SYS_ICC_HPPIR0_EL1), write_to_read_only }, - { SYS_DESC(SYS_ICC_DIR_EL1), read_from_write_only }, - { SYS_DESC(SYS_ICC_RPR_EL1), write_to_read_only }, + { SYS_DESC(SYS_ICC_IAR0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_EOIR0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_HPPIR0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_BPR0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP0R0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP0R1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP0R2_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP0R3_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP1R0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP1R1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP1R2_EL1), undef_access }, + { SYS_DESC(SYS_ICC_AP1R3_EL1), undef_access }, + { SYS_DESC(SYS_ICC_DIR_EL1), undef_access }, + { SYS_DESC(SYS_ICC_RPR_EL1), undef_access }, { SYS_DESC(SYS_ICC_SGI1R_EL1), access_gic_sgi }, { SYS_DESC(SYS_ICC_ASGI1R_EL1), access_gic_sgi }, { SYS_DESC(SYS_ICC_SGI0R_EL1), access_gic_sgi }, - { SYS_DESC(SYS_ICC_IAR1_EL1), write_to_read_only }, - { SYS_DESC(SYS_ICC_EOIR1_EL1), read_from_write_only }, - { SYS_DESC(SYS_ICC_HPPIR1_EL1), write_to_read_only }, + { SYS_DESC(SYS_ICC_IAR1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_EOIR1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_HPPIR1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_BPR1_EL1), undef_access }, + { SYS_DESC(SYS_ICC_CTLR_EL1), undef_access }, { SYS_DESC(SYS_ICC_SRE_EL1), access_gic_sre }, + { SYS_DESC(SYS_ICC_IGRPEN0_EL1), undef_access }, + { SYS_DESC(SYS_ICC_IGRPEN1_EL1), undef_access }, { SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 }, { SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 }, @@ -2541,7 +2603,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { CTR_EL0_IDC_MASK | CTR_EL0_DminLine_MASK | CTR_EL0_IminLine_MASK), - { SYS_DESC(SYS_SVCR), undef_access }, + { SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility = sme_visibility }, + { SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility = fp8_visibility }, { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr, .reg = PMCR_EL0, .get_user = get_pmcr, .set_user = set_pmcr }, @@ -2584,6 +2647,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { .access = access_pmovs, .reg = PMOVSSET_EL0, .get_user = get_pmreg, .set_user = set_pmreg }, + { SYS_DESC(SYS_POR_EL0), NULL, reset_unknown, POR_EL0, + .visibility = s1poe_visibility }, { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 }, { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 }, { SYS_DESC(SYS_TPIDR2_EL0), undef_access }, @@ -2764,7 +2829,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { EL2_REG_VNCR(VTTBR_EL2, reset_val, 0), EL2_REG_VNCR(VTCR_EL2, reset_val, 0), - { SYS_DESC(SYS_DACR32_EL2), trap_undef, reset_unknown, DACR32_EL2 }, + { SYS_DESC(SYS_DACR32_EL2), undef_access, reset_unknown, DACR32_EL2 }, EL2_REG_VNCR(HDFGRTR_EL2, reset_val, 0), EL2_REG_VNCR(HDFGWTR_EL2, reset_val, 0), EL2_REG_VNCR(HAFGRTR_EL2, reset_val, 0), @@ -2773,20 +2838,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_SP_EL1), access_sp_el1}, /* AArch32 SPSR_* are RES0 if trapped from a NV guest */ - { SYS_DESC(SYS_SPSR_irq), .access = trap_raz_wi, - .visibility = hidden_user_visibility }, - { SYS_DESC(SYS_SPSR_abt), .access = trap_raz_wi, - .visibility = hidden_user_visibility }, - { SYS_DESC(SYS_SPSR_und), .access = trap_raz_wi, - .visibility = hidden_user_visibility }, - { SYS_DESC(SYS_SPSR_fiq), .access = trap_raz_wi, - .visibility = hidden_user_visibility }, - - { SYS_DESC(SYS_IFSR32_EL2), trap_undef, reset_unknown, IFSR32_EL2 }, + { SYS_DESC(SYS_SPSR_irq), .access = trap_raz_wi }, + { SYS_DESC(SYS_SPSR_abt), .access = trap_raz_wi }, + { SYS_DESC(SYS_SPSR_und), .access = trap_raz_wi }, + { SYS_DESC(SYS_SPSR_fiq), .access = trap_raz_wi }, + + { SYS_DESC(SYS_IFSR32_EL2), undef_access, reset_unknown, IFSR32_EL2 }, EL2_REG(AFSR0_EL2, access_rw, reset_val, 0), EL2_REG(AFSR1_EL2, access_rw, reset_val, 0), EL2_REG_REDIR(ESR_EL2, reset_val, 0), - { SYS_DESC(SYS_FPEXC32_EL2), trap_undef, reset_val, FPEXC32_EL2, 0x700 }, + { SYS_DESC(SYS_FPEXC32_EL2), undef_access, reset_val, FPEXC32_EL2, 0x700 }, EL2_REG_REDIR(FAR_EL2, reset_val, 0), EL2_REG(HPFAR_EL2, access_rw, reset_val, 0), @@ -2796,7 +2857,9 @@ static const struct sys_reg_desc sys_reg_descs[] = { EL2_REG(VBAR_EL2, access_rw, reset_val, 0), EL2_REG(RVBAR_EL2, access_rw, reset_val, 0), - { SYS_DESC(SYS_RMR_EL2), trap_undef }, + { SYS_DESC(SYS_RMR_EL2), undef_access }, + + EL2_REG_VNCR(ICH_HCR_EL2, reset_val, 0), EL2_REG(CONTEXTIDR_EL2, access_rw, reset_val, 0), EL2_REG(TPIDR_EL2, access_rw, reset_val, 0), @@ -2804,11 +2867,48 @@ static const struct sys_reg_desc sys_reg_descs[] = { EL2_REG_VNCR(CNTVOFF_EL2, reset_val, 0), EL2_REG(CNTHCTL_EL2, access_rw, reset_val, 0), - EL12_REG(CNTKCTL, access_rw, reset_val, 0), + { SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 }, EL2_REG(SP_EL2, NULL, reset_unknown, 0), }; +static bool handle_at_s1e01(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); + + __kvm_at_s1e01(vcpu, op, p->regval); + + return true; +} + +static bool handle_at_s1e2(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); + + /* There is no FGT associated with AT S1E2A :-( */ + if (op == OP_AT_S1E2A && + !kvm_has_feat(vcpu->kvm, ID_AA64ISAR2_EL1, ATS1A, IMP)) { + kvm_inject_undefined(vcpu); + return false; + } + + __kvm_at_s1e2(vcpu, op, p->regval); + + return true; +} + +static bool handle_at_s12(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + u32 op = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); + + __kvm_at_s12(vcpu, op, p->regval); + + return true; +} + static bool kvm_supported_tlbi_s12_op(struct kvm_vcpu *vpcu, u32 instr) { struct kvm *kvm = vpcu->kvm; @@ -2830,10 +2930,8 @@ static bool handle_alle1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, { u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); - if (!kvm_supported_tlbi_s12_op(vcpu, sys_encoding)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_supported_tlbi_s12_op(vcpu, sys_encoding)) + return undef_access(vcpu, p, r); write_lock(&vcpu->kvm->mmu_lock); @@ -2841,7 +2939,7 @@ static bool handle_alle1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, * Drop all shadow S2s, resulting in S1/S2 TLBIs for each of the * corresponding VMIDs. */ - kvm_nested_s2_unmap(vcpu->kvm); + kvm_nested_s2_unmap(vcpu->kvm, true); write_unlock(&vcpu->kvm->mmu_lock); @@ -2893,7 +2991,30 @@ union tlbi_info { static void s2_mmu_unmap_range(struct kvm_s2_mmu *mmu, const union tlbi_info *info) { - kvm_stage2_unmap_range(mmu, info->range.start, info->range.size); + /* + * The unmap operation is allowed to drop the MMU lock and block, which + * means that @mmu could be used for a different context than the one + * currently being invalidated. + * + * This behavior is still safe, as: + * + * 1) The vCPU(s) that recycled the MMU are responsible for invalidating + * the entire MMU before reusing it, which still honors the intent + * of a TLBI. + * + * 2) Until the guest TLBI instruction is 'retired' (i.e. increment PC + * and ERET to the guest), other vCPUs are allowed to use stale + * translations. + * + * 3) Accidentally unmapping an unrelated MMU context is nonfatal, and + * at worst may cause more aborts for shadow stage-2 fills. + * + * Dropping the MMU lock also implies that shadow stage-2 fills could + * happen behind the back of the TLBI. This is still safe, though, as + * the L1 needs to put its stage-2 in a consistent state before doing + * the TLBI. + */ + kvm_stage2_unmap_range(mmu, info->range.start, info->range.size, true); } static bool handle_vmalls12e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, @@ -2902,10 +3023,8 @@ static bool handle_vmalls12e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); u64 limit, vttbr; - if (!kvm_supported_tlbi_s12_op(vcpu, sys_encoding)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_supported_tlbi_s12_op(vcpu, sys_encoding)) + return undef_access(vcpu, p, r); vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2); limit = BIT_ULL(kvm_get_pa_bits(vcpu->kvm)); @@ -2930,10 +3049,8 @@ static bool handle_ripas2e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, u64 base, range, tg, num, scale; int shift; - if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) + return undef_access(vcpu, p, r); /* * Because the shadow S2 structure doesn't necessarily reflect that @@ -2992,7 +3109,11 @@ static void s2_mmu_unmap_ipa(struct kvm_s2_mmu *mmu, max_size = compute_tlb_inval_range(mmu, info->ipa.addr); base_addr &= ~(max_size - 1); - kvm_stage2_unmap_range(mmu, base_addr, max_size); + /* + * See comment in s2_mmu_unmap_range() for why this is allowed to + * reschedule. + */ + kvm_stage2_unmap_range(mmu, base_addr, max_size, true); } static bool handle_ipas2e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, @@ -3001,10 +3122,8 @@ static bool handle_ipas2e1is(struct kvm_vcpu *vcpu, struct sys_reg_params *p, u32 sys_encoding = sys_insn(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); u64 vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2); - if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_supported_tlbi_ipas2_op(vcpu, sys_encoding)) + return undef_access(vcpu, p, r); kvm_s2_mmu_iterate_by_vmid(vcpu->kvm, get_vmid(vttbr), &(union tlbi_info) { @@ -3044,10 +3163,8 @@ static bool handle_tlbi_el1(struct kvm_vcpu *vcpu, struct sys_reg_params *p, WARN_ON(!vcpu_is_el2(vcpu)); - if (!kvm_supported_tlbi_s1e1_op(vcpu, sys_encoding)) { - kvm_inject_undefined(vcpu); - return false; - } + if (!kvm_supported_tlbi_s1e1_op(vcpu, sys_encoding)) + return undef_access(vcpu, p, r); kvm_s2_mmu_iterate_by_vmid(vcpu->kvm, get_vmid(vttbr), &(union tlbi_info) { @@ -3071,6 +3188,14 @@ static struct sys_reg_desc sys_insn_descs[] = { { SYS_DESC(SYS_DC_ISW), access_dcsw }, { SYS_DESC(SYS_DC_IGSW), access_dcgsw }, { SYS_DESC(SYS_DC_IGDSW), access_dcgsw }, + + SYS_INSN(AT_S1E1R, handle_at_s1e01), + SYS_INSN(AT_S1E1W, handle_at_s1e01), + SYS_INSN(AT_S1E0R, handle_at_s1e01), + SYS_INSN(AT_S1E0W, handle_at_s1e01), + SYS_INSN(AT_S1E1RP, handle_at_s1e01), + SYS_INSN(AT_S1E1WP, handle_at_s1e01), + { SYS_DESC(SYS_DC_CSW), access_dcsw }, { SYS_DESC(SYS_DC_CGSW), access_dcgsw }, { SYS_DESC(SYS_DC_CGDSW), access_dcgsw }, @@ -3150,19 +3275,27 @@ static struct sys_reg_desc sys_insn_descs[] = { SYS_INSN(TLBI_VALE1NXS, handle_tlbi_el1), SYS_INSN(TLBI_VAALE1NXS, handle_tlbi_el1), + SYS_INSN(AT_S1E2R, handle_at_s1e2), + SYS_INSN(AT_S1E2W, handle_at_s1e2), + SYS_INSN(AT_S12E1R, handle_at_s12), + SYS_INSN(AT_S12E1W, handle_at_s12), + SYS_INSN(AT_S12E0R, handle_at_s12), + SYS_INSN(AT_S12E0W, handle_at_s12), + SYS_INSN(AT_S1E2A, handle_at_s1e2), + SYS_INSN(TLBI_IPAS2E1IS, handle_ipas2e1is), SYS_INSN(TLBI_RIPAS2E1IS, handle_ripas2e1is), SYS_INSN(TLBI_IPAS2LE1IS, handle_ipas2e1is), SYS_INSN(TLBI_RIPAS2LE1IS, handle_ripas2e1is), - SYS_INSN(TLBI_ALLE2OS, trap_undef), - SYS_INSN(TLBI_VAE2OS, trap_undef), + SYS_INSN(TLBI_ALLE2OS, undef_access), + SYS_INSN(TLBI_VAE2OS, undef_access), SYS_INSN(TLBI_ALLE1OS, handle_alle1is), - SYS_INSN(TLBI_VALE2OS, trap_undef), + SYS_INSN(TLBI_VALE2OS, undef_access), SYS_INSN(TLBI_VMALLS12E1OS, handle_vmalls12e1is), - SYS_INSN(TLBI_RVAE2IS, trap_undef), - SYS_INSN(TLBI_RVALE2IS, trap_undef), + SYS_INSN(TLBI_RVAE2IS, undef_access), + SYS_INSN(TLBI_RVALE2IS, undef_access), SYS_INSN(TLBI_ALLE1IS, handle_alle1is), SYS_INSN(TLBI_VMALLS12E1IS, handle_vmalls12e1is), @@ -3174,10 +3307,10 @@ static struct sys_reg_desc sys_insn_descs[] = { SYS_INSN(TLBI_IPAS2LE1, handle_ipas2e1is), SYS_INSN(TLBI_RIPAS2LE1, handle_ripas2e1is), SYS_INSN(TLBI_RIPAS2LE1OS, handle_ripas2e1is), - SYS_INSN(TLBI_RVAE2OS, trap_undef), - SYS_INSN(TLBI_RVALE2OS, trap_undef), - SYS_INSN(TLBI_RVAE2, trap_undef), - SYS_INSN(TLBI_RVALE2, trap_undef), + SYS_INSN(TLBI_RVAE2OS, undef_access), + SYS_INSN(TLBI_RVALE2OS, undef_access), + SYS_INSN(TLBI_RVAE2, undef_access), + SYS_INSN(TLBI_RVALE2, undef_access), SYS_INSN(TLBI_ALLE1, handle_alle1is), SYS_INSN(TLBI_VMALLS12E1, handle_vmalls12e1is), @@ -3186,19 +3319,19 @@ static struct sys_reg_desc sys_insn_descs[] = { SYS_INSN(TLBI_IPAS2LE1ISNXS, handle_ipas2e1is), SYS_INSN(TLBI_RIPAS2LE1ISNXS, handle_ripas2e1is), - SYS_INSN(TLBI_ALLE2OSNXS, trap_undef), - SYS_INSN(TLBI_VAE2OSNXS, trap_undef), + SYS_INSN(TLBI_ALLE2OSNXS, undef_access), + SYS_INSN(TLBI_VAE2OSNXS, undef_access), SYS_INSN(TLBI_ALLE1OSNXS, handle_alle1is), - SYS_INSN(TLBI_VALE2OSNXS, trap_undef), + SYS_INSN(TLBI_VALE2OSNXS, undef_access), SYS_INSN(TLBI_VMALLS12E1OSNXS, handle_vmalls12e1is), - SYS_INSN(TLBI_RVAE2ISNXS, trap_undef), - SYS_INSN(TLBI_RVALE2ISNXS, trap_undef), - SYS_INSN(TLBI_ALLE2ISNXS, trap_undef), - SYS_INSN(TLBI_VAE2ISNXS, trap_undef), + SYS_INSN(TLBI_RVAE2ISNXS, undef_access), + SYS_INSN(TLBI_RVALE2ISNXS, undef_access), + SYS_INSN(TLBI_ALLE2ISNXS, undef_access), + SYS_INSN(TLBI_VAE2ISNXS, undef_access), SYS_INSN(TLBI_ALLE1ISNXS, handle_alle1is), - SYS_INSN(TLBI_VALE2ISNXS, trap_undef), + SYS_INSN(TLBI_VALE2ISNXS, undef_access), SYS_INSN(TLBI_VMALLS12E1ISNXS, handle_vmalls12e1is), SYS_INSN(TLBI_IPAS2E1OSNXS, handle_ipas2e1is), SYS_INSN(TLBI_IPAS2E1NXS, handle_ipas2e1is), @@ -3208,14 +3341,14 @@ static struct sys_reg_desc sys_insn_descs[] = { SYS_INSN(TLBI_IPAS2LE1NXS, handle_ipas2e1is), SYS_INSN(TLBI_RIPAS2LE1NXS, handle_ripas2e1is), SYS_INSN(TLBI_RIPAS2LE1OSNXS, handle_ripas2e1is), - SYS_INSN(TLBI_RVAE2OSNXS, trap_undef), - SYS_INSN(TLBI_RVALE2OSNXS, trap_undef), - SYS_INSN(TLBI_RVAE2NXS, trap_undef), - SYS_INSN(TLBI_RVALE2NXS, trap_undef), - SYS_INSN(TLBI_ALLE2NXS, trap_undef), - SYS_INSN(TLBI_VAE2NXS, trap_undef), + SYS_INSN(TLBI_RVAE2OSNXS, undef_access), + SYS_INSN(TLBI_RVALE2OSNXS, undef_access), + SYS_INSN(TLBI_RVAE2NXS, undef_access), + SYS_INSN(TLBI_RVALE2NXS, undef_access), + SYS_INSN(TLBI_ALLE2NXS, undef_access), + SYS_INSN(TLBI_VAE2NXS, undef_access), SYS_INSN(TLBI_ALLE1NXS, handle_alle1is), - SYS_INSN(TLBI_VALE2NXS, trap_undef), + SYS_INSN(TLBI_VALE2NXS, undef_access), SYS_INSN(TLBI_VMALLS12E1NXS, handle_vmalls12e1is), }; @@ -3393,6 +3526,7 @@ static const struct sys_reg_desc cp15_regs[] = { /* TTBCR2 */ { AA32(HI), Op1( 0), CRn( 2), CRm( 0), Op2( 3), access_vm_reg, NULL, TCR_EL1 }, { Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, DACR32_EL2 }, + { CP15_SYS_DESC(SYS_ICC_PMR_EL1), undef_access }, /* DFSR */ { Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, ESR_EL1 }, { Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, IFSR32_EL2 }, @@ -3442,8 +3576,28 @@ static const struct sys_reg_desc cp15_regs[] = { /* AMAIR1 */ { AA32(HI), Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, AMAIR_EL1 }, - /* ICC_SRE */ - { Op1( 0), CRn(12), CRm(12), Op2( 5), access_gic_sre }, + { CP15_SYS_DESC(SYS_ICC_IAR0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_EOIR0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_HPPIR0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_BPR0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP0R0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP0R1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP0R2_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP0R3_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP1R0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP1R1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP1R2_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_AP1R3_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_DIR_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_RPR_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_IAR1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_EOIR1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_HPPIR1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_BPR1_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_CTLR_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_SRE_EL1), access_gic_sre }, + { CP15_SYS_DESC(SYS_ICC_IGRPEN0_EL1), undef_access }, + { CP15_SYS_DESC(SYS_ICC_IGRPEN1_EL1), undef_access }, { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, CONTEXTIDR_EL1 }, @@ -4280,7 +4434,7 @@ int kvm_sys_reg_get_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, int ret; r = id_to_sys_reg_desc(vcpu, reg->id, table, num); - if (!r || sysreg_hidden_user(vcpu, r)) + if (!r || sysreg_hidden(vcpu, r)) return -ENOENT; if (r->get_user) { @@ -4324,7 +4478,7 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, return -EFAULT; r = id_to_sys_reg_desc(vcpu, reg->id, table, num); - if (!r || sysreg_hidden_user(vcpu, r)) + if (!r || sysreg_hidden(vcpu, r)) return -ENOENT; if (sysreg_user_write_ignore(vcpu, r)) @@ -4410,7 +4564,7 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu, if (!(rd->reg || rd->get_user)) return 0; - if (sysreg_hidden_user(vcpu, rd)) + if (sysreg_hidden(vcpu, rd)) return 0; if (!copy_reg_to_user(rd, uind)) @@ -4551,6 +4705,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) mutex_lock(&kvm->arch.config_lock); vcpu_set_hcr(vcpu); + vcpu_set_ich_hcr(vcpu); if (cpus_have_final_cap(ARM64_HAS_HCX)) { /* @@ -4566,6 +4721,9 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En; + + if (kvm_has_fpmr(kvm)) + vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM; } if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags)) @@ -4574,8 +4732,6 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) kvm->arch.fgu[HFGxTR_GROUP] = (HFGxTR_EL2_nAMAIR2_EL1 | HFGxTR_EL2_nMAIR2_EL1 | HFGxTR_EL2_nS2POR_EL1 | - HFGxTR_EL2_nPOR_EL1 | - HFGxTR_EL2_nPOR_EL0 | HFGxTR_EL2_nACCDATA_EL1 | HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK); @@ -4606,10 +4762,21 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) HFGITR_EL2_TLBIRVAAE1OS | HFGITR_EL2_TLBIRVAE1OS); + if (!kvm_has_feat(kvm, ID_AA64ISAR2_EL1, ATS1A, IMP)) + kvm->arch.fgu[HFGITR_GROUP] |= HFGITR_EL2_ATS1E1A; + + if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, PAN, PAN2)) + kvm->arch.fgu[HFGITR_GROUP] |= (HFGITR_EL2_ATS1E1RP | + HFGITR_EL2_ATS1E1WP); + if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1PIE, IMP)) kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 | HFGxTR_EL2_nPIR_EL1); + if (!kvm_has_feat(kvm, ID_AA64MMFR3_EL1, S1POE, IMP)) + kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPOR_EL1 | + HFGxTR_EL2_nPOR_EL0); + if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP)) kvm->arch.fgu[HAFGRTR_GROUP] |= ~(HAFGRTR_EL2_RES0 | HAFGRTR_EL2_RES1); @@ -4619,6 +4786,36 @@ out: mutex_unlock(&kvm->arch.config_lock); } +/* + * Perform last adjustments to the ID registers that are implied by the + * configuration outside of the ID regs themselves, as well as any + * initialisation that directly depend on these ID registers (such as + * RES0/RES1 behaviours). This is not the place to configure traps though. + * + * Because this can be called once per CPU, changes must be idempotent. + */ +int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + + guard(mutex)(&kvm->arch.config_lock); + + if (!(static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) && + irqchip_in_kernel(kvm) && + kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)) { + kvm->arch.id_regs[IDREG_IDX(SYS_ID_AA64PFR0_EL1)] &= ~ID_AA64PFR0_EL1_GIC_MASK; + kvm->arch.id_regs[IDREG_IDX(SYS_ID_PFR1_EL1)] &= ~ID_PFR1_EL1_GIC_MASK; + } + + if (vcpu_has_nv(vcpu)) { + int ret = kvm_init_nv_sysregs(kvm); + if (ret) + return ret; + } + + return 0; +} + int __init kvm_sys_reg_table_init(void) { bool valid = true; diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index 997eea21ba2a..1d94ed6efad2 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -95,9 +95,8 @@ struct sys_reg_desc { }; #define REG_HIDDEN (1 << 0) /* hidden from userspace and guest */ -#define REG_HIDDEN_USER (1 << 1) /* hidden from userspace only */ -#define REG_RAZ (1 << 2) /* RAZ from userspace and guest */ -#define REG_USER_WI (1 << 3) /* WI from userspace only */ +#define REG_RAZ (1 << 1) /* RAZ from userspace and guest */ +#define REG_USER_WI (1 << 2) /* WI from userspace only */ static __printf(2, 3) inline void print_sys_reg_msg(const struct sys_reg_params *p, @@ -165,15 +164,6 @@ static inline bool sysreg_hidden(const struct kvm_vcpu *vcpu, return sysreg_visibility(vcpu, r) & REG_HIDDEN; } -static inline bool sysreg_hidden_user(const struct kvm_vcpu *vcpu, - const struct sys_reg_desc *r) -{ - if (likely(!r->visibility)) - return false; - - return r->visibility(vcpu, r) & (REG_HIDDEN | REG_HIDDEN_USER); -} - static inline bool sysreg_visible_as_raz(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -235,6 +225,8 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index); +int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu); + #define AA32(_x) .aarch32_map = AA32_##_x #define Op0(_x) .Op0 = _x #define Op1(_x) .Op1 = _x @@ -248,4 +240,11 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index); CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \ Op2(sys_reg_Op2(reg)) +#define CP15_SYS_DESC(reg) \ + .name = #reg, \ + .aarch32_map = AA32_DIRECT, \ + Op0(0), Op1(sys_reg_Op1(reg)), \ + CRn(sys_reg_CRn(reg)), CRm(sys_reg_CRm(reg)), \ + Op2(sys_reg_Op2(reg)) + #endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */ diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index e7c53e8af3d1..48c952563e85 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -417,8 +417,28 @@ static void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) kfree(vgic_cpu->private_irqs); vgic_cpu->private_irqs = NULL; - if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { + /* + * If this vCPU is being destroyed because of a failed creation + * then unregister the redistributor to avoid leaving behind a + * dangling pointer to the vCPU struct. + * + * vCPUs that have been successfully created (i.e. added to + * kvm->vcpu_array) get unregistered in kvm_vgic_destroy(), as + * this function gets called while holding kvm->arch.config_lock + * in the VM teardown path and would otherwise introduce a lock + * inversion w.r.t. kvm->srcu. + * + * vCPUs that failed creation are torn down outside of the + * kvm->arch.config_lock and do not get unregistered in + * kvm_vgic_destroy(), meaning it is both safe and necessary to + * do so here. + */ + if (kvm_get_vcpu_by_id(vcpu->kvm, vcpu->vcpu_id) != vcpu) + vgic_unregister_redist_iodev(vcpu); + vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; + } } void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) @@ -524,22 +544,31 @@ int kvm_vgic_map_resources(struct kvm *kvm) if (ret) goto out; - dist->ready = true; dist_base = dist->vgic_dist_base; mutex_unlock(&kvm->arch.config_lock); ret = vgic_register_dist_iodev(kvm, dist_base, type); - if (ret) + if (ret) { kvm_err("Unable to register VGIC dist MMIO regions\n"); + goto out_slots; + } + /* + * kvm_io_bus_register_dev() guarantees all readers see the new MMIO + * registration before returning through synchronize_srcu(), which also + * implies a full memory barrier. As such, marking the distributor as + * 'ready' here is guaranteed to be ordered after all vCPUs having seen + * a completely configured distributor. + */ + dist->ready = true; goto out_slots; out: mutex_unlock(&kvm->arch.config_lock); out_slots: - mutex_unlock(&kvm->slots_lock); - if (ret) - kvm_vgic_destroy(kvm); + kvm_vm_dead(kvm); + + mutex_unlock(&kvm->slots_lock); return ret; } diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c index 1d26bb5b02f4..5f4f57aaa23e 100644 --- a/arch/arm64/kvm/vgic/vgic-kvm-device.c +++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c @@ -236,7 +236,12 @@ static int vgic_set_common_attr(struct kvm_device *dev, mutex_lock(&dev->kvm->arch.config_lock); - if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis) + /* + * Either userspace has already configured NR_IRQS or + * the vgic has already been initialized and vgic_init() + * supplied a default amount of SPIs. + */ + if (dev->kvm->arch.vgic.nr_spis) ret = -EBUSY; else dev->kvm->arch.vgic.nr_spis = diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index 3eecdd2f4b8f..b217b256853c 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -292,6 +292,18 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu) /* Get the show on the road... */ vgic_v3->vgic_hcr = ICH_HCR_EN; +} + +void vcpu_set_ich_hcr(struct kvm_vcpu *vcpu) +{ + struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3; + + /* Hide GICv3 sysreg if necessary */ + if (!kvm_has_gicv3(vcpu->kvm)) { + vgic_v3->vgic_hcr |= ICH_HCR_TALL0 | ICH_HCR_TALL1 | ICH_HCR_TC; + return; + } + if (group0_trap) vgic_v3->vgic_hcr |= ICH_HCR_TALL0; if (group1_trap) diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c index abe29c7d85d0..f50274fd5581 100644 --- a/arch/arm64/kvm/vgic/vgic.c +++ b/arch/arm64/kvm/vgic/vgic.c @@ -922,10 +922,13 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) void kvm_vgic_load(struct kvm_vcpu *vcpu) { - if (unlikely(!vgic_initialized(vcpu->kvm))) + if (unlikely(!irqchip_in_kernel(vcpu->kvm) || !vgic_initialized(vcpu->kvm))) { + if (has_vhe() && static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) + __vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3); return; + } - if (kvm_vgic_global_state.type == VGIC_V2) + if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) vgic_v2_load(vcpu); else vgic_v3_load(vcpu); @@ -933,10 +936,13 @@ void kvm_vgic_load(struct kvm_vcpu *vcpu) void kvm_vgic_put(struct kvm_vcpu *vcpu) { - if (unlikely(!vgic_initialized(vcpu->kvm))) + if (unlikely(!irqchip_in_kernel(vcpu->kvm) || !vgic_initialized(vcpu->kvm))) { + if (has_vhe() && static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) + __vgic_v3_deactivate_traps(&vcpu->arch.vgic_cpu.vgic_v3); return; + } - if (kvm_vgic_global_state.type == VGIC_V2) + if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) vgic_v2_put(vcpu); else vgic_v3_put(vcpu); diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 8532bfe3fed4..f2486b4d9f95 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -346,11 +346,11 @@ void vgic_v4_configure_vsgis(struct kvm *kvm); void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val); int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq); +void vcpu_set_ich_hcr(struct kvm_vcpu *vcpu); + static inline bool kvm_has_gicv3(struct kvm *kvm) { - return (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) && - irqchip_in_kernel(kvm) && - kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3); + return kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP); } #endif diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 13e6a2829116..8e882f479d98 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -13,7 +13,7 @@ endif lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o -obj-$(CONFIG_CRC32) += crc32.o +obj-$(CONFIG_CRC32) += crc32.o crc32-glue.o obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o diff --git a/arch/arm64/lib/clear_page.S b/arch/arm64/lib/clear_page.S index ebde40e7fa2b..bd6f7d5eb6eb 100644 --- a/arch/arm64/lib/clear_page.S +++ b/arch/arm64/lib/clear_page.S @@ -15,6 +15,19 @@ * x0 - dest */ SYM_FUNC_START(__pi_clear_page) +#ifdef CONFIG_AS_HAS_MOPS + .arch_extension mops +alternative_if_not ARM64_HAS_MOPS + b .Lno_mops +alternative_else_nop_endif + + mov x1, #PAGE_SIZE + setpn [x0]!, x1!, xzr + setmn [x0]!, x1!, xzr + seten [x0]!, x1!, xzr + ret +.Lno_mops: +#endif mrs x1, dczid_el0 tbnz x1, #4, 2f /* Branch if DC ZVA is prohibited */ and w1, w1, #0xf diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S index 6a56d7cf309d..e6374e7e5511 100644 --- a/arch/arm64/lib/copy_page.S +++ b/arch/arm64/lib/copy_page.S @@ -18,6 +18,19 @@ * x1 - src */ SYM_FUNC_START(__pi_copy_page) +#ifdef CONFIG_AS_HAS_MOPS + .arch_extension mops +alternative_if_not ARM64_HAS_MOPS + b .Lno_mops +alternative_else_nop_endif + + mov x2, #PAGE_SIZE + cpypwn [x0]!, [x1]!, x2! + cpymwn [x0]!, [x1]!, x2! + cpyewn [x0]!, [x1]!, x2! + ret +.Lno_mops: +#endif ldp x2, x3, [x1] ldp x4, x5, [x1, #16] ldp x6, x7, [x1, #32] diff --git a/arch/arm64/lib/crc32-glue.c b/arch/arm64/lib/crc32-glue.c new file mode 100644 index 000000000000..295ae3e6b997 --- /dev/null +++ b/arch/arm64/lib/crc32-glue.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/crc32.h> +#include <linux/linkage.h> + +#include <asm/alternative.h> +#include <asm/cpufeature.h> +#include <asm/neon.h> +#include <asm/simd.h> + +#include <crypto/internal/simd.h> + +// The minimum input length to consider the 4-way interleaved code path +static const size_t min_len = 1024; + +asmlinkage u32 crc32_le_arm64(u32 crc, unsigned char const *p, size_t len); +asmlinkage u32 crc32c_le_arm64(u32 crc, unsigned char const *p, size_t len); +asmlinkage u32 crc32_be_arm64(u32 crc, unsigned char const *p, size_t len); + +asmlinkage u32 crc32_le_arm64_4way(u32 crc, unsigned char const *p, size_t len); +asmlinkage u32 crc32c_le_arm64_4way(u32 crc, unsigned char const *p, size_t len); +asmlinkage u32 crc32_be_arm64_4way(u32 crc, unsigned char const *p, size_t len); + +u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + if (!alternative_has_cap_likely(ARM64_HAS_CRC32)) + return crc32_le_base(crc, p, len); + + if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) { + kernel_neon_begin(); + crc = crc32_le_arm64_4way(crc, p, len); + kernel_neon_end(); + + p += round_down(len, 64); + len %= 64; + + if (!len) + return crc; + } + + return crc32_le_arm64(crc, p, len); +} + +u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) +{ + if (!alternative_has_cap_likely(ARM64_HAS_CRC32)) + return __crc32c_le_base(crc, p, len); + + if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) { + kernel_neon_begin(); + crc = crc32c_le_arm64_4way(crc, p, len); + kernel_neon_end(); + + p += round_down(len, 64); + len %= 64; + + if (!len) + return crc; + } + + return crc32c_le_arm64(crc, p, len); +} + +u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) +{ + if (!alternative_has_cap_likely(ARM64_HAS_CRC32)) + return crc32_be_base(crc, p, len); + + if (len >= min_len && cpu_have_named_feature(PMULL) && crypto_simd_usable()) { + kernel_neon_begin(); + crc = crc32_be_arm64_4way(crc, p, len); + kernel_neon_end(); + + p += round_down(len, 64); + len %= 64; + + if (!len) + return crc; + } + + return crc32_be_arm64(crc, p, len); +} diff --git a/arch/arm64/lib/crc32.S b/arch/arm64/lib/crc32.S index 8340dccff46f..68825317460f 100644 --- a/arch/arm64/lib/crc32.S +++ b/arch/arm64/lib/crc32.S @@ -1,54 +1,60 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Accelerated CRC32(C) using AArch64 CRC instructions + * Accelerated CRC32(C) using AArch64 CRC and PMULL instructions * - * Copyright (C) 2016 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org> + * Copyright (C) 2016 - 2018 Linaro Ltd. + * Copyright (C) 2024 Google LLC + * + * Author: Ard Biesheuvel <ardb@kernel.org> */ #include <linux/linkage.h> -#include <asm/alternative.h> #include <asm/assembler.h> - .arch armv8-a+crc + .cpu generic+crc+crypto - .macro byteorder, reg, be - .if \be -CPU_LE( rev \reg, \reg ) - .else -CPU_BE( rev \reg, \reg ) - .endif + .macro bitle, reg .endm - .macro byteorder16, reg, be - .if \be -CPU_LE( rev16 \reg, \reg ) - .else -CPU_BE( rev16 \reg, \reg ) - .endif + .macro bitbe, reg + rbit \reg, \reg .endm - .macro bitorder, reg, be - .if \be - rbit \reg, \reg - .endif + .macro bytele, reg .endm - .macro bitorder16, reg, be - .if \be + .macro bytebe, reg rbit \reg, \reg - lsr \reg, \reg, #16 - .endif + lsr \reg, \reg, #24 .endm - .macro bitorder8, reg, be - .if \be + .macro hwordle, reg +CPU_BE( rev16 \reg, \reg ) + .endm + + .macro hwordbe, reg +CPU_LE( rev \reg, \reg ) rbit \reg, \reg - lsr \reg, \reg, #24 - .endif +CPU_BE( lsr \reg, \reg, #16 ) + .endm + + .macro le, regs:vararg + .irp r, \regs +CPU_BE( rev \r, \r ) + .endr .endm - .macro __crc32, c, be=0 - bitorder w0, \be + .macro be, regs:vararg + .irp r, \regs +CPU_LE( rev \r, \r ) + .endr + .irp r, \regs + rbit \r, \r + .endr + .endm + + .macro __crc32, c, order=le + bit\order w0 cmp x2, #16 b.lt 8f // less than 16 bytes @@ -61,14 +67,7 @@ CPU_BE( rev16 \reg, \reg ) add x8, x8, x1 add x1, x1, x7 ldp x5, x6, [x8] - byteorder x3, \be - byteorder x4, \be - byteorder x5, \be - byteorder x6, \be - bitorder x3, \be - bitorder x4, \be - bitorder x5, \be - bitorder x6, \be + \order x3, x4, x5, x6 tst x7, #8 crc32\c\()x w8, w0, x3 @@ -96,65 +95,268 @@ CPU_BE( rev16 \reg, \reg ) 32: ldp x3, x4, [x1], #32 sub x2, x2, #32 ldp x5, x6, [x1, #-16] - byteorder x3, \be - byteorder x4, \be - byteorder x5, \be - byteorder x6, \be - bitorder x3, \be - bitorder x4, \be - bitorder x5, \be - bitorder x6, \be + \order x3, x4, x5, x6 crc32\c\()x w0, w0, x3 crc32\c\()x w0, w0, x4 crc32\c\()x w0, w0, x5 crc32\c\()x w0, w0, x6 cbnz x2, 32b -0: bitorder w0, \be +0: bit\order w0 ret 8: tbz x2, #3, 4f ldr x3, [x1], #8 - byteorder x3, \be - bitorder x3, \be + \order x3 crc32\c\()x w0, w0, x3 4: tbz x2, #2, 2f ldr w3, [x1], #4 - byteorder w3, \be - bitorder w3, \be + \order w3 crc32\c\()w w0, w0, w3 2: tbz x2, #1, 1f ldrh w3, [x1], #2 - byteorder16 w3, \be - bitorder16 w3, \be + hword\order w3 crc32\c\()h w0, w0, w3 1: tbz x2, #0, 0f ldrb w3, [x1] - bitorder8 w3, \be + byte\order w3 crc32\c\()b w0, w0, w3 -0: bitorder w0, \be +0: bit\order w0 ret .endm .align 5 -SYM_FUNC_START(crc32_le) -alternative_if_not ARM64_HAS_CRC32 - b crc32_le_base -alternative_else_nop_endif +SYM_FUNC_START(crc32_le_arm64) __crc32 -SYM_FUNC_END(crc32_le) +SYM_FUNC_END(crc32_le_arm64) .align 5 -SYM_FUNC_START(__crc32c_le) -alternative_if_not ARM64_HAS_CRC32 - b __crc32c_le_base -alternative_else_nop_endif +SYM_FUNC_START(crc32c_le_arm64) __crc32 c -SYM_FUNC_END(__crc32c_le) +SYM_FUNC_END(crc32c_le_arm64) .align 5 -SYM_FUNC_START(crc32_be) -alternative_if_not ARM64_HAS_CRC32 - b crc32_be_base -alternative_else_nop_endif - __crc32 be=1 -SYM_FUNC_END(crc32_be) +SYM_FUNC_START(crc32_be_arm64) + __crc32 order=be +SYM_FUNC_END(crc32_be_arm64) + + in .req x1 + len .req x2 + + /* + * w0: input CRC at entry, output CRC at exit + * x1: pointer to input buffer + * x2: length of input in bytes + */ + .macro crc4way, insn, table, order=le + bit\order w0 + lsr len, len, #6 // len := # of 64-byte blocks + + /* Process up to 64 blocks of 64 bytes at a time */ +.La\@: mov x3, #64 + cmp len, #64 + csel x3, x3, len, hi // x3 := min(len, 64) + sub len, len, x3 + + /* Divide the input into 4 contiguous blocks */ + add x4, x3, x3, lsl #1 // x4 := 3 * x3 + add x7, in, x3, lsl #4 // x7 := in + 16 * x3 + add x8, in, x3, lsl #5 // x8 := in + 32 * x3 + add x9, in, x4, lsl #4 // x9 := in + 16 * x4 + + /* Load the folding coefficients from the lookup table */ + adr_l x5, \table - 12 // entry 0 omitted + add x5, x5, x4, lsl #2 // x5 += 12 * x3 + ldp s0, s1, [x5] + ldr s2, [x5, #8] + + /* Zero init partial CRCs for this iteration */ + mov w4, wzr + mov w5, wzr + mov w6, wzr + mov x17, xzr + +.Lb\@: sub x3, x3, #1 + \insn w6, w6, x17 + ldp x10, x11, [in], #16 + ldp x12, x13, [x7], #16 + ldp x14, x15, [x8], #16 + ldp x16, x17, [x9], #16 + + \order x10, x11, x12, x13, x14, x15, x16, x17 + + /* Apply the CRC transform to 4 16-byte blocks in parallel */ + \insn w0, w0, x10 + \insn w4, w4, x12 + \insn w5, w5, x14 + \insn w6, w6, x16 + \insn w0, w0, x11 + \insn w4, w4, x13 + \insn w5, w5, x15 + cbnz x3, .Lb\@ + + /* Combine the 4 partial results into w0 */ + mov v3.d[0], x0 + mov v4.d[0], x4 + mov v5.d[0], x5 + pmull v0.1q, v0.1d, v3.1d + pmull v1.1q, v1.1d, v4.1d + pmull v2.1q, v2.1d, v5.1d + eor v0.8b, v0.8b, v1.8b + eor v0.8b, v0.8b, v2.8b + mov x5, v0.d[0] + eor x5, x5, x17 + \insn w0, w6, x5 + + mov in, x9 + cbnz len, .La\@ + + bit\order w0 + ret + .endm + + .align 5 +SYM_FUNC_START(crc32c_le_arm64_4way) + crc4way crc32cx, .L0 +SYM_FUNC_END(crc32c_le_arm64_4way) + + .align 5 +SYM_FUNC_START(crc32_le_arm64_4way) + crc4way crc32x, .L1 +SYM_FUNC_END(crc32_le_arm64_4way) + + .align 5 +SYM_FUNC_START(crc32_be_arm64_4way) + crc4way crc32x, .L1, be +SYM_FUNC_END(crc32_be_arm64_4way) + + .section .rodata, "a", %progbits + .align 6 +.L0: .long 0xddc0152b, 0xba4fc28e, 0x493c7d27 + .long 0x0715ce53, 0x9e4addf8, 0xba4fc28e + .long 0xc96cfdc0, 0x0715ce53, 0xddc0152b + .long 0xab7aff2a, 0x0d3b6092, 0x9e4addf8 + .long 0x299847d5, 0x878a92a7, 0x39d3b296 + .long 0xb6dd949b, 0xab7aff2a, 0x0715ce53 + .long 0xa60ce07b, 0x83348832, 0x47db8317 + .long 0xd270f1a2, 0xb9e02b86, 0x0d3b6092 + .long 0x65863b64, 0xb6dd949b, 0xc96cfdc0 + .long 0xb3e32c28, 0xbac2fd7b, 0x878a92a7 + .long 0xf285651c, 0xce7f39f4, 0xdaece73e + .long 0x271d9844, 0xd270f1a2, 0xab7aff2a + .long 0x6cb08e5c, 0x2b3cac5d, 0x2162d385 + .long 0xcec3662e, 0x1b03397f, 0x83348832 + .long 0x8227bb8a, 0xb3e32c28, 0x299847d5 + .long 0xd7a4825c, 0xdd7e3b0c, 0xb9e02b86 + .long 0xf6076544, 0x10746f3c, 0x18b33a4e + .long 0x98d8d9cb, 0x271d9844, 0xb6dd949b + .long 0x57a3d037, 0x93a5f730, 0x78d9ccb7 + .long 0x3771e98f, 0x6b749fb2, 0xbac2fd7b + .long 0xe0ac139e, 0xcec3662e, 0xa60ce07b + .long 0x6f345e45, 0xe6fc4e6a, 0xce7f39f4 + .long 0xa2b73df1, 0xb0cd4768, 0x61d82e56 + .long 0x86d8e4d2, 0xd7a4825c, 0xd270f1a2 + .long 0xa90fd27a, 0x0167d312, 0xc619809d + .long 0xca6ef3ac, 0x26f6a60a, 0x2b3cac5d + .long 0x4597456a, 0x98d8d9cb, 0x65863b64 + .long 0xc9c8b782, 0x68bce87a, 0x1b03397f + .long 0x62ec6c6d, 0x6956fc3b, 0xebb883bd + .long 0x2342001e, 0x3771e98f, 0xb3e32c28 + .long 0xe8b6368b, 0x2178513a, 0x064f7f26 + .long 0x9ef68d35, 0x170076fa, 0xdd7e3b0c + .long 0x0b0bf8ca, 0x6f345e45, 0xf285651c + .long 0x02ee03b2, 0xff0dba97, 0x10746f3c + .long 0x135c83fd, 0xf872e54c, 0xc7a68855 + .long 0x00bcf5f6, 0x86d8e4d2, 0x271d9844 + .long 0x58ca5f00, 0x5bb8f1bc, 0x8e766a0c + .long 0xded288f8, 0xb3af077a, 0x93a5f730 + .long 0x37170390, 0xca6ef3ac, 0x6cb08e5c + .long 0xf48642e9, 0xdd66cbbb, 0x6b749fb2 + .long 0xb25b29f2, 0xe9e28eb4, 0x1393e203 + .long 0x45cddf4e, 0xc9c8b782, 0xcec3662e + .long 0xdfd94fb2, 0x93e106a4, 0x96c515bb + .long 0x021ac5ef, 0xd813b325, 0xe6fc4e6a + .long 0x8e1450f7, 0x2342001e, 0x8227bb8a + .long 0xe0cdcf86, 0x6d9a4957, 0xb0cd4768 + .long 0x613eee91, 0xd2c3ed1a, 0x39c7ff35 + .long 0xbedc6ba1, 0x9ef68d35, 0xd7a4825c + .long 0x0cd1526a, 0xf2271e60, 0x0ab3844b + .long 0xd6c3a807, 0x2664fd8b, 0x0167d312 + .long 0x1d31175f, 0x02ee03b2, 0xf6076544 + .long 0x4be7fd90, 0x363bd6b3, 0x26f6a60a + .long 0x6eeed1c9, 0x5fabe670, 0xa741c1bf + .long 0xb3a6da94, 0x00bcf5f6, 0x98d8d9cb + .long 0x2e7d11a7, 0x17f27698, 0x49c3cc9c + .long 0x889774e1, 0xaa7c7ad5, 0x68bce87a + .long 0x8a074012, 0xded288f8, 0x57a3d037 + .long 0xbd0bb25f, 0x6d390dec, 0x6956fc3b + .long 0x3be3c09b, 0x6353c1cc, 0x42d98888 + .long 0x465a4eee, 0xf48642e9, 0x3771e98f + .long 0x2e5f3c8c, 0xdd35bc8d, 0xb42ae3d9 + .long 0xa52f58ec, 0x9a5ede41, 0x2178513a + .long 0x47972100, 0x45cddf4e, 0xe0ac139e + .long 0x359674f7, 0xa51b6135, 0x170076fa + +.L1: .long 0xaf449247, 0x81256527, 0xccaa009e + .long 0x57c54819, 0x1d9513d7, 0x81256527 + .long 0x3f41287a, 0x57c54819, 0xaf449247 + .long 0xf5e48c85, 0x910eeec1, 0x1d9513d7 + .long 0x1f0c2cdd, 0x9026d5b1, 0xae0b5394 + .long 0x71d54a59, 0xf5e48c85, 0x57c54819 + .long 0x1c63267b, 0xfe807bbd, 0x0cbec0ed + .long 0xd31343ea, 0xe95c1271, 0x910eeec1 + .long 0xf9d9c7ee, 0x71d54a59, 0x3f41287a + .long 0x9ee62949, 0xcec97417, 0x9026d5b1 + .long 0xa55d1514, 0xf183c71b, 0xd1df2327 + .long 0x21aa2b26, 0xd31343ea, 0xf5e48c85 + .long 0x9d842b80, 0xeea395c4, 0x3c656ced + .long 0xd8110ff1, 0xcd669a40, 0xfe807bbd + .long 0x3f9e9356, 0x9ee62949, 0x1f0c2cdd + .long 0x1d6708a0, 0x0c30f51d, 0xe95c1271 + .long 0xef82aa68, 0xdb3935ea, 0xb918a347 + .long 0xd14bcc9b, 0x21aa2b26, 0x71d54a59 + .long 0x99cce860, 0x356d209f, 0xff6f2fc2 + .long 0xd8af8e46, 0xc352f6de, 0xcec97417 + .long 0xf1996890, 0xd8110ff1, 0x1c63267b + .long 0x631bc508, 0xe95c7216, 0xf183c71b + .long 0x8511c306, 0x8e031a19, 0x9b9bdbd0 + .long 0xdb3839f3, 0x1d6708a0, 0xd31343ea + .long 0x7a92fffb, 0xf7003835, 0x4470ac44 + .long 0x6ce68f2a, 0x00eba0c8, 0xeea395c4 + .long 0x4caaa263, 0xd14bcc9b, 0xf9d9c7ee + .long 0xb46f7cff, 0x9a1b53c8, 0xcd669a40 + .long 0x60290934, 0x81b6f443, 0x6d40f445 + .long 0x8e976a7d, 0xd8af8e46, 0x9ee62949 + .long 0xdcf5088a, 0x9dbdc100, 0x145575d5 + .long 0x1753ab84, 0xbbf2f6d6, 0x0c30f51d + .long 0x255b139e, 0x631bc508, 0xa55d1514 + .long 0xd784eaa8, 0xce26786c, 0xdb3935ea + .long 0x6d2c864a, 0x8068c345, 0x2586d334 + .long 0x02072e24, 0xdb3839f3, 0x21aa2b26 + .long 0x06689b0a, 0x5efd72f5, 0xe0575528 + .long 0x1e52f5ea, 0x4117915b, 0x356d209f + .long 0x1d3d1db6, 0x6ce68f2a, 0x9d842b80 + .long 0x3796455c, 0xb8e0e4a8, 0xc352f6de + .long 0xdf3a4eb3, 0xc55a2330, 0xb84ffa9c + .long 0x28ae0976, 0xb46f7cff, 0xd8110ff1 + .long 0x9764bc8d, 0xd7e7a22c, 0x712510f0 + .long 0x13a13e18, 0x3e9a43cd, 0xe95c7216 + .long 0xb8ee242e, 0x8e976a7d, 0x3f9e9356 + .long 0x0c540e7b, 0x753c81ff, 0x8e031a19 + .long 0x9924c781, 0xb9220208, 0x3edcde65 + .long 0x3954de39, 0x1753ab84, 0x1d6708a0 + .long 0xf32238b5, 0xbec81497, 0x9e70b943 + .long 0xbbd2cd2c, 0x0925d861, 0xf7003835 + .long 0xcc401304, 0xd784eaa8, 0xef82aa68 + .long 0x4987e684, 0x6044fbb0, 0x00eba0c8 + .long 0x3aa11427, 0x18fe3b4a, 0x87441142 + .long 0x297aad60, 0x02072e24, 0xd14bcc9b + .long 0xf60c5e51, 0x6ef6f487, 0x5b7fdd0a + .long 0x632d78c5, 0x3fc33de4, 0x9a1b53c8 + .long 0x25b8822a, 0x1e52f5ea, 0x99cce860 + .long 0xd4fc84bc, 0x1af62fb8, 0x81b6f443 + .long 0x5690aa32, 0xa91fdefb, 0x688a110e + .long 0x1357a093, 0x3796455c, 0xd8af8e46 + .long 0x798fdd33, 0xaaa18a37, 0x357b9517 + .long 0xc2815395, 0x54d42691, 0x9dbdc100 + .long 0x21cfc0f7, 0x28ae0976, 0xf1996890 + .long 0xa0decef3, 0x7b4aa8b7, 0xbbf2f6d6 diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S index 4ab48d49c451..9b99106fb95f 100644 --- a/arch/arm64/lib/memcpy.S +++ b/arch/arm64/lib/memcpy.S @@ -57,7 +57,7 @@ The loop tail is handled by always copying 64 bytes from the end. */ -SYM_FUNC_START(__pi_memcpy) +SYM_FUNC_START_LOCAL(__pi_memcpy_generic) add srcend, src, count add dstend, dstin, count cmp count, 128 @@ -238,7 +238,24 @@ L(copy64_from_start): stp B_l, B_h, [dstin, 16] stp C_l, C_h, [dstin] ret +SYM_FUNC_END(__pi_memcpy_generic) + +#ifdef CONFIG_AS_HAS_MOPS + .arch_extension mops +SYM_FUNC_START(__pi_memcpy) +alternative_if_not ARM64_HAS_MOPS + b __pi_memcpy_generic +alternative_else_nop_endif + + mov dst, dstin + cpyp [dst]!, [src]!, count! + cpym [dst]!, [src]!, count! + cpye [dst]!, [src]!, count! + ret SYM_FUNC_END(__pi_memcpy) +#else +SYM_FUNC_ALIAS(__pi_memcpy, __pi_memcpy_generic) +#endif SYM_FUNC_ALIAS(__memcpy, __pi_memcpy) EXPORT_SYMBOL(__memcpy) diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S index a5aebe82ad73..97157da65ec6 100644 --- a/arch/arm64/lib/memset.S +++ b/arch/arm64/lib/memset.S @@ -26,6 +26,7 @@ */ dstin .req x0 +val_x .req x1 val .req w1 count .req x2 tmp1 .req x3 @@ -42,7 +43,7 @@ dst .req x8 tmp3w .req w9 tmp3 .req x9 -SYM_FUNC_START(__pi_memset) +SYM_FUNC_START_LOCAL(__pi_memset_generic) mov dst, dstin /* Preserve return value. */ and A_lw, val, #255 orr A_lw, A_lw, A_lw, lsl #8 @@ -201,7 +202,24 @@ SYM_FUNC_START(__pi_memset) ands count, count, zva_bits_x b.ne .Ltail_maybe_long ret +SYM_FUNC_END(__pi_memset_generic) + +#ifdef CONFIG_AS_HAS_MOPS + .arch_extension mops +SYM_FUNC_START(__pi_memset) +alternative_if_not ARM64_HAS_MOPS + b __pi_memset_generic +alternative_else_nop_endif + + mov dst, dstin + setp [dst]!, count!, val_x + setm [dst]!, count!, val_x + sete [dst]!, count!, val_x + ret SYM_FUNC_END(__pi_memset) +#else +SYM_FUNC_ALIAS(__pi_memset, __pi_memset_generic) +#endif SYM_FUNC_ALIAS(__memset, __pi_memset) EXPORT_SYMBOL(__memset) diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 60454256945b..fc92170a8f37 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-y := dma-mapping.o extable.o fault.o init.o \ cache.o copypage.o flush.o \ - ioremap.o mmap.o pgd.o mmu.o \ + ioremap.o mmap.o pgd.o mem_encrypt.o mmu.o \ context.o proc.o pageattr.o fixmap.o obj-$(CONFIG_ARM64_CONTPTE) += contpte.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o @@ -11,6 +11,7 @@ obj-$(CONFIG_TRANS_TABLE) += trans_pgd.o obj-$(CONFIG_TRANS_TABLE) += trans_pgd-asm.o obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o obj-$(CONFIG_ARM64_MTE) += mteswap.o +obj-$(CONFIG_ARM64_GCS) += gcs.o KASAN_SANITIZE_physaddr.o += n obj-$(CONFIG_KASAN) += kasan_init.o diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c index a3edced29ac1..55107d27d3f8 100644 --- a/arch/arm64/mm/contpte.c +++ b/arch/arm64/mm/contpte.c @@ -421,6 +421,12 @@ int contpte_ptep_set_access_flags(struct vm_area_struct *vma, ptep = contpte_align_down(ptep); start_addr = addr = ALIGN_DOWN(addr, CONT_PTE_SIZE); + /* + * We are not advancing entry because __ptep_set_access_flags() + * only consumes access flags from entry. And since we have checked + * for the whole contpte block and returned early, pte_same() + * within __ptep_set_access_flags() is likely false. + */ for (i = 0; i < CONT_PTES; i++, ptep++, addr += PAGE_SIZE) __ptep_set_access_flags(vma, addr, ptep, entry, 0); diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c index a7bb20055ce0..87b3f1a25535 100644 --- a/arch/arm64/mm/copypage.c +++ b/arch/arm64/mm/copypage.c @@ -18,15 +18,40 @@ void copy_highpage(struct page *to, struct page *from) { void *kto = page_address(to); void *kfrom = page_address(from); + struct folio *src = page_folio(from); + struct folio *dst = page_folio(to); + unsigned int i, nr_pages; copy_page(kto, kfrom); if (kasan_hw_tags_enabled()) page_kasan_tag_reset(to); - if (system_supports_mte() && page_mte_tagged(from)) { + if (!system_supports_mte()) + return; + + if (folio_test_hugetlb(src) && + folio_test_hugetlb_mte_tagged(src)) { + if (!folio_try_hugetlb_mte_tagging(dst)) + return; + + /* + * Populate tags for all subpages. + * + * Don't assume the first page is head page since + * huge page copy may start from any subpage. + */ + nr_pages = folio_nr_pages(src); + for (i = 0; i < nr_pages; i++) { + kfrom = page_address(folio_page(src, i)); + kto = page_address(folio_page(dst, i)); + mte_copy_page_tags(kto, kfrom); + } + folio_set_hugetlb_mte_tagged(dst); + } else if (page_mte_tagged(from)) { /* It's a new page, shouldn't have been tagged yet */ WARN_ON_ONCE(!try_page_mte_tagging(to)); + mte_copy_page_tags(kto, kfrom); set_page_mte_tagged(to); } diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 451ba7cbd5ad..c2f89a678ac0 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -23,6 +23,7 @@ #include <linux/sched/debug.h> #include <linux/highmem.h> #include <linux/perf_event.h> +#include <linux/pkeys.h> #include <linux/preempt.h> #include <linux/hugetlb.h> @@ -486,6 +487,31 @@ static void do_bad_area(unsigned long far, unsigned long esr, } } +static bool fault_from_pkey(unsigned long esr, struct vm_area_struct *vma, + unsigned int mm_flags) +{ + unsigned long iss2 = ESR_ELx_ISS2(esr); + + if (!system_supports_poe()) + return false; + + if (esr_fsc_is_permission_fault(esr) && (iss2 & ESR_ELx_Overlay)) + return true; + + return !arch_vma_access_permitted(vma, + mm_flags & FAULT_FLAG_WRITE, + mm_flags & FAULT_FLAG_INSTRUCTION, + false); +} + +static bool is_gcs_fault(unsigned long esr) +{ + if (!esr_is_data_abort(esr)) + return false; + + return ESR_ELx_ISS2(esr) & ESR_ELx_GCS; +} + static bool is_el0_instruction_abort(unsigned long esr) { return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; @@ -500,6 +526,23 @@ static bool is_write_abort(unsigned long esr) return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); } +static bool is_invalid_gcs_access(struct vm_area_struct *vma, u64 esr) +{ + if (!system_supports_gcs()) + return false; + + if (unlikely(is_gcs_fault(esr))) { + /* GCS accesses must be performed on a GCS page */ + if (!(vma->vm_flags & VM_SHADOW_STACK)) + return true; + } else if (unlikely(vma->vm_flags & VM_SHADOW_STACK)) { + /* Only GCS operations can write to a GCS page */ + return esr_is_data_abort(esr) && is_write_abort(esr); + } + + return false; +} + static int __kprobes do_page_fault(unsigned long far, unsigned long esr, struct pt_regs *regs) { @@ -511,6 +554,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, unsigned long addr = untagged_addr(far); struct vm_area_struct *vma; int si_code; + int pkey = -1; if (kprobe_page_fault(regs, esr)) return 0; @@ -535,6 +579,14 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, /* It was exec fault */ vm_flags = VM_EXEC; mm_flags |= FAULT_FLAG_INSTRUCTION; + } else if (is_gcs_fault(esr)) { + /* + * The GCS permission on a page implies both read and + * write so always handle any GCS fault as a write fault, + * we need to trigger CoW even for GCS reads. + */ + vm_flags = VM_WRITE; + mm_flags |= FAULT_FLAG_WRITE; } else if (is_write_abort(esr)) { /* It was write fault */ vm_flags = VM_WRITE; @@ -568,6 +620,13 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, if (!vma) goto lock_mmap; + if (is_invalid_gcs_access(vma, esr)) { + vma_end_read(vma); + fault = 0; + si_code = SEGV_ACCERR; + goto bad_area; + } + if (!(vma->vm_flags & vm_flags)) { vma_end_read(vma); fault = 0; @@ -575,6 +634,16 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, count_vm_vma_lock_event(VMA_LOCK_SUCCESS); goto bad_area; } + + if (fault_from_pkey(esr, vma, mm_flags)) { + pkey = vma_pkey(vma); + vma_end_read(vma); + fault = 0; + si_code = SEGV_PKUERR; + count_vm_vma_lock_event(VMA_LOCK_SUCCESS); + goto bad_area; + } + fault = handle_mm_fault(vma, addr, mm_flags | FAULT_FLAG_VMA_LOCK, regs); if (!(fault & (VM_FAULT_RETRY | VM_FAULT_COMPLETED))) vma_end_read(vma); @@ -610,7 +679,16 @@ retry: goto bad_area; } + if (fault_from_pkey(esr, vma, mm_flags)) { + pkey = vma_pkey(vma); + mmap_read_unlock(mm); + fault = 0; + si_code = SEGV_PKUERR; + goto bad_area; + } + fault = handle_mm_fault(vma, addr, mm_flags, regs); + /* Quick path to respond to signals */ if (fault_signal_pending(fault, regs)) { if (!user_mode(regs)) @@ -669,8 +747,23 @@ bad_area: arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name); } else { + /* + * The pkey value that we return to userspace can be different + * from the pkey that caused the fault. + * + * 1. T1 : mprotect_key(foo, PAGE_SIZE, pkey=4); + * 2. T1 : set POR_EL0 to deny access to pkey=4, touches, page + * 3. T1 : faults... + * 4. T2: mprotect_key(foo, PAGE_SIZE, pkey=5); + * 5. T1 : enters fault handler, takes mmap_lock, etc... + * 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really + * faulted on a pte with its pkey=4. + */ /* Something tried to access memory that out of memory map */ - arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name); + if (si_code == SEGV_PKUERR) + arm64_force_sig_fault_pkey(far, inf->name, pkey); + else + arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name); } return 0; diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c index de1e09d986ad..c5c5425791da 100644 --- a/arch/arm64/mm/fixmap.c +++ b/arch/arm64/mm/fixmap.c @@ -47,7 +47,8 @@ static void __init early_fixmap_init_pte(pmd_t *pmdp, unsigned long addr) if (pmd_none(pmd)) { ptep = bm_pte[BM_PTE_TABLE_IDX(addr)]; - __pmd_populate(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE); + __pmd_populate(pmdp, __pa_symbol(ptep), + PMD_TYPE_TABLE | PMD_TABLE_AF); } } @@ -59,7 +60,8 @@ static void __init early_fixmap_init_pmd(pud_t *pudp, unsigned long addr, pmd_t *pmdp; if (pud_none(pud)) - __pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE); + __pud_populate(pudp, __pa_symbol(bm_pmd), + PUD_TYPE_TABLE | PUD_TABLE_AF); pmdp = pmd_offset_kimg(pudp, addr); do { @@ -86,7 +88,8 @@ static void __init early_fixmap_init_pud(p4d_t *p4dp, unsigned long addr, } if (p4d_none(p4d)) - __p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE); + __p4d_populate(p4dp, __pa_symbol(bm_pud), + P4D_TYPE_TABLE | P4D_TABLE_AF); pudp = pud_offset_kimg(p4dp, addr); early_fixmap_init_pmd(pudp, addr, end); diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c new file mode 100644 index 000000000000..5c46ec527b1c --- /dev/null +++ b/arch/arm64/mm/gcs.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/mm.h> +#include <linux/mman.h> +#include <linux/syscalls.h> +#include <linux/types.h> + +#include <asm/cmpxchg.h> +#include <asm/cpufeature.h> +#include <asm/gcs.h> +#include <asm/page.h> + +static unsigned long alloc_gcs(unsigned long addr, unsigned long size) +{ + int flags = MAP_ANONYMOUS | MAP_PRIVATE; + struct mm_struct *mm = current->mm; + unsigned long mapped_addr, unused; + + if (addr) + flags |= MAP_FIXED_NOREPLACE; + + mmap_write_lock(mm); + mapped_addr = do_mmap(NULL, addr, size, PROT_READ, flags, + VM_SHADOW_STACK | VM_WRITE, 0, &unused, NULL); + mmap_write_unlock(mm); + + return mapped_addr; +} + +static unsigned long gcs_size(unsigned long size) +{ + if (size) + return PAGE_ALIGN(size); + + /* Allocate RLIMIT_STACK/2 with limits of PAGE_SIZE..2G */ + size = PAGE_ALIGN(min_t(unsigned long long, + rlimit(RLIMIT_STACK) / 2, SZ_2G)); + return max(PAGE_SIZE, size); +} + +unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, + const struct kernel_clone_args *args) +{ + unsigned long addr, size; + + if (!system_supports_gcs()) + return 0; + + if (!task_gcs_el0_enabled(tsk)) + return 0; + + if ((args->flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM) { + tsk->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); + return 0; + } + + size = args->stack_size / 2; + + size = gcs_size(size); + addr = alloc_gcs(0, size); + if (IS_ERR_VALUE(addr)) + return addr; + + tsk->thread.gcs_base = addr; + tsk->thread.gcs_size = size; + tsk->thread.gcspr_el0 = addr + size - sizeof(u64); + + return addr; +} + +SYSCALL_DEFINE3(map_shadow_stack, unsigned long, addr, unsigned long, size, unsigned int, flags) +{ + unsigned long alloc_size; + unsigned long __user *cap_ptr; + unsigned long cap_val; + int ret = 0; + int cap_offset; + + if (!system_supports_gcs()) + return -EOPNOTSUPP; + + if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER)) + return -EINVAL; + + if (!PAGE_ALIGNED(addr)) + return -EINVAL; + + if (size == 8 || !IS_ALIGNED(size, 8)) + return -EINVAL; + + /* + * An overflow would result in attempting to write the restore token + * to the wrong location. Not catastrophic, but just return the right + * error code and block it. + */ + alloc_size = PAGE_ALIGN(size); + if (alloc_size < size) + return -EOVERFLOW; + + addr = alloc_gcs(addr, alloc_size); + if (IS_ERR_VALUE(addr)) + return addr; + + /* + * Put a cap token at the end of the allocated region so it + * can be switched to. + */ + if (flags & SHADOW_STACK_SET_TOKEN) { + /* Leave an extra empty frame as a top of stack marker? */ + if (flags & SHADOW_STACK_SET_MARKER) + cap_offset = 2; + else + cap_offset = 1; + + cap_ptr = (unsigned long __user *)(addr + size - + (cap_offset * sizeof(unsigned long))); + cap_val = GCS_CAP(cap_ptr); + + put_user_gcs(cap_val, cap_ptr, &ret); + if (ret != 0) { + vm_munmap(addr, size); + return -EFAULT; + } + + /* + * Ensure the new cap is ordered before standard + * memory accesses to the same location. + */ + gcsb_dsync(); + } + + return addr; +} + +/* + * Apply the GCS mode configured for the specified task to the + * hardware. + */ +void gcs_set_el0_mode(struct task_struct *task) +{ + u64 gcscre0_el1 = GCSCRE0_EL1_nTR; + + if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE) + gcscre0_el1 |= GCSCRE0_EL1_RVCHKEN | GCSCRE0_EL1_PCRSEL; + + if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_WRITE) + gcscre0_el1 |= GCSCRE0_EL1_STREn; + + if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_PUSH) + gcscre0_el1 |= GCSCRE0_EL1_PUSHMEn; + + write_sysreg_s(gcscre0_el1, SYS_GCSCRE0_EL1); +} + +void gcs_free(struct task_struct *task) +{ + if (!system_supports_gcs()) + return; + + /* + * When fork() with CLONE_VM fails, the child (tsk) already + * has a GCS allocated, and exit_thread() calls this function + * to free it. In this case the parent (current) and the + * child share the same mm struct. + */ + if (!task->mm || task->mm != current->mm) + return; + + if (task->thread.gcs_base) + vm_munmap(task->thread.gcs_base, task->thread.gcs_size); + + task->thread.gcspr_el0 = 0; + task->thread.gcs_base = 0; + task->thread.gcs_size = 0; +} + +int arch_set_shadow_stack_status(struct task_struct *task, unsigned long arg) +{ + unsigned long gcs, size; + int ret; + + if (!system_supports_gcs()) + return -EINVAL; + + if (is_compat_thread(task_thread_info(task))) + return -EINVAL; + + /* Reject unknown flags */ + if (arg & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK) + return -EINVAL; + + ret = gcs_check_locked(task, arg); + if (ret != 0) + return ret; + + /* If we are enabling GCS then make sure we have a stack */ + if (arg & PR_SHADOW_STACK_ENABLE && + !task_gcs_el0_enabled(task)) { + /* Do not allow GCS to be reenabled */ + if (task->thread.gcs_base || task->thread.gcspr_el0) + return -EINVAL; + + if (task != current) + return -EBUSY; + + size = gcs_size(0); + gcs = alloc_gcs(0, size); + if (!gcs) + return -ENOMEM; + + task->thread.gcspr_el0 = gcs + size - sizeof(u64); + task->thread.gcs_base = gcs; + task->thread.gcs_size = size; + if (task == current) + write_sysreg_s(task->thread.gcspr_el0, + SYS_GCSPR_EL0); + } + + task->thread.gcs_el0_mode = arg; + if (task == current) + gcs_set_el0_mode(task); + + return 0; +} + +int arch_get_shadow_stack_status(struct task_struct *task, + unsigned long __user *arg) +{ + if (!system_supports_gcs()) + return -EINVAL; + + if (is_compat_thread(task_thread_info(task))) + return -EINVAL; + + return put_user(task->thread.gcs_el0_mode, arg); +} + +int arch_lock_shadow_stack_status(struct task_struct *task, + unsigned long arg) +{ + if (!system_supports_gcs()) + return -EINVAL; + + if (is_compat_thread(task_thread_info(task))) + return -EINVAL; + + /* + * We support locking unknown bits so applications can prevent + * any changes in a future proof manner. + */ + task->thread.gcs_el0_locked |= arg; + + return 0; +} diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 5f1e2103888b..3215adf48a1b 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -361,14 +361,25 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags) { size_t pagesize = 1UL << shift; - entry = pte_mkhuge(entry); - if (pagesize == CONT_PTE_SIZE) { - entry = pte_mkcont(entry); - } else if (pagesize == CONT_PMD_SIZE) { + switch (pagesize) { +#ifndef __PAGETABLE_PMD_FOLDED + case PUD_SIZE: + entry = pud_pte(pud_mkhuge(pte_pud(entry))); + break; +#endif + case CONT_PMD_SIZE: entry = pmd_pte(pmd_mkcont(pte_pmd(entry))); - } else if (pagesize != PUD_SIZE && pagesize != PMD_SIZE) { + fallthrough; + case PMD_SIZE: + entry = pmd_pte(pmd_mkhuge(pte_pmd(entry))); + break; + case CONT_PTE_SIZE: + entry = pte_mkcont(entry); + break; + default: pr_warn("%s: unrecognized huge page size 0x%lx\n", __func__, pagesize); + break; } return entry; } diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 9b5ab6818f7f..d21f67d67cf5 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -41,6 +41,7 @@ #include <asm/kvm_host.h> #include <asm/memory.h> #include <asm/numa.h> +#include <asm/rsi.h> #include <asm/sections.h> #include <asm/setup.h> #include <linux/sizes.h> @@ -114,36 +115,33 @@ static void __init arch_reserve_crashkernel(void) low_size, high); } -/* - * Return the maximum physical address for a zone accessible by the given bits - * limit. If DRAM starts above 32-bit, expand the zone to the maximum - * available memory, otherwise cap it at 32-bit. - */ -static phys_addr_t __init max_zone_phys(unsigned int zone_bits) +static phys_addr_t __init max_zone_phys(phys_addr_t zone_limit) { - phys_addr_t zone_mask = DMA_BIT_MASK(zone_bits); - phys_addr_t phys_start = memblock_start_of_DRAM(); - - if (phys_start > U32_MAX) - zone_mask = PHYS_ADDR_MAX; - else if (phys_start > zone_mask) - zone_mask = U32_MAX; + /** + * Information we get from firmware (e.g. DT dma-ranges) describe DMA + * bus constraints. Devices using DMA might have their own limitations. + * Some of them rely on DMA zone in low 32-bit memory. Keep low RAM + * DMA zone on platforms that have RAM there. + */ + if (memblock_start_of_DRAM() < U32_MAX) + zone_limit = min(zone_limit, U32_MAX); - return min(zone_mask, memblock_end_of_DRAM() - 1) + 1; + return min(zone_limit, memblock_end_of_DRAM() - 1) + 1; } static void __init zone_sizes_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; - unsigned int __maybe_unused acpi_zone_dma_bits; - unsigned int __maybe_unused dt_zone_dma_bits; - phys_addr_t __maybe_unused dma32_phys_limit = max_zone_phys(32); + phys_addr_t __maybe_unused acpi_zone_dma_limit; + phys_addr_t __maybe_unused dt_zone_dma_limit; + phys_addr_t __maybe_unused dma32_phys_limit = + max_zone_phys(DMA_BIT_MASK(32)); #ifdef CONFIG_ZONE_DMA - acpi_zone_dma_bits = fls64(acpi_iort_dma_get_max_cpu_address()); - dt_zone_dma_bits = fls64(of_dma_get_max_cpu_address(NULL)); - zone_dma_bits = min3(32U, dt_zone_dma_bits, acpi_zone_dma_bits); - arm64_dma_phys_limit = max_zone_phys(zone_dma_bits); + acpi_zone_dma_limit = acpi_iort_dma_get_max_cpu_address(); + dt_zone_dma_limit = of_dma_get_max_cpu_address(NULL); + zone_dma_limit = min(dt_zone_dma_limit, acpi_zone_dma_limit); + arm64_dma_phys_limit = max_zone_phys(zone_dma_limit); max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit); #endif #ifdef CONFIG_ZONE_DMA32 @@ -369,8 +367,14 @@ void __init bootmem_init(void) */ void __init mem_init(void) { + unsigned int flags = SWIOTLB_VERBOSE; bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit); + if (is_realm_world()) { + swiotlb = true; + flags |= SWIOTLB_FORCE; + } + if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) { /* * If no bouncing needed for ZONE_DMA, reduce the swiotlb @@ -382,7 +386,8 @@ void __init mem_init(void) swiotlb = true; } - swiotlb_init(swiotlb, SWIOTLB_VERBOSE); + swiotlb_init(swiotlb, flags); + swiotlb_update_mem_attributes(); /* this will put all unused low memory onto the freelists */ memblock_free_all(); @@ -414,8 +419,16 @@ void __init mem_init(void) void free_initmem(void) { - free_reserved_area(lm_alias(__init_begin), - lm_alias(__init_end), + void *lm_init_begin = lm_alias(__init_begin); + void *lm_init_end = lm_alias(__init_end); + + WARN_ON(!IS_ALIGNED((unsigned long)lm_init_begin, PAGE_SIZE)); + WARN_ON(!IS_ALIGNED((unsigned long)lm_init_end, PAGE_SIZE)); + + /* Delete __init region from memblock.reserved. */ + memblock_free(lm_init_begin, lm_init_end - lm_init_begin); + + free_reserved_area(lm_init_begin, lm_init_end, POISON_FREE_INITMEM, "unused kernel"); /* * Unmap the __init region but leave the VM area in place. This diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c index 269f2f63ab7d..6cc0b7e7eb03 100644 --- a/arch/arm64/mm/ioremap.c +++ b/arch/arm64/mm/ioremap.c @@ -3,10 +3,22 @@ #include <linux/mm.h> #include <linux/io.h> +static ioremap_prot_hook_t ioremap_prot_hook; + +int arm64_ioremap_prot_hook_register(ioremap_prot_hook_t hook) +{ + if (WARN_ON(ioremap_prot_hook)) + return -EBUSY; + + ioremap_prot_hook = hook; + return 0; +} + void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, unsigned long prot) { unsigned long last_addr = phys_addr + size - 1; + pgprot_t pgprot = __pgprot(prot); /* Don't allow outside PHYS_MASK */ if (last_addr & ~PHYS_MASK) @@ -16,7 +28,16 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr)))) return NULL; - return generic_ioremap_prot(phys_addr, size, __pgprot(prot)); + /* + * If a hook is registered (e.g. for confidential computing + * purposes), call that now and barf if it fails. + */ + if (unlikely(ioremap_prot_hook) && + WARN_ON(ioremap_prot_hook(phys_addr, size, &pgprot))) { + return NULL; + } + + return generic_ioremap_prot(phys_addr, size, pgprot); } EXPORT_SYMBOL(ioremap_prot); diff --git a/arch/arm64/mm/mem_encrypt.c b/arch/arm64/mm/mem_encrypt.c new file mode 100644 index 000000000000..ee3c0ab04384 --- /dev/null +++ b/arch/arm64/mm/mem_encrypt.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Implementation of the memory encryption/decryption API. + * + * Since the low-level details of the operation depend on the + * Confidential Computing environment (e.g. pKVM, CCA, ...), this just + * acts as a top-level dispatcher to whatever hooks may have been + * registered. + * + * Author: Will Deacon <will@kernel.org> + * Copyright (C) 2024 Google LLC + * + * "Hello, boils and ghouls!" + */ + +#include <linux/bug.h> +#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/mm.h> + +#include <asm/mem_encrypt.h> + +static const struct arm64_mem_crypt_ops *crypt_ops; + +int arm64_mem_crypt_ops_register(const struct arm64_mem_crypt_ops *ops) +{ + if (WARN_ON(crypt_ops)) + return -EBUSY; + + crypt_ops = ops; + return 0; +} + +int set_memory_encrypted(unsigned long addr, int numpages) +{ + if (likely(!crypt_ops) || WARN_ON(!PAGE_ALIGNED(addr))) + return 0; + + return crypt_ops->encrypt(addr, numpages); +} +EXPORT_SYMBOL_GPL(set_memory_encrypted); + +int set_memory_decrypted(unsigned long addr, int numpages) +{ + if (likely(!crypt_ops) || WARN_ON(!PAGE_ALIGNED(addr))) + return 0; + + return crypt_ops->decrypt(addr, numpages); +} +EXPORT_SYMBOL_GPL(set_memory_decrypted); diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index 642bdf908b22..07aeab8a7606 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -83,8 +83,15 @@ arch_initcall(adjust_protection_map); pgprot_t vm_get_page_prot(unsigned long vm_flags) { - pteval_t prot = pgprot_val(protection_map[vm_flags & + pteval_t prot; + + /* Short circuit GCS to avoid bloating the table. */ + if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) { + prot = _PAGE_GCS_RO; + } else { + prot = pgprot_val(protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]); + } if (vm_flags & VM_ARM64_BTI) prot |= PTE_GP; @@ -102,6 +109,17 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags) if (vm_flags & VM_MTE) prot |= PTE_ATTRINDX(MT_NORMAL_TAGGED); +#ifdef CONFIG_ARCH_HAS_PKEYS + if (system_supports_poe()) { + if (vm_flags & VM_PKEY_BIT0) + prot |= PTE_PO_IDX_0; + if (vm_flags & VM_PKEY_BIT1) + prot |= PTE_PO_IDX_1; + if (vm_flags & VM_PKEY_BIT2) + prot |= PTE_PO_IDX_2; + } +#endif + return __pgprot(prot); } EXPORT_SYMBOL(vm_get_page_prot); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 353ea5dc32b8..e2739b69e11b 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -25,6 +25,7 @@ #include <linux/vmalloc.h> #include <linux/set_memory.h> #include <linux/kfence.h> +#include <linux/pkeys.h> #include <asm/barrier.h> #include <asm/cputype.h> @@ -118,7 +119,7 @@ static phys_addr_t __init early_pgtable_alloc(int shift) return phys; } -bool pgattr_change_is_safe(u64 old, u64 new) +bool pgattr_change_is_safe(pteval_t old, pteval_t new) { /* * The following mapping attributes may be updated in live @@ -200,7 +201,7 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr, BUG_ON(pmd_sect(pmd)); if (pmd_none(pmd)) { - pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN; + pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF; phys_addr_t pte_phys; if (flags & NO_EXEC_MAPPINGS) @@ -287,7 +288,7 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr, */ BUG_ON(pud_sect(pud)); if (pud_none(pud)) { - pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN; + pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF; phys_addr_t pmd_phys; if (flags & NO_EXEC_MAPPINGS) @@ -332,7 +333,7 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end, pud_t *pudp; if (p4d_none(p4d)) { - p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN; + p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF; phys_addr_t pud_phys; if (flags & NO_EXEC_MAPPINGS) @@ -390,7 +391,7 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end, p4d_t *p4dp; if (pgd_none(pgd)) { - pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN; + pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF; phys_addr_t p4d_phys; if (flags & NO_EXEC_MAPPINGS) @@ -1549,3 +1550,47 @@ void __cpu_replace_ttbr1(pgd_t *pgdp, bool cnp) cpu_uninstall_idmap(); } + +#ifdef CONFIG_ARCH_HAS_PKEYS +int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long init_val) +{ + u64 new_por = POE_RXW; + u64 old_por; + u64 pkey_shift; + + if (!system_supports_poe()) + return -ENOSPC; + + /* + * This code should only be called with valid 'pkey' + * values originating from in-kernel users. Complain + * if a bad value is observed. + */ + if (WARN_ON_ONCE(pkey >= arch_max_pkey())) + return -EINVAL; + + /* Set the bits we need in POR: */ + new_por = POE_RXW; + if (init_val & PKEY_DISABLE_WRITE) + new_por &= ~POE_W; + if (init_val & PKEY_DISABLE_ACCESS) + new_por &= ~POE_RW; + if (init_val & PKEY_DISABLE_READ) + new_por &= ~POE_R; + if (init_val & PKEY_DISABLE_EXECUTE) + new_por &= ~POE_X; + + /* Shift the bits in to the correct place in POR for pkey: */ + pkey_shift = pkey * POR_BITS_PER_PKEY; + new_por <<= pkey_shift; + + /* Get old POR and mask off any old bits in place: */ + old_por = read_sysreg_s(SYS_POR_EL0); + old_por &= ~(POE_MASK << pkey_shift); + + /* Write old part along with new part: */ + write_sysreg_s(old_por | new_por, SYS_POR_EL0); + + return 0; +} +#endif diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 0e270a1c51e6..6ae6ae806454 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -5,10 +5,12 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> +#include <linux/mem_encrypt.h> #include <linux/sched.h> #include <linux/vmalloc.h> #include <asm/cacheflush.h> +#include <asm/pgtable-prot.h> #include <asm/set_memory.h> #include <asm/tlbflush.h> #include <asm/kfence.h> @@ -23,14 +25,16 @@ bool rodata_full __ro_after_init = IS_ENABLED(CONFIG_RODATA_FULL_DEFAULT_ENABLED bool can_set_direct_map(void) { /* - * rodata_full and DEBUG_PAGEALLOC require linear map to be - * mapped at page granularity, so that it is possible to + * rodata_full, DEBUG_PAGEALLOC and a Realm guest all require linear + * map to be mapped at page granularity, so that it is possible to * protect/unprotect single pages. * * KFENCE pool requires page-granular mapping if initialized late. + * + * Realms need to make pages shared/protected at page granularity. */ return rodata_full || debug_pagealloc_enabled() || - arm64_kfence_can_set_direct_map(); + arm64_kfence_can_set_direct_map() || is_realm_world(); } static int change_page_range(pte_t *ptep, unsigned long addr, void *data) @@ -60,7 +64,13 @@ static int __change_memory_common(unsigned long start, unsigned long size, ret = apply_to_page_range(&init_mm, start, size, change_page_range, &data); - flush_tlb_kernel_range(start, start + size); + /* + * If the memory is being made valid without changing any other bits + * then a TLBI isn't required as a non-valid entry cannot be cached in + * the TLB. + */ + if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask)) + flush_tlb_kernel_range(start, start + size); return ret; } @@ -192,6 +202,86 @@ int set_direct_map_default_noflush(struct page *page) PAGE_SIZE, change_page_range, &data); } +static int __set_memory_enc_dec(unsigned long addr, + int numpages, + bool encrypt) +{ + unsigned long set_prot = 0, clear_prot = 0; + phys_addr_t start, end; + int ret; + + if (!is_realm_world()) + return 0; + + if (!__is_lm_address(addr)) + return -EINVAL; + + start = __virt_to_phys(addr); + end = start + numpages * PAGE_SIZE; + + if (encrypt) + clear_prot = PROT_NS_SHARED; + else + set_prot = PROT_NS_SHARED; + + /* + * Break the mapping before we make any changes to avoid stale TLB + * entries or Synchronous External Aborts caused by RIPAS_EMPTY + */ + ret = __change_memory_common(addr, PAGE_SIZE * numpages, + __pgprot(set_prot), + __pgprot(clear_prot | PTE_VALID)); + + if (ret) + return ret; + + if (encrypt) + ret = rsi_set_memory_range_protected(start, end); + else + ret = rsi_set_memory_range_shared(start, end); + + if (ret) + return ret; + + return __change_memory_common(addr, PAGE_SIZE * numpages, + __pgprot(PTE_VALID), + __pgprot(0)); +} + +static int realm_set_memory_encrypted(unsigned long addr, int numpages) +{ + int ret = __set_memory_enc_dec(addr, numpages, true); + + /* + * If the request to change state fails, then the only sensible cause + * of action for the caller is to leak the memory + */ + WARN(ret, "Failed to encrypt memory, %d pages will be leaked", + numpages); + + return ret; +} + +static int realm_set_memory_decrypted(unsigned long addr, int numpages) +{ + int ret = __set_memory_enc_dec(addr, numpages, false); + + WARN(ret, "Failed to decrypt memory, %d pages will be leaked", + numpages); + + return ret; +} + +static const struct arm64_mem_crypt_ops realm_crypt_ops = { + .encrypt = realm_set_memory_encrypted, + .decrypt = realm_set_memory_decrypted, +}; + +int realm_register_memory_enc_ops(void) +{ + return arm64_mem_crypt_ops_register(&realm_crypt_ops); +} + #ifdef CONFIG_DEBUG_PAGEALLOC void __kernel_map_pages(struct page *page, int numpages, int enable) { diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index f4bc6c5bac06..b8edc5765441 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -36,8 +36,6 @@ #define TCR_KASLR_FLAGS 0 #endif -#define TCR_SMP_FLAGS TCR_SHARED - /* PTWs cacheable, inner/outer WBWA */ #define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA @@ -467,10 +465,12 @@ SYM_FUNC_START(__cpu_setup) */ mair .req x17 tcr .req x16 + tcr2 .req x15 mov_q mair, MAIR_EL1_SET mov_q tcr, TCR_T0SZ(IDMAP_VA_BITS) | TCR_T1SZ(VA_BITS_MIN) | TCR_CACHE_FLAGS | \ - TCR_SMP_FLAGS | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ + TCR_SHARED | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS + mov tcr2, xzr tcr_clear_errata_bits tcr, x9, x5 @@ -495,9 +495,14 @@ alternative_else_nop_endif * via capabilities. */ mrs x9, ID_AA64MMFR1_EL1 - and x9, x9, ID_AA64MMFR1_EL1_HAFDBS_MASK + ubfx x9, x9, ID_AA64MMFR1_EL1_HAFDBS_SHIFT, #4 cbz x9, 1f orr tcr, tcr, #TCR_HA // hardware Access flag update +#ifdef CONFIG_ARM64_HAFT + cmp x9, ID_AA64MMFR1_EL1_HAFDBS_HAFT + b.lt 1f + orr tcr2, tcr2, TCR2_EL1x_HAFT +#endif /* CONFIG_ARM64_HAFT */ 1: #endif /* CONFIG_ARM64_HW_AFDBM */ msr mair_el1, mair @@ -527,11 +532,16 @@ alternative_else_nop_endif #undef PTE_MAYBE_NG #undef PTE_MAYBE_SHARED - mov x0, TCR2_EL1x_PIE - msr REG_TCR2_EL1, x0 + orr tcr2, tcr2, TCR2_EL1x_PIE .Lskip_indirection: + mrs_s x1, SYS_ID_AA64MMFR3_EL1 + ubfx x1, x1, #ID_AA64MMFR3_EL1_TCRX_SHIFT, #4 + cbz x1, 1f + msr REG_TCR2_EL1, tcr2 +1: + /* * Prepare SCTLR */ @@ -540,4 +550,5 @@ alternative_else_nop_endif .unreq mair .unreq tcr + .unreq tcr2 SYM_FUNC_END(__cpu_setup) diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c index 6986827e0d64..688fbe0271ca 100644 --- a/arch/arm64/mm/ptdump.c +++ b/arch/arm64/mm/ptdump.c @@ -38,33 +38,7 @@ seq_printf(m, fmt); \ }) -/* - * The page dumper groups page table entries of the same type into a single - * description. It uses pg_state to track the range information while - * iterating over the pte entries. When the continuity is broken it then - * dumps out a description of the range. - */ -struct pg_state { - struct ptdump_state ptdump; - struct seq_file *seq; - const struct addr_marker *marker; - const struct mm_struct *mm; - unsigned long start_address; - int level; - u64 current_prot; - bool check_wx; - unsigned long wx_pages; - unsigned long uxn_pages; -}; - -struct prot_bits { - u64 mask; - u64 val; - const char *set; - const char *clear; -}; - -static const struct prot_bits pte_bits[] = { +static const struct ptdump_prot_bits pte_bits[] = { { .mask = PTE_VALID, .val = PTE_VALID, @@ -106,10 +80,10 @@ static const struct prot_bits pte_bits[] = { .set = "CON", .clear = " ", }, { - .mask = PTE_TABLE_BIT, - .val = PTE_TABLE_BIT, - .set = " ", - .clear = "BLK", + .mask = PTE_TABLE_BIT | PTE_VALID, + .val = PTE_VALID, + .set = "BLK", + .clear = " ", }, { .mask = PTE_UXN, .val = PTE_UXN, @@ -143,14 +117,7 @@ static const struct prot_bits pte_bits[] = { } }; -struct pg_level { - const struct prot_bits *bits; - char name[4]; - int num; - u64 mask; -}; - -static struct pg_level pg_level[] __ro_after_init = { +static struct ptdump_pg_level kernel_pg_levels[] __ro_after_init = { { /* pgd */ .name = "PGD", .bits = pte_bits, @@ -174,7 +141,7 @@ static struct pg_level pg_level[] __ro_after_init = { }, }; -static void dump_prot(struct pg_state *st, const struct prot_bits *bits, +static void dump_prot(struct ptdump_pg_state *st, const struct ptdump_prot_bits *bits, size_t num) { unsigned i; @@ -192,7 +159,7 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits, } } -static void note_prot_uxn(struct pg_state *st, unsigned long addr) +static void note_prot_uxn(struct ptdump_pg_state *st, unsigned long addr) { if (!st->check_wx) return; @@ -206,7 +173,7 @@ static void note_prot_uxn(struct pg_state *st, unsigned long addr) st->uxn_pages += (addr - st->start_address) / PAGE_SIZE; } -static void note_prot_wx(struct pg_state *st, unsigned long addr) +static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr) { if (!st->check_wx) return; @@ -221,16 +188,17 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr) st->wx_pages += (addr - st->start_address) / PAGE_SIZE; } -static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, - u64 val) +void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, + u64 val) { - struct pg_state *st = container_of(pt_st, struct pg_state, ptdump); + struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); + struct ptdump_pg_level *pg_level = st->pg_level; static const char units[] = "KMGTPE"; u64 prot = 0; /* check if the current level has been folded dynamically */ - if ((level == 1 && mm_p4d_folded(st->mm)) || - (level == 2 && mm_pud_folded(st->mm))) + if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) || + (level == 2 && mm_pud_folded(st->mm)))) level = 0; if (level >= 0) @@ -286,15 +254,16 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, void ptdump_walk(struct seq_file *s, struct ptdump_info *info) { unsigned long end = ~0UL; - struct pg_state st; + struct ptdump_pg_state st; if (info->base_addr < TASK_SIZE_64) end = TASK_SIZE_64; - st = (struct pg_state){ + st = (struct ptdump_pg_state){ .seq = s, .marker = info->markers, .mm = info->mm, + .pg_level = &kernel_pg_levels[0], .level = -1, .ptdump = { .note_page = note_page, @@ -312,10 +281,10 @@ static void __init ptdump_initialize(void) { unsigned i, j; - for (i = 0; i < ARRAY_SIZE(pg_level); i++) - if (pg_level[i].bits) - for (j = 0; j < pg_level[i].num; j++) - pg_level[i].mask |= pg_level[i].bits[j].mask; + for (i = 0; i < ARRAY_SIZE(kernel_pg_levels); i++) + if (kernel_pg_levels[i].bits) + for (j = 0; j < kernel_pg_levels[i].num; j++) + kernel_pg_levels[i].mask |= kernel_pg_levels[i].bits[j].mask; } static struct ptdump_info kernel_ptdump_info __ro_after_init = { @@ -324,12 +293,13 @@ static struct ptdump_info kernel_ptdump_info __ro_after_init = { bool ptdump_check_wx(void) { - struct pg_state st = { + struct ptdump_pg_state st = { .seq = NULL, .marker = (struct addr_marker[]) { { 0, NULL}, { -1, NULL}, }, + .pg_level = &kernel_pg_levels[0], .level = -1, .check_wx = true, .ptdump = { diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c index 5139a28130c0..0f7b484cb2ff 100644 --- a/arch/arm64/mm/trans_pgd.c +++ b/arch/arm64/mm/trans_pgd.c @@ -42,14 +42,16 @@ static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr) * the temporary mappings we use during restore. */ __set_pte(dst_ptep, pte_mkwrite_novma(pte)); - } else if ((debug_pagealloc_enabled() || - is_kfence_address((void *)addr)) && !pte_none(pte)) { + } else if (!pte_none(pte)) { /* * debug_pagealloc will removed the PTE_VALID bit if * the page isn't in use by the resume kernel. It may have * been in use by the original kernel, in which case we need * to put it back in our copy to do the restore. * + * Other cases include kfence / vmalloc / memfd_secret which + * may call `set_direct_map_invalid_noflush()`. + * * Before marking this entry valid, check the pfn should * be mapped. */ diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index dd0bb069df4b..5db82bfc9dc1 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -26,9 +26,8 @@ #define TMP_REG_1 (MAX_BPF_JIT_REG + 0) #define TMP_REG_2 (MAX_BPF_JIT_REG + 1) -#define TCALL_CNT (MAX_BPF_JIT_REG + 2) +#define TCCNT_PTR (MAX_BPF_JIT_REG + 2) #define TMP_REG_3 (MAX_BPF_JIT_REG + 3) -#define FP_BOTTOM (MAX_BPF_JIT_REG + 4) #define ARENA_VM_START (MAX_BPF_JIT_REG + 5) #define check_imm(bits, imm) do { \ @@ -63,11 +62,10 @@ static const int bpf2a64[] = { [TMP_REG_1] = A64_R(10), [TMP_REG_2] = A64_R(11), [TMP_REG_3] = A64_R(12), - /* tail_call_cnt */ - [TCALL_CNT] = A64_R(26), + /* tail_call_cnt_ptr */ + [TCCNT_PTR] = A64_R(26), /* temporary register for blinding constants */ [BPF_REG_AX] = A64_R(9), - [FP_BOTTOM] = A64_R(27), /* callee saved register for kern_vm_start address */ [ARENA_VM_START] = A64_R(28), }; @@ -78,11 +76,15 @@ struct jit_ctx { int epilogue_offset; int *offset; int exentry_idx; + int nr_used_callee_reg; + u8 used_callee_reg[8]; /* r6~r9, fp, arena_vm_start */ __le32 *image; __le32 *ro_image; u32 stack_size; - int fpb_offset; u64 user_vm_start; + u64 arena_vm_start; + bool fp_used; + bool write; }; struct bpf_plt { @@ -96,7 +98,7 @@ struct bpf_plt { static inline void emit(const u32 insn, struct jit_ctx *ctx) { - if (ctx->image != NULL) + if (ctx->image != NULL && ctx->write) ctx->image[ctx->idx] = cpu_to_le32(insn); ctx->idx++; @@ -181,14 +183,47 @@ static inline void emit_addr_mov_i64(const int reg, const u64 val, } } -static inline void emit_call(u64 target, struct jit_ctx *ctx) +static bool should_emit_indirect_call(long target, const struct jit_ctx *ctx) +{ + long offset; + + /* when ctx->ro_image is not allocated or the target is unknown, + * emit indirect call + */ + if (!ctx->ro_image || !target) + return true; + + offset = target - (long)&ctx->ro_image[ctx->idx]; + return offset < -SZ_128M || offset >= SZ_128M; +} + +static void emit_direct_call(u64 target, struct jit_ctx *ctx) { - u8 tmp = bpf2a64[TMP_REG_1]; + u32 insn; + unsigned long pc; + + pc = (unsigned long)&ctx->ro_image[ctx->idx]; + insn = aarch64_insn_gen_branch_imm(pc, target, AARCH64_INSN_BRANCH_LINK); + emit(insn, ctx); +} + +static void emit_indirect_call(u64 target, struct jit_ctx *ctx) +{ + u8 tmp; + tmp = bpf2a64[TMP_REG_1]; emit_addr_mov_i64(tmp, target, ctx); emit(A64_BLR(tmp), ctx); } +static void emit_call(u64 target, struct jit_ctx *ctx) +{ + if (should_emit_indirect_call((long)target, ctx)) + emit_indirect_call(target, ctx); + else + emit_direct_call(target, ctx); +} + static inline int bpf2a64_offset(int bpf_insn, int off, const struct jit_ctx *ctx) { @@ -273,21 +308,143 @@ static bool is_lsi_offset(int offset, int scale) return true; } -/* generated prologue: +/* generated main prog prologue: * bti c // if CONFIG_ARM64_BTI_KERNEL * mov x9, lr * nop // POKE_OFFSET * paciasp // if CONFIG_ARM64_PTR_AUTH_KERNEL * stp x29, lr, [sp, #-16]! * mov x29, sp - * stp x19, x20, [sp, #-16]! - * stp x21, x22, [sp, #-16]! - * stp x25, x26, [sp, #-16]! - * stp x27, x28, [sp, #-16]! - * mov x25, sp - * mov tcc, #0 + * stp xzr, x26, [sp, #-16]! + * mov x26, sp * // PROLOGUE_OFFSET + * // save callee-saved registers */ +static void prepare_bpf_tail_call_cnt(struct jit_ctx *ctx) +{ + const bool is_main_prog = !bpf_is_subprog(ctx->prog); + const u8 ptr = bpf2a64[TCCNT_PTR]; + + if (is_main_prog) { + /* Initialize tail_call_cnt. */ + emit(A64_PUSH(A64_ZR, ptr, A64_SP), ctx); + emit(A64_MOV(1, ptr, A64_SP), ctx); + } else + emit(A64_PUSH(ptr, ptr, A64_SP), ctx); +} + +static void find_used_callee_regs(struct jit_ctx *ctx) +{ + int i; + const struct bpf_prog *prog = ctx->prog; + const struct bpf_insn *insn = &prog->insnsi[0]; + int reg_used = 0; + + for (i = 0; i < prog->len; i++, insn++) { + if (insn->dst_reg == BPF_REG_6 || insn->src_reg == BPF_REG_6) + reg_used |= 1; + + if (insn->dst_reg == BPF_REG_7 || insn->src_reg == BPF_REG_7) + reg_used |= 2; + + if (insn->dst_reg == BPF_REG_8 || insn->src_reg == BPF_REG_8) + reg_used |= 4; + + if (insn->dst_reg == BPF_REG_9 || insn->src_reg == BPF_REG_9) + reg_used |= 8; + + if (insn->dst_reg == BPF_REG_FP || insn->src_reg == BPF_REG_FP) { + ctx->fp_used = true; + reg_used |= 16; + } + } + + i = 0; + if (reg_used & 1) + ctx->used_callee_reg[i++] = bpf2a64[BPF_REG_6]; + + if (reg_used & 2) + ctx->used_callee_reg[i++] = bpf2a64[BPF_REG_7]; + + if (reg_used & 4) + ctx->used_callee_reg[i++] = bpf2a64[BPF_REG_8]; + + if (reg_used & 8) + ctx->used_callee_reg[i++] = bpf2a64[BPF_REG_9]; + + if (reg_used & 16) + ctx->used_callee_reg[i++] = bpf2a64[BPF_REG_FP]; + + if (ctx->arena_vm_start) + ctx->used_callee_reg[i++] = bpf2a64[ARENA_VM_START]; + + ctx->nr_used_callee_reg = i; +} + +/* Save callee-saved registers */ +static void push_callee_regs(struct jit_ctx *ctx) +{ + int reg1, reg2, i; + + /* + * Program acting as exception boundary should save all ARM64 + * Callee-saved registers as the exception callback needs to recover + * all ARM64 Callee-saved registers in its epilogue. + */ + if (ctx->prog->aux->exception_boundary) { + emit(A64_PUSH(A64_R(19), A64_R(20), A64_SP), ctx); + emit(A64_PUSH(A64_R(21), A64_R(22), A64_SP), ctx); + emit(A64_PUSH(A64_R(23), A64_R(24), A64_SP), ctx); + emit(A64_PUSH(A64_R(25), A64_R(26), A64_SP), ctx); + emit(A64_PUSH(A64_R(27), A64_R(28), A64_SP), ctx); + } else { + find_used_callee_regs(ctx); + for (i = 0; i + 1 < ctx->nr_used_callee_reg; i += 2) { + reg1 = ctx->used_callee_reg[i]; + reg2 = ctx->used_callee_reg[i + 1]; + emit(A64_PUSH(reg1, reg2, A64_SP), ctx); + } + if (i < ctx->nr_used_callee_reg) { + reg1 = ctx->used_callee_reg[i]; + /* keep SP 16-byte aligned */ + emit(A64_PUSH(reg1, A64_ZR, A64_SP), ctx); + } + } +} + +/* Restore callee-saved registers */ +static void pop_callee_regs(struct jit_ctx *ctx) +{ + struct bpf_prog_aux *aux = ctx->prog->aux; + int reg1, reg2, i; + + /* + * Program acting as exception boundary pushes R23 and R24 in addition + * to BPF callee-saved registers. Exception callback uses the boundary + * program's stack frame, so recover these extra registers in the above + * two cases. + */ + if (aux->exception_boundary || aux->exception_cb) { + emit(A64_POP(A64_R(27), A64_R(28), A64_SP), ctx); + emit(A64_POP(A64_R(25), A64_R(26), A64_SP), ctx); + emit(A64_POP(A64_R(23), A64_R(24), A64_SP), ctx); + emit(A64_POP(A64_R(21), A64_R(22), A64_SP), ctx); + emit(A64_POP(A64_R(19), A64_R(20), A64_SP), ctx); + } else { + i = ctx->nr_used_callee_reg - 1; + if (ctx->nr_used_callee_reg % 2 != 0) { + reg1 = ctx->used_callee_reg[i]; + emit(A64_POP(reg1, A64_ZR, A64_SP), ctx); + i--; + } + while (i > 0) { + reg1 = ctx->used_callee_reg[i - 1]; + reg2 = ctx->used_callee_reg[i]; + emit(A64_POP(reg1, reg2, A64_SP), ctx); + i -= 2; + } + } +} #define BTI_INSNS (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) ? 1 : 0) #define PAC_INSNS (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) ? 1 : 0) @@ -296,20 +453,13 @@ static bool is_lsi_offset(int offset, int scale) #define POKE_OFFSET (BTI_INSNS + 1) /* Tail call offset to jump into */ -#define PROLOGUE_OFFSET (BTI_INSNS + 2 + PAC_INSNS + 8) +#define PROLOGUE_OFFSET (BTI_INSNS + 2 + PAC_INSNS + 4) -static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, - bool is_exception_cb, u64 arena_vm_start) +static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf) { const struct bpf_prog *prog = ctx->prog; const bool is_main_prog = !bpf_is_subprog(prog); - const u8 r6 = bpf2a64[BPF_REG_6]; - const u8 r7 = bpf2a64[BPF_REG_7]; - const u8 r8 = bpf2a64[BPF_REG_8]; - const u8 r9 = bpf2a64[BPF_REG_9]; const u8 fp = bpf2a64[BPF_REG_FP]; - const u8 tcc = bpf2a64[TCALL_CNT]; - const u8 fpb = bpf2a64[FP_BOTTOM]; const u8 arena_vm_base = bpf2a64[ARENA_VM_START]; const int idx0 = ctx->idx; int cur_offset; @@ -348,19 +498,28 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, emit(A64_MOV(1, A64_R(9), A64_LR), ctx); emit(A64_NOP, ctx); - if (!is_exception_cb) { + if (!prog->aux->exception_cb) { /* Sign lr */ if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL)) emit(A64_PACIASP, ctx); + /* Save FP and LR registers to stay align with ARM64 AAPCS */ emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx); emit(A64_MOV(1, A64_FP, A64_SP), ctx); - /* Save callee-saved registers */ - emit(A64_PUSH(r6, r7, A64_SP), ctx); - emit(A64_PUSH(r8, r9, A64_SP), ctx); - emit(A64_PUSH(fp, tcc, A64_SP), ctx); - emit(A64_PUSH(fpb, A64_R(28), A64_SP), ctx); + prepare_bpf_tail_call_cnt(ctx); + + if (!ebpf_from_cbpf && is_main_prog) { + cur_offset = ctx->idx - idx0; + if (cur_offset != PROLOGUE_OFFSET) { + pr_err_once("PROLOGUE_OFFSET = %d, expected %d!\n", + cur_offset, PROLOGUE_OFFSET); + return -1; + } + /* BTI landing pad for the tail call, done with a BR */ + emit_bti(A64_BTI_J, ctx); + } + push_callee_regs(ctx); } else { /* * Exception callback receives FP of Main Program as third @@ -372,58 +531,28 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf, * callee-saved registers. The exception callback will not push * anything and re-use the main program's stack. * - * 10 registers are on the stack + * 12 registers are on the stack */ - emit(A64_SUB_I(1, A64_SP, A64_FP, 80), ctx); + emit(A64_SUB_I(1, A64_SP, A64_FP, 96), ctx); } - /* Set up BPF prog stack base register */ - emit(A64_MOV(1, fp, A64_SP), ctx); - - if (!ebpf_from_cbpf && is_main_prog) { - /* Initialize tail_call_cnt */ - emit(A64_MOVZ(1, tcc, 0, 0), ctx); - - cur_offset = ctx->idx - idx0; - if (cur_offset != PROLOGUE_OFFSET) { - pr_err_once("PROLOGUE_OFFSET = %d, expected %d!\n", - cur_offset, PROLOGUE_OFFSET); - return -1; - } - - /* BTI landing pad for the tail call, done with a BR */ - emit_bti(A64_BTI_J, ctx); - } - - /* - * Program acting as exception boundary should save all ARM64 - * Callee-saved registers as the exception callback needs to recover - * all ARM64 Callee-saved registers in its epilogue. - */ - if (prog->aux->exception_boundary) { - /* - * As we are pushing two more registers, BPF_FP should be moved - * 16 bytes - */ - emit(A64_SUB_I(1, fp, fp, 16), ctx); - emit(A64_PUSH(A64_R(23), A64_R(24), A64_SP), ctx); - } - - emit(A64_SUB_I(1, fpb, fp, ctx->fpb_offset), ctx); + if (ctx->fp_used) + /* Set up BPF prog stack base register */ + emit(A64_MOV(1, fp, A64_SP), ctx); /* Stack must be multiples of 16B */ ctx->stack_size = round_up(prog->aux->stack_depth, 16); /* Set up function call stack */ - emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); + if (ctx->stack_size) + emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); - if (arena_vm_start) - emit_a64_mov_i64(arena_vm_base, arena_vm_start, ctx); + if (ctx->arena_vm_start) + emit_a64_mov_i64(arena_vm_base, ctx->arena_vm_start, ctx); return 0; } -static int out_offset = -1; /* initialized on the first pass of build_body() */ static int emit_bpf_tail_call(struct jit_ctx *ctx) { /* bpf_tail_call(void *prog_ctx, struct bpf_array *array, u64 index) */ @@ -432,11 +561,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) const u8 tmp = bpf2a64[TMP_REG_1]; const u8 prg = bpf2a64[TMP_REG_2]; - const u8 tcc = bpf2a64[TCALL_CNT]; - const int idx0 = ctx->idx; -#define cur_offset (ctx->idx - idx0) -#define jmp_offset (out_offset - (cur_offset)) + const u8 tcc = bpf2a64[TMP_REG_3]; + const u8 ptr = bpf2a64[TCCNT_PTR]; size_t off; + __le32 *branch1 = NULL; + __le32 *branch2 = NULL; + __le32 *branch3 = NULL; /* if (index >= array->map.max_entries) * goto out; @@ -446,16 +576,20 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) emit(A64_LDR32(tmp, r2, tmp), ctx); emit(A64_MOV(0, r3, r3), ctx); emit(A64_CMP(0, r3, tmp), ctx); - emit(A64_B_(A64_COND_CS, jmp_offset), ctx); + branch1 = ctx->image + ctx->idx; + emit(A64_NOP, ctx); /* - * if (tail_call_cnt >= MAX_TAIL_CALL_CNT) + * if ((*tail_call_cnt_ptr) >= MAX_TAIL_CALL_CNT) * goto out; - * tail_call_cnt++; */ emit_a64_mov_i64(tmp, MAX_TAIL_CALL_CNT, ctx); + emit(A64_LDR64I(tcc, ptr, 0), ctx); emit(A64_CMP(1, tcc, tmp), ctx); - emit(A64_B_(A64_COND_CS, jmp_offset), ctx); + branch2 = ctx->image + ctx->idx; + emit(A64_NOP, ctx); + + /* (*tail_call_cnt_ptr)++; */ emit(A64_ADD_I(1, tcc, tcc, 1), ctx); /* prog = array->ptrs[index]; @@ -467,27 +601,37 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) emit(A64_ADD(1, tmp, r2, tmp), ctx); emit(A64_LSL(1, prg, r3, 3), ctx); emit(A64_LDR64(prg, tmp, prg), ctx); - emit(A64_CBZ(1, prg, jmp_offset), ctx); + branch3 = ctx->image + ctx->idx; + emit(A64_NOP, ctx); + + /* Update tail_call_cnt if the slot is populated. */ + emit(A64_STR64I(tcc, ptr, 0), ctx); + + /* restore SP */ + if (ctx->stack_size) + emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); + + pop_callee_regs(ctx); /* goto *(prog->bpf_func + prologue_offset); */ off = offsetof(struct bpf_prog, bpf_func); emit_a64_mov_i64(tmp, off, ctx); emit(A64_LDR64(tmp, prg, tmp), ctx); emit(A64_ADD_I(1, tmp, tmp, sizeof(u32) * PROLOGUE_OFFSET), ctx); - emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); emit(A64_BR(tmp), ctx); - /* out: */ - if (out_offset == -1) - out_offset = cur_offset; - if (cur_offset != out_offset) { - pr_err_once("tail_call out_offset = %d, expected %d!\n", - cur_offset, out_offset); - return -1; + if (ctx->image) { + off = &ctx->image[ctx->idx] - branch1; + *branch1 = cpu_to_le32(A64_B_(A64_COND_CS, off)); + + off = &ctx->image[ctx->idx] - branch2; + *branch2 = cpu_to_le32(A64_B_(A64_COND_CS, off)); + + off = &ctx->image[ctx->idx] - branch3; + *branch3 = cpu_to_le32(A64_CBZ(1, prg, off)); } + return 0; -#undef cur_offset -#undef jmp_offset } #ifdef CONFIG_ARM64_LSE_ATOMICS @@ -713,36 +857,18 @@ static void build_plt(struct jit_ctx *ctx) plt->target = (u64)&dummy_tramp; } -static void build_epilogue(struct jit_ctx *ctx, bool is_exception_cb) +static void build_epilogue(struct jit_ctx *ctx) { const u8 r0 = bpf2a64[BPF_REG_0]; - const u8 r6 = bpf2a64[BPF_REG_6]; - const u8 r7 = bpf2a64[BPF_REG_7]; - const u8 r8 = bpf2a64[BPF_REG_8]; - const u8 r9 = bpf2a64[BPF_REG_9]; - const u8 fp = bpf2a64[BPF_REG_FP]; - const u8 fpb = bpf2a64[FP_BOTTOM]; + const u8 ptr = bpf2a64[TCCNT_PTR]; /* We're done with BPF stack */ - emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); + if (ctx->stack_size) + emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx); - /* - * Program acting as exception boundary pushes R23 and R24 in addition - * to BPF callee-saved registers. Exception callback uses the boundary - * program's stack frame, so recover these extra registers in the above - * two cases. - */ - if (ctx->prog->aux->exception_boundary || is_exception_cb) - emit(A64_POP(A64_R(23), A64_R(24), A64_SP), ctx); + pop_callee_regs(ctx); - /* Restore x27 and x28 */ - emit(A64_POP(fpb, A64_R(28), A64_SP), ctx); - /* Restore fs (x25) and x26 */ - emit(A64_POP(fp, A64_R(26), A64_SP), ctx); - - /* Restore callee-saved register */ - emit(A64_POP(r8, r9, A64_SP), ctx); - emit(A64_POP(r6, r7, A64_SP), ctx); + emit(A64_POP(A64_ZR, ptr, A64_SP), ctx); /* Restore FP/LR registers */ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); @@ -862,7 +988,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, const u8 tmp = bpf2a64[TMP_REG_1]; const u8 tmp2 = bpf2a64[TMP_REG_2]; const u8 fp = bpf2a64[BPF_REG_FP]; - const u8 fpb = bpf2a64[FP_BOTTOM]; const u8 arena_vm_base = bpf2a64[ARENA_VM_START]; const s16 off = insn->off; const s32 imm = insn->imm; @@ -1314,9 +1439,9 @@ emit_cond_jmp: emit(A64_ADD(1, tmp2, src, arena_vm_base), ctx); src = tmp2; } - if (ctx->fpb_offset > 0 && src == fp && BPF_MODE(insn->code) != BPF_PROBE_MEM32) { - src_adj = fpb; - off_adj = off + ctx->fpb_offset; + if (src == fp) { + src_adj = A64_SP; + off_adj = off + ctx->stack_size; } else { src_adj = src; off_adj = off; @@ -1407,9 +1532,9 @@ emit_cond_jmp: emit(A64_ADD(1, tmp2, dst, arena_vm_base), ctx); dst = tmp2; } - if (ctx->fpb_offset > 0 && dst == fp && BPF_MODE(insn->code) != BPF_PROBE_MEM32) { - dst_adj = fpb; - off_adj = off + ctx->fpb_offset; + if (dst == fp) { + dst_adj = A64_SP; + off_adj = off + ctx->stack_size; } else { dst_adj = dst; off_adj = off; @@ -1469,9 +1594,9 @@ emit_cond_jmp: emit(A64_ADD(1, tmp2, dst, arena_vm_base), ctx); dst = tmp2; } - if (ctx->fpb_offset > 0 && dst == fp && BPF_MODE(insn->code) != BPF_PROBE_MEM32) { - dst_adj = fpb; - off_adj = off + ctx->fpb_offset; + if (dst == fp) { + dst_adj = A64_SP; + off_adj = off + ctx->stack_size; } else { dst_adj = dst; off_adj = off; @@ -1540,79 +1665,6 @@ emit_cond_jmp: return 0; } -/* - * Return 0 if FP may change at runtime, otherwise find the minimum negative - * offset to FP, converts it to positive number, and align down to 8 bytes. - */ -static int find_fpb_offset(struct bpf_prog *prog) -{ - int i; - int offset = 0; - - for (i = 0; i < prog->len; i++) { - const struct bpf_insn *insn = &prog->insnsi[i]; - const u8 class = BPF_CLASS(insn->code); - const u8 mode = BPF_MODE(insn->code); - const u8 src = insn->src_reg; - const u8 dst = insn->dst_reg; - const s32 imm = insn->imm; - const s16 off = insn->off; - - switch (class) { - case BPF_STX: - case BPF_ST: - /* fp holds atomic operation result */ - if (class == BPF_STX && mode == BPF_ATOMIC && - ((imm == BPF_XCHG || - imm == (BPF_FETCH | BPF_ADD) || - imm == (BPF_FETCH | BPF_AND) || - imm == (BPF_FETCH | BPF_XOR) || - imm == (BPF_FETCH | BPF_OR)) && - src == BPF_REG_FP)) - return 0; - - if (mode == BPF_MEM && dst == BPF_REG_FP && - off < offset) - offset = insn->off; - break; - - case BPF_JMP32: - case BPF_JMP: - break; - - case BPF_LDX: - case BPF_LD: - /* fp holds load result */ - if (dst == BPF_REG_FP) - return 0; - - if (class == BPF_LDX && mode == BPF_MEM && - src == BPF_REG_FP && off < offset) - offset = off; - break; - - case BPF_ALU: - case BPF_ALU64: - default: - /* fp holds ALU result */ - if (dst == BPF_REG_FP) - return 0; - } - } - - if (offset < 0) { - /* - * safely be converted to a positive 'int', since insn->off - * is 's16' - */ - offset = -offset; - /* align down to 8 bytes */ - offset = ALIGN_DOWN(offset, 8); - } - - return offset; -} - static int build_body(struct jit_ctx *ctx, bool extra_pass) { const struct bpf_prog *prog = ctx->prog; @@ -1631,13 +1683,11 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass) const struct bpf_insn *insn = &prog->insnsi[i]; int ret; - if (ctx->image == NULL) - ctx->offset[i] = ctx->idx; + ctx->offset[i] = ctx->idx; ret = build_insn(insn, ctx, extra_pass); if (ret > 0) { i++; - if (ctx->image == NULL) - ctx->offset[i] = ctx->idx; + ctx->offset[i] = ctx->idx; continue; } if (ret) @@ -1648,8 +1698,7 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass) * the last element with the offset after the last * instruction (end of program) */ - if (ctx->image == NULL) - ctx->offset[i] = ctx->idx; + ctx->offset[i] = ctx->idx; return 0; } @@ -1701,9 +1750,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) bool tmp_blinded = false; bool extra_pass = false; struct jit_ctx ctx; - u64 arena_vm_start; u8 *image_ptr; u8 *ro_image_ptr; + int body_idx; + int exentry_idx; if (!prog->jit_requested) return orig_prog; @@ -1719,7 +1769,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = tmp; } - arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena); jit_data = prog->aux->jit_data; if (!jit_data) { jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL); @@ -1749,17 +1798,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) goto out_off; } - ctx.fpb_offset = find_fpb_offset(prog); ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena); + ctx.arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena); - /* - * 1. Initial fake pass to compute ctx->idx and ctx->offset. + /* Pass 1: Estimate the maximum image size. * * BPF line info needs ctx->offset[i] to be the offset of * instruction[i] in jited image, so build prologue first. */ - if (build_prologue(&ctx, was_classic, prog->aux->exception_cb, - arena_vm_start)) { + if (build_prologue(&ctx, was_classic)) { prog = orig_prog; goto out_off; } @@ -1770,14 +1817,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) } ctx.epilogue_offset = ctx.idx; - build_epilogue(&ctx, prog->aux->exception_cb); + build_epilogue(&ctx); build_plt(&ctx); extable_align = __alignof__(struct exception_table_entry); extable_size = prog->aux->num_exentries * sizeof(struct exception_table_entry); - /* Now we know the actual image size. */ + /* Now we know the maximum image size. */ prog_size = sizeof(u32) * ctx.idx; /* also allocate space for plt target */ extable_offset = round_up(prog_size + PLT_TARGET_SIZE, extable_align); @@ -1790,7 +1837,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) goto out_off; } - /* 2. Now, the actual pass. */ + /* Pass 2: Determine jited position and result for each instruction */ /* * Use the image(RW) for writing the JITed instructions. But also save @@ -1806,30 +1853,56 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) skip_init_ctx: ctx.idx = 0; ctx.exentry_idx = 0; + ctx.write = true; + + build_prologue(&ctx, was_classic); - build_prologue(&ctx, was_classic, prog->aux->exception_cb, arena_vm_start); + /* Record exentry_idx and body_idx before first build_body */ + exentry_idx = ctx.exentry_idx; + body_idx = ctx.idx; + /* Dont write body instructions to memory for now */ + ctx.write = false; if (build_body(&ctx, extra_pass)) { prog = orig_prog; goto out_free_hdr; } - build_epilogue(&ctx, prog->aux->exception_cb); + ctx.epilogue_offset = ctx.idx; + ctx.exentry_idx = exentry_idx; + ctx.idx = body_idx; + ctx.write = true; + + /* Pass 3: Adjust jump offset and write final image */ + if (build_body(&ctx, extra_pass) || + WARN_ON_ONCE(ctx.idx != ctx.epilogue_offset)) { + prog = orig_prog; + goto out_free_hdr; + } + + build_epilogue(&ctx); build_plt(&ctx); - /* 3. Extra pass to validate JITed code. */ + /* Extra pass to validate JITed code. */ if (validate_ctx(&ctx)) { prog = orig_prog; goto out_free_hdr; } + /* update the real prog size */ + prog_size = sizeof(u32) * ctx.idx; + /* And we're done. */ if (bpf_jit_enable > 1) bpf_jit_dump(prog->len, prog_size, 2, ctx.image); if (!prog->is_func || extra_pass) { - if (extra_pass && ctx.idx != jit_data->ctx.idx) { - pr_err_once("multi-func JIT bug %d != %d\n", + /* The jited image may shrink since the jited result for + * BPF_CALL to subprog may be changed from indirect call + * to direct call. + */ + if (extra_pass && ctx.idx > jit_data->ctx.idx) { + pr_err_once("multi-func JIT bug %d > %d\n", ctx.idx, jit_data->ctx.idx); prog->bpf_func = NULL; prog->jited = 0; @@ -2147,7 +2220,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx); if (flags & BPF_TRAMP_F_CALL_ORIG) { - emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); + /* for the first pass, assume the worst case */ + if (!ctx->image) + ctx->idx += 4; + else + emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); emit_call((const u64)__bpf_tramp_enter, ctx); } @@ -2191,7 +2268,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im, if (flags & BPF_TRAMP_F_CALL_ORIG) { im->ip_epilogue = ctx->ro_image + ctx->idx; - emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); + /* for the first pass, assume the worst case */ + if (!ctx->image) + ctx->idx += 4; + else + emit_a64_mov_i64(A64_R(0), (const u64)im, ctx); emit_call((const u64)__bpf_tramp_exit, ctx); } @@ -2300,6 +2381,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image, .image = image, .ro_image = ro_image, .idx = 0, + .write = true, }; nregs = btf_func_model_nregs(m); diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps index ac3429d892b9..8dfb2fa51d12 100644 --- a/arch/arm64/tools/cpucaps +++ b/arch/arm64/tools/cpucaps @@ -29,6 +29,7 @@ HAS_EVT HAS_FPMR HAS_FGT HAS_FPSIMD +HAS_GCS HAS_GENERIC_AUTH HAS_GENERIC_AUTH_ARCH_QARMA3 HAS_GENERIC_AUTH_ARCH_QARMA5 @@ -45,6 +46,7 @@ HAS_MOPS HAS_NESTED_VIRT HAS_PAN HAS_S1PIE +HAS_S1POE HAS_RAS_EXTN HAS_RNG HAS_SB @@ -55,6 +57,7 @@ HAS_TLB_RANGE HAS_VA52 HAS_VIRT_HOST_EXTN HAS_WFXT +HAFT HW_DBM KVM_HVHE KVM_PROTECTED_MODE diff --git a/arch/arm64/tools/syscall_32.tbl b/arch/arm64/tools/syscall_32.tbl index 9a37930d4e26..69a829912a05 100644 --- a/arch/arm64/tools/syscall_32.tbl +++ b/arch/arm64/tools/syscall_32.tbl @@ -474,3 +474,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 7ceaa1e0b4bc..283279af932c 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -1238,6 +1238,7 @@ UnsignedEnum 11:8 PMUVer 0b0110 V3P5 0b0111 V3P7 0b1000 V3P8 + 0b1001 V3P9 0b1111 IMP_DEF EndEnum UnsignedEnum 7:4 TraceVer @@ -1648,6 +1649,8 @@ EndEnum UnsignedEnum 39:36 ETS 0b0000 NI 0b0001 IMP + 0b0010 ETS2 + 0b0011 ETS3 EndEnum UnsignedEnum 35:32 TWED 0b0000 NI @@ -1688,6 +1691,8 @@ UnsignedEnum 3:0 HAFDBS 0b0000 NI 0b0001 AF 0b0010 DBM + 0b0011 HAFT + 0b0100 HDBSS EndEnum EndSysreg @@ -2029,6 +2034,31 @@ Sysreg FAR_EL1 3 0 6 0 0 Field 63:0 ADDR EndSysreg +Sysreg PMICNTR_EL0 3 3 9 4 0 +Field 63:0 ICNT +EndSysreg + +Sysreg PMICFILTR_EL0 3 3 9 6 0 +Res0 63:59 +Field 58 SYNC +Field 57:56 VS +Res0 55:32 +Field 31 P +Field 30 U +Field 29 NSK +Field 28 NSU +Field 27 NSH +Field 26 M +Res0 25 +Field 24 SH +Field 23 T +Field 22 RLK +Field 21 RLU +Field 20 RLH +Res0 19:16 +Field 15:0 evtCount +EndSysreg + Sysreg PMSCR_EL1 3 0 9 9 0 Res0 63:8 Field 7:6 PCT @@ -2153,6 +2183,18 @@ Field 4 P Field 3:0 ALIGN EndSysreg +Sysreg PMUACR_EL1 3 0 9 14 4 +Res0 63:33 +Field 32 F0 +Field 31 C +Field 30:0 P +EndSysreg + +Sysreg PMSELR_EL0 3 3 9 12 5 +Res0 63:5 +Field 4:0 SEL +EndSysreg + SysregFields CONTEXTIDR_ELx Res0 63:32 Field 31:0 PROCID diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 5479707eb5d1..acc431c331b0 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -64,9 +64,6 @@ config CSKY select GENERIC_IRQ_MULTI_HANDLER select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD - select GENERIC_TIME_VSYSCALL - select GENERIC_VDSO_32 - select GENERIC_GETTIMEOFDAY select GX6605S_TIMER if CPU_CK610 select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_AUDITSYSCALL @@ -80,7 +77,6 @@ config CSKY select HAVE_DEBUG_KMEMLEAK select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE_WITH_REGS - select HAVE_GENERIC_VDSO select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_ERROR_INJECTION diff --git a/arch/csky/abiv1/mmap.c b/arch/csky/abiv1/mmap.c index 7f826331d409..1047865e82a9 100644 --- a/arch/csky/abiv1/mmap.c +++ b/arch/csky/abiv1/mmap.c @@ -23,7 +23,8 @@ */ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, + unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h index 0ca6c408c07f..f8beae295afb 100644 --- a/arch/csky/include/asm/page.h +++ b/arch/csky/include/asm/page.h @@ -7,12 +7,8 @@ #include <asm/cache.h> #include <linux/const.h> -/* - * PAGE_SHIFT determines the page size: 4KB - */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) +#include <vdso/page.h> + #define THREAD_SIZE (PAGE_SIZE * 2) #define THREAD_MASK (~(THREAD_SIZE - 1)) #define THREAD_SHIFT (PAGE_SHIFT + 1) diff --git a/arch/csky/include/asm/vdso/clocksource.h b/arch/csky/include/asm/vdso/clocksource.h deleted file mode 100644 index dfca7b4724b7..000000000000 --- a/arch/csky/include/asm/vdso/clocksource.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef __ASM_VDSO_CSKY_CLOCKSOURCE_H -#define __ASM_VDSO_CSKY_CLOCKSOURCE_H - -#define VDSO_ARCH_CLOCKMODES \ - VDSO_CLOCKMODE_ARCHTIMER - -#endif /* __ASM_VDSO_CSKY_CLOCKSOURCE_H */ diff --git a/arch/csky/include/asm/vdso/gettimeofday.h b/arch/csky/include/asm/vdso/gettimeofday.h deleted file mode 100644 index 6c4f1446944f..000000000000 --- a/arch/csky/include/asm/vdso/gettimeofday.h +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef __ASM_VDSO_CSKY_GETTIMEOFDAY_H -#define __ASM_VDSO_CSKY_GETTIMEOFDAY_H - -#ifndef __ASSEMBLY__ - -#include <asm/barrier.h> -#include <asm/unistd.h> -#include <abi/regdef.h> -#include <uapi/linux/time.h> - -#define VDSO_HAS_CLOCK_GETRES 1 - -static __always_inline -int gettimeofday_fallback(struct __kernel_old_timeval *_tv, - struct timezone *_tz) -{ - register struct __kernel_old_timeval *tv asm("a0") = _tv; - register struct timezone *tz asm("a1") = _tz; - register long ret asm("a0"); - register long nr asm(syscallid) = __NR_gettimeofday; - - asm volatile ("trap 0\n" - : "=r" (ret) - : "r"(tv), "r"(tz), "r"(nr) - : "memory"); - - return ret; -} - -static __always_inline -long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) -{ - register clockid_t clkid asm("a0") = _clkid; - register struct __kernel_timespec *ts asm("a1") = _ts; - register long ret asm("a0"); - register long nr asm(syscallid) = __NR_clock_gettime64; - - asm volatile ("trap 0\n" - : "=r" (ret) - : "r"(clkid), "r"(ts), "r"(nr) - : "memory"); - - return ret; -} - -static __always_inline -long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) -{ - register clockid_t clkid asm("a0") = _clkid; - register struct old_timespec32 *ts asm("a1") = _ts; - register long ret asm("a0"); - register long nr asm(syscallid) = __NR_clock_gettime; - - asm volatile ("trap 0\n" - : "=r" (ret) - : "r"(clkid), "r"(ts), "r"(nr) - : "memory"); - - return ret; -} - -static __always_inline -int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) -{ - register clockid_t clkid asm("a0") = _clkid; - register struct __kernel_timespec *ts asm("a1") = _ts; - register long ret asm("a0"); - register long nr asm(syscallid) = __NR_clock_getres_time64; - - asm volatile ("trap 0\n" - : "=r" (ret) - : "r"(clkid), "r"(ts), "r"(nr) - : "memory"); - - return ret; -} - -static __always_inline -int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) -{ - register clockid_t clkid asm("a0") = _clkid; - register struct old_timespec32 *ts asm("a1") = _ts; - register long ret asm("a0"); - register long nr asm(syscallid) = __NR_clock_getres; - - asm volatile ("trap 0\n" - : "=r" (ret) - : "r"(clkid), "r"(ts), "r"(nr) - : "memory"); - - return ret; -} - -uint64_t csky_pmu_read_cc(void); -static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, - const struct vdso_data *vd) -{ -#ifdef CONFIG_CSKY_PMU_V1 - return csky_pmu_read_cc(); -#else - return 0; -#endif -} - -static __always_inline const struct vdso_data *__arch_get_vdso_data(void) -{ - return _vdso_data; -} - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_VDSO_CSKY_GETTIMEOFDAY_H */ diff --git a/arch/csky/include/asm/vdso/processor.h b/arch/csky/include/asm/vdso/processor.h deleted file mode 100644 index 39a6b561d0cc..000000000000 --- a/arch/csky/include/asm/vdso/processor.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __ASM_VDSO_CSKY_PROCESSOR_H -#define __ASM_VDSO_CSKY_PROCESSOR_H - -#ifndef __ASSEMBLY__ - -#define cpu_relax() barrier() - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_VDSO_CSKY_PROCESSOR_H */ diff --git a/arch/csky/include/asm/vdso/vsyscall.h b/arch/csky/include/asm/vdso/vsyscall.h deleted file mode 100644 index c276211a7c4d..000000000000 --- a/arch/csky/include/asm/vdso/vsyscall.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef __ASM_VDSO_CSKY_VSYSCALL_H -#define __ASM_VDSO_CSKY_VSYSCALL_H - -#ifndef __ASSEMBLY__ - -#include <vdso/datapage.h> - -extern struct vdso_data *vdso_data; - -static __always_inline struct vdso_data *__csky_get_k_vdso_data(void) -{ - return vdso_data; -} -#define __arch_get_k_vdso_data __csky_get_k_vdso_data - -#include <asm-generic/vdso/vsyscall.h> - -#endif /* !__ASSEMBLY__ */ - -#endif /* __ASM_VDSO_CSKY_VSYSCALL_H */ diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c index 51012e90780d..fe715b707fd0 100644 --- a/arch/csky/kernel/setup.c +++ b/arch/csky/kernel/setup.c @@ -112,9 +112,9 @@ asmlinkage __visible void __init csky_start(unsigned int unused, pre_trap_init(); if (dtb_start == NULL) - early_init_dt_scan(__dtb_start); + early_init_dt_scan(__dtb_start, __pa(dtb_start)); else - early_init_dt_scan(dtb_start); + early_init_dt_scan(dtb_start, __pa(dtb_start)); start_kernel(); diff --git a/arch/csky/kernel/vdso.c b/arch/csky/kernel/vdso.c index 2ca886e4a458..c54d019d66bc 100644 --- a/arch/csky/kernel/vdso.c +++ b/arch/csky/kernel/vdso.c @@ -8,23 +8,19 @@ #include <linux/slab.h> #include <asm/page.h> -#include <vdso/datapage.h> extern char vdso_start[], vdso_end[]; static unsigned int vdso_pages; static struct page **vdso_pagelist; -static union vdso_data_store vdso_data_store __page_aligned_data; -struct vdso_data *vdso_data = vdso_data_store.data; - static int __init vdso_init(void) { unsigned int i; vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; vdso_pagelist = - kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL); + kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL); if (unlikely(vdso_pagelist == NULL)) { pr_err("vdso: pagelist allocation failed\n"); return -ENOMEM; @@ -36,7 +32,6 @@ static int __init vdso_init(void) pg = virt_to_page(vdso_start + (i << PAGE_SHIFT)); vdso_pagelist[i] = pg; } - vdso_pagelist[i] = virt_to_page(vdso_data); return 0; } @@ -45,11 +40,15 @@ arch_initcall(vdso_init); int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { + struct vm_area_struct *vma; struct mm_struct *mm = current->mm; unsigned long vdso_base, vdso_len; int ret; + static struct vm_special_mapping vdso_mapping = { + .name = "[vdso]", + }; - vdso_len = (vdso_pages + 1) << PAGE_SHIFT; + vdso_len = vdso_pages << PAGE_SHIFT; mmap_write_lock(mm); vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0); @@ -65,33 +64,21 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, */ mm->context.vdso = (void *)vdso_base; - ret = - install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT, + vdso_mapping.pages = vdso_pagelist; + vma = + _install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT, (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC), - vdso_pagelist); + &vdso_mapping); - if (unlikely(ret)) { + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); mm->context.vdso = NULL; goto end; } vdso_base += (vdso_pages << PAGE_SHIFT); - ret = install_special_mapping(mm, vdso_base, PAGE_SIZE, - (VM_READ | VM_MAYREAD), &vdso_pagelist[vdso_pages]); - - if (unlikely(ret)) - mm->context.vdso = NULL; + ret = 0; end: mmap_write_unlock(mm); return ret; } - -const char *arch_vma_name(struct vm_area_struct *vma) -{ - if (vma->vm_mm && (vma->vm_start == (long)vma->vm_mm->context.vdso)) - return "[vdso]"; - if (vma->vm_mm && (vma->vm_start == - (long)vma->vm_mm->context.vdso + PAGE_SIZE)) - return "[vdso_data]"; - return NULL; -} diff --git a/arch/csky/kernel/vdso/Makefile b/arch/csky/kernel/vdso/Makefile index bc2261f5a8d4..069ef0b17fe5 100644 --- a/arch/csky/kernel/vdso/Makefile +++ b/arch/csky/kernel/vdso/Makefile @@ -5,7 +5,6 @@ include $(srctree)/lib/vdso/Makefile # Symbols present in the vdso vdso-syms += rt_sigreturn -vdso-syms += vgettimeofday # Files to link into the vdso obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o diff --git a/arch/csky/kernel/vdso/vdso.lds.S b/arch/csky/kernel/vdso/vdso.lds.S index 590a6c79fff7..8d226252d439 100644 --- a/arch/csky/kernel/vdso/vdso.lds.S +++ b/arch/csky/kernel/vdso/vdso.lds.S @@ -49,10 +49,6 @@ VERSION LINUX_5.10 { global: __vdso_rt_sigreturn; - __vdso_clock_gettime; - __vdso_clock_gettime64; - __vdso_gettimeofday; - __vdso_clock_getres; local: *; }; } diff --git a/arch/csky/kernel/vdso/vgettimeofday.c b/arch/csky/kernel/vdso/vgettimeofday.c deleted file mode 100644 index 55af30e83752..000000000000 --- a/arch/csky/kernel/vdso/vgettimeofday.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include <linux/time.h> -#include <linux/types.h> -#include <vdso/gettime.h> - -extern -int __vdso_clock_gettime(clockid_t clock, - struct old_timespec32 *ts) -{ - return __cvdso_clock_gettime32(clock, ts); -} - -int __vdso_clock_gettime64(clockid_t clock, - struct __kernel_timespec *ts) -{ - return __cvdso_clock_gettime(clock, ts); -} - -int __vdso_gettimeofday(struct __kernel_old_timeval *tv, - struct timezone *tz) -{ - return __cvdso_gettimeofday(tv, tz); -} - -int __vdso_clock_getres(clockid_t clock_id, - struct old_timespec32 *res) -{ - return __cvdso_clock_getres_time32(clock_id, res); -} diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h index 8a6af57274c2..b01f8df69dd4 100644 --- a/arch/hexagon/include/asm/page.h +++ b/arch/hexagon/include/asm/page.h @@ -45,9 +45,7 @@ #define HVM_HUGEPAGE_SIZE 0x5 #endif -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +#include <vdso/page.h> #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c index 2e4872d62124..8119084dc519 100644 --- a/arch/hexagon/kernel/vdso.c +++ b/arch/hexagon/kernel/vdso.c @@ -51,7 +51,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { int ret; unsigned long vdso_base; + struct vm_area_struct *vma; struct mm_struct *mm = current->mm; + static struct vm_special_mapping vdso_mapping = { + .name = "[vdso]", + }; if (mmap_write_lock_killable(mm)) return -EINTR; @@ -66,16 +70,18 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) } /* MAYWRITE to allow gdb to COW and set breakpoints. */ - ret = install_special_mapping(mm, vdso_base, PAGE_SIZE, + vdso_mapping.pages = &vdso_page; + vma = _install_special_mapping(mm, vdso_base, PAGE_SIZE, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - &vdso_page); + &vdso_mapping); - if (ret) + ret = PTR_ERR(vma); + if (IS_ERR(vma)) goto up_fail; mm->context.vdso = (void *)vdso_base; - + ret = 0; up_fail: mmap_write_unlock(mm); return ret; diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 70f169210b52..d9fce0fd475a 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -25,6 +25,8 @@ config LOONGARCH select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_PTE_DEVMAP select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_SET_MEMORY + select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_INLINE_READ_LOCK if !PREEMPTION select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION @@ -82,9 +84,11 @@ config LOONGARCH select GENERIC_CMOS_UPDATE select GENERIC_CPU_AUTOPROBE select GENERIC_CPU_DEVICES + select GENERIC_CPU_VULNERABILITIES select GENERIC_ENTRY select GENERIC_GETTIMEOFDAY select GENERIC_IOREMAP if !ARCH_IOREMAP + select GENERIC_IRQ_MATRIX_ALLOCATOR select GENERIC_IRQ_MULTI_HANDLER select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW @@ -146,7 +150,7 @@ config LOONGARCH select HAVE_LIVEPATCH select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI - select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB && !CC_IS_CLANG + select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB select HAVE_PCI select HAVE_PERF_EVENTS select HAVE_PERF_REGS @@ -190,6 +194,7 @@ config LOONGARCH select TRACE_IRQFLAGS_SUPPORT select USE_PERCPU_NUMA_NODE_ID select USER_STACKTRACE_SUPPORT + select VDSO_GETRANDOM select ZONE_DMA32 config 32BIT @@ -265,7 +270,7 @@ config AS_HAS_FCSR_CLASS def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0) config AS_HAS_THIN_ADD_SUB - def_bool $(cc-option,-Wa$(comma)-mthin-add-sub) + def_bool $(cc-option,-Wa$(comma)-mthin-add-sub) || AS_IS_LLVM config AS_HAS_LSX_EXTENSION def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0) @@ -599,6 +604,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_CRASH_DUMP def_bool y +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config ARCH_SELECTS_CRASH_DUMP def_bool y depends on CRASH_DUMP diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index b4252c357c8e..75b366407a60 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -96,7 +96,6 @@ CONFIG_ZPOOL=y CONFIG_ZSWAP=y CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y CONFIG_ZBUD=y -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=m # CONFIG_COMPAT_BRK is not set CONFIG_MEMORY_HOTPLUG=y diff --git a/arch/loongarch/crypto/crc32-loongarch.c b/arch/loongarch/crypto/crc32-loongarch.c index 3eebea3a7b47..b7d9782827f5 100644 --- a/arch/loongarch/crypto/crc32-loongarch.c +++ b/arch/loongarch/crypto/crc32-loongarch.c @@ -13,7 +13,7 @@ #include <crypto/internal/hash.h> #include <asm/cpu-features.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define _CRC32(crc, value, size, type) \ do { \ diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild index 2bb3676429c0..5b5a6c90e6e2 100644 --- a/arch/loongarch/include/asm/Kbuild +++ b/arch/loongarch/include/asm/Kbuild @@ -6,8 +6,8 @@ generic-y += mcs_spinlock.h generic-y += parport.h generic-y += early_ioremap.h generic-y += qrwlock.h -generic-y += qspinlock.h generic-y += user.h generic-y += ioctl.h +generic-y += mmzone.h generic-y += statfs.h generic-y += param.h diff --git a/arch/loongarch/include/asm/atomic.h b/arch/loongarch/include/asm/atomic.h index 99af8b3160a8..c86f0ab922ec 100644 --- a/arch/loongarch/include/asm/atomic.h +++ b/arch/loongarch/include/asm/atomic.h @@ -15,6 +15,7 @@ #define __LL "ll.w " #define __SC "sc.w " #define __AMADD "amadd.w " +#define __AMOR "amor.w " #define __AMAND_DB "amand_db.w " #define __AMOR_DB "amor_db.w " #define __AMXOR_DB "amxor_db.w " @@ -22,6 +23,7 @@ #define __LL "ll.d " #define __SC "sc.d " #define __AMADD "amadd.d " +#define __AMOR "amor.d " #define __AMAND_DB "amand_db.d " #define __AMOR_DB "amor_db.d " #define __AMXOR_DB "amxor_db.d " diff --git a/arch/loongarch/include/asm/bootinfo.h b/arch/loongarch/include/asm/bootinfo.h index 6d5846dd075c..7657e016233f 100644 --- a/arch/loongarch/include/asm/bootinfo.h +++ b/arch/loongarch/include/asm/bootinfo.h @@ -26,6 +26,10 @@ struct loongson_board_info { #define NR_WORDS DIV_ROUND_UP(NR_CPUS, BITS_PER_LONG) +/* + * The "core" of cores_per_node and cores_per_package stands for a + * logical core, which means in a SMT system it stands for a thread. + */ struct loongson_system_configuration { int nr_cpus; int nr_nodes; diff --git a/arch/loongarch/include/asm/cpu-features.h b/arch/loongarch/include/asm/cpu-features.h index 2eafe6a6aca8..fc83bb32f9f0 100644 --- a/arch/loongarch/include/asm/cpu-features.h +++ b/arch/loongarch/include/asm/cpu-features.h @@ -51,6 +51,7 @@ #define cpu_has_lbt_mips cpu_opt(LOONGARCH_CPU_LBT_MIPS) #define cpu_has_lbt (cpu_has_lbt_x86|cpu_has_lbt_arm|cpu_has_lbt_mips) #define cpu_has_csr cpu_opt(LOONGARCH_CPU_CSR) +#define cpu_has_iocsr cpu_opt(LOONGARCH_CPU_IOCSR) #define cpu_has_tlb cpu_opt(LOONGARCH_CPU_TLB) #define cpu_has_watch cpu_opt(LOONGARCH_CPU_WATCH) #define cpu_has_vint cpu_opt(LOONGARCH_CPU_VINT) @@ -65,5 +66,7 @@ #define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID) #define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR) #define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW) +#define cpu_has_lspw cpu_opt(LOONGARCH_CPU_LSPW) +#define cpu_has_avecint cpu_opt(LOONGARCH_CPU_AVECINT) #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/loongarch/include/asm/cpu.h b/arch/loongarch/include/asm/cpu.h index 48b9f7168bcc..98cf4d7b4b0a 100644 --- a/arch/loongarch/include/asm/cpu.h +++ b/arch/loongarch/include/asm/cpu.h @@ -87,18 +87,21 @@ enum cpu_type_enum { #define CPU_FEATURE_LBT_MIPS 12 /* CPU has MIPS Binary Translation */ #define CPU_FEATURE_TLB 13 /* CPU has TLB */ #define CPU_FEATURE_CSR 14 /* CPU has CSR */ -#define CPU_FEATURE_WATCH 15 /* CPU has watchpoint registers */ -#define CPU_FEATURE_VINT 16 /* CPU has vectored interrupts */ -#define CPU_FEATURE_CSRIPI 17 /* CPU has CSR-IPI */ -#define CPU_FEATURE_EXTIOI 18 /* CPU has EXT-IOI */ -#define CPU_FEATURE_PREFETCH 19 /* CPU has prefetch instructions */ -#define CPU_FEATURE_PMP 20 /* CPU has perfermance counter */ -#define CPU_FEATURE_SCALEFREQ 21 /* CPU supports cpufreq scaling */ -#define CPU_FEATURE_FLATMODE 22 /* CPU has flat mode */ -#define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */ -#define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */ -#define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */ -#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */ +#define CPU_FEATURE_IOCSR 15 /* CPU has IOCSR */ +#define CPU_FEATURE_WATCH 16 /* CPU has watchpoint registers */ +#define CPU_FEATURE_VINT 17 /* CPU has vectored interrupts */ +#define CPU_FEATURE_CSRIPI 18 /* CPU has CSR-IPI */ +#define CPU_FEATURE_EXTIOI 19 /* CPU has EXT-IOI */ +#define CPU_FEATURE_PREFETCH 20 /* CPU has prefetch instructions */ +#define CPU_FEATURE_PMP 21 /* CPU has perfermance counter */ +#define CPU_FEATURE_SCALEFREQ 22 /* CPU supports cpufreq scaling */ +#define CPU_FEATURE_FLATMODE 23 /* CPU has flat mode */ +#define CPU_FEATURE_EIODECODE 24 /* CPU has EXTIOI interrupt pin decode mode */ +#define CPU_FEATURE_GUESTID 25 /* CPU has GuestID feature */ +#define CPU_FEATURE_HYPERVISOR 26 /* CPU has hypervisor (running in VM) */ +#define CPU_FEATURE_PTW 27 /* CPU has hardware page table walker */ +#define CPU_FEATURE_LSPW 28 /* CPU has LSPW (lddir/ldpte instructions) */ +#define CPU_FEATURE_AVECINT 29 /* CPU has AVEC interrupt */ #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) @@ -114,6 +117,7 @@ enum cpu_type_enum { #define LOONGARCH_CPU_LBT_ARM BIT_ULL(CPU_FEATURE_LBT_ARM) #define LOONGARCH_CPU_LBT_MIPS BIT_ULL(CPU_FEATURE_LBT_MIPS) #define LOONGARCH_CPU_TLB BIT_ULL(CPU_FEATURE_TLB) +#define LOONGARCH_CPU_IOCSR BIT_ULL(CPU_FEATURE_IOCSR) #define LOONGARCH_CPU_CSR BIT_ULL(CPU_FEATURE_CSR) #define LOONGARCH_CPU_WATCH BIT_ULL(CPU_FEATURE_WATCH) #define LOONGARCH_CPU_VINT BIT_ULL(CPU_FEATURE_VINT) @@ -127,5 +131,7 @@ enum cpu_type_enum { #define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID) #define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR) #define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW) +#define LOONGARCH_CPU_LSPW BIT_ULL(CPU_FEATURE_LSPW) +#define LOONGARCH_CPU_AVECINT BIT_ULL(CPU_FEATURE_AVECINT) #endif /* _ASM_CPU_H */ diff --git a/arch/loongarch/include/asm/dma-direct.h b/arch/loongarch/include/asm/dma-direct.h deleted file mode 100644 index 75ccd808a2af..000000000000 --- a/arch/loongarch/include/asm/dma-direct.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2020-2022 Loongson Technology Corporation Limited - */ -#ifndef _LOONGARCH_DMA_DIRECT_H -#define _LOONGARCH_DMA_DIRECT_H - -dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr); -phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr); - -#endif /* _LOONGARCH_DMA_DIRECT_H */ diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/asm/ftrace.h index c0a682808e07..8f13eaeaa325 100644 --- a/arch/loongarch/include/asm/ftrace.h +++ b/arch/loongarch/include/asm/ftrace.h @@ -44,40 +44,19 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent); #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS struct ftrace_ops; -struct ftrace_regs { - struct pt_regs regs; -}; +#include <linux/ftrace_regs.h> static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs) { - return &fregs->regs; -} - -static __always_inline unsigned long -ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs) -{ - return instruction_pointer(&fregs->regs); + return &arch_ftrace_regs(fregs)->regs; } static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip) { - instruction_pointer_set(&fregs->regs, ip); + instruction_pointer_set(&arch_ftrace_regs(fregs)->regs, ip); } -#define ftrace_regs_get_argument(fregs, n) \ - regs_get_kernel_argument(&(fregs)->regs, n) -#define ftrace_regs_get_stack_pointer(fregs) \ - kernel_stack_pointer(&(fregs)->regs) -#define ftrace_regs_return_value(fregs) \ - regs_return_value(&(fregs)->regs) -#define ftrace_regs_set_return_value(fregs, ret) \ - regs_set_return_value(&(fregs)->regs, ret) -#define ftrace_override_function_with_return(fregs) \ - override_function_with_return(&(fregs)->regs) -#define ftrace_regs_query_register_offset(name) \ - regs_query_register_offset(name) - #define ftrace_graph_func ftrace_graph_func void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs); @@ -90,7 +69,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) } #define arch_ftrace_set_direct_caller(fregs, addr) \ - __arch_ftrace_set_direct_caller(&(fregs)->regs, addr) + __arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr) #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ #endif diff --git a/arch/loongarch/include/asm/hardirq.h b/arch/loongarch/include/asm/hardirq.h index 1d7feb719515..10da8d6961cb 100644 --- a/arch/loongarch/include/asm/hardirq.h +++ b/arch/loongarch/include/asm/hardirq.h @@ -12,12 +12,13 @@ extern void ack_bad_irq(unsigned int irq); #define ack_bad_irq ack_bad_irq -#define NR_IPI 3 +#define NR_IPI 4 enum ipi_msg_type { IPI_RESCHEDULE, IPI_CALL_FUNCTION, IPI_IRQ_WORK, + IPI_CLEAR_VECTOR, }; typedef struct { diff --git a/arch/loongarch/include/asm/hw_irq.h b/arch/loongarch/include/asm/hw_irq.h index af4f4e8fbd85..8156ffb67415 100644 --- a/arch/loongarch/include/asm/hw_irq.h +++ b/arch/loongarch/include/asm/hw_irq.h @@ -9,6 +9,8 @@ extern atomic_t irq_err_count; +#define ARCH_IRQ_INIT_FLAGS IRQ_NOPROBE + /* * interrupt-retrigger: NOP for now. This may not be appropriate for all * machines, we'll see ... diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 480418bc5071..9c2ca785faa9 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -39,11 +39,22 @@ void spurious_interrupt(void); #define NR_IRQS_LEGACY 16 +/* + * 256 Vectors Mapping for AVECINTC: + * + * 0 - 15: Mapping classic IPs, e.g. IP0-12. + * 16 - 255: Mapping vectors for external IRQ. + * + */ +#define NR_VECTORS 256 +#define NR_LEGACY_VECTORS 16 +#define IRQ_MATRIX_BITS NR_VECTORS + #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace void arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu); #define MAX_IO_PICS 2 -#define NR_IRQS (64 + (256 * MAX_IO_PICS)) +#define NR_IRQS (64 + NR_VECTORS * (NR_CPUS + MAX_IO_PICS)) struct acpi_vector_group { int node; @@ -65,7 +76,7 @@ extern struct acpi_vector_group msi_group[MAX_IO_PICS]; #define LOONGSON_LPC_LAST_IRQ (LOONGSON_LPC_IRQ_BASE + 15) #define LOONGSON_CPU_IRQ_BASE 16 -#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 14) +#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 15) #define LOONGSON_PCH_IRQ_BASE 64 #define LOONGSON_PCH_ACPI_IRQ (LOONGSON_PCH_IRQ_BASE + 47) @@ -88,20 +99,8 @@ struct acpi_madt_bio_pic; struct acpi_madt_msi_pic; struct acpi_madt_lpc_pic; -int liointc_acpi_init(struct irq_domain *parent, - struct acpi_madt_lio_pic *acpi_liointc); -int eiointc_acpi_init(struct irq_domain *parent, - struct acpi_madt_eio_pic *acpi_eiointc); - -int htvec_acpi_init(struct irq_domain *parent, - struct acpi_madt_ht_pic *acpi_htvec); -int pch_lpc_acpi_init(struct irq_domain *parent, - struct acpi_madt_lpc_pic *acpi_pchlpc); -int pch_msi_acpi_init(struct irq_domain *parent, - struct acpi_madt_msi_pic *acpi_pchmsi); -int pch_pic_acpi_init(struct irq_domain *parent, - struct acpi_madt_bio_pic *acpi_pchpic); -int find_pch_pic(u32 gsi); +void complete_irq_moving(void); + struct fwnode_handle *get_pch_msi_handle(int pci_segment); extern struct acpi_madt_lio_pic *acpi_liointc; diff --git a/arch/loongarch/include/asm/kasan.h b/arch/loongarch/include/asm/kasan.h index cd6084f4e153..7f52bd31b9d4 100644 --- a/arch/loongarch/include/asm/kasan.h +++ b/arch/loongarch/include/asm/kasan.h @@ -16,7 +16,7 @@ #define XRANGE_SHIFT (48) /* Valid address length */ -#define XRANGE_SHADOW_SHIFT (PGDIR_SHIFT + PAGE_SHIFT - 3) +#define XRANGE_SHADOW_SHIFT min(cpu_vabits, VA_BITS) /* Used for taking out the valid address */ #define XRANGE_SHADOW_MASK GENMASK_ULL(XRANGE_SHADOW_SHIFT - 1, 0) /* One segment whole address space size */ @@ -25,6 +25,7 @@ /* 64-bit segment value. */ #define XKPRANGE_UC_SEG (0x8000) #define XKPRANGE_CC_SEG (0x9000) +#define XKPRANGE_WC_SEG (0xa000) #define XKVRANGE_VC_SEG (0xffff) /* Cached */ @@ -41,20 +42,28 @@ #define XKPRANGE_UC_SHADOW_SIZE (XKPRANGE_UC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) #define XKPRANGE_UC_SHADOW_END (XKPRANGE_UC_KASAN_OFFSET + XKPRANGE_UC_SHADOW_SIZE) +/* WriteCombine */ +#define XKPRANGE_WC_START WRITECOMBINE_BASE +#define XKPRANGE_WC_SIZE XRANGE_SIZE +#define XKPRANGE_WC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END +#define XKPRANGE_WC_SHADOW_SIZE (XKPRANGE_WC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) +#define XKPRANGE_WC_SHADOW_END (XKPRANGE_WC_KASAN_OFFSET + XKPRANGE_WC_SHADOW_SIZE) + /* VMALLOC (Cached or UnCached) */ #define XKVRANGE_VC_START MODULES_VADDR #define XKVRANGE_VC_SIZE round_up(KFENCE_AREA_END - MODULES_VADDR + 1, PGDIR_SIZE) -#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_UC_SHADOW_END +#define XKVRANGE_VC_KASAN_OFFSET XKPRANGE_WC_SHADOW_END #define XKVRANGE_VC_SHADOW_SIZE (XKVRANGE_VC_SIZE >> KASAN_SHADOW_SCALE_SHIFT) #define XKVRANGE_VC_SHADOW_END (XKVRANGE_VC_KASAN_OFFSET + XKVRANGE_VC_SHADOW_SIZE) /* KAsan shadow memory start right after vmalloc. */ #define KASAN_SHADOW_START round_up(KFENCE_AREA_END, PGDIR_SIZE) #define KASAN_SHADOW_SIZE (XKVRANGE_VC_SHADOW_END - XKPRANGE_CC_KASAN_OFFSET) -#define KASAN_SHADOW_END round_up(KASAN_SHADOW_START + KASAN_SHADOW_SIZE, PGDIR_SIZE) +#define KASAN_SHADOW_END (round_up(KASAN_SHADOW_START + KASAN_SHADOW_SIZE, PGDIR_SIZE) - 1) #define XKPRANGE_CC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_CC_KASAN_OFFSET) #define XKPRANGE_UC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_UC_KASAN_OFFSET) +#define XKPRANGE_WC_SHADOW_OFFSET (KASAN_SHADOW_START + XKPRANGE_WC_KASAN_OFFSET) #define XKVRANGE_VC_SHADOW_OFFSET (KASAN_SHADOW_START + XKVRANGE_VC_KASAN_OFFSET) extern bool kasan_early_stage; diff --git a/arch/loongarch/include/asm/kvm_csr.h b/arch/loongarch/include/asm/kvm_csr.h index 724ca8b7b401..4a76ce796f1f 100644 --- a/arch/loongarch/include/asm/kvm_csr.h +++ b/arch/loongarch/include/asm/kvm_csr.h @@ -30,6 +30,7 @@ : [val] "+r" (__v) \ : [reg] "i" (csr) \ : "memory"); \ + __v; \ }) #define gcsr_xchg(v, m, csr) \ @@ -181,6 +182,8 @@ __BUILD_GCSR_OP(tlbidx) #define kvm_save_hw_gcsr(csr, gid) (csr->csrs[gid] = gcsr_read(gid)) #define kvm_restore_hw_gcsr(csr, gid) (gcsr_write(csr->csrs[gid], gid)) +#define kvm_read_clear_hw_gcsr(csr, gid) (csr->csrs[gid] = gcsr_write(0, gid)) + int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu); static __always_inline unsigned long kvm_read_sw_gcsr(struct loongarch_csrs *csr, int gid) @@ -208,4 +211,7 @@ static __always_inline void kvm_change_sw_gcsr(struct loongarch_csrs *csr, csr->csrs[gid] |= val & _mask; } +#define KVM_PMU_EVENT_ENABLED (CSR_PERFCTRL_PLV0 | CSR_PERFCTRL_PLV1 | \ + CSR_PERFCTRL_PLV2 | CSR_PERFCTRL_PLV3) + #endif /* __ASM_LOONGARCH_KVM_CSR_H__ */ diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h index 5f0677e03817..d6bb72424027 100644 --- a/arch/loongarch/include/asm/kvm_host.h +++ b/arch/loongarch/include/asm/kvm_host.h @@ -30,6 +30,7 @@ #define KVM_HALT_POLL_NS_DEFAULT 500000 #define KVM_REQ_TLB_FLUSH_GPA KVM_ARCH_REQ(0) #define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(1) +#define KVM_REQ_PMU KVM_ARCH_REQ(2) #define KVM_GUESTDBG_SW_BP_MASK \ (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP) @@ -60,9 +61,13 @@ struct kvm_arch_memory_slot { unsigned long flags; }; +#define HOST_MAX_PMNUM 16 struct kvm_context { unsigned long vpid_cache; struct kvm_vcpu *last_vcpu; + /* Host PMU CSR */ + u64 perf_ctrl[HOST_MAX_PMNUM]; + u64 perf_cntr[HOST_MAX_PMNUM]; }; struct kvm_world_switch { @@ -107,6 +112,8 @@ struct kvm_arch { unsigned int root_level; spinlock_t phyid_map_lock; struct kvm_phyid_map *phyid_map; + /* Enabled PV features */ + unsigned long pv_features; s64 time_offset; struct kvm_context __percpu *vmcs; @@ -133,8 +140,15 @@ enum emulation_result { #define KVM_LARCH_FPU (0x1 << 0) #define KVM_LARCH_LSX (0x1 << 1) #define KVM_LARCH_LASX (0x1 << 2) -#define KVM_LARCH_SWCSR_LATEST (0x1 << 3) -#define KVM_LARCH_HWCSR_USABLE (0x1 << 4) +#define KVM_LARCH_LBT (0x1 << 3) +#define KVM_LARCH_PMU (0x1 << 4) +#define KVM_LARCH_SWCSR_LATEST (0x1 << 5) +#define KVM_LARCH_HWCSR_USABLE (0x1 << 6) + +#define LOONGARCH_PV_FEAT_UPDATED BIT_ULL(63) +#define LOONGARCH_PV_FEAT_MASK (BIT(KVM_FEATURE_IPI) | \ + BIT(KVM_FEATURE_STEAL_TIME) | \ + BIT(KVM_FEATURE_VIRT_EXTIOI)) struct kvm_vcpu_arch { /* @@ -168,10 +182,14 @@ struct kvm_vcpu_arch { /* FPU state */ struct loongarch_fpu fpu FPU_ALIGN; + struct loongarch_lbt lbt; /* CSR state */ struct loongarch_csrs *csr; + /* Guest max PMU CSR id */ + int max_pmu_csrid; + /* GPR used as IO source/target */ u32 io_gpr; @@ -239,6 +257,21 @@ static inline bool kvm_guest_has_lasx(struct kvm_vcpu_arch *arch) return arch->cpucfg[2] & CPUCFG2_LASX; } +static inline bool kvm_guest_has_lbt(struct kvm_vcpu_arch *arch) +{ + return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT | CPUCFG2_MIPSBT); +} + +static inline bool kvm_guest_has_pmu(struct kvm_vcpu_arch *arch) +{ + return arch->cpucfg[6] & CPUCFG6_PMP; +} + +static inline int kvm_get_pmu_num(struct kvm_vcpu_arch *arch) +{ + return (arch->cpucfg[6] & CPUCFG6_PMNUM) >> CPUCFG6_PMNUM_SHIFT; +} + /* Debug: dump vcpu state */ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu); diff --git a/arch/loongarch/include/asm/kvm_para.h b/arch/loongarch/include/asm/kvm_para.h index 43ec61589e6c..c4e84227280d 100644 --- a/arch/loongarch/include/asm/kvm_para.h +++ b/arch/loongarch/include/asm/kvm_para.h @@ -2,6 +2,8 @@ #ifndef _ASM_LOONGARCH_KVM_PARA_H #define _ASM_LOONGARCH_KVM_PARA_H +#include <uapi/asm/kvm_para.h> + /* * Hypercall code field */ @@ -154,10 +156,20 @@ static __always_inline long kvm_hypercall5(u64 fid, return ret; } +#ifdef CONFIG_PARAVIRT +bool kvm_para_available(void); +unsigned int kvm_arch_para_features(void); +#else +static inline bool kvm_para_available(void) +{ + return false; +} + static inline unsigned int kvm_arch_para_features(void) { return 0; } +#endif static inline unsigned int kvm_arch_para_hints(void) { diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h index c416cb7125c0..d7e8f7d50ee0 100644 --- a/arch/loongarch/include/asm/kvm_vcpu.h +++ b/arch/loongarch/include/asm/kvm_vcpu.h @@ -75,8 +75,13 @@ static inline void kvm_save_lasx(struct loongarch_fpu *fpu) { } static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { } #endif +#ifdef CONFIG_CPU_HAS_LBT +int kvm_own_lbt(struct kvm_vcpu *vcpu); +#else +static inline int kvm_own_lbt(struct kvm_vcpu *vcpu) { return -EINVAL; } +#endif + void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz); -void kvm_reset_timer(struct kvm_vcpu *vcpu); void kvm_save_timer(struct kvm_vcpu *vcpu); void kvm_restore_timer(struct kvm_vcpu *vcpu); @@ -125,4 +130,9 @@ static inline bool kvm_pvtime_supported(void) return !!sched_info_on(); } +static inline bool kvm_guest_has_pv_feature(struct kvm_vcpu *vcpu, unsigned int feature) +{ + return vcpu->kvm->arch.pv_features & BIT(feature); +} + #endif /* __ASM_LOONGARCH_KVM_VCPU_H__ */ diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 04a78010fc72..64ad277e096e 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -62,6 +62,7 @@ #define LOONGARCH_CPUCFG1 0x1 #define CPUCFG1_ISGR32 BIT(0) #define CPUCFG1_ISGR64 BIT(1) +#define CPUCFG1_ISA GENMASK(1, 0) #define CPUCFG1_PAGING BIT(2) #define CPUCFG1_IOCSR BIT(3) #define CPUCFG1_PABITS GENMASK(11, 4) @@ -119,6 +120,7 @@ #define CPUCFG6_PMP BIT(0) #define CPUCFG6_PAMVER GENMASK(3, 1) #define CPUCFG6_PMNUM GENMASK(7, 4) +#define CPUCFG6_PMNUM_SHIFT 4 #define CPUCFG6_PMBITS GENMASK(13, 8) #define CPUCFG6_UPM BIT(14) @@ -160,16 +162,8 @@ /* * CPUCFG index area: 0x40000000 -- 0x400000ff - * SW emulation for KVM hypervirsor + * SW emulation for KVM hypervirsor, see arch/loongarch/include/uapi/asm/kvm_para.h */ -#define CPUCFG_KVM_BASE 0x40000000 -#define CPUCFG_KVM_SIZE 0x100 - -#define CPUCFG_KVM_SIG (CPUCFG_KVM_BASE + 0) -#define KVM_SIGNATURE "KVM\0" -#define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4) -#define KVM_FEATURE_IPI BIT(1) -#define KVM_FEATURE_STEAL_TIME BIT(2) #ifndef __ASSEMBLY__ @@ -253,10 +247,10 @@ #define CSR_ESTAT_EXC_WIDTH 6 #define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT) #define CSR_ESTAT_IS_SHIFT 0 -#define CSR_ESTAT_IS_WIDTH 14 -#define CSR_ESTAT_IS (_ULCAST_(0x3fff) << CSR_ESTAT_IS_SHIFT) +#define CSR_ESTAT_IS_WIDTH 15 +#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT) -#define LOONGARCH_CSR_ERA 0x6 /* ERA */ +#define LOONGARCH_CSR_ERA 0x6 /* Exception return address */ #define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */ @@ -649,6 +643,13 @@ #define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */ +#define LOONGARCH_CSR_ISR0 0xa0 +#define LOONGARCH_CSR_ISR1 0xa1 +#define LOONGARCH_CSR_ISR2 0xa2 +#define LOONGARCH_CSR_ISR3 0xa3 + +#define LOONGARCH_CSR_IRR 0xa4 + #define LOONGARCH_CSR_PRID 0xc0 /* Shadow MCSR : 0xc0 ~ 0xff */ @@ -1011,7 +1012,7 @@ /* * CSR_ECFG IM */ -#define ECFG0_IM 0x00001fff +#define ECFG0_IM 0x00005fff #define ECFGB_SIP0 0 #define ECFGF_SIP0 (_ULCAST_(1) << ECFGB_SIP0) #define ECFGB_SIP1 1 @@ -1054,6 +1055,7 @@ #define IOCSRF_EIODECODE BIT_ULL(9) #define IOCSRF_FLATMODE BIT_ULL(10) #define IOCSRF_VM BIT_ULL(11) +#define IOCSRF_AVEC BIT_ULL(15) #define LOONGARCH_IOCSR_VENDOR 0x10 @@ -1065,6 +1067,7 @@ #define IOCSR_MISC_FUNC_SOFT_INT BIT_ULL(10) #define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) #define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) +#define IOCSR_MISC_FUNC_AVEC_EN BIT_ULL(51) #define LOONGARCH_IOCSR_CPUTEMP 0x428 @@ -1387,9 +1390,10 @@ __BUILD_CSR_OP(tlbidx) #define INT_TI 11 /* Timer */ #define INT_IPI 12 #define INT_NMI 13 +#define INT_AVEC 14 /* ExcCodes corresponding to interrupts */ -#define EXCCODE_INT_NUM (INT_NMI + 1) +#define EXCCODE_INT_NUM (INT_AVEC + 1) #define EXCCODE_INT_START 64 #define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1) diff --git a/arch/loongarch/include/asm/mmu_context.h b/arch/loongarch/include/asm/mmu_context.h index 9f97c3453b9c..304363bd3935 100644 --- a/arch/loongarch/include/asm/mmu_context.h +++ b/arch/loongarch/include/asm/mmu_context.h @@ -49,12 +49,12 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) /* Normal, classic get_new_mmu_context */ static inline void -get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) +get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, bool *need_flush) { u64 asid = asid_cache(cpu); if (!((++asid) & cpu_asid_mask(&cpu_data[cpu]))) - local_flush_tlb_user(); /* start new asid cycle */ + *need_flush = true; /* start new asid cycle */ cpu_context(cpu, mm) = asid_cache(cpu) = asid; } @@ -74,21 +74,34 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) return 0; } +static inline void atomic_update_pgd_asid(unsigned long asid, unsigned long pgdl) +{ + __asm__ __volatile__( + "csrwr %[pgdl_val], %[pgdl_reg] \n\t" + "csrwr %[asid_val], %[asid_reg] \n\t" + : [asid_val] "+r" (asid), [pgdl_val] "+r" (pgdl) + : [asid_reg] "i" (LOONGARCH_CSR_ASID), [pgdl_reg] "i" (LOONGARCH_CSR_PGDL) + : "memory" + ); +} + static inline void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { + bool need_flush = false; unsigned int cpu = smp_processor_id(); /* Check if our ASID is of an older version and thus invalid */ if (!asid_valid(next, cpu)) - get_new_mmu_context(next, cpu); - - write_csr_asid(cpu_asid(cpu, next)); + get_new_mmu_context(next, cpu, &need_flush); if (next != &init_mm) - csr_write64((unsigned long)next->pgd, LOONGARCH_CSR_PGDL); + atomic_update_pgd_asid(cpu_asid(cpu, next), (unsigned long)next->pgd); else - csr_write64((unsigned long)invalid_pg_dir, LOONGARCH_CSR_PGDL); + atomic_update_pgd_asid(cpu_asid(cpu, next), (unsigned long)invalid_pg_dir); + + if (need_flush) + local_flush_tlb_user(); /* Flush tlb after update ASID */ /* * Mark current->active_mm as not "active" anymore. @@ -135,9 +148,15 @@ drop_mmu_context(struct mm_struct *mm, unsigned int cpu) asid = read_csr_asid() & cpu_asid_mask(¤t_cpu_data); if (asid == cpu_asid(cpu, mm)) { + bool need_flush = false; + if (!current->mm || (current->mm == mm)) { - get_new_mmu_context(mm, cpu); + get_new_mmu_context(mm, cpu, &need_flush); + write_csr_asid(cpu_asid(cpu, mm)); + if (need_flush) + local_flush_tlb_user(); /* Flush tlb after update ASID */ + goto out; } } diff --git a/arch/loongarch/include/asm/mmzone.h b/arch/loongarch/include/asm/mmzone.h deleted file mode 100644 index 2b9a90727e19..000000000000 --- a/arch/loongarch/include/asm/mmzone.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Author: Huacai Chen (chenhuacai@loongson.cn) - * Copyright (C) 2020-2022 Loongson Technology Corporation Limited - */ -#ifndef _ASM_MMZONE_H_ -#define _ASM_MMZONE_H_ - -#include <asm/page.h> -#include <asm/numa.h> - -extern struct pglist_data *node_data[]; - -#define NODE_DATA(nid) (node_data[(nid)]) - -#endif /* _ASM_MMZONE_H_ */ diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h index e85df33f11c7..2e56a773660f 100644 --- a/arch/loongarch/include/asm/page.h +++ b/arch/loongarch/include/asm/page.h @@ -8,12 +8,7 @@ #include <linux/const.h> #include <asm/addrspace.h> -/* - * PAGE_SHIFT determines the page size - */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) +#include <vdso/page.h> #define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) @@ -113,10 +108,7 @@ struct page *tlb_virt_to_page(unsigned long kaddr); extern int __virt_addr_valid(volatile void *kaddr); #define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr)) -#define VM_DATA_DEFAULT_FLAGS \ - (VM_READ | VM_WRITE | \ - ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC #include <asm-generic/memory_model.h> #include <asm-generic/getorder.h> diff --git a/arch/loongarch/include/asm/paravirt.h b/arch/loongarch/include/asm/paravirt.h index dddec49671ae..3f4323603e6a 100644 --- a/arch/loongarch/include/asm/paravirt.h +++ b/arch/loongarch/include/asm/paravirt.h @@ -19,6 +19,7 @@ static inline u64 paravirt_steal_clock(int cpu) int __init pv_ipi_init(void); int __init pv_time_init(void); +int __init pv_spinlock_init(void); #else @@ -31,5 +32,11 @@ static inline int pv_time_init(void) { return 0; } + +static inline int pv_spinlock_init(void) +{ + return 0; +} + #endif // CONFIG_PARAVIRT #endif diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h index 8f290e5546cf..87be9b14e9da 100644 --- a/arch/loongarch/include/asm/percpu.h +++ b/arch/loongarch/include/asm/percpu.h @@ -68,75 +68,6 @@ PERCPU_OP(and, and, &) PERCPU_OP(or, or, |) #undef PERCPU_OP -static __always_inline unsigned long __percpu_read(void __percpu *ptr, int size) -{ - unsigned long ret; - - switch (size) { - case 1: - __asm__ __volatile__ ("ldx.b %[ret], $r21, %[ptr] \n" - : [ret] "=&r"(ret) - : [ptr] "r"(ptr) - : "memory"); - break; - case 2: - __asm__ __volatile__ ("ldx.h %[ret], $r21, %[ptr] \n" - : [ret] "=&r"(ret) - : [ptr] "r"(ptr) - : "memory"); - break; - case 4: - __asm__ __volatile__ ("ldx.w %[ret], $r21, %[ptr] \n" - : [ret] "=&r"(ret) - : [ptr] "r"(ptr) - : "memory"); - break; - case 8: - __asm__ __volatile__ ("ldx.d %[ret], $r21, %[ptr] \n" - : [ret] "=&r"(ret) - : [ptr] "r"(ptr) - : "memory"); - break; - default: - ret = 0; - BUILD_BUG(); - } - - return ret; -} - -static __always_inline void __percpu_write(void __percpu *ptr, unsigned long val, int size) -{ - switch (size) { - case 1: - __asm__ __volatile__("stx.b %[val], $r21, %[ptr] \n" - : - : [val] "r" (val), [ptr] "r" (ptr) - : "memory"); - break; - case 2: - __asm__ __volatile__("stx.h %[val], $r21, %[ptr] \n" - : - : [val] "r" (val), [ptr] "r" (ptr) - : "memory"); - break; - case 4: - __asm__ __volatile__("stx.w %[val], $r21, %[ptr] \n" - : - : [val] "r" (val), [ptr] "r" (ptr) - : "memory"); - break; - case 8: - __asm__ __volatile__("stx.d %[val], $r21, %[ptr] \n" - : - : [val] "r" (val), [ptr] "r" (ptr) - : "memory"); - break; - default: - BUILD_BUG(); - } -} - static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size) { switch (size) { @@ -157,6 +88,33 @@ static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, return 0; } +#define __pcpu_op_1(op) op ".b " +#define __pcpu_op_2(op) op ".h " +#define __pcpu_op_4(op) op ".w " +#define __pcpu_op_8(op) op ".d " + +#define _percpu_read(size, _pcp) \ +({ \ + typeof(_pcp) __pcp_ret; \ + \ + __asm__ __volatile__( \ + __pcpu_op_##size("ldx") "%[ret], $r21, %[ptr] \n" \ + : [ret] "=&r"(__pcp_ret) \ + : [ptr] "r"(&(_pcp)) \ + : "memory"); \ + \ + __pcp_ret; \ +}) + +#define _percpu_write(size, _pcp, _val) \ +do { \ + __asm__ __volatile__( \ + __pcpu_op_##size("stx") "%[val], $r21, %[ptr] \n" \ + : \ + : [val] "r"(_val), [ptr] "r"(&(_pcp)) \ + : "memory"); \ +} while (0) + /* this_cpu_cmpxchg */ #define _protect_cmpxchg_local(pcp, o, n) \ ({ \ @@ -167,18 +125,6 @@ static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, __ret; \ }) -#define _percpu_read(pcp) \ -({ \ - typeof(pcp) __retval; \ - __retval = (typeof(pcp))__percpu_read(&(pcp), sizeof(pcp)); \ - __retval; \ -}) - -#define _percpu_write(pcp, val) \ -do { \ - __percpu_write(&(pcp), (unsigned long)(val), sizeof(pcp)); \ -} while (0) \ - #define _pcp_protect(operation, pcp, val) \ ({ \ typeof(pcp) __retval; \ @@ -215,15 +161,15 @@ do { \ #define this_cpu_or_4(pcp, val) _percpu_or(pcp, val) #define this_cpu_or_8(pcp, val) _percpu_or(pcp, val) -#define this_cpu_read_1(pcp) _percpu_read(pcp) -#define this_cpu_read_2(pcp) _percpu_read(pcp) -#define this_cpu_read_4(pcp) _percpu_read(pcp) -#define this_cpu_read_8(pcp) _percpu_read(pcp) +#define this_cpu_read_1(pcp) _percpu_read(1, pcp) +#define this_cpu_read_2(pcp) _percpu_read(2, pcp) +#define this_cpu_read_4(pcp) _percpu_read(4, pcp) +#define this_cpu_read_8(pcp) _percpu_read(8, pcp) -#define this_cpu_write_1(pcp, val) _percpu_write(pcp, val) -#define this_cpu_write_2(pcp, val) _percpu_write(pcp, val) -#define this_cpu_write_4(pcp, val) _percpu_write(pcp, val) -#define this_cpu_write_8(pcp, val) _percpu_write(pcp, val) +#define this_cpu_write_1(pcp, val) _percpu_write(1, pcp, val) +#define this_cpu_write_2(pcp, val) _percpu_write(2, pcp, val) +#define this_cpu_write_4(pcp, val) _percpu_write(4, pcp, val) +#define this_cpu_write_8(pcp, val) _percpu_write(8, pcp, val) #define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val) #define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val) diff --git a/arch/loongarch/include/asm/pgalloc.h b/arch/loongarch/include/asm/pgalloc.h index 4e2d6b7ca2ee..a7b9c9e73593 100644 --- a/arch/loongarch/include/asm/pgalloc.h +++ b/arch/loongarch/include/asm/pgalloc.h @@ -10,6 +10,7 @@ #define __HAVE_ARCH_PMD_ALLOC_ONE #define __HAVE_ARCH_PUD_ALLOC_ONE +#define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL #include <asm-generic/pgalloc.h> static inline void pmd_populate_kernel(struct mm_struct *mm, @@ -44,6 +45,16 @@ extern void pagetable_init(void); extern pgd_t *pgd_alloc(struct mm_struct *mm); +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm) +{ + pte_t *pte = __pte_alloc_one_kernel(mm); + + if (pte) + kernel_pte_init(pte); + + return pte; +} + #define __pte_free_tlb(tlb, pte, address) \ do { \ pagetable_pte_dtor(page_ptdesc(pte)); \ diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index 85431f20a14d..20714b73f14c 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -269,6 +269,7 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pm extern void pgd_init(void *addr); extern void pud_init(void *addr); extern void pmd_init(void *addr); +extern void kernel_pte_init(void *addr); /* * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that @@ -325,45 +326,17 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) { WRITE_ONCE(*ptep, pteval); - if (pte_val(pteval) & _PAGE_GLOBAL) { - pte_t *buddy = ptep_buddy(ptep); - /* - * Make sure the buddy is global too (if it's !none, - * it better already be global) - */ #ifdef CONFIG_SMP - /* - * For SMP, multiple CPUs can race, so we need to do - * this atomically. - */ - unsigned long page_global = _PAGE_GLOBAL; - unsigned long tmp; - - __asm__ __volatile__ ( - "1:" __LL "%[tmp], %[buddy] \n" - " bnez %[tmp], 2f \n" - " or %[tmp], %[tmp], %[global] \n" - __SC "%[tmp], %[buddy] \n" - " beqz %[tmp], 1b \n" - " nop \n" - "2: \n" - __WEAK_LLSC_MB - : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp) - : [global] "r" (page_global)); -#else /* !CONFIG_SMP */ - if (pte_none(ptep_get(buddy))) - WRITE_ONCE(*buddy, __pte(pte_val(ptep_get(buddy)) | _PAGE_GLOBAL)); -#endif /* CONFIG_SMP */ - } + if (pte_val(pteval) & _PAGE_GLOBAL) + DBAR(0b11000); /* o_wrw = 0b11000 */ +#endif } static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - /* Preserve global status for the pair */ - if (pte_val(ptep_get(ptep_buddy(ptep))) & _PAGE_GLOBAL) - set_pte(ptep, __pte(_PAGE_GLOBAL)); - else - set_pte(ptep, __pte(0)); + pte_t pte = ptep_get(ptep); + pte_val(pte) &= _PAGE_GLOBAL; + set_pte(ptep, pte); } #define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1) diff --git a/arch/loongarch/include/asm/qspinlock.h b/arch/loongarch/include/asm/qspinlock.h new file mode 100644 index 000000000000..e76d3aa1e1eb --- /dev/null +++ b/arch/loongarch/include/asm/qspinlock.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LOONGARCH_QSPINLOCK_H +#define _ASM_LOONGARCH_QSPINLOCK_H + +#include <linux/jump_label.h> + +#ifdef CONFIG_PARAVIRT + +DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key); + +#define virt_spin_lock virt_spin_lock + +static inline bool virt_spin_lock(struct qspinlock *lock) +{ + int val; + + if (!static_branch_unlikely(&virt_spin_lock_key)) + return false; + + /* + * On hypervisors without PARAVIRT_SPINLOCKS support we fall + * back to a Test-and-Set spinlock, because fair locks have + * horrible lock 'holder' preemption issues. + */ + +__retry: + val = atomic_read(&lock->val); + + if (val || !atomic_try_cmpxchg(&lock->val, &val, _Q_LOCKED_VAL)) { + cpu_relax(); + goto __retry; + } + + return true; +} + +#endif /* CONFIG_PARAVIRT */ + +#include <asm-generic/qspinlock.h> + +#endif // _ASM_LOONGARCH_QSPINLOCK_H diff --git a/arch/loongarch/include/asm/set_memory.h b/arch/loongarch/include/asm/set_memory.h new file mode 100644 index 000000000000..d70505b6676c --- /dev/null +++ b/arch/loongarch/include/asm/set_memory.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#ifndef _ASM_LOONGARCH_SET_MEMORY_H +#define _ASM_LOONGARCH_SET_MEMORY_H + +/* + * Functions to change memory attributes. + */ +int set_memory_x(unsigned long addr, int numpages); +int set_memory_nx(unsigned long addr, int numpages); +int set_memory_ro(unsigned long addr, int numpages); +int set_memory_rw(unsigned long addr, int numpages); + +bool kernel_page_present(struct page *page); +int set_direct_map_default_noflush(struct page *page); +int set_direct_map_invalid_noflush(struct page *page); + +#endif /* _ASM_LOONGARCH_SET_MEMORY_H */ diff --git a/arch/loongarch/include/asm/smp.h b/arch/loongarch/include/asm/smp.h index 50db503f44e3..3383c9d24e94 100644 --- a/arch/loongarch/include/asm/smp.h +++ b/arch/loongarch/include/asm/smp.h @@ -70,10 +70,12 @@ extern int __cpu_logical_map[NR_CPUS]; #define ACTION_RESCHEDULE 1 #define ACTION_CALL_FUNCTION 2 #define ACTION_IRQ_WORK 3 +#define ACTION_CLEAR_VECTOR 4 #define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU) #define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE) #define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION) #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) +#define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) struct secondary_data { unsigned long stack; diff --git a/arch/loongarch/include/asm/topology.h b/arch/loongarch/include/asm/topology.h index 66128dec0bf6..50273c9187d0 100644 --- a/arch/loongarch/include/asm/topology.h +++ b/arch/loongarch/include/asm/topology.h @@ -8,6 +8,7 @@ #include <linux/smp.h> #ifdef CONFIG_NUMA +#include <asm/numa.h> extern cpumask_t cpus_on_node[]; diff --git a/arch/loongarch/include/asm/vdso/getrandom.h b/arch/loongarch/include/asm/vdso/getrandom.h new file mode 100644 index 000000000000..e80f3c4ac748 --- /dev/null +++ b/arch/loongarch/include/asm/vdso/getrandom.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Xi Ruoyao <xry111@xry111.site>. All Rights Reserved. + */ +#ifndef __ASM_VDSO_GETRANDOM_H +#define __ASM_VDSO_GETRANDOM_H + +#ifndef __ASSEMBLY__ + +#include <asm/unistd.h> +#include <asm/vdso/vdso.h> + +static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, unsigned int _flags) +{ + register long ret asm("a0"); + register long nr asm("a7") = __NR_getrandom; + register void *buffer asm("a0") = _buffer; + register size_t len asm("a1") = _len; + register unsigned int flags asm("a2") = _flags; + + asm volatile( + " syscall 0\n" + : "+r" (ret) + : "r" (nr), "r" (buffer), "r" (len), "r" (flags) + : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", + "memory"); + + return ret; +} + +static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) +{ + return &_loongarch_data.rng_data; +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_VDSO_GETRANDOM_H */ diff --git a/arch/loongarch/include/asm/vdso/gettimeofday.h b/arch/loongarch/include/asm/vdso/gettimeofday.h index 89e6b222c2f2..7eb3f041af76 100644 --- a/arch/loongarch/include/asm/vdso/gettimeofday.h +++ b/arch/loongarch/include/asm/vdso/gettimeofday.h @@ -91,14 +91,14 @@ static inline bool loongarch_vdso_hres_capable(void) static __always_inline const struct vdso_data *__arch_get_vdso_data(void) { - return (const struct vdso_data *)get_vdso_data(); + return _vdso_data; } #ifdef CONFIG_TIME_NS static __always_inline const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) { - return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE); + return _timens_data; } #endif #endif /* !__ASSEMBLY__ */ diff --git a/arch/loongarch/include/asm/vdso/vdso.h b/arch/loongarch/include/asm/vdso/vdso.h index 5a12309d9fb5..1c183a9b2115 100644 --- a/arch/loongarch/include/asm/vdso/vdso.h +++ b/arch/loongarch/include/asm/vdso/vdso.h @@ -4,6 +4,9 @@ * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ +#ifndef _ASM_VDSO_VDSO_H +#define _ASM_VDSO_VDSO_H + #ifndef __ASSEMBLY__ #include <asm/asm.h> @@ -16,6 +19,7 @@ struct vdso_pcpu_data { struct loongarch_vdso_data { struct vdso_pcpu_data pdata[NR_CPUS]; + struct vdso_rng_data rng_data; }; /* @@ -44,22 +48,8 @@ enum vvar_pages { #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) -static inline unsigned long get_vdso_base(void) -{ - unsigned long addr; - - __asm__( - " la.pcrel %0, _start\n" - : "=r" (addr) - : - :); - - return addr; -} - -static inline unsigned long get_vdso_data(void) -{ - return get_vdso_base() - VVAR_SIZE; -} +extern struct loongarch_vdso_data _loongarch_data __attribute__((visibility("hidden"))); #endif /* __ASSEMBLY__ */ + +#endif diff --git a/arch/loongarch/include/asm/vdso/vsyscall.h b/arch/loongarch/include/asm/vdso/vsyscall.h index 5de615383a22..8987e951d0a9 100644 --- a/arch/loongarch/include/asm/vdso/vsyscall.h +++ b/arch/loongarch/include/asm/vdso/vsyscall.h @@ -4,14 +4,11 @@ #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> extern struct vdso_data *vdso_data; +extern struct vdso_rng_data *vdso_rng_data; -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ static __always_inline struct vdso_data *__loongarch_get_k_vdso_data(void) { @@ -19,6 +16,13 @@ struct vdso_data *__loongarch_get_k_vdso_data(void) } #define __arch_get_k_vdso_data __loongarch_get_k_vdso_data +static __always_inline +struct vdso_rng_data *__loongarch_get_k_vdso_rng_data(void) +{ + return vdso_rng_data; +} +#define __arch_get_k_vdso_rng_data __loongarch_get_k_vdso_rng_data + /* The asm-generic header needs to be included after the definitions above */ #include <asm-generic/vdso/vsyscall.h> diff --git a/arch/loongarch/include/uapi/asm/Kbuild b/arch/loongarch/include/uapi/asm/Kbuild index c6d141d7b7d7..517761419999 100644 --- a/arch/loongarch/include/uapi/asm/Kbuild +++ b/arch/loongarch/include/uapi/asm/Kbuild @@ -1,4 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 syscall-y += unistd_64.h - -generic-y += kvm_para.h diff --git a/arch/loongarch/include/uapi/asm/hwcap.h b/arch/loongarch/include/uapi/asm/hwcap.h index 6955a7cb2c65..2b34e56cfa9e 100644 --- a/arch/loongarch/include/uapi/asm/hwcap.h +++ b/arch/loongarch/include/uapi/asm/hwcap.h @@ -17,5 +17,6 @@ #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) #define HWCAP_LOONGARCH_PTW (1 << 13) +#define HWCAP_LOONGARCH_LSPW (1 << 14) #endif /* _UAPI_ASM_HWCAP_H */ diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h index ddc5cab0ffd0..70d89070bfeb 100644 --- a/arch/loongarch/include/uapi/asm/kvm.h +++ b/arch/loongarch/include/uapi/asm/kvm.h @@ -64,6 +64,7 @@ struct kvm_fpu { #define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x20000ULL) #define KVM_REG_LOONGARCH_FPSIMD (KVM_REG_LOONGARCH | 0x30000ULL) #define KVM_REG_LOONGARCH_CPUCFG (KVM_REG_LOONGARCH | 0x40000ULL) +#define KVM_REG_LOONGARCH_LBT (KVM_REG_LOONGARCH | 0x50000ULL) #define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x70000ULL) #define KVM_CSR_IDX_MASK 0x7fff #define KVM_CPUCFG_IDX_MASK 0x7fff @@ -77,11 +78,30 @@ struct kvm_fpu { /* Debugging: Special instruction for software breakpoint */ #define KVM_REG_LOONGARCH_DEBUG_INST (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3) +/* LBT registers */ +#define KVM_REG_LOONGARCH_LBT_SCR0 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_LOONGARCH_LBT_SCR1 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 2) +#define KVM_REG_LOONGARCH_LBT_SCR2 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 3) +#define KVM_REG_LOONGARCH_LBT_SCR3 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_LOONGARCH_LBT_EFLAGS (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 5) +#define KVM_REG_LOONGARCH_LBT_FTOP (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 6) + #define LOONGARCH_REG_SHIFT 3 #define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT)) #define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG) #define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG) +/* Device Control API on vm fd */ +#define KVM_LOONGARCH_VM_FEAT_CTRL 0 +#define KVM_LOONGARCH_VM_FEAT_LSX 0 +#define KVM_LOONGARCH_VM_FEAT_LASX 1 +#define KVM_LOONGARCH_VM_FEAT_X86BT 2 +#define KVM_LOONGARCH_VM_FEAT_ARMBT 3 +#define KVM_LOONGARCH_VM_FEAT_MIPSBT 4 +#define KVM_LOONGARCH_VM_FEAT_PMU 5 +#define KVM_LOONGARCH_VM_FEAT_PV_IPI 6 +#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7 + /* Device Control API on vcpu fd */ #define KVM_LOONGARCH_VCPU_CPUCFG 0 #define KVM_LOONGARCH_VCPU_PVTIME_CTRL 1 diff --git a/arch/loongarch/include/uapi/asm/kvm_para.h b/arch/loongarch/include/uapi/asm/kvm_para.h new file mode 100644 index 000000000000..b0604aa9b4bb --- /dev/null +++ b/arch/loongarch/include/uapi/asm/kvm_para.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_KVM_PARA_H +#define _UAPI_ASM_KVM_PARA_H + +#include <linux/types.h> + +/* + * CPUCFG index area: 0x40000000 -- 0x400000ff + * SW emulation for KVM hypervirsor + */ +#define CPUCFG_KVM_BASE 0x40000000 +#define CPUCFG_KVM_SIZE 0x100 +#define CPUCFG_KVM_SIG (CPUCFG_KVM_BASE + 0) +#define KVM_SIGNATURE "KVM\0" +#define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4) +#define KVM_FEATURE_IPI 1 +#define KVM_FEATURE_STEAL_TIME 2 +/* BIT 24 - 31 are features configurable by user space vmm */ +#define KVM_FEATURE_VIRT_EXTIOI 24 + +#endif /* _UAPI_ASM_KVM_PARA_H */ diff --git a/arch/loongarch/include/uapi/asm/sigcontext.h b/arch/loongarch/include/uapi/asm/sigcontext.h index 6c22f616b8f1..5cd121275bac 100644 --- a/arch/loongarch/include/uapi/asm/sigcontext.h +++ b/arch/loongarch/include/uapi/asm/sigcontext.h @@ -9,7 +9,6 @@ #define _UAPI_ASM_SIGCONTEXT_H #include <linux/types.h> -#include <linux/posix_types.h> /* FP context was used */ #define SC_USED_FP (1 << 0) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 929a497c987e..382a09a7152c 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -9,6 +9,7 @@ #include <linux/init.h> #include <linux/acpi.h> +#include <linux/efi-bgrt.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/memblock.h> @@ -57,48 +58,48 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) return ioremap_cache(phys, size); } -static int cpu_enumerated = 0; - #ifdef CONFIG_SMP -static int set_processor_mask(u32 id, u32 flags) +static int set_processor_mask(u32 id, u32 pass) { - int nr_cpus; - int cpu, cpuid = id; - - if (!cpu_enumerated) - nr_cpus = NR_CPUS; - else - nr_cpus = nr_cpu_ids; + int cpu = -1, cpuid = id; - if (num_processors >= nr_cpus) { + if (num_processors >= NR_CPUS) { pr_warn(PREFIX "nr_cpus limit of %i reached." - " processor 0x%x ignored.\n", nr_cpus, cpuid); + " processor 0x%x ignored.\n", NR_CPUS, cpuid); return -ENODEV; } + if (cpuid == loongson_sysconf.boot_cpu_id) cpu = 0; - else - cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); - - if (!cpu_enumerated) - set_cpu_possible(cpu, true); - if (flags & ACPI_MADT_ENABLED) { + switch (pass) { + case 1: /* Pass 1 handle enabled processors */ + if (cpu < 0) + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); num_processors++; set_cpu_present(cpu, true); - __cpu_number_map[cpuid] = cpu; - __cpu_logical_map[cpu] = cpuid; - } else + break; + case 2: /* Pass 2 handle disabled processors */ + if (cpu < 0) + cpu = find_first_zero_bit(cpumask_bits(cpu_possible_mask), NR_CPUS); disabled_cpus++; + break; + default: + return cpu; + } + + set_cpu_possible(cpu, true); + __cpu_number_map[cpuid] = cpu; + __cpu_logical_map[cpu] = cpuid; return cpu; } #endif static int __init -acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long end) +acpi_parse_p1_processor(union acpi_subtable_headers *header, const unsigned long end) { struct acpi_madt_core_pic *processor = NULL; @@ -109,13 +110,30 @@ acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long en acpi_table_print_madt_entry(&header->common); #ifdef CONFIG_SMP acpi_core_pic[processor->core_id] = *processor; - set_processor_mask(processor->core_id, processor->flags); + if (processor->flags & ACPI_MADT_ENABLED) + set_processor_mask(processor->core_id, 1); #endif return 0; } static int __init +acpi_parse_p2_processor(union acpi_subtable_headers *header, const unsigned long end) +{ + struct acpi_madt_core_pic *processor = NULL; + + processor = (struct acpi_madt_core_pic *)header; + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + +#ifdef CONFIG_SMP + if (!(processor->flags & ACPI_MADT_ENABLED)) + set_processor_mask(processor->core_id, 2); +#endif + + return 0; +} +static int __init acpi_parse_eio_master(union acpi_subtable_headers *header, const unsigned long end) { static int core = 0; @@ -142,12 +160,14 @@ static void __init acpi_process_madt(void) } #endif acpi_table_parse_madt(ACPI_MADT_TYPE_CORE_PIC, - acpi_parse_processor, MAX_CORE_PIC); + acpi_parse_p1_processor, MAX_CORE_PIC); + + acpi_table_parse_madt(ACPI_MADT_TYPE_CORE_PIC, + acpi_parse_p2_processor, MAX_CORE_PIC); acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, acpi_parse_eio_master, MAX_IO_PICS); - cpu_enumerated = 1; loongson_sysconf.nr_cpus = num_processors; } @@ -212,6 +232,9 @@ void __init acpi_boot_table_init(void) /* Do not enable ACPI SPCR console by default */ acpi_parse_spcr(earlycon_acpi_spcr_enable, false); + if (IS_ENABLED(CONFIG_ACPI_BGRT)) + acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); + return; fdt_earlycon: @@ -306,6 +329,10 @@ static int __ref acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) int nid; nid = acpi_get_node(handle); + + if (nid != NUMA_NO_NODE) + nid = early_cpu_to_node(cpu); + if (nid != NUMA_NO_NODE) { set_cpuid_to_node(physid, nid); node_set(nid, numa_nodes_parsed); @@ -320,12 +347,14 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id, int *pcpu { int cpu; - cpu = set_processor_mask(physid, ACPI_MADT_ENABLED); - if (cpu < 0) { + cpu = cpu_number_map(physid); + if (cpu < 0 || cpu >= nr_cpu_ids) { pr_info(PREFIX "Unable to map lapic to logical cpu number\n"); - return cpu; + return -ERANGE; } + num_processors++; + set_cpu_present(cpu, true); acpi_map_cpu2node(handle, cpu, physid); *pcpu = cpu; diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c index bee9f7a3108f..049c5c3e370c 100644 --- a/arch/loongarch/kernel/asm-offsets.c +++ b/arch/loongarch/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include <asm/ptrace.h> #include <asm/processor.h> #include <asm/ftrace.h> +#include <vdso/datapage.h> static void __used output_ptreg_defines(void) { @@ -321,3 +322,11 @@ static void __used output_kvm_defines(void) OFFSET(KVM_GPGD, kvm, arch.pgd); BLANK(); } + +static void __used output_vdso_defines(void) +{ + COMMENT("LoongArch vDSO offsets."); + + DEFINE(__VVAR_PAGES, VVAR_NR_PAGES); + BLANK(); +} diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c index 55320813ee08..cbce099037b2 100644 --- a/arch/loongarch/kernel/cpu-probe.c +++ b/arch/loongarch/kernel/cpu-probe.c @@ -91,12 +91,30 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) unsigned int config; unsigned long asid_mask; - c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR | - LOONGARCH_CPU_TLB | LOONGARCH_CPU_VINT | LOONGARCH_CPU_WATCH; + c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR | LOONGARCH_CPU_VINT; elf_hwcap = HWCAP_LOONGARCH_CPUCFG; config = read_cpucfg(LOONGARCH_CPUCFG1); + + switch (config & CPUCFG1_ISA) { + case 0: + set_isa(c, LOONGARCH_CPU_ISA_LA32R); + break; + case 1: + set_isa(c, LOONGARCH_CPU_ISA_LA32S); + break; + case 2: + set_isa(c, LOONGARCH_CPU_ISA_LA64); + break; + default: + pr_warn("Warning: unknown ISA level\n"); + } + + if (config & CPUCFG1_PAGING) + c->options |= LOONGARCH_CPU_TLB; + if (config & CPUCFG1_IOCSR) + c->options |= LOONGARCH_CPU_IOCSR; if (config & CPUCFG1_UAL) { c->options |= LOONGARCH_CPU_UAL; elf_hwcap |= HWCAP_LOONGARCH_UAL; @@ -106,7 +124,6 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) elf_hwcap |= HWCAP_LOONGARCH_CRC32; } - config = read_cpucfg(LOONGARCH_CPUCFG2); if (config & CPUCFG2_LAM) { c->options |= LOONGARCH_CPU_LAM; @@ -140,6 +157,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_PTW; elf_hwcap |= HWCAP_LOONGARCH_PTW; } + if (config & CPUCFG2_LSPW) { + c->options |= LOONGARCH_CPU_LSPW; + elf_hwcap |= HWCAP_LOONGARCH_LSPW; + } if (config & CPUCFG2_LVZP) { c->options |= LOONGARCH_CPU_LVZ; elf_hwcap |= HWCAP_LOONGARCH_LVZ; @@ -163,20 +184,6 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) if (config & CPUCFG6_PMP) c->options |= LOONGARCH_CPU_PMP; - config = iocsr_read32(LOONGARCH_IOCSR_FEATURES); - if (config & IOCSRF_CSRIPI) - c->options |= LOONGARCH_CPU_CSRIPI; - if (config & IOCSRF_EXTIOI) - c->options |= LOONGARCH_CPU_EXTIOI; - if (config & IOCSRF_FREQSCALE) - c->options |= LOONGARCH_CPU_SCALEFREQ; - if (config & IOCSRF_FLATMODE) - c->options |= LOONGARCH_CPU_FLATMODE; - if (config & IOCSRF_EIODECODE) - c->options |= LOONGARCH_CPU_EIODECODE; - if (config & IOCSRF_VM) - c->options |= LOONGARCH_CPU_HYPERVISOR; - config = csr_read32(LOONGARCH_CSR_ASID); config = (config & CSR_ASID_BIT) >> CSR_ASID_BIT_SHIFT; asid_mask = GENMASK(config - 1, 0); @@ -209,6 +216,9 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) default: pr_warn("Warning: unknown TLB type\n"); } + + if (get_num_brps() + get_num_wrps()) + c->options |= LOONGARCH_CPU_WATCH; } #define MAX_NAME_LEN 32 @@ -219,52 +229,67 @@ static char cpu_full_name[MAX_NAME_LEN] = " - "; static inline void cpu_probe_loongson(struct cpuinfo_loongarch *c, unsigned int cpu) { + uint32_t config; uint64_t *vendor = (void *)(&cpu_full_name[VENDOR_OFFSET]); uint64_t *cpuname = (void *)(&cpu_full_name[CPUNAME_OFFSET]); + const char *core_name = "Unknown"; - if (!__cpu_full_name[cpu]) - __cpu_full_name[cpu] = cpu_full_name; - - *vendor = iocsr_read64(LOONGARCH_IOCSR_VENDOR); - *cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME); - - switch (c->processor_id & PRID_SERIES_MASK) { - case PRID_SERIES_LA132: + switch (BIT(fls(c->isa_level) - 1)) { + case LOONGARCH_CPU_ISA_LA32R: + case LOONGARCH_CPU_ISA_LA32S: c->cputype = CPU_LOONGSON32; - set_isa(c, LOONGARCH_CPU_ISA_LA32S); __cpu_family[cpu] = "Loongson-32bit"; - pr_info("32-bit Loongson Processor probed (LA132 Core)\n"); break; - case PRID_SERIES_LA264: + case LOONGARCH_CPU_ISA_LA64: c->cputype = CPU_LOONGSON64; - set_isa(c, LOONGARCH_CPU_ISA_LA64); __cpu_family[cpu] = "Loongson-64bit"; - pr_info("64-bit Loongson Processor probed (LA264 Core)\n"); + break; + } + + switch (c->processor_id & PRID_SERIES_MASK) { + case PRID_SERIES_LA132: + core_name = "LA132"; + break; + case PRID_SERIES_LA264: + core_name = "LA264"; break; case PRID_SERIES_LA364: - c->cputype = CPU_LOONGSON64; - set_isa(c, LOONGARCH_CPU_ISA_LA64); - __cpu_family[cpu] = "Loongson-64bit"; - pr_info("64-bit Loongson Processor probed (LA364 Core)\n"); + core_name = "LA364"; break; case PRID_SERIES_LA464: - c->cputype = CPU_LOONGSON64; - set_isa(c, LOONGARCH_CPU_ISA_LA64); - __cpu_family[cpu] = "Loongson-64bit"; - pr_info("64-bit Loongson Processor probed (LA464 Core)\n"); + core_name = "LA464"; break; case PRID_SERIES_LA664: - c->cputype = CPU_LOONGSON64; - set_isa(c, LOONGARCH_CPU_ISA_LA64); - __cpu_family[cpu] = "Loongson-64bit"; - pr_info("64-bit Loongson Processor probed (LA664 Core)\n"); + core_name = "LA664"; break; - default: /* Default to 64 bit */ - c->cputype = CPU_LOONGSON64; - set_isa(c, LOONGARCH_CPU_ISA_LA64); - __cpu_family[cpu] = "Loongson-64bit"; - pr_info("64-bit Loongson Processor probed (Unknown Core)\n"); } + + pr_info("%s Processor probed (%s Core)\n", __cpu_family[cpu], core_name); + + if (!cpu_has_iocsr) + return; + + if (!__cpu_full_name[cpu]) + __cpu_full_name[cpu] = cpu_full_name; + + *vendor = iocsr_read64(LOONGARCH_IOCSR_VENDOR); + *cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME); + + config = iocsr_read32(LOONGARCH_IOCSR_FEATURES); + if (config & IOCSRF_CSRIPI) + c->options |= LOONGARCH_CPU_CSRIPI; + if (config & IOCSRF_EXTIOI) + c->options |= LOONGARCH_CPU_EXTIOI; + if (config & IOCSRF_FREQSCALE) + c->options |= LOONGARCH_CPU_SCALEFREQ; + if (config & IOCSRF_FLATMODE) + c->options |= LOONGARCH_CPU_FLATMODE; + if (config & IOCSRF_EIODECODE) + c->options |= LOONGARCH_CPU_EIODECODE; + if (config & IOCSRF_AVEC) + c->options |= LOONGARCH_CPU_AVECINT; + if (config & IOCSRF_VM) + c->options |= LOONGARCH_CPU_HYPERVISOR; } #ifdef CONFIG_64BIT diff --git a/arch/loongarch/kernel/fpu.S b/arch/loongarch/kernel/fpu.S index 69a85f2479fb..6ab640101457 100644 --- a/arch/loongarch/kernel/fpu.S +++ b/arch/loongarch/kernel/fpu.S @@ -530,6 +530,10 @@ SYM_FUNC_END(_restore_lasx_context) #ifdef CONFIG_CPU_HAS_LBT STACK_FRAME_NON_STANDARD _restore_fp +#ifdef CONFIG_CPU_HAS_LSX STACK_FRAME_NON_STANDARD _restore_lsx +#endif +#ifdef CONFIG_CPU_HAS_LASX STACK_FRAME_NON_STANDARD _restore_lasx #endif +#endif diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c index bff058317062..18056229e22e 100644 --- a/arch/loongarch/kernel/ftrace_dyn.c +++ b/arch/loongarch/kernel/ftrace_dyn.c @@ -241,7 +241,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent) void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - struct pt_regs *regs = &fregs->regs; + struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs; unsigned long *parent = (unsigned long *)®s->regs[1]; prepare_ftrace_return(ip, (unsigned long *)parent); diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index f4991c03514f..80946cafaec1 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -87,6 +87,18 @@ static void __init init_vec_parent_group(void) acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); } +int __init arch_probe_nr_irqs(void) +{ + int nr_io_pics = bitmap_weight(loongson_sysconf.cores_io_master, NR_CPUS); + + if (!cpu_has_avecint) + irq_set_nr_irqs(64 + NR_VECTORS * nr_io_pics); + else + irq_set_nr_irqs(64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics)); + + return NR_IRQS_LEGACY; +} + void __init init_IRQ(void) { int i; @@ -102,9 +114,6 @@ void __init init_IRQ(void) mp_ops.init_ipi(); #endif - for (i = 0; i < NR_IRQS; i++) - irq_set_noprobe(i); - for_each_possible_cpu(i) { page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, order); diff --git a/arch/loongarch/kernel/numa.c b/arch/loongarch/kernel/numa.c index 8fe21f868f72..84fe7f854820 100644 --- a/arch/loongarch/kernel/numa.c +++ b/arch/loongarch/kernel/numa.c @@ -27,10 +27,7 @@ #include <asm/time.h> int numa_off; -struct pglist_data *node_data[MAX_NUMNODES]; unsigned char node_distances[MAX_NUMNODES][MAX_NUMNODES]; - -EXPORT_SYMBOL(node_data); EXPORT_SYMBOL(node_distances); static struct numa_meminfo numa_meminfo; @@ -190,24 +187,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end) return numa_add_memblk_to(nid, start, end, &numa_meminfo); } -static void __init alloc_node_data(int nid) -{ - void *nd; - unsigned long nd_pa; - size_t nd_sz = roundup(sizeof(pg_data_t), PAGE_SIZE); - - nd_pa = memblock_phys_alloc_try_nid(nd_sz, SMP_CACHE_BYTES, nid); - if (!nd_pa) { - pr_err("Cannot find %zu Byte for node_data (initial node: %d)\n", nd_sz, nid); - return; - } - - nd = __va(nd_pa); - - node_data[nid] = nd; - memset(nd, 0, sizeof(pg_data_t)); -} - static void __init node_mem_init(unsigned int node) { unsigned long start_pfn, end_pfn; diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 9c9b75b76f62..e5a39bbad078 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -13,6 +13,7 @@ static int has_steal_clock; struct static_key paravirt_steal_enabled; struct static_key paravirt_steal_rq_enabled; static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64); +DEFINE_STATIC_KEY_FALSE(virt_spin_lock_key); static u64 native_steal_clock(int cpu) { @@ -50,11 +51,18 @@ static u64 paravt_steal_clock(int cpu) } #ifdef CONFIG_SMP +static struct smp_ops native_ops; + static void pv_send_ipi_single(int cpu, unsigned int action) { int min, old; irq_cpustat_t *info = &per_cpu(irq_stat, cpu); + if (unlikely(action == ACTION_BOOT_CPU)) { + native_ops.send_ipi_single(cpu, action); + return; + } + old = atomic_fetch_or(BIT(action), &info->message); if (old) return; @@ -74,6 +82,11 @@ static void pv_send_ipi_mask(const struct cpumask *mask, unsigned int action) if (cpumask_empty(mask)) return; + if (unlikely(action == ACTION_BOOT_CPU)) { + native_ops.send_ipi_mask(mask, action); + return; + } + action = BIT(action); for_each_cpu(i, mask) { info = &per_cpu(irq_stat, i); @@ -134,6 +147,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev) info->ipi_irqs[IPI_IRQ_WORK]++; } + if (action & SMP_CLEAR_VECTOR) { + complete_irq_moving(); + info->ipi_irqs[IPI_CLEAR_VECTOR]++; + } + return IRQ_HANDLED; } @@ -141,6 +159,8 @@ static void pv_init_ipi(void) { int r, swi; + /* Init native ipi irq for ACTION_BOOT_CPU */ + native_ops.init_ipi(); swi = get_percpu_irq(INT_SWI0); if (swi < 0) panic("SWI0 IRQ mapping failed\n"); @@ -151,11 +171,14 @@ static void pv_init_ipi(void) } #endif -static bool kvm_para_available(void) +bool kvm_para_available(void) { int config; static int hypervisor_type; + if (!cpu_has_hypervisor) + return false; + if (!hypervisor_type) { config = read_cpucfg(CPUCFG_KVM_SIG); if (!memcmp(&config, KVM_SIGNATURE, 4)) @@ -165,20 +188,26 @@ static bool kvm_para_available(void) return hypervisor_type == HYPERVISOR_KVM; } -int __init pv_ipi_init(void) +unsigned int kvm_arch_para_features(void) { - int feature; + static unsigned int feature; - if (!cpu_has_hypervisor) - return 0; if (!kvm_para_available()) return 0; - feature = read_cpucfg(CPUCFG_KVM_FEATURE); - if (!(feature & KVM_FEATURE_IPI)) + if (!feature) + feature = read_cpucfg(CPUCFG_KVM_FEATURE); + + return feature; +} + +int __init pv_ipi_init(void) +{ + if (!kvm_para_has_feature(KVM_FEATURE_IPI)) return 0; #ifdef CONFIG_SMP + native_ops = mp_ops; mp_ops.init_ipi = pv_init_ipi; mp_ops.send_ipi_single = pv_send_ipi_single; mp_ops.send_ipi_mask = pv_send_ipi_mask; @@ -206,7 +235,7 @@ static int pv_enable_steal_time(void) } addr |= KVM_STEAL_PHYS_VALID; - kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, addr); + kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), addr); return 0; } @@ -214,7 +243,7 @@ static int pv_enable_steal_time(void) static void pv_disable_steal_time(void) { if (has_steal_clock) - kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, KVM_FEATURE_STEAL_TIME, 0); + kvm_hypercall2(KVM_HCALL_FUNC_NOTIFY, BIT(KVM_FEATURE_STEAL_TIME), 0); } #ifdef CONFIG_SMP @@ -258,15 +287,9 @@ static struct notifier_block pv_reboot_nb = { int __init pv_time_init(void) { - int r, feature; - - if (!cpu_has_hypervisor) - return 0; - if (!kvm_para_available()) - return 0; + int r; - feature = read_cpucfg(CPUCFG_KVM_FEATURE); - if (!(feature & KVM_FEATURE_STEAL_TIME)) + if (!kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) return 0; has_steal_clock = 1; @@ -300,3 +323,13 @@ int __init pv_time_init(void) return 0; } + +int __init pv_spinlock_init(void) +{ + if (!cpu_has_hypervisor) + return 0; + + static_branch_enable(&virt_spin_lock_key); + + return 0; +} diff --git a/arch/loongarch/kernel/proc.c b/arch/loongarch/kernel/proc.c index 0d33cbc47e51..6ce46d92f1f1 100644 --- a/arch/loongarch/kernel/proc.c +++ b/arch/loongarch/kernel/proc.c @@ -31,6 +31,7 @@ int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v) static int show_cpuinfo(struct seq_file *m, void *v) { unsigned long n = (unsigned long) v - 1; + unsigned int isa = cpu_data[n].isa_level; unsigned int version = cpu_data[n].processor_id & 0xff; unsigned int fp_version = cpu_data[n].fpu_vers; struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args; @@ -64,9 +65,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpu_pabits + 1, cpu_vabits + 1); seq_printf(m, "ISA\t\t\t:"); - if (cpu_has_loongarch32) - seq_printf(m, " loongarch32"); - if (cpu_has_loongarch64) + if (isa & LOONGARCH_CPU_ISA_LA32R) + seq_printf(m, " loongarch32r"); + if (isa & LOONGARCH_CPU_ISA_LA32S) + seq_printf(m, " loongarch32s"); + if (isa & LOONGARCH_CPU_ISA_LA64) seq_printf(m, " loongarch64"); seq_printf(m, "\n"); @@ -81,6 +84,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_complex) seq_printf(m, " complex"); if (cpu_has_crypto) seq_printf(m, " crypto"); if (cpu_has_ptw) seq_printf(m, " ptw"); + if (cpu_has_lspw) seq_printf(m, " lspw"); if (cpu_has_lvz) seq_printf(m, " lvz"); if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86"); if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm"); diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c index f2ff8b5d591e..6e58f65455c7 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -293,13 +293,15 @@ unsigned long stack_top(void) { unsigned long top = TASK_SIZE & PAGE_MASK; - /* Space for the VDSO & data page */ - top -= PAGE_ALIGN(current->thread.vdso->size); - top -= VVAR_SIZE; - - /* Space to randomize the VDSO base */ - if (current->flags & PF_RANDOMIZE) - top -= VDSO_RANDOMIZE_SIZE; + if (current->thread.vdso) { + /* Space for the VDSO & data page */ + top -= PAGE_ALIGN(current->thread.vdso->size); + top -= VVAR_SIZE; + + /* Space to randomize the VDSO base */ + if (current->flags & PF_RANDOMIZE) + top -= VDSO_RANDOMIZE_SIZE; + } return top; } diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 0f0740f0be27..56934fe58170 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -55,6 +55,7 @@ #define SMBIOS_FREQHIGH_OFFSET 0x17 #define SMBIOS_FREQLOW_MASK 0xFF #define SMBIOS_CORE_PACKAGE_OFFSET 0x23 +#define SMBIOS_THREAD_PACKAGE_OFFSET 0x25 #define LOONGSON_EFI_ENABLE (1 << 3) unsigned long fw_arg0, fw_arg1, fw_arg2; @@ -125,7 +126,7 @@ static void __init parse_cpu_table(const struct dmi_header *dm) cpu_clock_freq = freq_temp * 1000000; loongson_sysconf.cpuname = (void *)dmi_string_parse(dm, dmi_data[16]); - loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_CORE_PACKAGE_OFFSET); + loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_THREAD_PACKAGE_OFFSET); pr_info("CpuClock = %llu\n", cpu_clock_freq); } @@ -290,7 +291,7 @@ static void __init fdt_setup(void) if (!fdt_pointer || fdt_check_header(fdt_pointer)) return; - early_init_dt_scan(fdt_pointer); + early_init_dt_scan(fdt_pointer, __pa(fdt_pointer)); early_init_fdt_reserve_self(); max_low_pfn = PFN_PHYS(memblock_end_of_DRAM()); @@ -603,6 +604,8 @@ void __init setup_arch(char **cmdline_p) arch_mem_init(cmdline_p); resource_init(); + jump_label_init(); /* Initialise the static keys for paravirtualization */ + #ifdef CONFIG_SMP plat_smp_setup(); prefill_possible_map(); diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index ca405ab86aae..5d59e9ce2772 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -72,6 +72,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { [IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_CALL_FUNCTION] = "Function call interrupts", [IPI_IRQ_WORK] = "IRQ work interrupts", + [IPI_CLEAR_VECTOR] = "Clear vector interrupts", }; void show_ipi_list(struct seq_file *p, int prec) @@ -248,6 +249,11 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) per_cpu(irq_stat, cpu).ipi_irqs[IPI_IRQ_WORK]++; } + if (action & SMP_CLEAR_VECTOR) { + complete_irq_moving(); + per_cpu(irq_stat, cpu).ipi_irqs[IPI_CLEAR_VECTOR]++; + } + return IRQ_HANDLED; } @@ -296,7 +302,7 @@ static void __init fdt_smp_setup(void) __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; - early_numa_add_cpu(cpu, 0); + early_numa_add_cpu(cpuid, 0); set_cpuid_to_node(cpuid, 0); } @@ -325,11 +331,11 @@ void __init loongson_prepare_cpus(unsigned int max_cpus) int i = 0; parse_acpi_topology(); + cpu_data[0].global_id = cpu_logical_map(0); for (i = 0; i < loongson_sysconf.nr_cpus; i++) { set_cpu_present(i, true); csr_mail_send(0, __cpu_logical_map[i], 0); - cpu_data[i].global_id = __cpu_logical_map[i]; } per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; @@ -374,6 +380,7 @@ void loongson_init_secondary(void) cpu_logical_map(cpu) / loongson_sysconf.cores_per_package; cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core : cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; + cpu_data[cpu].global_id = cpu_logical_map(cpu); } void loongson_smp_finish(void) @@ -476,7 +483,7 @@ core_initcall(ipi_pm_init); #endif /* Preload SMP state for boot cpu */ -void smp_prepare_boot_cpu(void) +void __init smp_prepare_boot_cpu(void) { unsigned int cpu, node, rr_node; @@ -509,6 +516,8 @@ void smp_prepare_boot_cpu(void) rr_node = next_node_in(rr_node, node_online_map); } } + + pv_spinlock_init(); } /* called from main before smp_init() */ diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index ba5d0930a74f..168bd97540f8 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -79,7 +79,3 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) syscall_exit_to_user_mode(regs); } - -#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET -STACK_FRAME_NON_STANDARD(do_syscall); -#endif diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index f9f4eb00c92e..c57b4134f3e8 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -555,6 +555,9 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs) #else unsigned int *pc; + if (regs->csr_prmd & CSR_PRMD_PIE) + local_irq_enable(); + perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->csr_badvaddr); /* @@ -579,6 +582,8 @@ sigbus: die_if_kernel("Kernel ale access", regs); force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr); out: + if (regs->csr_prmd & CSR_PRMD_PIE) + local_irq_disable(); #endif irqentry_exit(regs, state); } diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c index 90dfccb41c14..05e5fbac102a 100644 --- a/arch/loongarch/kernel/vdso.c +++ b/arch/loongarch/kernel/vdso.c @@ -15,7 +15,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/time_namespace.h> -#include <linux/timekeeper_internal.h> #include <asm/page.h> #include <asm/vdso.h> @@ -34,9 +33,9 @@ static union { struct loongarch_vdso_data vdata; } loongarch_vdso_data __page_aligned_data; -static struct page *vdso_pages[] = { NULL }; struct vdso_data *vdso_data = generic_vdso_data.data; struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata; +struct vdso_rng_data *vdso_rng_data = &loongarch_vdso_data.vdata.rng_data; static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) { @@ -84,10 +83,8 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, struct loongarch_vdso_info vdso_info = { .vdso = vdso_start, - .size = PAGE_SIZE, .code_mapping = { .name = "[vdso]", - .pages = vdso_pages, .mremap = vdso_mremap, }, .data_mapping = { @@ -102,11 +99,14 @@ static int __init init_vdso(void) unsigned long i, cpu, pfn; BUG_ON(!PAGE_ALIGNED(vdso_info.vdso)); - BUG_ON(!PAGE_ALIGNED(vdso_info.size)); for_each_possible_cpu(cpu) vdso_pdata[cpu].node = cpu_to_node(cpu); + vdso_info.size = PAGE_ALIGN(vdso_end - vdso_start); + vdso_info.code_mapping.pages = + kcalloc(vdso_info.size / PAGE_SIZE, sizeof(struct page *), GFP_KERNEL); + pfn = __phys_to_pfn(__pa_symbol(vdso_info.vdso)); for (i = 0; i < vdso_info.size / PAGE_SIZE; i++) vdso_info.code_mapping.pages[i] = pfn_to_page(pfn + i); diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index ea73f9dc2cc6..90894f70ff4a 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -50,9 +50,7 @@ static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst) vcpu->arch.gprs[rd] = *(unsigned int *)KVM_SIGNATURE; break; case CPUCFG_KVM_FEATURE: - ret = KVM_FEATURE_IPI; - if (kvm_pvtime_supported()) - ret |= KVM_FEATURE_STEAL_TIME; + ret = vcpu->kvm->arch.pv_features & LOONGARCH_PV_FEAT_MASK; vcpu->arch.gprs[rd] = ret; break; default: @@ -127,6 +125,14 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst) rj = inst.reg2csr_format.rj; csrid = inst.reg2csr_format.csr; + if (csrid >= LOONGARCH_CSR_PERFCTRL0 && csrid <= vcpu->arch.max_pmu_csrid) { + if (kvm_guest_has_pmu(&vcpu->arch)) { + vcpu->arch.pc -= 4; + kvm_make_request(KVM_REQ_PMU, vcpu); + return EMULATE_DONE; + } + } + /* Process CSR ops */ switch (rj) { case 0: /* process csrrd */ @@ -697,25 +703,22 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu) id = kvm_read_reg(vcpu, LOONGARCH_GPR_A1); data = kvm_read_reg(vcpu, LOONGARCH_GPR_A2); switch (id) { - case KVM_FEATURE_STEAL_TIME: - if (!kvm_pvtime_supported()) - return KVM_HCALL_INVALID_CODE; - + case BIT(KVM_FEATURE_STEAL_TIME): if (data & ~(KVM_STEAL_PHYS_MASK | KVM_STEAL_PHYS_VALID)) return KVM_HCALL_INVALID_PARAMETER; vcpu->arch.st.guest_addr = data; if (!(data & KVM_STEAL_PHYS_VALID)) - break; + return 0; vcpu->arch.st.last_steal = current->sched_info.run_delay; kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); - break; + return 0; default: - break; + return KVM_HCALL_INVALID_CODE; }; - return 0; + return KVM_HCALL_INVALID_CODE; }; /* @@ -748,6 +751,14 @@ static int kvm_handle_lasx_disabled(struct kvm_vcpu *vcpu) return RESUME_GUEST; } +static int kvm_handle_lbt_disabled(struct kvm_vcpu *vcpu) +{ + if (kvm_own_lbt(vcpu)) + kvm_queue_exception(vcpu, EXCCODE_INE, 0); + + return RESUME_GUEST; +} + static int kvm_send_pv_ipi(struct kvm_vcpu *vcpu) { unsigned int min, cpu, i; @@ -781,19 +792,21 @@ static int kvm_send_pv_ipi(struct kvm_vcpu *vcpu) */ static void kvm_handle_service(struct kvm_vcpu *vcpu) { + long ret = KVM_HCALL_INVALID_CODE; unsigned long func = kvm_read_reg(vcpu, LOONGARCH_GPR_A0); - long ret; switch (func) { case KVM_HCALL_FUNC_IPI: - kvm_send_pv_ipi(vcpu); - ret = KVM_HCALL_SUCCESS; + if (kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_IPI)) { + kvm_send_pv_ipi(vcpu); + ret = KVM_HCALL_SUCCESS; + } break; case KVM_HCALL_FUNC_NOTIFY: - ret = kvm_save_notify(vcpu); + if (kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME)) + ret = kvm_save_notify(vcpu); break; default: - ret = KVM_HCALL_INVALID_CODE; break; } @@ -865,6 +878,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = { [EXCCODE_FPDIS] = kvm_handle_fpu_disabled, [EXCCODE_LSXDIS] = kvm_handle_lsx_disabled, [EXCCODE_LASXDIS] = kvm_handle_lasx_disabled, + [EXCCODE_BTDIS] = kvm_handle_lbt_disabled, [EXCCODE_GSPR] = kvm_handle_gspr, [EXCCODE_HVC] = kvm_handle_hypercall, }; diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c index 844736b99d38..27e9b94c0a0b 100644 --- a/arch/loongarch/kvm/main.c +++ b/arch/loongarch/kvm/main.c @@ -261,7 +261,7 @@ long kvm_arch_dev_ioctl(struct file *filp, return -ENOIOCTLCMD; } -int kvm_arch_hardware_enable(void) +int kvm_arch_enable_virtualization_cpu(void) { unsigned long env, gcfg = 0; @@ -300,7 +300,7 @@ int kvm_arch_hardware_enable(void) return 0; } -void kvm_arch_hardware_disable(void) +void kvm_arch_disable_virtualization_cpu(void) { write_csr_gcfg(0); write_csr_gstat(0); diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S index 80e988985a6a..0c292f818492 100644 --- a/arch/loongarch/kvm/switch.S +++ b/arch/loongarch/kvm/switch.S @@ -277,6 +277,10 @@ SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest) #ifdef CONFIG_CPU_HAS_LBT STACK_FRAME_NON_STANDARD kvm_restore_fpu +#ifdef CONFIG_CPU_HAS_LSX STACK_FRAME_NON_STANDARD kvm_restore_lsx +#endif +#ifdef CONFIG_CPU_HAS_LASX STACK_FRAME_NON_STANDARD kvm_restore_lasx #endif +#endif diff --git a/arch/loongarch/kvm/timer.c b/arch/loongarch/kvm/timer.c index bcc6b6d063d9..32dc213374be 100644 --- a/arch/loongarch/kvm/timer.c +++ b/arch/loongarch/kvm/timer.c @@ -161,10 +161,11 @@ static void _kvm_save_timer(struct kvm_vcpu *vcpu) if (kvm_vcpu_is_blocking(vcpu)) { /* - * HRTIMER_MODE_PINNED is suggested since vcpu may run in - * the same physical cpu in next time + * HRTIMER_MODE_PINNED_HARD is suggested since vcpu may run in + * the same physical cpu in next time, and the timer should run + * in hardirq context even in the PREEMPT_RT case. */ - hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED); + hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED_HARD); } } @@ -188,10 +189,3 @@ void kvm_save_timer(struct kvm_vcpu *vcpu) kvm_save_hw_gcsr(csr, LOONGARCH_CSR_ESTAT); preempt_enable(); } - -void kvm_reset_timer(struct kvm_vcpu *vcpu) -{ - write_gcsr_timercfg(0); - kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_TCFG, 0); - hrtimer_cancel(&vcpu->arch.swtimer); -} diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 16756ffb55e8..174734a23d0a 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -6,6 +6,7 @@ #include <linux/kvm_host.h> #include <linux/entry-kvm.h> #include <asm/fpu.h> +#include <asm/lbt.h> #include <asm/loongarch.h> #include <asm/setup.h> #include <asm/time.h> @@ -31,6 +32,126 @@ const struct kvm_stats_header kvm_vcpu_stats_header = { sizeof(kvm_vcpu_stats_desc), }; +static inline void kvm_save_host_pmu(struct kvm_vcpu *vcpu) +{ + struct kvm_context *context; + + context = this_cpu_ptr(vcpu->kvm->arch.vmcs); + context->perf_cntr[0] = read_csr_perfcntr0(); + context->perf_cntr[1] = read_csr_perfcntr1(); + context->perf_cntr[2] = read_csr_perfcntr2(); + context->perf_cntr[3] = read_csr_perfcntr3(); + context->perf_ctrl[0] = write_csr_perfctrl0(0); + context->perf_ctrl[1] = write_csr_perfctrl1(0); + context->perf_ctrl[2] = write_csr_perfctrl2(0); + context->perf_ctrl[3] = write_csr_perfctrl3(0); +} + +static inline void kvm_restore_host_pmu(struct kvm_vcpu *vcpu) +{ + struct kvm_context *context; + + context = this_cpu_ptr(vcpu->kvm->arch.vmcs); + write_csr_perfcntr0(context->perf_cntr[0]); + write_csr_perfcntr1(context->perf_cntr[1]); + write_csr_perfcntr2(context->perf_cntr[2]); + write_csr_perfcntr3(context->perf_cntr[3]); + write_csr_perfctrl0(context->perf_ctrl[0]); + write_csr_perfctrl1(context->perf_ctrl[1]); + write_csr_perfctrl2(context->perf_ctrl[2]); + write_csr_perfctrl3(context->perf_ctrl[3]); +} + + +static inline void kvm_save_guest_pmu(struct kvm_vcpu *vcpu) +{ + struct loongarch_csrs *csr = vcpu->arch.csr; + + kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR0); + kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR1); + kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR2); + kvm_save_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR3); + kvm_read_clear_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL0); + kvm_read_clear_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL1); + kvm_read_clear_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL2); + kvm_read_clear_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL3); +} + +static inline void kvm_restore_guest_pmu(struct kvm_vcpu *vcpu) +{ + struct loongarch_csrs *csr = vcpu->arch.csr; + + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR0); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR1); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR2); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCNTR3); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL0); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL1); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL2); + kvm_restore_hw_gcsr(csr, LOONGARCH_CSR_PERFCTRL3); +} + +static int kvm_own_pmu(struct kvm_vcpu *vcpu) +{ + unsigned long val; + + if (!kvm_guest_has_pmu(&vcpu->arch)) + return -EINVAL; + + kvm_save_host_pmu(vcpu); + + /* Set PM0-PM(num) to guest */ + val = read_csr_gcfg() & ~CSR_GCFG_GPERF; + val |= (kvm_get_pmu_num(&vcpu->arch) + 1) << CSR_GCFG_GPERF_SHIFT; + write_csr_gcfg(val); + + kvm_restore_guest_pmu(vcpu); + + return 0; +} + +static void kvm_lose_pmu(struct kvm_vcpu *vcpu) +{ + unsigned long val; + struct loongarch_csrs *csr = vcpu->arch.csr; + + if (!(vcpu->arch.aux_inuse & KVM_LARCH_PMU)) + return; + + kvm_save_guest_pmu(vcpu); + + /* Disable pmu access from guest */ + write_csr_gcfg(read_csr_gcfg() & ~CSR_GCFG_GPERF); + + /* + * Clear KVM_LARCH_PMU if the guest is not using PMU CSRs when + * exiting the guest, so that the next time trap into the guest. + * We don't need to deal with PMU CSRs contexts. + */ + val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL0); + val |= kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL1); + val |= kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL2); + val |= kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL3); + if (!(val & KVM_PMU_EVENT_ENABLED)) + vcpu->arch.aux_inuse &= ~KVM_LARCH_PMU; + + kvm_restore_host_pmu(vcpu); +} + +static void kvm_restore_pmu(struct kvm_vcpu *vcpu) +{ + if ((vcpu->arch.aux_inuse & KVM_LARCH_PMU)) + kvm_make_request(KVM_REQ_PMU, vcpu); +} + +static void kvm_check_pmu(struct kvm_vcpu *vcpu) +{ + if (kvm_check_request(KVM_REQ_PMU, vcpu)) { + kvm_own_pmu(vcpu); + vcpu->arch.aux_inuse |= KVM_LARCH_PMU; + } +} + static void kvm_update_stolen_time(struct kvm_vcpu *vcpu) { u32 version; @@ -158,6 +279,7 @@ static int kvm_pre_enter_guest(struct kvm_vcpu *vcpu) /* Make sure the vcpu mode has been written */ smp_store_mb(vcpu->mode, IN_GUEST_MODE); kvm_check_vpid(vcpu); + kvm_check_pmu(vcpu); /* * Called after function kvm_check_vpid() @@ -195,6 +317,8 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) /* Set a default exit reason */ run->exit_reason = KVM_EXIT_UNKNOWN; + kvm_lose_pmu(vcpu); + guest_timing_exit_irqoff(); guest_state_exit_irqoff(); local_irq_enable(); @@ -468,6 +592,22 @@ static int _kvm_setcsr(struct kvm_vcpu *vcpu, unsigned int id, u64 val) kvm_write_sw_gcsr(csr, id, val); + /* + * After modifying the PMU CSR register value of the vcpu. + * If the PMU CSRs are used, we need to set KVM_REQ_PMU. + */ + if (id >= LOONGARCH_CSR_PERFCTRL0 && id <= LOONGARCH_CSR_PERFCNTR3) { + unsigned long val; + + val = kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL0) | + kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL1) | + kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL2) | + kvm_read_sw_gcsr(csr, LOONGARCH_CSR_PERFCTRL3); + + if (val & KVM_PMU_EVENT_ENABLED) + kvm_make_request(KVM_REQ_PMU, vcpu); + } + return ret; } @@ -497,6 +637,12 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v) *v |= CPUCFG2_LSX; if (cpu_has_lasx) *v |= CPUCFG2_LASX; + if (cpu_has_lbt_x86) + *v |= CPUCFG2_X86BT; + if (cpu_has_lbt_arm) + *v |= CPUCFG2_ARMBT; + if (cpu_has_lbt_mips) + *v |= CPUCFG2_MIPSBT; return 0; case LOONGARCH_CPUCFG3: @@ -506,6 +652,12 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v) case LOONGARCH_CPUCFG5: *v = GENMASK(31, 0); return 0; + case LOONGARCH_CPUCFG6: + if (cpu_has_pmp) + *v = GENMASK(14, 0); + else + *v = 0; + return 0; case LOONGARCH_CPUCFG16: *v = GENMASK(16, 0); return 0; @@ -550,6 +702,17 @@ static int kvm_check_cpucfg(int id, u64 val) /* LASX architecturally implies LSX and FP but val does not satisfy that */ return -EINVAL; return 0; + case LOONGARCH_CPUCFG6: + if (val & CPUCFG6_PMP) { + u32 host = read_cpucfg(LOONGARCH_CPUCFG6); + if ((val & CPUCFG6_PMBITS) != (host & CPUCFG6_PMBITS)) + return -EINVAL; + if ((val & CPUCFG6_PMNUM) > (host & CPUCFG6_PMNUM)) + return -EINVAL; + if ((val & CPUCFG6_UPM) && !(host & CPUCFG6_UPM)) + return -EINVAL; + } + return 0; default: /* * Values for the other CPUCFG IDs are not being further validated @@ -577,6 +740,34 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu, else ret = -EINVAL; break; + case KVM_REG_LOONGARCH_LBT: + if (!kvm_guest_has_lbt(&vcpu->arch)) + return -ENXIO; + + switch (reg->id) { + case KVM_REG_LOONGARCH_LBT_SCR0: + *v = vcpu->arch.lbt.scr0; + break; + case KVM_REG_LOONGARCH_LBT_SCR1: + *v = vcpu->arch.lbt.scr1; + break; + case KVM_REG_LOONGARCH_LBT_SCR2: + *v = vcpu->arch.lbt.scr2; + break; + case KVM_REG_LOONGARCH_LBT_SCR3: + *v = vcpu->arch.lbt.scr3; + break; + case KVM_REG_LOONGARCH_LBT_EFLAGS: + *v = vcpu->arch.lbt.eflags; + break; + case KVM_REG_LOONGARCH_LBT_FTOP: + *v = vcpu->arch.fpu.ftop; + break; + default: + ret = -EINVAL; + break; + } + break; case KVM_REG_LOONGARCH_KVM: switch (reg->id) { case KVM_REG_LOONGARCH_COUNTER: @@ -635,6 +826,37 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, if (ret) break; vcpu->arch.cpucfg[id] = (u32)v; + if (id == LOONGARCH_CPUCFG6) + vcpu->arch.max_pmu_csrid = + LOONGARCH_CSR_PERFCTRL0 + 2 * kvm_get_pmu_num(&vcpu->arch) + 1; + break; + case KVM_REG_LOONGARCH_LBT: + if (!kvm_guest_has_lbt(&vcpu->arch)) + return -ENXIO; + + switch (reg->id) { + case KVM_REG_LOONGARCH_LBT_SCR0: + vcpu->arch.lbt.scr0 = v; + break; + case KVM_REG_LOONGARCH_LBT_SCR1: + vcpu->arch.lbt.scr1 = v; + break; + case KVM_REG_LOONGARCH_LBT_SCR2: + vcpu->arch.lbt.scr2 = v; + break; + case KVM_REG_LOONGARCH_LBT_SCR3: + vcpu->arch.lbt.scr3 = v; + break; + case KVM_REG_LOONGARCH_LBT_EFLAGS: + vcpu->arch.lbt.eflags = v; + break; + case KVM_REG_LOONGARCH_LBT_FTOP: + vcpu->arch.fpu.ftop = v; + break; + default: + ret = -EINVAL; + break; + } break; case KVM_REG_LOONGARCH_KVM: switch (reg->id) { @@ -647,7 +869,7 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, vcpu->kvm->arch.time_offset = (signed long)(v - drdtime()); break; case KVM_REG_LOONGARCH_VCPU_RESET: - kvm_reset_timer(vcpu); + vcpu->arch.st.guest_addr = 0; memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending)); memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear)); break; @@ -728,7 +950,10 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { switch (attr->attr) { - case 2: + case LOONGARCH_CPUCFG2: + case LOONGARCH_CPUCFG6: + return 0; + case CPUCFG_KVM_FEATURE: return 0; default: return -ENXIO; @@ -740,8 +965,8 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu, static int kvm_loongarch_pvtime_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME) + || attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) return -ENXIO; return 0; @@ -773,9 +998,18 @@ static int kvm_loongarch_cpucfg_get_attr(struct kvm_vcpu *vcpu, uint64_t val; uint64_t __user *uaddr = (uint64_t __user *)attr->addr; - ret = _kvm_get_cpucfg_mask(attr->attr, &val); - if (ret) - return ret; + switch (attr->attr) { + case 0 ... (KVM_MAX_CPUCFG_REGS - 1): + ret = _kvm_get_cpucfg_mask(attr->attr, &val); + if (ret) + return ret; + break; + case CPUCFG_KVM_FEATURE: + val = vcpu->kvm->arch.pv_features & LOONGARCH_PV_FEAT_MASK; + break; + default: + return -ENXIO; + } put_user(val, uaddr); @@ -788,8 +1022,8 @@ static int kvm_loongarch_pvtime_get_attr(struct kvm_vcpu *vcpu, u64 gpa; u64 __user *user = (u64 __user *)attr->addr; - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME) + || attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) return -ENXIO; gpa = vcpu->arch.st.guest_addr; @@ -821,7 +1055,28 @@ static int kvm_loongarch_vcpu_get_attr(struct kvm_vcpu *vcpu, static int kvm_loongarch_cpucfg_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { - return -ENXIO; + u64 val, valid; + u64 __user *user = (u64 __user *)attr->addr; + struct kvm *kvm = vcpu->kvm; + + switch (attr->attr) { + case CPUCFG_KVM_FEATURE: + if (get_user(val, user)) + return -EFAULT; + + valid = LOONGARCH_PV_FEAT_MASK; + if (val & ~valid) + return -EINVAL; + + /* All vCPUs need set the same PV features */ + if ((kvm->arch.pv_features & LOONGARCH_PV_FEAT_UPDATED) + && ((kvm->arch.pv_features & valid) != val)) + return -EINVAL; + kvm->arch.pv_features = val | LOONGARCH_PV_FEAT_UPDATED; + return 0; + default: + return -ENXIO; + } } static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu, @@ -831,8 +1086,8 @@ static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu, u64 gpa, __user *user = (u64 __user *)attr->addr; struct kvm *kvm = vcpu->kvm; - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + if (!kvm_guest_has_pv_feature(vcpu, KVM_FEATURE_STEAL_TIME) + || attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) return -ENXIO; if (get_user(gpa, user)) @@ -977,12 +1232,66 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) return 0; } +#ifdef CONFIG_CPU_HAS_LBT +int kvm_own_lbt(struct kvm_vcpu *vcpu) +{ + if (!kvm_guest_has_lbt(&vcpu->arch)) + return -EINVAL; + + preempt_disable(); + set_csr_euen(CSR_EUEN_LBTEN); + _restore_lbt(&vcpu->arch.lbt); + vcpu->arch.aux_inuse |= KVM_LARCH_LBT; + preempt_enable(); + + return 0; +} + +static void kvm_lose_lbt(struct kvm_vcpu *vcpu) +{ + preempt_disable(); + if (vcpu->arch.aux_inuse & KVM_LARCH_LBT) { + _save_lbt(&vcpu->arch.lbt); + clear_csr_euen(CSR_EUEN_LBTEN); + vcpu->arch.aux_inuse &= ~KVM_LARCH_LBT; + } + preempt_enable(); +} + +static void kvm_check_fcsr(struct kvm_vcpu *vcpu, unsigned long fcsr) +{ + /* + * If TM is enabled, top register save/restore will + * cause lbt exception, here enable lbt in advance + */ + if (fcsr & FPU_CSR_TM) + kvm_own_lbt(vcpu); +} + +static void kvm_check_fcsr_alive(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.aux_inuse & KVM_LARCH_FPU) { + if (vcpu->arch.aux_inuse & KVM_LARCH_LBT) + return; + kvm_check_fcsr(vcpu, read_fcsr(LOONGARCH_FCSR0)); + } +} +#else +static inline void kvm_lose_lbt(struct kvm_vcpu *vcpu) { } +static inline void kvm_check_fcsr(struct kvm_vcpu *vcpu, unsigned long fcsr) { } +static inline void kvm_check_fcsr_alive(struct kvm_vcpu *vcpu) { } +#endif + /* Enable FPU and restore context */ void kvm_own_fpu(struct kvm_vcpu *vcpu) { preempt_disable(); - /* Enable FPU */ + /* + * Enable FPU for guest + * Set FR and FRE according to guest context + */ + kvm_check_fcsr(vcpu, vcpu->arch.fpu.fcsr); set_csr_euen(CSR_EUEN_FPEN); kvm_restore_fpu(&vcpu->arch.fpu); @@ -1002,6 +1311,7 @@ int kvm_own_lsx(struct kvm_vcpu *vcpu) preempt_disable(); /* Enable LSX for guest */ + kvm_check_fcsr(vcpu, vcpu->arch.fpu.fcsr); set_csr_euen(CSR_EUEN_LSXEN | CSR_EUEN_FPEN); switch (vcpu->arch.aux_inuse & KVM_LARCH_FPU) { case KVM_LARCH_FPU: @@ -1036,6 +1346,7 @@ int kvm_own_lasx(struct kvm_vcpu *vcpu) preempt_disable(); + kvm_check_fcsr(vcpu, vcpu->arch.fpu.fcsr); set_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN); switch (vcpu->arch.aux_inuse & (KVM_LARCH_FPU | KVM_LARCH_LSX)) { case KVM_LARCH_LSX: @@ -1067,6 +1378,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu) { preempt_disable(); + kvm_check_fcsr_alive(vcpu); if (vcpu->arch.aux_inuse & KVM_LARCH_LASX) { kvm_save_lasx(&vcpu->arch.fpu); vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LASX); @@ -1089,6 +1401,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu) /* Disable FPU */ clear_csr_euen(CSR_EUEN_FPEN); } + kvm_lose_lbt(vcpu); preempt_enable(); } @@ -1144,7 +1457,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) vcpu->arch.vpid = 0; vcpu->arch.flush_gpa = INVALID_GPA; - hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); + hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); vcpu->arch.swtimer.function = kvm_swtimer_wakeup; vcpu->arch.handle_exit = kvm_handle_exit; @@ -1235,6 +1548,9 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) change_csr_gcfg(CSR_GCFG_MATC_MASK, CSR_GCFG_MATC_ROOT); kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); + /* Restore hardware PMU CSRs */ + kvm_restore_pmu(vcpu); + /* Don't bother restoring registers multiple times unless necessary */ if (vcpu->arch.aux_inuse & KVM_LARCH_HWCSR_USABLE) return 0; diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c index 6b2e4f66ad26..4ba734aaef87 100644 --- a/arch/loongarch/kvm/vm.c +++ b/arch/loongarch/kvm/vm.c @@ -5,6 +5,7 @@ #include <linux/kvm_host.h> #include <asm/kvm_mmu.h> +#include <asm/kvm_vcpu.h> const struct _kvm_stats_desc kvm_vm_stats_desc[] = { KVM_GENERIC_VM_STATS(), @@ -39,6 +40,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) spin_lock_init(&kvm->arch.phyid_map_lock); kvm_init_vmcs(kvm); + + /* Enable all PV features by default */ + kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); + if (kvm_pvtime_supported()) + kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); + kvm->arch.gpa_size = BIT(cpu_vabits - 1); kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1; kvm->arch.invalid_ptes[0] = 0; @@ -99,7 +106,67 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) return r; } +static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + switch (attr->attr) { + case KVM_LOONGARCH_VM_FEAT_LSX: + if (cpu_has_lsx) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_LASX: + if (cpu_has_lasx) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_X86BT: + if (cpu_has_lbt_x86) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_ARMBT: + if (cpu_has_lbt_arm) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_MIPSBT: + if (cpu_has_lbt_mips) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_PMU: + if (cpu_has_pmp) + return 0; + return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_PV_IPI: + return 0; + case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: + if (kvm_pvtime_supported()) + return 0; + return -ENXIO; + default: + return -ENXIO; + } +} + +static int kvm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) +{ + switch (attr->group) { + case KVM_LOONGARCH_VM_FEAT_CTRL: + return kvm_vm_feature_has_attr(kvm, attr); + default: + return -ENXIO; + } +} + int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { - return -ENOIOCTLCMD; + void __user *argp = (void __user *)arg; + struct kvm *kvm = filp->private_data; + struct kvm_device_attr attr; + + switch (ioctl) { + case KVM_HAS_DEVICE_ATTR: + if (copy_from_user(&attr, argp, sizeof(attr))) + return -EFAULT; + + return kvm_vm_has_attr(kvm, &attr); + default: + return -ENOIOCTLCMD; + } } diff --git a/arch/loongarch/mm/Makefile b/arch/loongarch/mm/Makefile index e4d1e581dbae..278be2c8fc36 100644 --- a/arch/loongarch/mm/Makefile +++ b/arch/loongarch/mm/Makefile @@ -4,7 +4,8 @@ # obj-y += init.o cache.o tlb.o tlbex.o extable.o \ - fault.o ioremap.o maccess.o mmap.o pgtable.o page.o + fault.o ioremap.o maccess.o mmap.o pgtable.o \ + page.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_KASAN) += kasan_init.o diff --git a/arch/loongarch/mm/fault.c b/arch/loongarch/mm/fault.c index 97b40defde06..deefd9617d00 100644 --- a/arch/loongarch/mm/fault.c +++ b/arch/loongarch/mm/fault.c @@ -31,11 +31,52 @@ int show_unhandled_signals = 1; +static int __kprobes spurious_fault(unsigned long write, unsigned long address) +{ + pgd_t *pgd; + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + if (!(address & __UA_LIMIT)) + return 0; + + pgd = pgd_offset_k(address); + if (!pgd_present(pgdp_get(pgd))) + return 0; + + p4d = p4d_offset(pgd, address); + if (!p4d_present(p4dp_get(p4d))) + return 0; + + pud = pud_offset(p4d, address); + if (!pud_present(pudp_get(pud))) + return 0; + + pmd = pmd_offset(pud, address); + if (!pmd_present(pmdp_get(pmd))) + return 0; + + if (pmd_leaf(*pmd)) { + return write ? pmd_write(pmdp_get(pmd)) : 1; + } else { + pte = pte_offset_kernel(pmd, address); + if (!pte_present(ptep_get(pte))) + return 0; + + return write ? pte_write(ptep_get(pte)) : 1; + } +} + static void __kprobes no_context(struct pt_regs *regs, unsigned long write, unsigned long address) { const int field = sizeof(unsigned long) * 2; + if (spurious_fault(write, address)) + return; + /* Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) return; diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index 8a87a482c8f4..188b52bbb254 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -201,7 +201,9 @@ pte_t * __init populate_kernel_pte(unsigned long addr) pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE); if (!pte) panic("%s: Failed to allocate memory\n", __func__); + pmd_populate_kernel(&init_mm, pmd, pte); + kernel_pte_init(pte); } return pte_offset_kernel(pmd, addr); diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c index 427d6b1aec09..d2681272d8f0 100644 --- a/arch/loongarch/mm/kasan_init.c +++ b/arch/loongarch/mm/kasan_init.c @@ -13,6 +13,13 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); +#ifdef __PAGETABLE_P4D_FOLDED +#define __pgd_none(early, pgd) (0) +#else +#define __pgd_none(early, pgd) (early ? (pgd_val(pgd) == 0) : \ +(__pa(pgd_val(pgd)) == (unsigned long)__pa(kasan_early_shadow_p4d))) +#endif + #ifdef __PAGETABLE_PUD_FOLDED #define __p4d_none(early, p4d) (0) #else @@ -55,6 +62,9 @@ void *kasan_mem_to_shadow(const void *addr) case XKPRANGE_UC_SEG: offset = XKPRANGE_UC_SHADOW_OFFSET; break; + case XKPRANGE_WC_SEG: + offset = XKPRANGE_WC_SHADOW_OFFSET; + break; case XKVRANGE_VC_SEG: offset = XKVRANGE_VC_SHADOW_OFFSET; break; @@ -79,6 +89,8 @@ const void *kasan_shadow_to_mem(const void *shadow_addr) if (addr >= XKVRANGE_VC_SHADOW_OFFSET) return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START); + else if (addr >= XKPRANGE_WC_SHADOW_OFFSET) + return (void *)(((addr - XKPRANGE_WC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_WC_START); else if (addr >= XKPRANGE_UC_SHADOW_OFFSET) return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START); else if (addr >= XKPRANGE_CC_SHADOW_OFFSET) @@ -142,6 +154,19 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node, return pud_offset(p4dp, addr); } +static p4d_t *__init kasan_p4d_offset(pgd_t *pgdp, unsigned long addr, int node, bool early) +{ + if (__pgd_none(early, pgdp_get(pgdp))) { + phys_addr_t p4d_phys = early ? + __pa_symbol(kasan_early_shadow_p4d) : kasan_alloc_zeroed_page(node); + if (!early) + memcpy(__va(p4d_phys), kasan_early_shadow_p4d, sizeof(kasan_early_shadow_p4d)); + pgd_populate(&init_mm, pgdp, (p4d_t *)__va(p4d_phys)); + } + + return p4d_offset(pgdp, addr); +} + static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr, unsigned long end, int node, bool early) { @@ -178,19 +203,19 @@ static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr, do { next = pud_addr_end(addr, end); kasan_pmd_populate(pudp, addr, next, node, early); - } while (pudp++, addr = next, addr != end); + } while (pudp++, addr = next, addr != end && __pud_none(early, READ_ONCE(*pudp))); } static void __init kasan_p4d_populate(pgd_t *pgdp, unsigned long addr, unsigned long end, int node, bool early) { unsigned long next; - p4d_t *p4dp = p4d_offset(pgdp, addr); + p4d_t *p4dp = kasan_p4d_offset(pgdp, addr, node, early); do { next = p4d_addr_end(addr, end); kasan_pud_populate(p4dp, addr, next, node, early); - } while (p4dp++, addr = next, addr != end); + } while (p4dp++, addr = next, addr != end && __p4d_none(early, READ_ONCE(*p4dp))); } static void __init kasan_pgd_populate(unsigned long addr, unsigned long end, @@ -218,7 +243,7 @@ static void __init kasan_map_populate(unsigned long start, unsigned long end, asmlinkage void __init kasan_early_init(void) { BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); - BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END + 1, PGDIR_SIZE)); } static inline void kasan_set_pgd(pgd_t *pgdp, pgd_t pgdval) @@ -233,7 +258,7 @@ static void __init clear_pgds(unsigned long start, unsigned long end) * swapper_pg_dir. pgd_clear() can't be used * here because it's nop on 2,3-level pagetable setups */ - for (; start < end; start += PGDIR_SIZE) + for (; start < end; start = pgd_addr_end(start, end)) kasan_set_pgd((pgd_t *)pgd_offset_k(start), __pgd(0)); } @@ -243,6 +268,17 @@ void __init kasan_init(void) phys_addr_t pa_start, pa_end; /* + * If PGDIR_SIZE is too large for cpu_vabits, KASAN_SHADOW_END will + * overflow UINTPTR_MAX and then looks like a user space address. + * For example, PGDIR_SIZE of CONFIG_4KB_4LEVEL is 2^39, which is too + * large for Loongson-2K series whose cpu_vabits = 39. + */ + if (KASAN_SHADOW_END < vm_map_base) { + pr_warn("PGDIR_SIZE too large for cpu_vabits, KernelAddressSanitizer disabled.\n"); + return; + } + + /* * PGD was populated as invalid_pmd_table or invalid_pud_table * in pagetable_init() which depends on how many levels of page * table you are using, but we had to clean the gpd of kasan diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c index 889030985135..914e82ff3f65 100644 --- a/arch/loongarch/mm/mmap.c +++ b/arch/loongarch/mm/mmap.c @@ -89,7 +89,8 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, } unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, unsigned long flags, + vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, UP); @@ -101,7 +102,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0, */ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, DOWN); diff --git a/arch/loongarch/mm/pageattr.c b/arch/loongarch/mm/pageattr.c new file mode 100644 index 000000000000..ffd8d76021d4 --- /dev/null +++ b/arch/loongarch/mm/pageattr.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#include <linux/pagewalk.h> +#include <linux/pgtable.h> +#include <asm/set_memory.h> +#include <asm/tlbflush.h> + +struct pageattr_masks { + pgprot_t set_mask; + pgprot_t clear_mask; +}; + +static unsigned long set_pageattr_masks(unsigned long val, struct mm_walk *walk) +{ + unsigned long new_val = val; + struct pageattr_masks *masks = walk->private; + + new_val &= ~(pgprot_val(masks->clear_mask)); + new_val |= (pgprot_val(masks->set_mask)); + + return new_val; +} + +static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + pgd_t val = pgdp_get(pgd); + + if (pgd_leaf(val)) { + val = __pgd(set_pageattr_masks(pgd_val(val), walk)); + set_pgd(pgd, val); + } + + return 0; +} + +static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + p4d_t val = p4dp_get(p4d); + + if (p4d_leaf(val)) { + val = __p4d(set_pageattr_masks(p4d_val(val), walk)); + set_p4d(p4d, val); + } + + return 0; +} + +static int pageattr_pud_entry(pud_t *pud, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + pud_t val = pudp_get(pud); + + if (pud_leaf(val)) { + val = __pud(set_pageattr_masks(pud_val(val), walk)); + set_pud(pud, val); + } + + return 0; +} + +static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + pmd_t val = pmdp_get(pmd); + + if (pmd_leaf(val)) { + val = __pmd(set_pageattr_masks(pmd_val(val), walk)); + set_pmd(pmd, val); + } + + return 0; +} + +static int pageattr_pte_entry(pte_t *pte, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + pte_t val = ptep_get(pte); + + val = __pte(set_pageattr_masks(pte_val(val), walk)); + set_pte(pte, val); + + return 0; +} + +static int pageattr_pte_hole(unsigned long addr, unsigned long next, + int depth, struct mm_walk *walk) +{ + return 0; +} + +static const struct mm_walk_ops pageattr_ops = { + .pgd_entry = pageattr_pgd_entry, + .p4d_entry = pageattr_p4d_entry, + .pud_entry = pageattr_pud_entry, + .pmd_entry = pageattr_pmd_entry, + .pte_entry = pageattr_pte_entry, + .pte_hole = pageattr_pte_hole, + .walk_lock = PGWALK_RDLOCK, +}; + +static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask, pgprot_t clear_mask) +{ + int ret; + unsigned long start = addr; + unsigned long end = start + PAGE_SIZE * numpages; + struct pageattr_masks masks = { + .set_mask = set_mask, + .clear_mask = clear_mask + }; + + if (!numpages) + return 0; + + mmap_write_lock(&init_mm); + ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL, &masks); + mmap_write_unlock(&init_mm); + + flush_tlb_kernel_range(start, end); + + return ret; +} + +int set_memory_x(unsigned long addr, int numpages) +{ + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_NO_EXEC)); +} + +int set_memory_nx(unsigned long addr, int numpages) +{ + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, numpages, __pgprot(_PAGE_NO_EXEC), __pgprot(0)); +} + +int set_memory_ro(unsigned long addr, int numpages) +{ + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_WRITE | _PAGE_DIRTY)); +} + +int set_memory_rw(unsigned long addr, int numpages) +{ + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, numpages, __pgprot(_PAGE_WRITE | _PAGE_DIRTY), __pgprot(0)); +} + +bool kernel_page_present(struct page *page) +{ + pgd_t *pgd; + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + unsigned long addr = (unsigned long)page_address(page); + + if (addr < vm_map_base) + return true; + + pgd = pgd_offset_k(addr); + if (pgd_none(pgdp_get(pgd))) + return false; + if (pgd_leaf(pgdp_get(pgd))) + return true; + + p4d = p4d_offset(pgd, addr); + if (p4d_none(p4dp_get(p4d))) + return false; + if (p4d_leaf(p4dp_get(p4d))) + return true; + + pud = pud_offset(p4d, addr); + if (pud_none(pudp_get(pud))) + return false; + if (pud_leaf(pudp_get(pud))) + return true; + + pmd = pmd_offset(pud, addr); + if (pmd_none(pmdp_get(pmd))) + return false; + if (pmd_leaf(pmdp_get(pmd))) + return true; + + pte = pte_offset_kernel(pmd, addr); + return pte_present(ptep_get(pte)); +} + +int set_direct_map_default_noflush(struct page *page) +{ + unsigned long addr = (unsigned long)page_address(page); + + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, 1, PAGE_KERNEL, __pgprot(0)); +} + +int set_direct_map_invalid_noflush(struct page *page) +{ + unsigned long addr = (unsigned long)page_address(page); + + if (addr < vm_map_base) + return 0; + + return __set_memory(addr, 1, __pgprot(0), __pgprot(_PAGE_PRESENT | _PAGE_VALID)); +} diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c index eb6a29b491a7..3fa69b23ff84 100644 --- a/arch/loongarch/mm/pgtable.c +++ b/arch/loongarch/mm/pgtable.c @@ -116,6 +116,26 @@ void pud_init(void *addr) EXPORT_SYMBOL_GPL(pud_init); #endif +void kernel_pte_init(void *addr) +{ + unsigned long *p, *end; + + p = (unsigned long *)addr; + end = p + PTRS_PER_PTE; + + do { + p[0] = _PAGE_GLOBAL; + p[1] = _PAGE_GLOBAL; + p[2] = _PAGE_GLOBAL; + p[3] = _PAGE_GLOBAL; + p[4] = _PAGE_GLOBAL; + p += 8; + p[-3] = _PAGE_GLOBAL; + p[-2] = _PAGE_GLOBAL; + p[-1] = _PAGE_GLOBAL; + } while (p != end); +} + pmd_t mk_pmd(struct page *page, pgprot_t prot) { pmd_t pmd; diff --git a/arch/loongarch/pci/acpi.c b/arch/loongarch/pci/acpi.c index 365f7de771cb..1da4dc46df43 100644 --- a/arch/loongarch/pci/acpi.c +++ b/arch/loongarch/pci/acpi.c @@ -225,6 +225,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) if (bus) { memcpy(bus->sysdata, info->cfg, sizeof(struct pci_config_window)); kfree(info); + kfree(root_ops); } else { struct pci_bus *child; diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile index d724d46b07c8..40c1175823d6 100644 --- a/arch/loongarch/vdso/Makefile +++ b/arch/loongarch/vdso/Makefile @@ -4,7 +4,8 @@ # Include the generic Makefile to check the built vdso. include $(srctree)/lib/vdso/Makefile -obj-vdso-y := elf.o vgetcpu.o vgettimeofday.o sigreturn.o +obj-vdso-y := elf.o vgetcpu.o vgettimeofday.o vgetrandom.o \ + vgetrandom-chacha.o sigreturn.o # Common compiler flags between ABIs. ccflags-vdso := \ @@ -29,6 +30,10 @@ ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) endif +ifneq ($(c-getrandom-y),) + CFLAGS_vgetrandom.o += -include $(c-getrandom-y) +endif + # VDSO linker flags. ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \ $(filter -E%,$(KBUILD_CFLAGS)) -nostdlib -shared \ diff --git a/arch/loongarch/vdso/vdso.lds.S b/arch/loongarch/vdso/vdso.lds.S index 56ad855896de..160cfaef2de4 100644 --- a/arch/loongarch/vdso/vdso.lds.S +++ b/arch/loongarch/vdso/vdso.lds.S @@ -3,6 +3,8 @@ * Author: Huacai Chen <chenhuacai@loongson.cn> * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ +#include <asm/page.h> +#include <generated/asm-offsets.h> OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch") @@ -10,7 +12,11 @@ OUTPUT_ARCH(loongarch) SECTIONS { - PROVIDE(_start = .); + PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE); +#ifdef CONFIG_TIME_NS + PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); +#endif + PROVIDE(_loongarch_data = _vdso_data + 2 * PAGE_SIZE); . = SIZEOF_HEADERS; .hash : { *(.hash) } :text @@ -62,6 +68,7 @@ VERSION __vdso_clock_getres; __vdso_clock_gettime; __vdso_gettimeofday; + __vdso_getrandom; __vdso_rt_sigreturn; local: *; }; diff --git a/arch/loongarch/vdso/vgetcpu.c b/arch/loongarch/vdso/vgetcpu.c index 9e445be39763..0db51258b2a7 100644 --- a/arch/loongarch/vdso/vgetcpu.c +++ b/arch/loongarch/vdso/vgetcpu.c @@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void) static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void) { - return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE); + return _loongarch_data.pdata; } extern diff --git a/arch/loongarch/vdso/vgetrandom-chacha.S b/arch/loongarch/vdso/vgetrandom-chacha.S new file mode 100644 index 000000000000..c2733e6c3a8d --- /dev/null +++ b/arch/loongarch/vdso/vgetrandom-chacha.S @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Xi Ruoyao <xry111@xry111.site>. All Rights Reserved. + */ + +#include <asm/asm.h> +#include <asm/regdef.h> +#include <linux/linkage.h> + +.text + +.macro OP_4REG op d0 d1 d2 d3 s0 s1 s2 s3 + \op \d0, \d0, \s0 + \op \d1, \d1, \s1 + \op \d2, \d2, \s2 + \op \d3, \d3, \s3 +.endm + +/* + * Very basic LoongArch implementation of ChaCha20. Produces a given positive + * number of blocks of output with a nonce of 0, taking an input key and + * 8-byte counter. Importantly does not spill to the stack. Its arguments + * are: + * + * a0: output bytes + * a1: 32-byte key input + * a2: 8-byte counter input/output + * a3: number of 64-byte blocks to write to output + */ +SYM_FUNC_START(__arch_chacha20_blocks_nostack) + +/* We don't need a frame pointer */ +#define s9 fp + +#define output a0 +#define key a1 +#define counter a2 +#define nblocks a3 +#define i a4 +#define state0 s0 +#define state1 s1 +#define state2 s2 +#define state3 s3 +#define state4 s4 +#define state5 s5 +#define state6 s6 +#define state7 s7 +#define state8 s8 +#define state9 s9 +#define state10 a5 +#define state11 a6 +#define state12 a7 +#define state13 t0 +#define state14 t1 +#define state15 t2 +#define cnt_lo t3 +#define cnt_hi t4 +#define copy0 t5 +#define copy1 t6 +#define copy2 t7 + +/* Reuse i as copy3 */ +#define copy3 i + +/* Packs to be used with OP_4REG */ +#define line0 state0, state1, state2, state3 +#define line1 state4, state5, state6, state7 +#define line2 state8, state9, state10, state11 +#define line3 state12, state13, state14, state15 + +#define line1_perm state5, state6, state7, state4 +#define line2_perm state10, state11, state8, state9 +#define line3_perm state15, state12, state13, state14 + +#define copy copy0, copy1, copy2, copy3 + +#define _16 16, 16, 16, 16 +#define _20 20, 20, 20, 20 +#define _24 24, 24, 24, 24 +#define _25 25, 25, 25, 25 + + /* + * The ABI requires s0-s9 saved, and sp aligned to 16-byte. + * This does not violate the stack-less requirement: no sensitive data + * is spilled onto the stack. + */ + PTR_ADDI sp, sp, (-SZREG * 10) & STACK_ALIGN + REG_S s0, sp, 0 + REG_S s1, sp, SZREG + REG_S s2, sp, SZREG * 2 + REG_S s3, sp, SZREG * 3 + REG_S s4, sp, SZREG * 4 + REG_S s5, sp, SZREG * 5 + REG_S s6, sp, SZREG * 6 + REG_S s7, sp, SZREG * 7 + REG_S s8, sp, SZREG * 8 + REG_S s9, sp, SZREG * 9 + + li.w copy0, 0x61707865 + li.w copy1, 0x3320646e + li.w copy2, 0x79622d32 + + ld.w cnt_lo, counter, 0 + ld.w cnt_hi, counter, 4 + +.Lblock: + /* state[0,1,2,3] = "expand 32-byte k" */ + move state0, copy0 + move state1, copy1 + move state2, copy2 + li.w state3, 0x6b206574 + + /* state[4,5,..,11] = key */ + ld.w state4, key, 0 + ld.w state5, key, 4 + ld.w state6, key, 8 + ld.w state7, key, 12 + ld.w state8, key, 16 + ld.w state9, key, 20 + ld.w state10, key, 24 + ld.w state11, key, 28 + + /* state[12,13] = counter */ + move state12, cnt_lo + move state13, cnt_hi + + /* state[14,15] = 0 */ + move state14, zero + move state15, zero + + li.w i, 10 +.Lpermute: + /* odd round */ + OP_4REG add.w line0, line1 + OP_4REG xor line3, line0 + OP_4REG rotri.w line3, _16 + + OP_4REG add.w line2, line3 + OP_4REG xor line1, line2 + OP_4REG rotri.w line1, _20 + + OP_4REG add.w line0, line1 + OP_4REG xor line3, line0 + OP_4REG rotri.w line3, _24 + + OP_4REG add.w line2, line3 + OP_4REG xor line1, line2 + OP_4REG rotri.w line1, _25 + + /* even round */ + OP_4REG add.w line0, line1_perm + OP_4REG xor line3_perm, line0 + OP_4REG rotri.w line3_perm, _16 + + OP_4REG add.w line2_perm, line3_perm + OP_4REG xor line1_perm, line2_perm + OP_4REG rotri.w line1_perm, _20 + + OP_4REG add.w line0, line1_perm + OP_4REG xor line3_perm, line0 + OP_4REG rotri.w line3_perm, _24 + + OP_4REG add.w line2_perm, line3_perm + OP_4REG xor line1_perm, line2_perm + OP_4REG rotri.w line1_perm, _25 + + addi.w i, i, -1 + bnez i, .Lpermute + + /* + * copy[3] = "expa", materialize it here because copy[3] shares the + * same register with i which just became dead. + */ + li.w copy3, 0x6b206574 + + /* output[0,1,2,3] = copy[0,1,2,3] + state[0,1,2,3] */ + OP_4REG add.w line0, copy + st.w state0, output, 0 + st.w state1, output, 4 + st.w state2, output, 8 + st.w state3, output, 12 + + /* from now on state[0,1,2,3] are scratch registers */ + + /* state[0,1,2,3] = lo32(key) */ + ld.w state0, key, 0 + ld.w state1, key, 4 + ld.w state2, key, 8 + ld.w state3, key, 12 + + /* output[4,5,6,7] = state[0,1,2,3] + state[4,5,6,7] */ + OP_4REG add.w line1, line0 + st.w state4, output, 16 + st.w state5, output, 20 + st.w state6, output, 24 + st.w state7, output, 28 + + /* state[0,1,2,3] = hi32(key) */ + ld.w state0, key, 16 + ld.w state1, key, 20 + ld.w state2, key, 24 + ld.w state3, key, 28 + + /* output[8,9,10,11] = state[0,1,2,3] + state[8,9,10,11] */ + OP_4REG add.w line2, line0 + st.w state8, output, 32 + st.w state9, output, 36 + st.w state10, output, 40 + st.w state11, output, 44 + + /* output[12,13,14,15] = state[12,13,14,15] + [cnt_lo, cnt_hi, 0, 0] */ + add.w state12, state12, cnt_lo + add.w state13, state13, cnt_hi + st.w state12, output, 48 + st.w state13, output, 52 + st.w state14, output, 56 + st.w state15, output, 60 + + /* ++counter */ + addi.w cnt_lo, cnt_lo, 1 + sltui state0, cnt_lo, 1 + add.w cnt_hi, cnt_hi, state0 + + /* output += 64 */ + PTR_ADDI output, output, 64 + /* --nblocks */ + PTR_ADDI nblocks, nblocks, -1 + bnez nblocks, .Lblock + + /* counter = [cnt_lo, cnt_hi] */ + st.w cnt_lo, counter, 0 + st.w cnt_hi, counter, 4 + + /* + * Zero out the potentially sensitive regs, in case nothing uses these + * again. As at now copy[0,1,2,3] just contains "expand 32-byte k" and + * state[0,...,9] are s0-s9 those we'll restore in the epilogue, so we + * only need to zero state[11,...,15]. + */ + move state10, zero + move state11, zero + move state12, zero + move state13, zero + move state14, zero + move state15, zero + + REG_L s0, sp, 0 + REG_L s1, sp, SZREG + REG_L s2, sp, SZREG * 2 + REG_L s3, sp, SZREG * 3 + REG_L s4, sp, SZREG * 4 + REG_L s5, sp, SZREG * 5 + REG_L s6, sp, SZREG * 6 + REG_L s7, sp, SZREG * 7 + REG_L s8, sp, SZREG * 8 + REG_L s9, sp, SZREG * 9 + PTR_ADDI sp, sp, -((-SZREG * 10) & STACK_ALIGN) + + jr ra +SYM_FUNC_END(__arch_chacha20_blocks_nostack) diff --git a/arch/loongarch/vdso/vgetrandom.c b/arch/loongarch/vdso/vgetrandom.c new file mode 100644 index 000000000000..d5f258ac4a36 --- /dev/null +++ b/arch/loongarch/vdso/vgetrandom.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Xi Ruoyao <xry111@xry111.site>. All Rights Reserved. + */ +#include <linux/types.h> + +ssize_t __vdso_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len) +{ + return __cvdso_getrandom(buffer, len, flags, opaque_state, opaque_len); +} diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index cc26df907bfe..7c4f7bcc89d7 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -84,24 +84,23 @@ config MMU support by paged memory management. If unsure, say 'Y'. config MMU_MOTOROLA - bool + def_bool MMU && M68KCLASSIC select HAVE_PAGE_SIZE_4KB config MMU_COLDFIRE + def_bool MMU && COLDFIRE select HAVE_PAGE_SIZE_8KB - bool config MMU_SUN3 - bool + def_bool MMU && SUN3 select HAVE_PAGE_SIZE_8KB - depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE config ARCH_SUPPORTS_KEXEC - def_bool M68KCLASSIC && MMU + def_bool (M68KCLASSIC || SUN3) && MMU config BOOTINFO_PROC bool "Export bootinfo in procfs" - depends on KEXEC && M68KCLASSIC + depends on KEXEC && (M68KCLASSIC || SUN3) help Say Y to export the bootinfo used to boot the kernel in a "bootinfo" file in procfs. This is useful with kexec. diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index c777a129768a..c9a7e602d8a4 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -2,7 +2,7 @@ comment "Processor Type" choice - prompt "CPU family support" + prompt "CPU/machine family support" default M68KCLASSIC if MMU default COLDFIRE if !MMU help @@ -19,8 +19,9 @@ choice processor, select COLDFIRE. config M68KCLASSIC - bool "Classic M68K CPU family support" + bool "Classic M68K CPU/machine family support" select HAVE_ARCH_PFN_VALID + select M68020 if MMU && !(M68030 || M68040 || M68060) config COLDFIRE bool "Coldfire CPU family support" @@ -32,13 +33,23 @@ config COLDFIRE select HAVE_LEGACY_CLK select HAVE_PAGE_SIZE_8KB if !MMU -endchoice +config SUN3 + bool "Sun3 machine support" + depends on MMU + select HAVE_ARCH_PFN_VALID + select LEGACY_TIMER_TICK + select NO_DMA + select M68020 + help + This option enables support for the Sun 3 series of workstations + (3/50, 3/60, 3/1xx, 3/2xx systems). These use a classic 68020 CPU + but the custom memory management unit makes them incompatible with + all other classic m68k machines, including Sun 3x. -if M68KCLASSIC +endchoice config M68000 - def_bool y - depends on !MMU + def_bool M68KCLASSIC && !MMU select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_CAS select CPU_HAS_NO_MULDIV64 @@ -56,7 +67,7 @@ config M68000 a paging MMU. config M68020 - bool "68020 support" + bool "68020 support" if M68KCLASSIC depends on MMU select FPU select CPU_HAS_ADDRESS_SPACES @@ -66,9 +77,10 @@ config M68020 68851 MMU (Memory Management Unit) to run Linux/m68k, except on the Sun 3, which provides its own version. +if M68KCLASSIC && MMU + config M68030 bool "68030 support" - depends on MMU && !MMU_SUN3 select FPU select CPU_HAS_ADDRESS_SPACES help @@ -78,7 +90,6 @@ config M68030 config M68040 bool "68040 support" - depends on MMU && !MMU_SUN3 select FPU select CPU_HAS_ADDRESS_SPACES help @@ -89,13 +100,14 @@ config M68040 config M68060 bool "68060 support" - depends on MMU && !MMU_SUN3 select FPU select CPU_HAS_ADDRESS_SPACES help If you anticipate running this kernel on a computer with a MC68060 processor, say Y. Otherwise, say N. +endif # M68KCLASSIC + config M68328 bool depends on !MMU @@ -117,8 +129,6 @@ config M68VZ328 help Motorola 68VZ328 processor support. -endif # M68KCLASSIC - if COLDFIRE choice @@ -325,7 +335,7 @@ comment "Processor Specific Options" config M68KFPU_EMU bool "Math emulation support" - depends on M68KCLASSIC && FPU + depends on (M68KCLASSIC || SUN3) && FPU help At some point in the future, this will cause floating-point math instructions to be emulated by the kernel on machines that lack a diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine index d06b1c5d9b0c..de39f23b180e 100644 --- a/arch/m68k/Kconfig.machine +++ b/arch/m68k/Kconfig.machine @@ -6,7 +6,6 @@ if M68KCLASSIC config AMIGA bool "Amiga support" depends on MMU - select MMU_MOTOROLA if MMU select LEGACY_TIMER_TICK help This option enables support for the Amiga series of computers. If @@ -16,7 +15,6 @@ config AMIGA config ATARI bool "Atari support" depends on MMU - select MMU_MOTOROLA if MMU select HAVE_ARCH_NVRAM_OPS select LEGACY_TIMER_TICK help @@ -31,7 +29,6 @@ config ATARI_KBD_CORE config MAC bool "Macintosh support" depends on MMU - select MMU_MOTOROLA if MMU select HAVE_ARCH_NVRAM_OPS select HAVE_PATA_PLATFORM select LEGACY_TIMER_TICK @@ -44,7 +41,6 @@ config MAC config APOLLO bool "Apollo support" depends on MMU - select MMU_MOTOROLA if MMU select LEGACY_TIMER_TICK help Say Y here if you want to run Linux on an MC680x0-based Apollo @@ -53,7 +49,6 @@ config APOLLO config VME bool "VME (Motorola and BVM) support" depends on MMU - select MMU_MOTOROLA if MMU help Say Y here if you want to build a kernel for a 680x0 based VME board. Boards currently supported include Motorola boards MVME147, @@ -97,7 +92,6 @@ config BVME6000 config HP300 bool "HP9000/300 and HP9000/400 support" depends on MMU - select MMU_MOTOROLA if MMU select LEGACY_TIMER_TICK help This option enables support for the HP9000/300 and HP9000/400 series @@ -110,7 +104,6 @@ config SUN3X bool "Sun3x support" depends on MMU select LEGACY_TIMER_TICK - select MMU_MOTOROLA if MMU select M68030 help This option enables support for the Sun 3x series of workstations. @@ -124,7 +117,6 @@ config SUN3X config Q40 bool "Q40/Q60 support" depends on MMU - select MMU_MOTOROLA if MMU select LEGACY_TIMER_TICK help The Q40 is a Motorola 68040-based successor to the Sinclair QL @@ -133,22 +125,6 @@ config Q40 Q60. Select your CPU below. For 68LC060 don't forget to enable FPU emulation. -config SUN3 - bool "Sun3 support" - depends on MMU - depends on !MMU_MOTOROLA - select MMU_SUN3 if MMU - select LEGACY_TIMER_TICK - select NO_DMA - select M68020 - help - This option enables support for the Sun 3 series of workstations - (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires - that all other hardware types must be disabled, as Sun 3 kernels - are incompatible with all other m68k targets (including Sun 3x!). - - If you don't want to compile a kernel exclusively for a Sun 3, say N. - config VIRT bool "Virtual M68k Machine support" depends on MMU @@ -157,7 +133,6 @@ config VIRT select GOLDFISH_TIMER select GOLDFISH_TTY select M68040 - select MMU_MOTOROLA if MMU select RTC_CLASS select RTC_DRV_GOLDFISH select TTY diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 9a084943a68a..a70aec9a05c4 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -559,7 +559,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -621,6 +620,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -636,7 +636,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 58ec725bf392..312853f3d26a 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -516,7 +516,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -578,6 +577,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -593,7 +593,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 63ab7e892e59..0853e4358de9 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -536,7 +536,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -598,6 +597,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -613,7 +613,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index ca40744eec60..f738202d1f36 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -508,7 +508,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -570,6 +569,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -585,7 +585,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 77bcc6faf468..74f74e03ccc9 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -518,7 +518,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -580,6 +579,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -595,7 +595,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index e73d4032b659..14c8f1b374aa 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -535,7 +535,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -597,6 +596,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -612,7 +612,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 638df8442c98..41c8112c6d0d 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -621,7 +621,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -683,6 +682,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -698,7 +698,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 2248db426081..e72d37ee90a7 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -507,7 +507,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -569,6 +568,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -584,7 +584,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 2975b66521f6..733f1fc9a50a 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -508,7 +508,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -570,6 +569,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -585,7 +585,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 0a0e32344033..3efe25435561 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -525,7 +525,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -587,6 +586,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -602,7 +602,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index f16f1a99c2ba..1b8ea0e7acb4 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -506,7 +506,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -567,6 +566,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -582,7 +582,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 667bd61ae9b3..5bda93f6a200 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -506,7 +506,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m @@ -568,6 +567,7 @@ CONFIG_KUNIT_ALL_TESTS=m CONFIG_TEST_DHRY=m CONFIG_TEST_MIN_HEAP=m CONFIG_TEST_DIV64=m +CONFIG_TEST_MULDIV64=m CONFIG_REED_SOLOMON_TEST=m CONFIG_ATOMIC64_SELFTEST=m CONFIG_ASYNC_RAID6_TEST=m @@ -583,7 +583,6 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_IDA=m CONFIG_TEST_BITOPS=m CONFIG_TEST_VMALLOC=m -CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_FIND_BIT_BENCHMARK=m diff --git a/arch/m68k/include/asm/cmpxchg.h b/arch/m68k/include/asm/cmpxchg.h index 4ba14f3535fc..71fbe5c5c564 100644 --- a/arch/m68k/include/asm/cmpxchg.h +++ b/arch/m68k/include/asm/cmpxchg.h @@ -3,6 +3,7 @@ #define __ARCH_M68K_CMPXCHG__ #include <linux/irqflags.h> +#include <linux/minmax.h> #define __xg(type, x) ((volatile type *)(x)) @@ -11,25 +12,19 @@ extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int); #ifndef CONFIG_RMW_INSNS static inline unsigned long __arch_xchg(unsigned long x, volatile void * ptr, int size) { - unsigned long flags, tmp; + unsigned long flags; local_irq_save(flags); switch (size) { case 1: - tmp = *(u8 *)ptr; - *(u8 *)ptr = x; - x = tmp; + swap(*(u8 *)ptr, x); break; case 2: - tmp = *(u16 *)ptr; - *(u16 *)ptr = x; - x = tmp; + swap(*(u16 *)ptr, x); break; case 4: - tmp = *(u32 *)ptr; - *(u32 *)ptr = x; - x = tmp; + swap(*(u32 *)ptr, x); break; default: x = __invalid_xchg_size(x, ptr, size); diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 14992fde7340..2263e92d418a 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -28,10 +28,8 @@ #define NR_IRQS 32 #elif defined(CONFIG_APOLLO) #define NR_IRQS 24 -#elif defined(CONFIG_HP300) +#else /* CONFIG_HP300 etc. */ #define NR_IRQS 8 -#else -#define NR_IRQS 0 #endif #if defined(CONFIG_M68020) || defined(CONFIG_M68030) || \ diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h index e28eb1c0e0bf..dbf88059e47a 100644 --- a/arch/m68k/include/asm/mvme147hw.h +++ b/arch/m68k/include/asm/mvme147hw.h @@ -93,8 +93,8 @@ struct pcc_regs { #define M147_SCC_B_ADDR 0xfffe3000 #define M147_SCC_PCLK 5000000 -#define MVME147_IRQ_SCSI_PORT (IRQ_USER+0x45) -#define MVME147_IRQ_SCSI_DMA (IRQ_USER+0x46) +#define MVME147_IRQ_SCSI_PORT (IRQ_USER + 5) +#define MVME147_IRQ_SCSI_DMA (IRQ_USER + 6) /* SCC interrupts, for MVME147 */ diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h index 8cfb84b49975..b173ba27d36f 100644 --- a/arch/m68k/include/asm/page.h +++ b/arch/m68k/include/asm/page.h @@ -6,10 +6,8 @@ #include <asm/setup.h> #include <asm/page_offset.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> + #define PAGE_OFFSET (PAGE_OFFSET_RAW) #ifndef __ASSEMBLY__ diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index f335bf3268a1..6c732ed3998b 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -5,16 +5,8 @@ extra-y += vmlinux.lds -obj-$(CONFIG_AMIGA) := head.o -obj-$(CONFIG_ATARI) := head.o -obj-$(CONFIG_MAC) := head.o -obj-$(CONFIG_APOLLO) := head.o -obj-$(CONFIG_VME) := head.o -obj-$(CONFIG_HP300) := head.o -obj-$(CONFIG_Q40) := head.o -obj-$(CONFIG_SUN3X) := head.o -obj-$(CONFIG_VIRT) := head.o -obj-$(CONFIG_SUN3) := sun3-head.o +obj-$(CONFIG_MMU_MOTOROLA) := head.o +obj-$(CONFIG_SUN3) := sun3-head.o obj-y += entry.o irq.o module.o process.o ptrace.o obj-y += setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c index 3cc944df04f6..f11ef9f1f56f 100644 --- a/arch/m68k/kernel/early_printk.c +++ b/arch/m68k/kernel/early_printk.c @@ -13,6 +13,7 @@ #include <asm/setup.h> +#include "../mvme147/mvme147.h" #include "../mvme16x/mvme16x.h" asmlinkage void __init debug_cons_nputs(const char *s, unsigned n); @@ -22,7 +23,9 @@ static void __ref debug_cons_write(struct console *c, { #if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \ defined(CONFIG_COLDFIRE)) - if (MACH_IS_MVME16x) + if (MACH_IS_MVME147) + mvme147_scc_write(c, s, n); + else if (MACH_IS_MVME16x) mvme16x_cons_write(c, s, n); else debug_cons_nputs(s, n); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 2584e94e2134..fda7eac23f87 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -117,7 +117,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) { /* regs will be equal to current_pt_regs() */ struct kernel_clone_args args = { - .flags = regs->d1 & ~CSIGNAL, + .flags = (u32)(regs->d1) & ~CSIGNAL, .pidfd = (int __user *)regs->d3, .child_tid = (int __user *)regs->d4, .parent_tid = (int __user *)regs->d3, diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index 10310b04f77d..15c1a595a1de 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -249,7 +249,11 @@ void __init setup_arch(char **cmdline_p) process_uboot_commandline(&m68k_command_line[0], CL_SIZE); *cmdline_p = m68k_command_line; memcpy(boot_command_line, *cmdline_p, CL_SIZE); - + /* + * Initialise the static keys early as they may be enabled by the + * cpufeature code and early parameters. + */ + jump_label_init(); parse_early_param(); switch (m68k_machtype) { diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 37fb663559b4..c926da9d5ec2 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -138,7 +138,7 @@ void __init setup_arch(char **cmdline_p) pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); - pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", + pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n", __bss_stop, memory_start, memory_start, memory_end); memblock_add(_rambase, memory_end - _rambase); diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 22a3cbd4c602..f5ed71f1910d 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -462,3 +462,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index a97600b2af50..acd4c2da562b 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -62,7 +62,7 @@ void timer_heartbeat(void) } #endif /* CONFIG_HEARTBEAT */ -#ifdef CONFIG_M68KCLASSIC +#if defined(CONFIG_M68KCLASSIC) || defined(CONFIG_SUN3) /* machine dependent timer functions */ int (*mach_hwclk) (int, struct rtc_time*); EXPORT_SYMBOL(mach_hwclk); @@ -149,7 +149,7 @@ static int __init rtc_init(void) module_init(rtc_init); #endif /* CONFIG_RTC_DRV_GENERIC */ -#endif /* CONFIG M68KCLASSIC */ +#endif /* CONFIG_M68KCLASSIC || SUN3 */ void __init time_init(void) { diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 53d0cf343d90..d2f25e8895e5 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -383,7 +383,7 @@ static inline void bus_error030 (struct frame *fp) fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); if (ssw & DF) pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", + str_read_write(ssw & RW), fp->un.fmtb.daddr, space_names[ssw & DFC], fp->ptregs.pc); @@ -419,7 +419,7 @@ static inline void bus_error030 (struct frame *fp) } pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", + str_read_write(ssw & RW), fp->un.fmtb.daddr, space_names[ssw & DFC], fp->ptregs.pc); } @@ -455,7 +455,7 @@ static inline void bus_error030 (struct frame *fp) pr_debug("*** unexpected busfault type=%#04x\n", buserr_type); pr_debug("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, + str_read_write(ssw & RW), addr, fp->ptregs.pc); die_if_kernel ("Oops", &fp->ptregs, buserr_type); force_sig (SIGBUS); @@ -514,7 +514,7 @@ static inline void bus_error030 (struct frame *fp) fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); if (ssw & DF) pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", + str_read_write(ssw & RW), fp->un.fmtb.daddr, space_names[ssw & DFC], fp->ptregs.pc); @@ -548,7 +548,7 @@ static inline void bus_error030 (struct frame *fp) /* We might have an exception table for this PC */ if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) { pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", + str_read_write(ssw & RW), fp->un.fmtb.daddr, space_names[ssw & DFC], fp->ptregs.pc); goto buserr; @@ -564,7 +564,7 @@ static inline void bus_error030 (struct frame *fp) mmusr); } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { pr_err("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, + str_read_write(ssw & RW), addr, fp->ptregs.pc); die_if_kernel("Oops",&fp->ptregs,mmusr); force_sig(SIGSEGV); @@ -575,7 +575,7 @@ static inline void bus_error030 (struct frame *fp) #endif pr_err("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", - !(ssw & RW) ? "write" : "read", addr, + str_read_write(ssw & RW), addr, fp->ptregs.pc, ssw); asm volatile ("ptestr #1,%1@,#0\n\t" "pmove %%psr,%0" @@ -991,7 +991,7 @@ static void bad_super_trap(struct frame *fp) fp->ptregs.pc + 4 : fp->un.fmtb.baddr); if (ssw & DF) pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", + str_read_write(ssw & RW), fp->un.fmtb.daddr, space_names[ssw & DFC], fp->ptregs.pc); } diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 8b5dc07f0811..824c42a302c6 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -32,9 +32,10 @@ #include <asm/mvme147hw.h> #include <asm/config.h> +#include "mvme147.h" static void mvme147_get_model(char *model); -extern void mvme147_sched_init(void); +static void __init mvme147_sched_init(void); extern int mvme147_hwclk (int, struct rtc_time *); extern void mvme147_reset (void); @@ -123,7 +124,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id) } -void mvme147_sched_init (void) +static void __init mvme147_sched_init(void) { if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER, "timer 1", NULL)) @@ -185,3 +186,32 @@ int mvme147_hwclk(int op, struct rtc_time *t) } return 0; } + +static void scc_delay(void) +{ + __asm__ __volatile__ ("nop; nop;"); +} + +static void scc_write(char ch) +{ + do { + scc_delay(); + } while (!(in_8(M147_SCC_A_ADDR) & BIT(2))); + scc_delay(); + out_8(M147_SCC_A_ADDR, 8); + scc_delay(); + out_8(M147_SCC_A_ADDR, ch); +} + +void mvme147_scc_write(struct console *co, const char *str, unsigned int count) +{ + unsigned long flags; + + local_irq_save(flags); + while (count--) { + if (*str == '\n') + scc_write('\r'); + scc_write(*str++); + } + local_irq_restore(flags); +} diff --git a/arch/m68k/mvme147/mvme147.h b/arch/m68k/mvme147/mvme147.h new file mode 100644 index 000000000000..140bc98b0102 --- /dev/null +++ b/arch/m68k/mvme147/mvme147.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +struct console; + +/* config.c */ +void mvme147_scc_write(struct console *co, const char *str, unsigned int count); diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 10f1f294e91f..14b774b9d308 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -106,7 +106,7 @@ void __init q40_init_IRQ(void) * this stuff doesn't really belong here.. */ -int ql_ticks; /* 200Hz ticks since last jiffie */ +int ql_ticks; /* 200Hz ticks since last jiffy */ static int sound_ticks; #define SVOL 45 diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h index 79a749f4ad04..edff4306fa70 100644 --- a/arch/microblaze/include/asm/flat.h +++ b/arch/microblaze/include/asm/flat.h @@ -8,7 +8,7 @@ #ifndef _ASM_MICROBLAZE_FLAT_H #define _ASM_MICROBLAZE_FLAT_H -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* * Microblaze works a little differently from other arches, because diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 8810f4f1c3b0..d1ec3806edab 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -19,10 +19,7 @@ #ifdef __KERNEL__ -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_KERNEL_BASE_ADDR)) diff --git a/arch/microblaze/include/uapi/asm/setup.h b/arch/microblaze/include/uapi/asm/setup.h index 6831794e6f2c..16c56807f86a 100644 --- a/arch/microblaze/include/uapi/asm/setup.h +++ b/arch/microblaze/include/uapi/asm/setup.h @@ -14,7 +14,4 @@ #define COMMAND_LINE_SIZE 256 -# ifndef __ASSEMBLY__ - -# endif /* __ASSEMBLY__ */ #endif /* _UAPI_ASM_MICROBLAZE_SETUP_H */ diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 9581d194d9e4..37cb2898216b 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c @@ -66,10 +66,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) " MSR:\t\t%s\n" " PCMP:\t\t%s\n" " DIV:\t\t%s\n", - (cpuinfo.use_instr & PVR0_USE_BARREL_MASK) ? "yes" : "no", - (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) ? "yes" : "no", - (cpuinfo.use_instr & PVR2_USE_PCMP_INSTR) ? "yes" : "no", - (cpuinfo.use_instr & PVR0_USE_DIV_MASK) ? "yes" : "no"); + str_yes_no(cpuinfo.use_instr & PVR0_USE_BARREL_MASK), + str_yes_no(cpuinfo.use_instr & PVR2_USE_MSR_INSTR), + str_yes_no(cpuinfo.use_instr & PVR2_USE_PCMP_INSTR), + str_yes_no(cpuinfo.use_instr & PVR0_USE_DIV_MASK)); seq_printf(m, " MMU:\t\t%x\n", cpuinfo.mmu); @@ -120,7 +120,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "HW-Debug:\t%s\n", - cpuinfo.hw_debug ? "yes" : "no"); + str_yes_no(cpuinfo.hw_debug)); seq_printf(m, "PVR-USR1:\t%02x\n" diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index c892e173ec99..a8553f54152b 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -16,6 +16,7 @@ #include <asm/page.h> #include <linux/ftrace.h> #include <linux/uaccess.h> +#include <asm/xilinx_mb_manager.h> #ifdef CONFIG_FUNCTION_TRACER extern void _mcount(void); @@ -46,3 +47,12 @@ extern void __udivsi3(void); EXPORT_SYMBOL(__udivsi3); extern void __umodsi3(void); EXPORT_SYMBOL(__umodsi3); + +#ifdef CONFIG_MB_MANAGER +extern void xmb_manager_register(uintptr_t phys_baseaddr, u32 cr_val, + void (*callback)(void *data), + void *priv, void (*reset_callback)(void *data)); +EXPORT_SYMBOL(xmb_manager_register); +extern asmlinkage void xmb_inject_err(void); +EXPORT_SYMBOL(xmb_inject_err); +#endif diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index e424c796e297..76ac4cfdfb42 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -18,7 +18,7 @@ void __init early_init_devtree(void *params) { pr_debug(" -> early_init_devtree(%p)\n", params); - early_init_dt_scan(params); + early_init_dt_scan(params, __pa(params)); if (!strlen(boot_command_line)) strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index 2b81a6bd78b2..680f568b77f2 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -468,3 +468,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 3827dc76edd8..4520c5741579 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -193,11 +193,6 @@ asmlinkage void __init mmu_init(void) { unsigned int kstart, ksize; - if (!memblock.reserved.cnt) { - pr_emerg("Error memory count\n"); - machine_restart(NULL); - } - if ((u32) memblock.memory.regions[0].size < 0x400000) { pr_emerg("Memory must be greater than 4MB\n"); machine_restart(NULL); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 60077e576935..467b10f4361a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -8,6 +8,7 @@ config MIPS select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CURRENT_STACK_POINTER if !CC_IS_CLANG || CLANG_VERSION >= 140000 select ARCH_HAS_DEBUG_VIRTUAL if !64BIT + select ARCH_HAS_DMA_OPS if MACH_JAZZ select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_KCOV select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if !EVA @@ -393,7 +394,6 @@ config MACH_JAZZ select ARC_PROMLIB select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO - select DMA_OPS select FW_ARC select FW_ARC32 select ARCH_MAY_HAVE_PC_FDC @@ -502,7 +502,6 @@ config MACH_LOONGSON64 select USE_OF select BUILTIN_DTB select PCI_HOST_GENERIC - select HAVE_ARCH_NODEDATA_EXTENSION if NUMA help This enables the support of Loongson-2/3 family of machines. @@ -735,7 +734,6 @@ config SGI_IP27 select WAR_R10000_LLSC select MIPS_L1_CACHE_SHIFT_7 select NUMA - select HAVE_ARCH_NODEDATA_EXTENSION help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -2613,9 +2611,6 @@ config NUMA config SYS_SUPPORTS_NUMA bool -config HAVE_ARCH_NODEDATA_EXTENSION - bool - config RELOCATABLE bool "Relocatable kernel" depends on SYS_SUPPORTS_RELOCATABLE @@ -2881,6 +2876,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_CRASH_DUMP def_bool y +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config PHYSICAL_START hex "Physical address where the kernel is loaded" default "0xffffffff84000000" diff --git a/arch/mips/alchemy/common/dma.c b/arch/mips/alchemy/common/dma.c index 973049b5bd61..44d8433b1f45 100644 --- a/arch/mips/alchemy/common/dma.c +++ b/arch/mips/alchemy/common/dma.c @@ -131,29 +131,6 @@ static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = { { AU1100_SD1_PHYS_ADDR + 0x04, DMA_DS | DMA_DW8 | DMA_DR } /* coherent */ }; -void dump_au1000_dma_channel(unsigned int dmanr) -{ - struct dma_chan *chan; - - if (dmanr >= NUM_AU1000_DMA_CHANNELS) - return; - chan = &au1000_dma_table[dmanr]; - - printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); - printk(KERN_INFO " mode = 0x%08x\n", - __raw_readl(chan->io + DMA_MODE_SET)); - printk(KERN_INFO " addr = 0x%08x\n", - __raw_readl(chan->io + DMA_PERIPHERAL_ADDR)); - printk(KERN_INFO " start0 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER0_START)); - printk(KERN_INFO " start1 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER1_START)); - printk(KERN_INFO " count0 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER0_COUNT)); - printk(KERN_INFO " count1 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER1_COUNT)); -} - /* * Finds a free channel, and binds the requested device to it. * Returns the allocated channel number, or negative on error. diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 99f321b6e417..9cc8fbf218a5 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -42,7 +42,7 @@ static struct board_info __initdata board_cvg834g = { .expected_cpu_id = 0x3368, .ephy_reset_gpio = 36, - .ephy_reset_gpio_flags = GPIOF_INIT_HIGH, + .ephy_reset_gpio_flags = GPIOF_OUT_INIT_HIGH, .has_pci = 1, .has_uart0 = 1, .has_uart1 = 1, diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index adb6d5b0e6eb..90021c6a8cab 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -16,7 +16,7 @@ #include <linux/libfdt.h> #include <asm/addrspace.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm-generic/vmlinux.lds.h> #include "decompress.h" diff --git a/arch/mips/boot/dts/brcm/bcm6358.dtsi b/arch/mips/boot/dts/brcm/bcm6358.dtsi index 777c4379ed03..5e487f66c343 100644 --- a/arch/mips/boot/dts/brcm/bcm6358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6358.dtsi @@ -13,6 +13,7 @@ #size-cells = <0>; mips-hpt-frequency = <150000000>; + brcm,bmips-cbr-reg = <0xff400000>; cpu@0 { compatible = "brcm,bmips4350"; diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi index fc15e200877d..087f3295a14b 100644 --- a/arch/mips/boot/dts/brcm/bcm6368.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi @@ -13,6 +13,7 @@ #size-cells = <0>; mips-hpt-frequency = <200000000>; + brcm,bmips-cbr-reg = <0xff400000>; cpu@0 { compatible = "brcm,bmips4350"; diff --git a/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts b/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts index ebc0d363fbf8..59a3e95050eb 100644 --- a/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts +++ b/arch/mips/boot/dts/mobileye/eyeq6h-epm6.dts @@ -8,7 +8,7 @@ #include "eyeq6h.dtsi" / { - compatible = "mobileye,eyeq6-epm6", "mobileye,eyeq6"; + compatible = "mobileye,eyeq6h-epm6", "mobileye,eyeq6h"; model = "Mobile EyeQ6H MP6 Evaluation board"; chosen { diff --git a/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts b/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts index 77d2566545f2..6789bf374044 100644 --- a/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts +++ b/arch/mips/boot/dts/realtek/cameo-rtl9302c-2x-rtl8224-2xge.dts @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /dts-v1/; -#include "rtl930x.dtsi" +#include "rtl9302c.dtsi" #include <dt-bindings/input/input.h> #include <dt-bindings/gpio/gpio.h> diff --git a/arch/mips/boot/dts/realtek/rtl9302c.dtsi b/arch/mips/boot/dts/realtek/rtl9302c.dtsi new file mode 100644 index 000000000000..8690433af498 --- /dev/null +++ b/arch/mips/boot/dts/realtek/rtl9302c.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause + +#include "rtl930x.dtsi" + +&switch0 { + compatible = "realtek,rtl9302c-switch", "syscon", "simple-mfd"; +}; + +&i2c0 { + compatible = "realtek,rtl9302c-i2c", "realtek,rtl9301-i2c"; +}; + +&i2c1 { + compatible = "realtek,rtl9302c-i2c", "realtek,rtl9301-i2c"; +}; diff --git a/arch/mips/boot/dts/realtek/rtl930x.dtsi b/arch/mips/boot/dts/realtek/rtl930x.dtsi index f271940f82be..6a6f3f3fe389 100644 --- a/arch/mips/boot/dts/realtek/rtl930x.dtsi +++ b/arch/mips/boot/dts/realtek/rtl930x.dtsi @@ -29,6 +29,35 @@ #clock-cells = <0>; clock-frequency = <175000000>; }; + + switch0: switch@1b000000 { + compatible = "realtek,rtl9301-switch", "syscon", "simple-mfd"; + reg = <0x1b000000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + + reboot@c { + compatible = "syscon-reboot"; + reg = <0x0c 0x4>; + value = <0x01>; + }; + + i2c0: i2c@36c { + compatible = "realtek,rtl9301-i2c"; + reg = <0x36c 0x14>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@388 { + compatible = "realtek,rtl9301-i2c"; + reg = <0x388 0x14>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; }; &soc { diff --git a/arch/mips/configs/generic/board-ocelot.config b/arch/mips/configs/generic/board-ocelot.config index 8cfbafa532e0..a5b5b5102472 100644 --- a/arch/mips/configs/generic/board-ocelot.config +++ b/arch/mips/configs/generic/board-ocelot.config @@ -31,6 +31,7 @@ CONFIG_MICROSEMI_PHY=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig index 78f498752066..98844b457b7f 100644 --- a/arch/mips/configs/loongson3_defconfig +++ b/arch/mips/configs/loongson3_defconfig @@ -5,6 +5,8 @@ CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y CONFIG_PREEMPT=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y @@ -22,18 +24,16 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_NAMESPACES=y CONFIG_USER_NS=y CONFIG_SCHED_AUTOGROUP=y -CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y -CONFIG_BPF_SYSCALL=y CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y +CONFIG_KEXEC=y CONFIG_MACH_LOONGSON64=y CONFIG_CPU_HAS_MSA=y CONFIG_NUMA=y CONFIG_NR_CPUS=16 CONFIG_HZ_256=y -CONFIG_KEXEC=y CONFIG_MIPS32_O32=y CONFIG_MIPS32_N32=y CONFIG_VIRTUALIZATION=y @@ -47,15 +47,12 @@ CONFIG_MODVERSIONS=y CONFIG_PARTITION_ADVANCED=y CONFIG_MQ_IOSCHED_DEADLINE=m CONFIG_IOSCHED_BFQ=y -CONFIG_BFQ_GROUP_IOSCHED=y CONFIG_BINFMT_MISC=m CONFIG_KSM=y CONFIG_NET=y CONFIG_PACKET=y -CONFIG_UNIX=y CONFIG_XFRM_USER=y CONFIG_NET_KEY=y -CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y @@ -106,7 +103,6 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m CONFIG_IP_NF_SECURITY=m -CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NF_TABLES_IPV6=y @@ -128,7 +124,6 @@ CONFIG_L2TP=m CONFIG_BRIDGE=m CONFIG_VSOCKETS=m CONFIG_VIRTIO_VSOCKETS=m -CONFIG_BPF_JIT=y CONFIG_CFG80211=m CONFIG_CFG80211_WEXT=y CONFIG_MAC80211=m @@ -146,6 +141,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_NVME=m CONFIG_RAID_ATTRS=m CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y @@ -167,12 +163,10 @@ CONFIG_SATA_AHCI=y CONFIG_PATA_ATIIXP=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m -CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID10=m CONFIG_MD_RAID456=m -CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m @@ -196,7 +190,6 @@ CONFIG_VIRTIO_NET=m # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_VENDOR_ATHEROS is not set # CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_CISCO is not set @@ -216,6 +209,7 @@ CONFIG_IXGBE=y # CONFIG_NET_VENDOR_NVIDIA is not set # CONFIG_NET_VENDOR_OKI is not set # CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_RDC is not set CONFIG_8139CP=m CONFIG_8139TOO=m @@ -242,7 +236,6 @@ CONFIG_PPPOL2TP=m CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m CONFIG_ATH9K=m -CONFIG_HOSTAP=m CONFIG_INPUT_SPARSEKMAP=y CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y @@ -276,23 +269,20 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_DRM=y +CONFIG_DRM_RADEON=m CONFIG_DRM_AMDGPU=m CONFIG_DRM_AMDGPU_SI=y CONFIG_DRM_AMDGPU_CIK=y CONFIG_DRM_AMDGPU_USERPTR=y CONFIG_DRM_AMD_ACP=y -CONFIG_DRM_AMD_DC=y CONFIG_DRM_AMD_DC_SI=y CONFIG_DRM_AST=m -CONFIG_DRM_RADEON=m CONFIG_DRM_QXL=y CONFIG_DRM_VIRTIO_GPU=y CONFIG_FB=y CONFIG_FB_RADEON=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=m -# CONFIG_VGA_CONSOLE is not set -CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y CONFIG_LOGO=y CONFIG_SOUND=y @@ -350,13 +340,11 @@ CONFIG_EXT3_FS_SECURITY=y CONFIG_XFS_FS=y CONFIG_XFS_POSIX_ACL=y CONFIG_QUOTA=y -# CONFIG_PRINT_QUOTA_WARNING is not set CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS_FS=y CONFIG_FUSE_FS=m CONFIG_VIRTIO_FS=m -CONFIG_NETFS_SUPPORT=m CONFIG_FSCACHE=y CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -391,23 +379,21 @@ CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_PATH=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y -CONFIG_SECURITY_SELINUX_DISABLE=y CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DEFLATE=m CONFIG_PRINTK_TIME=y CONFIG_STRIP_ASM_SYMS=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y # CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set CONFIG_FUNCTION_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_CMDLINE_BOOL=y diff --git a/arch/mips/crypto/crc32-mips.c b/arch/mips/crypto/crc32-mips.c index ec6d58008f8e..90eacf00cfc3 100644 --- a/arch/mips/crypto/crc32-mips.c +++ b/arch/mips/crypto/crc32-mips.c @@ -14,7 +14,7 @@ #include <linux/module.h> #include <linux/string.h> #include <asm/mipsregs.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/internal/hash.h> @@ -77,24 +77,26 @@ static u32 crc32_mips_le_hw(u32 crc_, const u8 *p, unsigned int len) { u32 crc = crc_; -#ifdef CONFIG_64BIT - while (len >= sizeof(u64)) { - u64 value = get_unaligned_le64(p); + if (IS_ENABLED(CONFIG_64BIT)) { + for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { + u64 value = get_unaligned_le64(p); - CRC32(crc, value, d); - p += sizeof(u64); - len -= sizeof(u64); - } + CRC32(crc, value, d); + } - if (len & sizeof(u32)) { -#else /* !CONFIG_64BIT */ - while (len >= sizeof(u32)) { -#endif - u32 value = get_unaligned_le32(p); + if (len & sizeof(u32)) { + u32 value = get_unaligned_le32(p); + + CRC32(crc, value, w); + p += sizeof(u32); + } + } else { + for (; len >= sizeof(u32); len -= sizeof(u32)) { + u32 value = get_unaligned_le32(p); - CRC32(crc, value, w); - p += sizeof(u32); - len -= sizeof(u32); + CRC32(crc, value, w); + p += sizeof(u32); + } } if (len & sizeof(u16)) { @@ -117,24 +119,26 @@ static u32 crc32c_mips_le_hw(u32 crc_, const u8 *p, unsigned int len) { u32 crc = crc_; -#ifdef CONFIG_64BIT - while (len >= sizeof(u64)) { - u64 value = get_unaligned_le64(p); + if (IS_ENABLED(CONFIG_64BIT)) { + for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { + u64 value = get_unaligned_le64(p); - CRC32C(crc, value, d); - p += sizeof(u64); - len -= sizeof(u64); - } + CRC32C(crc, value, d); + } - if (len & sizeof(u32)) { -#else /* !CONFIG_64BIT */ - while (len >= sizeof(u32)) { -#endif - u32 value = get_unaligned_le32(p); + if (len & sizeof(u32)) { + u32 value = get_unaligned_le32(p); + + CRC32C(crc, value, w); + p += sizeof(u32); + } + } else { + for (; len >= sizeof(u32); len -= sizeof(u32)) { + u32 value = get_unaligned_le32(p); - CRC32C(crc, value, w); - p += sizeof(u32); - len -= sizeof(u32); + CRC32C(crc, value, w); + p += sizeof(u32); + } } if (len & sizeof(u16)) { diff --git a/arch/mips/crypto/poly1305-glue.c b/arch/mips/crypto/poly1305-glue.c index 867728ee535a..c03ad0bbe69c 100644 --- a/arch/mips/crypto/poly1305-glue.c +++ b/arch/mips/crypto/poly1305-glue.c @@ -5,7 +5,7 @@ * Copyright (C) 2019 Linaro Ltd. <ard.biesheuvel@linaro.org> */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <crypto/algapi.h> #include <crypto/internal/hash.h> #include <crypto/internal/poly1305.h> diff --git a/arch/mips/include/asm/cmp.h b/arch/mips/include/asm/cmp.h index e9e87504bb0c..71e20e6cd38d 100644 --- a/arch/mips/include/asm/cmp.h +++ b/arch/mips/include/asm/cmp.h @@ -7,12 +7,4 @@ */ struct task_struct; -extern void cmp_smp_setup(void); -extern void cmp_smp_finish(void); -extern void cmp_boot_secondary(int cpu, struct task_struct *t); -extern void cmp_init_secondary(void); -extern void cmp_prepare_cpus(unsigned int max_cpus); - -/* This is platform specific */ -extern void cmp_send_ipi(int cpu, unsigned int action); #endif /* _ASM_CMP_H */ diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h index 908e96e3a311..8fcad6984389 100644 --- a/arch/mips/include/asm/dec/prom.h +++ b/arch/mips/include/asm/dec/prom.h @@ -160,6 +160,5 @@ extern void prom_identify_arch(u32); extern void prom_init_cmdline(s32, s32 *, u32); extern void register_prom_console(void); -extern void unregister_prom_console(void); #endif /* _ASM_DEC_PROM_H */ diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 6743a57c1ab4..f7222eb594ea 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -728,8 +728,8 @@ struct kvm_mips_callbacks { int (*handle_fpe)(struct kvm_vcpu *vcpu); int (*handle_msa_disabled)(struct kvm_vcpu *vcpu); int (*handle_guest_exit)(struct kvm_vcpu *vcpu); - int (*hardware_enable)(void); - void (*hardware_disable)(void); + int (*enable_virtualization_cpu)(void); + void (*disable_virtualization_cpu)(void); int (*check_extension)(struct kvm *kvm, long ext); int (*vcpu_init)(struct kvm_vcpu *vcpu); void (*vcpu_uninit)(struct kvm_vcpu *vcpu); diff --git a/arch/mips/include/asm/mach-au1x00/au1000_dma.h b/arch/mips/include/asm/mach-au1x00/au1000_dma.h index b82e513c8523..18c24051a1f2 100644 --- a/arch/mips/include/asm/mach-au1x00/au1000_dma.h +++ b/arch/mips/include/asm/mach-au1x00/au1000_dma.h @@ -124,7 +124,6 @@ extern int request_au1000_dma(int dev_id, extern void free_au1000_dma(unsigned int dmanr); extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data); -extern void dump_au1000_dma_channel(unsigned int dmanr); extern spinlock_t au1000_dma_spin_lock; static inline struct dma_chan *get_dma_chan(unsigned int dmanr) diff --git a/arch/mips/include/asm/mach-ip27/mmzone.h b/arch/mips/include/asm/mach-ip27/mmzone.h index 08c36e50a860..56959eb9cb26 100644 --- a/arch/mips/include/asm/mach-ip27/mmzone.h +++ b/arch/mips/include/asm/mach-ip27/mmzone.h @@ -22,7 +22,6 @@ struct node_data { extern struct node_data *__node_data[]; -#define NODE_DATA(n) (&__node_data[(n)]->pglist) #define hub_data(n) (&__node_data[(n)]->hub) #endif /* _ASM_MACH_MMZONE_H */ diff --git a/arch/mips/include/asm/mach-loongson64/mmzone.h b/arch/mips/include/asm/mach-loongson64/mmzone.h index a3d65d37b8b5..8fb70fd3c9c4 100644 --- a/arch/mips/include/asm/mach-loongson64/mmzone.h +++ b/arch/mips/include/asm/mach-loongson64/mmzone.h @@ -14,10 +14,6 @@ #define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) #define nid_to_addrbase(nid) ((unsigned long)(nid) << NODE_ADDRSPACE_SHIFT) -extern struct pglist_data *__node_data[]; - -#define NODE_DATA(n) (__node_data[n]) - extern void __init prom_init_numa_memory(void); #endif /* _ASM_MACH_MMZONE_H */ diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h index c904c24550f6..5befba569c9f 100644 --- a/arch/mips/include/asm/mips-boards/generic.h +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -73,7 +73,4 @@ extern void mips_pcibios_init(void); #define mips_pcibios_init() do { } while (0) #endif -extern void mips_scroll_message(void); -extern void mips_display_message(const char *str); - #endif /* __ASM_MIPS_BOARDS_GENERIC_H */ diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 1e782275850a..23ce951f445b 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -326,7 +326,9 @@ GCR_CX_ACCESSOR_RW(32, 0x018, other) /* GCR_Cx_RESET_BASE - Configure where powered up cores will fetch from */ GCR_CX_ACCESSOR_RW(32, 0x020, reset_base) +GCR_CX_ACCESSOR_RW(64, 0x020, reset64_base) #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE GENMASK(31, 12) +#define CM_GCR_Cx_RESET64_BASE_BEVEXCBASE GENMASK_ULL(47, 12) #define CM_GCR_Cx_RESET_BASE_MODE BIT(1) /* GCR_Cx_ID - Identify the current core */ diff --git a/arch/mips/include/asm/mips_mt.h b/arch/mips/include/asm/mips_mt.h index 28917f1582b3..6ea02af29876 100644 --- a/arch/mips/include/asm/mips_mt.h +++ b/arch/mips/include/asm/mips_mt.h @@ -17,8 +17,6 @@ extern int vpelimit; extern cpumask_t mt_fpu_cpumask; extern unsigned long mt_fpemul_threshold; -extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value); - #ifdef CONFIG_MIPS_MT extern void mips_mt_set_cpuoptions(void); #else diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 4609cb0326cf..bc3e3484c1bf 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -14,12 +14,7 @@ #include <linux/kernel.h> #include <asm/mipsregs.h> -/* - * PAGE_SHIFT determines the page size - */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +#include <vdso/page.h> /* * This is used for calculating the real page sizes diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index a4374b4cb88f..d6ccd5344021 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -97,7 +97,7 @@ do { \ } \ } while (0) #else -# define __sanitize_fcr31(next) +# define __sanitize_fcr31(next) do { (void) (next); } while (0) #endif /* diff --git a/arch/mips/include/asm/vdso/vsyscall.h b/arch/mips/include/asm/vdso/vsyscall.h index 47168aaf1eff..a4582870aaea 100644 --- a/arch/mips/include/asm/vdso/vsyscall.h +++ b/arch/mips/include/asm/vdso/vsyscall.h @@ -4,7 +4,6 @@ #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> extern struct vdso_data *vdso_data; diff --git a/arch/mips/include/uapi/asm/sigcontext.h b/arch/mips/include/uapi/asm/sigcontext.h index d0a540e88bb4..d10afd13ee5b 100644 --- a/arch/mips/include/uapi/asm/sigcontext.h +++ b/arch/mips/include/uapi/asm/sigcontext.h @@ -56,7 +56,6 @@ struct sigcontext { #if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 -#include <linux/posix_types.h> /* * Keep this struct definition in sync with the sigcontext fragment * in arch/mips/kernel/asm-offsets.c diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 60ebaed28a4c..8ab7582291ab 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -151,6 +151,12 @@ #define SO_PASSPIDFD 76 #define SO_PEERPIDFD 77 +#define SO_DEVMEM_LINEAR 78 +#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR +#define SO_DEVMEM_DMABUF 79 +#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF +#define SO_DEVMEM_DONTNEED 80 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index e318ea11c858..d21e5d441f53 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -23,8 +23,6 @@ #include <asm/reboot.h> #include <asm/tlbmisc.h> -extern asmlinkage void jazz_handle_int(void); - extern void jazz_machine_restart(char *command); static struct resource jazz_io_resources[] = { diff --git a/arch/mips/kernel/cmpxchg.c b/arch/mips/kernel/cmpxchg.c index e974a4954df8..c371def2302d 100644 --- a/arch/mips/kernel/cmpxchg.c +++ b/arch/mips/kernel/cmpxchg.c @@ -102,3 +102,4 @@ unsigned long __cmpxchg_small(volatile void *ptr, unsigned long old, return old; } } +EXPORT_SYMBOL(__cmpxchg_small); diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index bdb1fa8931f4..59eca397f297 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c @@ -21,9 +21,7 @@ static struct clocksource clocksource_mips = { .name = "MIPS", .read = c0_hpt_read, .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_MUST_VERIFY | - CLOCK_SOURCE_VERIFY_PERCPU, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; static u64 __maybe_unused notrace r4k_read_sched_clock(void) diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index c938ba208fc0..37676a44fefb 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -43,83 +43,6 @@ static int __init maxtcs(char *str) __setup("maxtcs=", maxtcs); -/* - * Dump new MIPS MT state for the core. Does not leave TCs halted. - * Takes an argument which taken to be a pre-call MVPControl value. - */ - -void mips_mt_regdump(unsigned long mvpctl) -{ - unsigned long flags; - unsigned long vpflags; - unsigned long mvpconf0; - int nvpe; - int ntc; - int i; - int tc; - unsigned long haltval; - unsigned long tcstatval; - - local_irq_save(flags); - vpflags = dvpe(); - printk("=== MIPS MT State Dump ===\n"); - printk("-- Global State --\n"); - printk(" MVPControl Passed: %08lx\n", mvpctl); - printk(" MVPControl Read: %08lx\n", vpflags); - printk(" MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0())); - nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; - ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; - printk("-- per-VPE State --\n"); - for (i = 0; i < nvpe; i++) { - for (tc = 0; tc < ntc; tc++) { - settc(tc); - if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) { - printk(" VPE %d\n", i); - printk(" VPEControl : %08lx\n", - read_vpe_c0_vpecontrol()); - printk(" VPEConf0 : %08lx\n", - read_vpe_c0_vpeconf0()); - printk(" VPE%d.Status : %08lx\n", - i, read_vpe_c0_status()); - printk(" VPE%d.EPC : %08lx %pS\n", - i, read_vpe_c0_epc(), - (void *) read_vpe_c0_epc()); - printk(" VPE%d.Cause : %08lx\n", - i, read_vpe_c0_cause()); - printk(" VPE%d.Config7 : %08lx\n", - i, read_vpe_c0_config7()); - break; /* Next VPE */ - } - } - } - printk("-- per-TC State --\n"); - for (tc = 0; tc < ntc; tc++) { - settc(tc); - if (read_tc_c0_tcbind() == read_c0_tcbind()) { - /* Are we dumping ourself? */ - haltval = 0; /* Then we're not halted, and mustn't be */ - tcstatval = flags; /* And pre-dump TCStatus is flags */ - printk(" TC %d (current TC with VPE EPC above)\n", tc); - } else { - haltval = read_tc_c0_tchalt(); - write_tc_c0_tchalt(1); - tcstatval = read_tc_c0_tcstatus(); - printk(" TC %d\n", tc); - } - printk(" TCStatus : %08lx\n", tcstatval); - printk(" TCBind : %08lx\n", read_tc_c0_tcbind()); - printk(" TCRestart : %08lx %pS\n", - read_tc_c0_tcrestart(), (void *) read_tc_c0_tcrestart()); - printk(" TCHalt : %08lx\n", haltval); - printk(" TCContext : %08lx\n", read_tc_c0_tccontext()); - if (!haltval) - write_tc_c0_tchalt(0); - } - printk("===========================\n"); - evpe(vpflags); - local_irq_restore(flags); -} - static int mt_opt_rpsctl = -1; static int mt_opt_nblsu = -1; static int mt_opt_forceconfig7; diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 8eba5a1ed664..8f0a0001540c 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -66,24 +66,23 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "BogoMIPS\t\t: %u.%02u\n", cpu_data[n].udelay_val / (500000/HZ), (cpu_data[n].udelay_val / (5000/HZ)) % 100); - seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); + seq_printf(m, "wait instruction\t: %s\n", str_yes_no(cpu_wait)); seq_printf(m, "microsecond timers\t: %s\n", - cpu_has_counter ? "yes" : "no"); + str_yes_no(cpu_has_counter)); seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); seq_printf(m, "extra interrupt vector\t: %s\n", - cpu_has_divec ? "yes" : "no"); - seq_printf(m, "hardware watchpoint\t: %s", - cpu_has_watch ? "yes, " : "no\n"); + str_yes_no(cpu_has_divec)); + seq_printf(m, "hardware watchpoint\t: %s", str_yes_no(cpu_has_watch)); if (cpu_has_watch) { - seq_printf(m, "count: %d, address/irw mask: [", + seq_printf(m, ", count: %d, address/irw mask: [", cpu_data[n].watch_reg_count); for (i = 0; i < cpu_data[n].watch_reg_count; i++) seq_printf(m, "%s0x%04x", i ? ", " : "", cpu_data[n].watch_reg_masks[i]); - seq_puts(m, "]\n"); + seq_puts(m, "]"); } - seq_puts(m, "isa\t\t\t:"); + seq_puts(m, "\nisa\t\t\t:"); if (cpu_has_mips_1) seq_puts(m, " mips1"); if (cpu_has_mips_2) @@ -155,7 +154,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_mmips) { seq_printf(m, "micromips kernel\t: %s\n", - (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); + str_yes_no(read_c0_config3() & MIPS_CONF3_ISA_OE)); } seq_puts(m, "Options implemented\t:"); diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 6062e6fa589a..4fd6da0a06c3 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -41,7 +41,7 @@ char *mips_get_machine_name(void) void __init __dt_setup_arch(void *bph) { - if (!early_init_dt_scan(bph)) + if (!early_init_dt_scan(bph, __pa(bph))) return; mips_set_machine_name(of_flat_dt_get_machine_name()); diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 7eeeaf1ff95d..cda7983e7c18 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -337,7 +337,7 @@ void *__init relocate_kernel(void) #if defined(CONFIG_USE_OF) /* Deal with the device tree */ fdt = plat_get_fdt(); - early_init_dt_scan(fdt); + early_init_dt_scan(fdt, __pa(fdt)); if (boot_command_line[0]) { /* Boot command line was passed in device tree */ strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 395622c37325..82c8f9b9573c 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -37,7 +37,7 @@ enum label_id { UASM_L_LA(_not_nmi) static DECLARE_BITMAP(core_power, NR_CPUS); -static uint32_t core_entry_reg; +static u64 core_entry_reg; static phys_addr_t cps_vec_pa; struct core_boot_config *mips_cps_core_bootcfg; @@ -94,6 +94,20 @@ static void __init *mips_cps_build_core_entry(void *addr) return p; } +static bool __init check_64bit_reset(void) +{ + bool cx_64bit_reset = false; + + mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL); + write_gcr_co_reset64_base(CM_GCR_Cx_RESET64_BASE_BEVEXCBASE); + if ((read_gcr_co_reset64_base() & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) == + CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) + cx_64bit_reset = true; + mips_cm_unlock_other(); + + return cx_64bit_reset; +} + static int __init allocate_cps_vecs(void) { /* Try to allocate in KSEG1 first */ @@ -105,11 +119,23 @@ static int __init allocate_cps_vecs(void) CM_GCR_Cx_RESET_BASE_BEVEXCBASE; if (!cps_vec_pa && mips_cm_is64) { - cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN, - 0x0, SZ_4G - 1); - if (cps_vec_pa) - core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) | + phys_addr_t end; + + if (check_64bit_reset()) { + pr_info("VP Local Reset Exception Base support 47 bits address\n"); + end = MEMBLOCK_ALLOC_ANYWHERE; + } else { + end = SZ_4G - 1; + } + cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN, 0, end); + if (cps_vec_pa) { + if (check_64bit_reset()) + core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) | + CM_GCR_Cx_RESET_BASE_MODE; + else + core_entry_reg = (cps_vec_pa & CM_GCR_Cx_RESET_BASE_BEVEXCBASE) | CM_GCR_Cx_RESET_BASE_MODE; + } } if (!cps_vec_pa) @@ -308,7 +334,10 @@ static void boot_core(unsigned int core, unsigned int vpe_id) mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL); /* Set its reset vector */ - write_gcr_co_reset_base(core_entry_reg); + if (mips_cm_is64) + write_gcr_co_reset64_base(core_entry_reg); + else + write_gcr_co_reset_base(core_entry_reg); /* Ensure its coherency is disabled */ write_gcr_co_coherence(0); @@ -411,7 +440,10 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle) if (cpu_has_vp) { mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL); - write_gcr_co_reset_base(core_entry_reg); + if (mips_cm_is64) + write_gcr_co_reset64_base(core_entry_reg); + else + write_gcr_co_reset_base(core_entry_reg); mips_cm_unlock_other(); } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 0362fc5df7b0..39e193cad2b9 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -439,7 +439,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) } /* preload SMP state for boot cpu */ -void smp_prepare_boot_cpu(void) +void __init smp_prepare_boot_cpu(void) { if (mp_ops->prepare_boot_cpu) mp_ops->prepare_boot_cpu(); diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 953f5b7dc723..0b9b7e25b69a 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -401,3 +401,7 @@ 460 n32 lsm_set_self_attr sys_lsm_set_self_attr 461 n32 lsm_list_modules sys_lsm_list_modules 462 n32 mseal sys_mseal +463 n32 setxattrat sys_setxattrat +464 n32 getxattrat sys_getxattrat +465 n32 listxattrat sys_listxattrat +466 n32 removexattrat sys_removexattrat diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 1464c6be6eb3..c844cd5cda62 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -377,3 +377,7 @@ 460 n64 lsm_set_self_attr sys_lsm_set_self_attr 461 n64 lsm_list_modules sys_lsm_list_modules 462 n64 mseal sys_mseal +463 n64 setxattrat sys_setxattrat +464 n64 getxattrat sys_getxattrat +465 n64 listxattrat sys_listxattrat +466 n64 removexattrat sys_removexattrat diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 2439a2491cff..349b8aad1159 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -450,3 +450,7 @@ 460 o32 lsm_set_self_attr sys_lsm_set_self_attr 461 o32 lsm_list_modules sys_lsm_list_modules 462 o32 mseal sys_mseal +463 o32 setxattrat sys_setxattrat +464 o32 getxattrat sys_getxattrat +465 o32 listxattrat sys_listxattrat +466 o32 removexattrat sys_removexattrat diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index dda36fa26307..4c8e3c0aa210 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -14,7 +14,6 @@ #include <linux/random.h> #include <linux/sched.h> #include <linux/slab.h> -#include <linux/timekeeper_internal.h> #include <asm/abi.h> #include <asm/mips-cps.h> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index b5de770b092e..60b43ea85c12 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -125,14 +125,14 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) return 1; } -int kvm_arch_hardware_enable(void) +int kvm_arch_enable_virtualization_cpu(void) { - return kvm_mips_callbacks->hardware_enable(); + return kvm_mips_callbacks->enable_virtualization_cpu(); } -void kvm_arch_hardware_disable(void) +void kvm_arch_disable_virtualization_cpu(void) { - kvm_mips_callbacks->hardware_disable(); + kvm_mips_callbacks->disable_virtualization_cpu(); } int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c index 99d5a71e4300..ccab4d76b126 100644 --- a/arch/mips/kvm/vz.c +++ b/arch/mips/kvm/vz.c @@ -2869,7 +2869,7 @@ static unsigned int kvm_vz_resize_guest_vtlb(unsigned int size) return ret + 1; } -static int kvm_vz_hardware_enable(void) +static int kvm_vz_enable_virtualization_cpu(void) { unsigned int mmu_size, guest_mmu_size, ftlb_size; u64 guest_cvmctl, cvmvmconfig; @@ -2983,7 +2983,7 @@ static int kvm_vz_hardware_enable(void) return 0; } -static void kvm_vz_hardware_disable(void) +static void kvm_vz_disable_virtualization_cpu(void) { u64 cvmvmconfig; unsigned int mmu_size; @@ -3280,8 +3280,8 @@ static struct kvm_mips_callbacks kvm_vz_callbacks = { .handle_msa_disabled = kvm_trap_vz_handle_msa_disabled, .handle_guest_exit = kvm_trap_vz_handle_guest_exit, - .hardware_enable = kvm_vz_hardware_enable, - .hardware_disable = kvm_vz_hardware_disable, + .enable_virtualization_cpu = kvm_vz_enable_virtualization_cpu, + .disable_virtualization_cpu = kvm_vz_disable_virtualization_cpu, .check_extension = kvm_vz_check_extension, .vcpu_init = kvm_vz_vcpu_init, .vcpu_uninit = kvm_vz_vcpu_uninit, diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c index 68dafd6d3e25..8388400d052f 100644 --- a/arch/mips/loongson64/numa.c +++ b/arch/mips/loongson64/numa.c @@ -29,8 +29,6 @@ unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; EXPORT_SYMBOL(__node_distances); -struct pglist_data *__node_data[MAX_NUMNODES]; -EXPORT_SYMBOL(__node_data); cpumask_t __node_cpumask[MAX_NUMNODES]; EXPORT_SYMBOL(__node_cpumask); @@ -83,12 +81,8 @@ static void __init init_topology_matrix(void) static void __init node_mem_init(unsigned int node) { - struct pglist_data *nd; unsigned long node_addrspace_offset; unsigned long start_pfn, end_pfn; - unsigned long nd_pa; - int tnid; - const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES); node_addrspace_offset = nid_to_addrbase(node); pr_info("Node%d's addrspace_offset is 0x%lx\n", @@ -98,16 +92,8 @@ static void __init node_mem_init(unsigned int node) pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n", node, start_pfn, end_pfn); - nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, node); - if (!nd_pa) - panic("Cannot allocate %zu bytes for node %d data\n", - nd_size, node); - nd = __va(nd_pa); - memset(nd, 0, sizeof(struct pglist_data)); - tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); - if (tnid != node) - pr_info("NODE_DATA(%d) on node %d\n", node, tnid); - __node_data[node] = nd; + alloc_node_data(node); + NODE_DATA(node)->node_start_pfn = start_pfn; NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; @@ -198,13 +184,3 @@ void __init prom_init_numa_memory(void) pr_info("CP0_PageGrain: CP0 5.1 (0x%x)\n", read_c0_pagegrain()); prom_meminit(); } - -pg_data_t * __init arch_alloc_nodedata(int nid) -{ - return memblock_alloc(sizeof(pg_data_t), SMP_CACHE_BYTES); -} - -void arch_refresh_nodedata(int nid, pg_data_t *pgdat) -{ - __node_data[nid] = pgdat; -} diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 7e11d7b58761..5d2a1225785b 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -98,7 +98,8 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, } unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, unsigned long flags, + vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, UP); @@ -110,7 +111,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0, */ unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr0, len, pgoff, flags, DOWN); diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index 08c012a2591f..910d059ec70b 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -1,13 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 if RALINK -config CLKEVT_RT3352 - bool - depends on SOC_RT305X || SOC_MT7620 - default y - select TIMER_OF - select CLKSRC_MMIO - config RALINK_ILL_ACC bool depends on SOC_RT305X diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 26fabbdea1f1..0c109eae1953 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -10,8 +10,6 @@ ifndef CONFIG_MIPS_GIC obj-y += clk.o timer.o endif -obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o - obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o obj-$(CONFIG_IRQ_INTC) += irq.o diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c deleted file mode 100644 index 269d4877d120..000000000000 --- a/arch/mips/ralink/cevt-rt3352.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2013 by John Crispin <john@phrozen.org> - */ - -#include <linux/clockchips.h> -#include <linux/clocksource.h> -#include <linux/interrupt.h> -#include <linux/reset.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/of.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> - -#include <asm/mach-ralink/ralink_regs.h> - -#define SYSTICK_FREQ (50 * 1000) - -#define SYSTICK_CONFIG 0x00 -#define SYSTICK_COMPARE 0x04 -#define SYSTICK_COUNT 0x08 - -/* route systick irq to mips irq 7 instead of the r4k-timer */ -#define CFG_EXT_STK_EN 0x2 -/* enable the counter */ -#define CFG_CNT_EN 0x1 - -struct systick_device { - void __iomem *membase; - struct clock_event_device dev; - int irq_requested; - int freq_scale; -}; - -static int systick_set_oneshot(struct clock_event_device *evt); -static int systick_shutdown(struct clock_event_device *evt); - -static int systick_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - struct systick_device *sdev; - u32 count; - - sdev = container_of(evt, struct systick_device, dev); - count = ioread32(sdev->membase + SYSTICK_COUNT); - count = (count + delta) % SYSTICK_FREQ; - iowrite32(count, sdev->membase + SYSTICK_COMPARE); - - return 0; -} - -static void systick_event_handler(struct clock_event_device *dev) -{ - /* noting to do here */ -} - -static irqreturn_t systick_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *dev = (struct clock_event_device *) dev_id; - - dev->event_handler(dev); - - return IRQ_HANDLED; -} - -static struct systick_device systick = { - .dev = { - /* - * cevt-r4k uses 300, make sure systick - * gets used if available - */ - .rating = 310, - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = systick_next_event, - .set_state_shutdown = systick_shutdown, - .set_state_oneshot = systick_set_oneshot, - .event_handler = systick_event_handler, - }, -}; - -static int systick_shutdown(struct clock_event_device *evt) -{ - struct systick_device *sdev; - - sdev = container_of(evt, struct systick_device, dev); - - if (sdev->irq_requested) - free_irq(systick.dev.irq, &systick.dev); - sdev->irq_requested = 0; - iowrite32(0, systick.membase + SYSTICK_CONFIG); - - return 0; -} - -static int systick_set_oneshot(struct clock_event_device *evt) -{ - const char *name = systick.dev.name; - struct systick_device *sdev; - int irq = systick.dev.irq; - - sdev = container_of(evt, struct systick_device, dev); - - if (!sdev->irq_requested) { - if (request_irq(irq, systick_interrupt, - IRQF_PERCPU | IRQF_TIMER, name, &systick.dev)) - pr_err("Failed to request irq %d (%s)\n", irq, name); - } - sdev->irq_requested = 1; - iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, - systick.membase + SYSTICK_CONFIG); - - return 0; -} - -static int __init ralink_systick_init(struct device_node *np) -{ - int ret; - - systick.membase = of_iomap(np, 0); - if (!systick.membase) - return -ENXIO; - - systick.dev.name = np->name; - clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); - systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); - systick.dev.max_delta_ticks = 0x7fff; - systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); - systick.dev.min_delta_ticks = 0x3; - systick.dev.irq = irq_of_parse_and_map(np, 0); - if (!systick.dev.irq) { - pr_err("%pOFn: request_irq failed", np); - return -EINVAL; - } - - ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, - SYSTICK_FREQ, 301, 16, - clocksource_mmio_readl_up); - if (ret) - return ret; - - clockevents_register_device(&systick.dev); - - pr_info("%pOFn: running - mult: %d, shift: %d\n", - np, systick.dev.mult, systick.dev.shift); - - return 0; -} - -TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); diff --git a/arch/mips/ralink/irq-gic.c b/arch/mips/ralink/irq-gic.c index 3bab51a5fb4c..8bc566ea00e5 100644 --- a/arch/mips/ralink/irq-gic.c +++ b/arch/mips/ralink/irq-gic.c @@ -10,6 +10,7 @@ #include <linux/of.h> #include <linux/irqchip.h> #include <asm/mips-cps.h> +#include <asm/time.h> int get_c0_perfcount_int(void) { diff --git a/arch/mips/ralink/timer-gic.c b/arch/mips/ralink/timer-gic.c index dcf2a44ac51e..926082655a78 100644 --- a/arch/mips/ralink/timer-gic.c +++ b/arch/mips/ralink/timer-gic.c @@ -11,6 +11,8 @@ #include <linux/of_clk.h> #include <linux/clocksource.h> +#include <asm/time.h> + #include "common.h" void __init plat_time_init(void) diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index d20eec742bfa..5893ea4e382c 100644 --- a/arch/mips/sgi-ip22/ip22-gio.c +++ b/arch/mips/sgi-ip22/ip22-gio.c @@ -165,9 +165,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, char *buf) { struct gio_device *gio_dev = to_gio_device(dev); - int len = snprintf(buf, PAGE_SIZE, "gio:%x\n", gio_dev->id.id); - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; + return sysfs_emit(buf, "gio:%x\n", gio_dev->id.id); } static DEVICE_ATTR_RO(modalias); @@ -177,7 +176,7 @@ static ssize_t name_show(struct device *dev, struct gio_device *giodev; giodev = to_gio_device(dev); - return sprintf(buf, "%s", giodev->name); + return sysfs_emit(buf, "%s\n", giodev->name); } static DEVICE_ATTR_RO(name); @@ -187,7 +186,7 @@ static ssize_t id_show(struct device *dev, struct gio_device *giodev; giodev = to_gio_device(dev); - return sprintf(buf, "%x", giodev->id.id); + return sysfs_emit(buf, "%x\n", giodev->id.id); } static DEVICE_ATTR_RO(id); diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index b8ca94cfb4fe..1963313f55d8 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -35,7 +35,6 @@ #define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) struct node_data *__node_data[MAX_NUMNODES]; - EXPORT_SYMBOL(__node_data); static u64 gen_region_mask(void) @@ -361,6 +360,7 @@ static void __init node_mem_init(nasid_t node) */ __node_data[node] = __va(slot_freepfn << PAGE_SHIFT); memset(__node_data[node], 0, PAGE_SIZE); + node_data[node] = &__node_data[node]->pglist; NODE_DATA(node)->node_start_pfn = start_pfn; NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; @@ -423,13 +423,3 @@ void __init mem_init(void) memblock_free_all(); setup_zero_pages(); /* This comes from node 0 */ } - -pg_data_t * __init arch_alloc_nodedata(int nid) -{ - return memblock_alloc(sizeof(pg_data_t), SMP_CACHE_BYTES); -} - -void arch_refresh_nodedata(int nid, pg_data_t *pgdat) -{ - __node_data[nid] = (struct node_data *)pgdat; -} diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 5d2652a1d35a..62733e049570 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -70,11 +70,13 @@ void cpu_node_probe(void) gda_t *gdap = GDA; nodes_clear(node_online_map); + nodes_clear(node_possible_map); for (i = 0; i < MAX_NUMNODES; i++) { nasid_t nasid = gdap->g_nasidtable[i]; if (nasid == INVALID_NASID) break; node_set_online(nasid); + node_set(nasid, node_possible_map); highest = node_scan_cpus(nasid, highest); } diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c index 09e30eb4be86..d47412ea6e67 100644 --- a/arch/mips/vdso/genvdso.c +++ b/arch/mips/vdso/genvdso.c @@ -270,7 +270,7 @@ int main(int argc, char **argv) /* Write out the stripped VDSO data. */ fprintf(out_file, - "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t", + "static unsigned char vdso_image_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t", vdso_size); for (i = 0; i < vdso_size; i++) { if (!(i % 10)) @@ -286,7 +286,7 @@ int main(int argc, char **argv) fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n", (vdso_name[0]) ? "_" : "", vdso_name); - fprintf(out_file, "\t.data = vdso_data,\n"); + fprintf(out_file, "\t.data = vdso_image_data,\n"); fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size); fprintf(out_file, "\t.mapping = {\n"); fprintf(out_file, "\t\t.name = \"[vdso]\",\n"); diff --git a/arch/nios2/include/asm/page.h b/arch/nios2/include/asm/page.h index 0722f88e63cc..2897ec1b74f6 100644 --- a/arch/nios2/include/asm/page.h +++ b/arch/nios2/include/asm/page.h @@ -18,12 +18,7 @@ #include <linux/pfn.h> #include <linux/const.h> -/* - * PAGE_SHIFT determines the page size - */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) +#include <vdso/page.h> /* * PAGE_OFFSET -- the first address of the first page of memory. diff --git a/arch/nios2/kernel/misaligned.c b/arch/nios2/kernel/misaligned.c index 23e0544e117c..2f2862eab3c6 100644 --- a/arch/nios2/kernel/misaligned.c +++ b/arch/nios2/kernel/misaligned.c @@ -23,7 +23,7 @@ #include <linux/seq_file.h> #include <asm/traps.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* instructions we emulate */ #define INST_LDHU 0x0b diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 9a8393e6b4a8..db049249766f 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c @@ -27,7 +27,7 @@ void __init early_init_devtree(void *params) if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) == OF_DT_HEADER) { params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR; - early_init_dt_scan(params); + early_init_dt_scan(params, __pa(params)); return; } #endif @@ -37,5 +37,5 @@ void __init early_init_devtree(void *params) params = (void *)__dtb_start; #endif - early_init_dt_scan(params); + early_init_dt_scan(params, __pa(params)); } diff --git a/arch/nios2/mm/init.c b/arch/nios2/mm/init.c index 3459df28afee..a2278485de19 100644 --- a/arch/nios2/mm/init.c +++ b/arch/nios2/mm/init.c @@ -82,6 +82,10 @@ void __init mmu_init(void) pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE); pte_t invalid_pte_table[PTRS_PER_PTE] __aligned(PAGE_SIZE); static struct page *kuser_page[1]; +static struct vm_special_mapping vdso_mapping = { + .name = "[vdso]", + .pages = kuser_page, +}; static int alloc_kuser_page(void) { @@ -106,18 +110,18 @@ arch_initcall(alloc_kuser_page); int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; - int ret; + struct vm_area_struct *vma; mmap_write_lock(mm); /* Map kuser helpers to user space address */ - ret = install_special_mapping(mm, KUSER_BASE, KUSER_SIZE, + vma = _install_special_mapping(mm, KUSER_BASE, KUSER_SIZE, VM_READ | VM_EXEC | VM_MAYREAD | - VM_MAYEXEC, kuser_page); + VM_MAYEXEC, &vdso_mapping); mmap_write_unlock(mm); - return ret; + return IS_ERR(vma) ? PTR_ERR(vma) : 0; } const char *arch_vma_name(struct vm_area_struct *vma) diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h index 1d5913f67c31..124a2db4b160 100644 --- a/arch/openrisc/include/asm/page.h +++ b/arch/openrisc/include/asm/page.h @@ -15,16 +15,7 @@ #ifndef __ASM_OPENRISC_PAGE_H #define __ASM_OPENRISC_PAGE_H - -/* PAGE_SHIFT determines the page size */ - -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#ifdef __ASSEMBLY__ -#define PAGE_SIZE (1 << PAGE_SHIFT) -#else -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#endif -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #define PAGE_OFFSET 0xc0000000 #define KERNELBASE PAGE_OFFSET diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c index 19e6008bf114..e424e9bd12a7 100644 --- a/arch/openrisc/kernel/prom.c +++ b/arch/openrisc/kernel/prom.c @@ -22,6 +22,6 @@ void __init early_init_devtree(void *params) { - early_init_dt_scan(params); + early_init_dt_scan(params, __pa(params)); memblock_allow_resize(); } diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index b0a2ac3ba916..aa6a3cad275d 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -10,6 +10,7 @@ config PARISC select ARCH_WANT_FRAME_POINTERS select ARCH_HAS_CPU_CACHE_ALIASING select ARCH_HAS_DMA_ALLOC if PA11 + select ARCH_HAS_DMA_OPS select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_MODULE_RWX @@ -23,7 +24,6 @@ config PARISC select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_DEBUG_VM_PGTABLE select HAVE_RELIABLE_STACKTRACE - select DMA_OPS select RTC_CLASS select RTC_DRV_GENERIC select INIT_ALL_POSSIBLE @@ -72,7 +72,7 @@ config PARISC select GENERIC_SCHED_CLOCK select GENERIC_IRQ_MIGRATION if SMP select HAVE_UNSTABLE_SCHED_CLOCK if SMP - select LEGACY_TIMER_TICK + select GENERIC_CLOCKEVENTS select CPU_NO_EFFICIENT_FFS select THREAD_INFO_IN_TASK select NEED_DMA_MAP_STATE diff --git a/arch/parisc/boot/compressed/misc.c b/arch/parisc/boot/compressed/misc.c index d389359e22ac..9c83bd06ef15 100644 --- a/arch/parisc/boot/compressed/misc.c +++ b/arch/parisc/boot/compressed/misc.c @@ -6,7 +6,7 @@ #include <linux/uaccess.h> #include <linux/elf.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/page.h> #include "sizes.h" diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h index 47c5a1991d10..663f587dc789 100644 --- a/arch/parisc/include/asm/mman.h +++ b/arch/parisc/include/asm/mman.h @@ -2,6 +2,7 @@ #ifndef __ASM_MMAN_H__ #define __ASM_MMAN_H__ +#include <linux/fs.h> #include <uapi/asm/mman.h> /* PARISC cannot allow mdwe as it needs writable stacks */ @@ -11,4 +12,18 @@ static inline bool arch_memory_deny_write_exec_supported(void) } #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported +static inline unsigned long arch_calc_vm_flag_bits(struct file *file, unsigned long flags) +{ + /* + * The stack on parisc grows upwards, so if userspace requests memory + * for a stack, mark it with VM_GROWSUP so that the stack expansion in + * the fault handler will work. + */ + if (flags & MAP_STACK) + return VM_GROWSUP; + + return 0; +} +#define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags) + #endif /* __ASM_MMAN_H__ */ diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h index 4bea2e95798f..6c4836fb5407 100644 --- a/arch/parisc/include/asm/page.h +++ b/arch/parisc/include/asm/page.h @@ -4,9 +4,7 @@ #include <linux/const.h> -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 982aca20f56f..77fac02188e1 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -298,7 +298,7 @@ extern unsigned int toc_handler_csum; extern void do_cpu_irq_mask(struct pt_regs *); extern irqreturn_t timer_interrupt(int, void *); extern irqreturn_t ipi_interrupt(int, void *); -extern void start_cpu_itimer(void); +extern void parisc_clockevent_init(void); extern void handle_interruption(int, struct pt_regs *); /* called from assembly code: */ diff --git a/arch/parisc/include/asm/unaligned.h b/arch/parisc/include/asm/unaligned.h deleted file mode 100644 index c0621295100d..000000000000 --- a/arch/parisc/include/asm/unaligned.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_PARISC_UNALIGNED_H -#define _ASM_PARISC_UNALIGNED_H - -#include <asm-generic/unaligned.h> - -struct pt_regs; -void handle_unaligned(struct pt_regs *regs); -int check_unaligned(struct pt_regs *regs); - -#endif /* _ASM_PARISC_UNALIGNED_H */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index be264c2b1a11..38fc0b188e08 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -132,6 +132,12 @@ #define SO_PASSPIDFD 0x404A #define SO_PEERPIDFD 0x404B +#define SO_DEVMEM_LINEAR 78 +#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR +#define SO_DEVMEM_DMABUF 79 +#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF +#define SO_DEVMEM_DONTNEED 80 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index ab23e61a6f01..ea57bcc21dc5 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1051,8 +1051,7 @@ ENTRY_CFI(intr_save) /* for os_hpmc */ STREG %r16, PT_ISR(%r29) STREG %r17, PT_IOR(%r29) -#if 0 && defined(CONFIG_64BIT) - /* Revisit when we have 64-bit code above 4Gb */ +#if defined(CONFIG_64BIT) b,n intr_save2 skip_save_ior: @@ -1060,8 +1059,7 @@ skip_save_ior: * need to adjust iasq/iaoq here in the same way we adjusted isr/ior * above. */ - extrd,u,* %r8,PSW_W_BIT,1,%r1 - cmpib,COND(=),n 1,%r1,intr_save2 + bb,COND(>=),n %r8,PSW_W_BIT,intr_save2 LDREG PT_IASQ0(%r29), %r16 LDREG PT_IAOQ0(%r29), %r17 /* adjust iasq/iaoq */ diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index b0f0816879df..5e8e37a722ef 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -466,7 +466,6 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } static const struct file_operations perf_fops = { - .llseek = no_llseek, .read = perf_read, .write = perf_write, .unlocked_ioctl = perf_ioctl, diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 800eb64e91ad..b2d12ab728b1 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -297,7 +297,7 @@ smp_cpu_init(int cpunum) enter_lazy_tlb(&init_mm, current); init_IRQ(); /* make sure no IRQs are enabled or pending */ - start_cpu_itimer(); + parisc_clockevent_init(); } diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index f7722451276e..f852fe274abe 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -167,7 +167,8 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, } unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, unsigned long flags, + vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr, len, pgoff, flags, UP); @@ -175,7 +176,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { return arch_get_unmapped_area_common(filp, addr, len, pgoff, flags, DOWN); diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 1f51aa9c8230..0fa81bf1466b 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -243,10 +243,10 @@ linux_gateway_entry: #ifdef CONFIG_64BIT ldil L%sys_call_table, %r1 - or,= %r2,%r2,%r2 - addil L%(sys_call_table64-sys_call_table), %r1 + or,ev %r2,%r2,%r2 + ldil L%sys_call_table64, %r1 ldo R%sys_call_table(%r1), %r19 - or,= %r2,%r2,%r2 + or,ev %r2,%r2,%r2 ldo R%sys_call_table64(%r1), %r19 #else load32 sys_call_table, %r19 @@ -379,10 +379,10 @@ tracesys_next: extrd,u %r19,63,1,%r2 /* W hidden in bottom bit */ ldil L%sys_call_table, %r1 - or,= %r2,%r2,%r2 - addil L%(sys_call_table64-sys_call_table), %r1 + or,ev %r2,%r2,%r2 + ldil L%sys_call_table64, %r1 ldo R%sys_call_table(%r1), %r19 - or,= %r2,%r2,%r2 + or,ev %r2,%r2,%r2 ldo R%sys_call_table64(%r1), %r19 #else load32 sys_call_table, %r19 @@ -1327,6 +1327,8 @@ ENTRY(sys_call_table) END(sys_call_table) #ifdef CONFIG_64BIT +#undef __SYSCALL_WITH_COMPAT +#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native) .align 8 ENTRY(sys_call_table64) #include <asm/syscall_table_64.h> /* 64-bit syscalls */ diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 66dc406b12e4..d9fc94c86965 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -461,3 +461,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 9714fbd7c42d..c17e2249115f 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -1,166 +1,119 @@ // SPDX-License-Identifier: GPL-2.0 /* - * linux/arch/parisc/kernel/time.c + * Common time service routines for parisc machines. + * based on arch/loongarch/kernel/time.c * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King - * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org) - * - * 1994-07-02 Alan Modra - * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime - * 1998-12-20 Updated NTP code according to technical memorandum Jan '96 - * "A Kernel Model for Precision Timekeeping" by Dave Mills + * Copyright (C) 2024 Helge Deller <deller@gmx.de> */ -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/rtc.h> -#include <linux/sched.h> -#include <linux/sched/clock.h> -#include <linux/sched_clock.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/time.h> +#include <linux/clockchips.h> +#include <linux/delay.h> +#include <linux/export.h> #include <linux/init.h> -#include <linux/smp.h> -#include <linux/profile.h> -#include <linux/clocksource.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/sched_clock.h> +#include <linux/spinlock.h> +#include <linux/rtc.h> #include <linux/platform_device.h> -#include <linux/ftrace.h> +#include <asm/processor.h> -#include <linux/uaccess.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/page.h> -#include <asm/param.h> -#include <asm/pdc.h> -#include <asm/led.h> +static u64 cr16_clock_freq; +static unsigned long clocktick; -#include <linux/timex.h> +int time_keeper_id; /* CPU used for timekeeping */ -int time_keeper_id __read_mostly; /* CPU used for timekeeping. */ +static DEFINE_PER_CPU(struct clock_event_device, parisc_clockevent_device); -static unsigned long clocktick __ro_after_init; /* timer cycles per tick */ +static void parisc_event_handler(struct clock_event_device *dev) +{ +} -/* - * We keep time on PA-RISC Linux by using the Interval Timer which is - * a pair of registers; one is read-only and one is write-only; both - * accessed through CR16. The read-only register is 32 or 64 bits wide, - * and increments by 1 every CPU clock tick. The architecture only - * guarantees us a rate between 0.5 and 2, but all implementations use a - * rate of 1. The write-only register is 32-bits wide. When the lowest - * 32 bits of the read-only register compare equal to the write-only - * register, it raises a maskable external interrupt. Each processor has - * an Interval Timer of its own and they are not synchronised. - * - * We want to generate an interrupt every 1/HZ seconds. So we program - * CR16 to interrupt every @clocktick cycles. The it_value in cpu_data - * is programmed with the intended time of the next tick. We can be - * held off for an arbitrarily long period of time by interrupts being - * disabled, so we may miss one or more ticks. - */ -irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) +static int parisc_timer_next_event(unsigned long delta, struct clock_event_device *evt) { - unsigned long now; - unsigned long next_tick; - unsigned long ticks_elapsed = 0; - unsigned int cpu = smp_processor_id(); - struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); - - /* gcc can optimize for "read-only" case with a local clocktick */ - unsigned long cpt = clocktick; - - /* Initialize next_tick to the old expected tick time. */ - next_tick = cpuinfo->it_value; - - /* Calculate how many ticks have elapsed. */ - now = mfctl(16); - do { - ++ticks_elapsed; - next_tick += cpt; - } while (next_tick - now > cpt); - - /* Store (in CR16 cycles) up to when we are accounting right now. */ - cpuinfo->it_value = next_tick; - - /* Go do system house keeping. */ - if (IS_ENABLED(CONFIG_SMP) && (cpu != time_keeper_id)) - ticks_elapsed = 0; - legacy_timer_tick(ticks_elapsed); - - /* Skip clockticks on purpose if we know we would miss those. - * The new CR16 must be "later" than current CR16 otherwise - * itimer would not fire until CR16 wrapped - e.g 4 seconds - * later on a 1Ghz processor. We'll account for the missed - * ticks on the next timer interrupt. - * We want IT to fire modulo clocktick even if we miss/skip some. - * But those interrupts don't in fact get delivered that regularly. - * - * "next_tick - now" will always give the difference regardless - * if one or the other wrapped. If "now" is "bigger" we'll end up - * with a very large unsigned number. - */ - now = mfctl(16); - while (next_tick - now > cpt) - next_tick += cpt; - - /* Program the IT when to deliver the next interrupt. - * Only bottom 32-bits of next_tick are writable in CR16! - * Timer interrupt will be delivered at least a few hundred cycles - * after the IT fires, so if we are too close (<= 8000 cycles) to the - * next cycle, simply skip it. - */ - if (next_tick - now <= 8000) - next_tick += cpt; - mtctl(next_tick, 16); + unsigned long new_cr16; - return IRQ_HANDLED; -} + new_cr16 = mfctl(16) + delta; + mtctl(new_cr16, 16); + return 0; +} -unsigned long profile_pc(struct pt_regs *regs) +irqreturn_t timer_interrupt(int irq, void *data) { - unsigned long pc = instruction_pointer(regs); + struct clock_event_device *cd; + int cpu = smp_processor_id(); - if (regs->gr[0] & PSW_N) - pc -= 4; + cd = &per_cpu(parisc_clockevent_device, cpu); -#ifdef CONFIG_SMP - if (in_lock_functions(pc)) - pc = regs->gr[2]; -#endif + if (clockevent_state_periodic(cd)) + parisc_timer_next_event(clocktick, cd); - return pc; + if (clockevent_state_periodic(cd) || clockevent_state_oneshot(cd)) + cd->event_handler(cd); + + return IRQ_HANDLED; } -EXPORT_SYMBOL(profile_pc); +static int parisc_set_state_oneshot(struct clock_event_device *evt) +{ + parisc_timer_next_event(clocktick, evt); -/* clock source code */ + return 0; +} -static u64 notrace read_cr16(struct clocksource *cs) +static int parisc_set_state_periodic(struct clock_event_device *evt) { - return get_cycles(); + parisc_timer_next_event(clocktick, evt); + + return 0; } -static struct clocksource clocksource_cr16 = { - .name = "cr16", - .rating = 300, - .read = read_cr16, - .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; +static int parisc_set_state_shutdown(struct clock_event_device *evt) +{ + return 0; +} -void start_cpu_itimer(void) +void parisc_clockevent_init(void) { unsigned int cpu = smp_processor_id(); - unsigned long next_tick = mfctl(16) + clocktick; + unsigned long min_delta = 0x600; /* XXX */ + unsigned long max_delta = (1UL << (BITS_PER_LONG - 1)); + struct clock_event_device *cd; + + cd = &per_cpu(parisc_clockevent_device, cpu); + + cd->name = "cr16_clockevent"; + cd->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_PERCPU; + + cd->irq = TIMER_IRQ; + cd->rating = 320; + cd->cpumask = cpumask_of(cpu); + cd->set_state_oneshot = parisc_set_state_oneshot; + cd->set_state_oneshot_stopped = parisc_set_state_shutdown; + cd->set_state_periodic = parisc_set_state_periodic; + cd->set_state_shutdown = parisc_set_state_shutdown; + cd->set_next_event = parisc_timer_next_event; + cd->event_handler = parisc_event_handler; + + clockevents_config_and_register(cd, cr16_clock_freq, min_delta, max_delta); +} + +unsigned long notrace profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); - mtctl(next_tick, 16); /* kick off Interval Timer (CR16) */ + if (regs->gr[0] & PSW_N) + pc -= 4; + +#ifdef CONFIG_SMP + if (in_lock_functions(pc)) + pc = regs->gr[2]; +#endif - per_cpu(cpu_data, cpu).it_value = next_tick; + return pc; } +EXPORT_SYMBOL(profile_pc); #if IS_ENABLED(CONFIG_RTC_DRV_GENERIC) static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm) @@ -224,12 +177,27 @@ void read_persistent_clock64(struct timespec64 *ts) } } - static u64 notrace read_cr16_sched_clock(void) { return get_cycles(); } +static u64 notrace read_cr16(struct clocksource *cs) +{ + return get_cycles(); +} + +static struct clocksource clocksource_cr16 = { + .name = "cr16", + .rating = 300, + .read = read_cr16, + .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), + .flags = CLOCK_SOURCE_IS_CONTINUOUS | + CLOCK_SOURCE_VALID_FOR_HRES | + CLOCK_SOURCE_MUST_VERIFY | + CLOCK_SOURCE_VERIFY_PERCPU, +}; + /* * timer interrupt and sched_clock() initialization @@ -237,33 +205,14 @@ static u64 notrace read_cr16_sched_clock(void) void __init time_init(void) { - unsigned long cr16_hz; - - clocktick = (100 * PAGE0->mem_10msec) / HZ; - start_cpu_itimer(); /* get CPU 0 started */ - - cr16_hz = 100 * PAGE0->mem_10msec; /* Hz */ + cr16_clock_freq = 100 * PAGE0->mem_10msec; /* Hz */ + clocktick = cr16_clock_freq / HZ; /* register as sched_clock source */ - sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz); -} + sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_clock_freq); -static int __init init_cr16_clocksource(void) -{ - /* - * The cr16 interval timers are not synchronized across CPUs. - */ - if (num_online_cpus() > 1 && !running_on_qemu) { - clocksource_cr16.name = "cr16_unstable"; - clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; - clocksource_cr16.rating = 0; - } + parisc_clockevent_init(); /* register at clocksource framework */ - clocksource_register_hz(&clocksource_cr16, - 100 * PAGE0->mem_10msec); - - return 0; + clocksource_register_hz(&clocksource_cr16, cr16_clock_freq); } - -device_initcall(init_cr16_clocksource); diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 1107ca819ac8..b9b3d527bc90 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -36,7 +36,7 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/traps.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/atomic.h> #include <asm/smp.h> #include <asm/pdc.h> @@ -47,6 +47,8 @@ #include <linux/kgdb.h> #include <linux/kprobes.h> +#include "unaligned.h" + #if defined(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK) #include <asm/spinlock.h> #endif @@ -504,7 +506,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) if (((unsigned long)regs->iaoq[0] & 3) && ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) { /* Kill the user process later */ - regs->iaoq[0] = 0 | 3; + regs->iaoq[0] = 0 | PRIV_USER; regs->iaoq[1] = regs->iaoq[0] + 4; regs->iasq[0] = regs->iasq[1] = regs->sr[7]; regs->gr[0] &= ~PSW_B; diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index 3e79e40e361d..f4626943633a 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -12,9 +12,10 @@ #include <linux/ratelimit.h> #include <linux/uaccess.h> #include <linux/sysctl.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/hardirq.h> #include <asm/traps.h> +#include "unaligned.h" /* #define DEBUG_UNALIGNED 1 */ diff --git a/arch/parisc/kernel/unaligned.h b/arch/parisc/kernel/unaligned.h new file mode 100644 index 000000000000..c1aa4b12e284 --- /dev/null +++ b/arch/parisc/kernel/unaligned.h @@ -0,0 +1,3 @@ +struct pt_regs; +void handle_unaligned(struct pt_regs *regs); +int check_unaligned(struct pt_regs *regs); diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c index 0356199bd9e7..aa664f7ddb63 100644 --- a/arch/parisc/mm/hugetlbpage.c +++ b/arch/parisc/mm/hugetlbpage.c @@ -40,7 +40,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, addr = ALIGN(addr, huge_page_size(h)); /* we need to make sure the colouring is OK */ - return arch_get_unmapped_area(file, addr, len, pgoff, flags); + return arch_get_unmapped_area(file, addr, len, pgoff, flags, 0); } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 34d91cb8b259..96970fa75e4a 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -459,7 +459,6 @@ void free_initmem(void) unsigned long kernel_end = (unsigned long)&_end; /* Remap kernel text and data, but do not touch init section yet. */ - kernel_set_to_readonly = true; map_pages(init_end, __pa(init_end), kernel_end - init_end, PAGE_KERNEL, 0); @@ -493,11 +492,18 @@ void free_initmem(void) #ifdef CONFIG_STRICT_KERNEL_RWX void mark_rodata_ro(void) { - /* rodata memory was already mapped with KERNEL_RO access rights by - pagetable_init() and map_pages(). No need to do additional stuff here */ - unsigned long roai_size = __end_ro_after_init - __start_ro_after_init; + unsigned long start = (unsigned long) &__start_rodata; + unsigned long end = (unsigned long) &__end_rodata; + + pr_info("Write protecting the kernel read-only data: %luk\n", + (end - start) >> 10); + + kernel_set_to_readonly = true; + map_pages(start, __pa(start), end - start, PAGE_KERNEL, 0); - pr_info("Write protected read-only-after-init data: %luk\n", roai_size >> 10); + /* force the kernel to see the new page table entries */ + flush_cache_all(); + flush_tlb_all(); } #endif diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index d7b09b064a8a..568560671cf4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -133,6 +133,7 @@ config PPC select ARCH_HAS_DEBUG_WX if STRICT_KERNEL_RWX select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DMA_MAP_DIRECT if PPC_PSERIES + select ARCH_HAS_DMA_OPS if PPC64 select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_KCOV @@ -185,7 +186,6 @@ config PPC select CPUMASK_OFFSTACK if NR_CPUS >= 8192 select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN select DMA_OPS_BYPASS if PPC64 - select DMA_OPS if PPC64 select DYNAMIC_FTRACE if FUNCTION_TRACER select EDAC_ATOMIC_SCRUB select EDAC_SUPPORT @@ -269,6 +269,7 @@ config PPC select HAVE_PERF_EVENTS_NMI if PPC64 select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP + select HAVE_RETHOOK if KPROBES select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE select HAVE_RSEQ @@ -311,6 +312,7 @@ config PPC select SYSCTL_EXCEPTION_TRACE select THREAD_INFO_IN_TASK select TRACE_IRQFLAGS_SUPPORT + select VDSO_GETRANDOM # # Please keep this list sorted alphabetically. # @@ -682,6 +684,10 @@ config RELOCATABLE_TEST config ARCH_SUPPORTS_CRASH_DUMP def_bool PPC64 || PPC_BOOK3S_32 || PPC_85xx || (44x && !SMP) +config ARCH_DEFAULT_CRASH_DUMP + bool + default y if !PPC_BOOK3S_32 + config ARCH_SELECTS_CRASH_DUMP def_bool y depends on CRASH_DUMP @@ -853,8 +859,8 @@ config DATA_SHIFT_BOOL bool "Set custom data alignment" depends on ADVANCED_OPTIONS depends on STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE - depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX) || \ - PPC_85xx + depends on (PPC_8xx && !PIN_TLB_DATA && (!STRICT_KERNEL_RWX || !PIN_TLB_TEXT)) || \ + PPC_BOOK3S_32 || PPC_85xx help This option allows you to set the kernel data alignment. When RAM is mapped by blocks, the alignment needs to fit the size and @@ -870,9 +876,9 @@ config DATA_SHIFT range 20 24 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_85xx default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32 default 18 if (DEBUG_PAGEALLOC || KFENCE) && PPC_BOOK3S_32 - default 23 if STRICT_KERNEL_RWX && PPC_8xx - default 23 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx && PIN_TLB_DATA - default 19 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx + default 23 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_8xx && \ + (PIN_TLB_DATA || PIN_TLB_TEXT) + default 19 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_8xx default 24 if STRICT_KERNEL_RWX && PPC_85xx default PAGE_SHIFT help @@ -1026,6 +1032,10 @@ config PPC_MEM_KEYS If unsure, say y. +config ARCH_PKEY_BITS + int + default 5 + config PPC_SECURE_BOOT prompt "Enable secure boot support" bool @@ -1269,10 +1279,37 @@ config TASK_SIZE_BOOL config TASK_SIZE hex "Size of user task space" if TASK_SIZE_BOOL default "0x80000000" if PPC_8xx - default "0xb0000000" if PPC_BOOK3S_32 + default "0xb0000000" if PPC_BOOK3S_32 && EXECMEM default "0xc0000000" + +config MODULES_SIZE_BOOL + bool "Set custom size for modules/execmem area" + depends on EXECMEM && ADVANCED_OPTIONS + help + This option allows you to set the size of kernel virtual address + space dedicated for modules/execmem. + For the time being it is only for 8xx and book3s/32. Other + platform share it with vmalloc space. + + Say N here unless you know what you are doing. + +config MODULES_SIZE + int "Size of modules/execmem area (In Mbytes)" if MODULES_SIZE_BOOL + range 1 256 if EXECMEM + default 64 if EXECMEM && PPC_BOOK3S_32 + default 32 if EXECMEM && PPC_8xx + default 0 + endmenu +config PPC64_PROC_SYSTEMCFG + def_bool y + depends on PPC64 && PROC_FS + help + This option enables the presence of /proc/ppc64/systemcfg through + which the systemcfg page can be accessed. + This interface only exists for backwards-compatibility. + if PPC64 # This value must have zeroes in the bottom 60 bits otherwise lots will break config PAGE_OFFSET diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 3799ceceb04a..0bbec4afc0d5 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -379,12 +379,6 @@ config FAIL_IOMMU If you are unsure, say N. -config PPC_FAST_ENDIAN_SWITCH - bool "Deprecated fast endian-switch syscall" - depends on DEBUG_KERNEL && PPC_BOOK3S_64 - help - If you're unsure what this is, say N. - config KASAN_SHADOW_OFFSET hex depends on KASAN diff --git a/arch/powerpc/boot/xz_config.h b/arch/powerpc/boot/xz_config.h index ebfadd39e192..9506a96ebbcc 100644 --- a/arch/powerpc/boot/xz_config.h +++ b/arch/powerpc/boot/xz_config.h @@ -50,11 +50,8 @@ static inline void put_unaligned_be32(u32 val, void *p) /* prevent the inclusion of the xz-preboot MM headers */ #define DECOMPR_MM_H #define memmove memmove -#define XZ_EXTERN static /* xz.h needs to be included directly since we need enum xz_mode */ #include "../../../include/linux/xz.h" -#undef XZ_EXTERN - #endif diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 544a65fda77b..a5e3e7f97f4d 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -81,7 +81,6 @@ CONFIG_MODULE_SIG_SHA512=y CONFIG_PARTITION_ADVANCED=y CONFIG_BINFMT_MISC=m CONFIG_ZSWAP=y -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_SLAB_MERGE_DEFAULT is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -93,6 +92,7 @@ CONFIG_MEMORY_HOTREMOVE=y CONFIG_KSM=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_MEM_SOFT_DIRTY=y +CONFIG_DEFERRED_STRUCT_PAGE_INIT=y CONFIG_ZONE_DEVICE=y CONFIG_NET=y CONFIG_PACKET=y diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig index 09ebcbdfb34f..951a43726461 100644 --- a/arch/powerpc/crypto/Kconfig +++ b/arch/powerpc/crypto/Kconfig @@ -112,6 +112,7 @@ config CRYPTO_AES_GCM_P10 select CRYPTO_ALGAPI select CRYPTO_AEAD select CRYPTO_SKCIPHER + select CRYPTO_SIMD help AEAD cipher: AES cipher algorithms (FIPS-197) GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D) diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c index f62ee54076c0..f37b3d13fc53 100644 --- a/arch/powerpc/crypto/aes-gcm-p10-glue.c +++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c @@ -5,9 +5,10 @@ * Copyright 2022- IBM Inc. All rights reserved */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/simd.h> #include <asm/switch_to.h> +#include <crypto/gcm.h> #include <crypto/aes.h> #include <crypto/algapi.h> #include <crypto/b128ops.h> @@ -24,6 +25,7 @@ #define PPC_ALIGN 16 #define GCM_IV_SIZE 12 +#define RFC4106_NONCE_SIZE 4 MODULE_DESCRIPTION("PPC64le AES-GCM with Stitched implementation"); MODULE_AUTHOR("Danny Tsen <dtsen@linux.ibm.com"); @@ -31,7 +33,7 @@ MODULE_LICENSE("GPL v2"); MODULE_ALIAS_CRYPTO("aes"); asmlinkage int aes_p10_set_encrypt_key(const u8 *userKey, const int bits, - void *key); + void *key); asmlinkage void aes_p10_encrypt(const u8 *in, u8 *out, const void *key); asmlinkage void aes_p10_gcm_encrypt(u8 *in, u8 *out, size_t len, void *rkey, u8 *iv, void *Xi); @@ -39,7 +41,8 @@ asmlinkage void aes_p10_gcm_decrypt(u8 *in, u8 *out, size_t len, void *rkey, u8 *iv, void *Xi); asmlinkage void gcm_init_htable(unsigned char htable[], unsigned char Xi[]); asmlinkage void gcm_ghash_p10(unsigned char *Xi, unsigned char *Htable, - unsigned char *aad, unsigned int alen); + unsigned char *aad, unsigned int alen); +asmlinkage void gcm_update(u8 *iv, void *Xi); struct aes_key { u8 key[AES_MAX_KEYLENGTH]; @@ -52,6 +55,7 @@ struct gcm_ctx { u8 aad_hash[16]; u64 aadLen; u64 Plen; /* offset 56 - used in aes_p10_gcm_{en/de}crypt */ + u8 pblock[16]; }; struct Hash_ctx { u8 H[16]; /* subkey */ @@ -60,17 +64,20 @@ struct Hash_ctx { struct p10_aes_gcm_ctx { struct aes_key enc_key; + u8 nonce[RFC4106_NONCE_SIZE]; }; static void vsx_begin(void) { preempt_disable(); + pagefault_disable(); enable_kernel_vsx(); } static void vsx_end(void) { disable_kernel_vsx(); + pagefault_enable(); preempt_enable(); } @@ -185,7 +192,7 @@ static int set_authsize(struct crypto_aead *tfm, unsigned int authsize) } static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, - unsigned int keylen) + unsigned int keylen) { struct crypto_tfm *tfm = crypto_aead_tfm(aead); struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm); @@ -198,7 +205,8 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, return ret ? -EINVAL : 0; } -static int p10_aes_gcm_crypt(struct aead_request *req, int enc) +static int p10_aes_gcm_crypt(struct aead_request *req, u8 *riv, + int assoclen, int enc) { struct crypto_tfm *tfm = req->base.tfm; struct p10_aes_gcm_ctx *ctx = crypto_tfm_ctx(tfm); @@ -210,7 +218,6 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) struct skcipher_walk walk; u8 *assocmem = NULL; u8 *assoc; - unsigned int assoclen = req->assoclen; unsigned int cryptlen = req->cryptlen; unsigned char ivbuf[AES_BLOCK_SIZE+PPC_ALIGN]; unsigned char *iv = PTR_ALIGN((void *)ivbuf, PPC_ALIGN); @@ -218,11 +225,12 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) unsigned long auth_tag_len = crypto_aead_authsize(__crypto_aead_cast(tfm)); u8 otag[16]; int total_processed = 0; + int nbytes; memset(databuf, 0, sizeof(databuf)); memset(hashbuf, 0, sizeof(hashbuf)); memset(ivbuf, 0, sizeof(ivbuf)); - memcpy(iv, req->iv, GCM_IV_SIZE); + memcpy(iv, riv, GCM_IV_SIZE); /* Linearize assoc, if not already linear */ if (req->src->length >= assoclen && req->src->length) { @@ -257,19 +265,25 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) if (ret) return ret; - while (walk.nbytes > 0 && ret == 0) { + while ((nbytes = walk.nbytes) > 0 && ret == 0) { + u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + u8 buf[AES_BLOCK_SIZE]; + + if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE)) + src = dst = memcpy(buf, src, nbytes); vsx_begin(); if (enc) - aes_p10_gcm_encrypt(walk.src.virt.addr, - walk.dst.virt.addr, - walk.nbytes, + aes_p10_gcm_encrypt(src, dst, nbytes, &ctx->enc_key, gctx->iv, hash->Htable); else - aes_p10_gcm_decrypt(walk.src.virt.addr, - walk.dst.virt.addr, - walk.nbytes, + aes_p10_gcm_decrypt(src, dst, nbytes, &ctx->enc_key, gctx->iv, hash->Htable); + + if (unlikely(nbytes > 0 && nbytes < AES_BLOCK_SIZE)) + memcpy(walk.dst.virt.addr, buf, nbytes); + vsx_end(); total_processed += walk.nbytes; @@ -281,6 +295,7 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) /* Finalize hash */ vsx_begin(); + gcm_update(gctx->iv, hash->Htable); finish_tag(gctx, hash, total_processed); vsx_end(); @@ -302,17 +317,63 @@ static int p10_aes_gcm_crypt(struct aead_request *req, int enc) return 0; } +static int rfc4106_setkey(struct crypto_aead *tfm, const u8 *inkey, + unsigned int keylen) +{ + struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(tfm); + int err; + + keylen -= RFC4106_NONCE_SIZE; + err = p10_aes_gcm_setkey(tfm, inkey, keylen); + if (err) + return err; + + memcpy(ctx->nonce, inkey + keylen, RFC4106_NONCE_SIZE); + return 0; +} + +static int rfc4106_setauthsize(struct crypto_aead *tfm, unsigned int authsize) +{ + return crypto_rfc4106_check_authsize(authsize); +} + +static int rfc4106_encrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead); + u8 iv[AES_BLOCK_SIZE]; + + memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE); + memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE); + + return crypto_ipsec_check_assoclen(req->assoclen) ?: + p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 1); +} + +static int rfc4106_decrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct p10_aes_gcm_ctx *ctx = crypto_aead_ctx(aead); + u8 iv[AES_BLOCK_SIZE]; + + memcpy(iv, ctx->nonce, RFC4106_NONCE_SIZE); + memcpy(iv + RFC4106_NONCE_SIZE, req->iv, GCM_RFC4106_IV_SIZE); + + return crypto_ipsec_check_assoclen(req->assoclen) ?: + p10_aes_gcm_crypt(req, iv, req->assoclen - GCM_RFC4106_IV_SIZE, 0); +} + static int p10_aes_gcm_encrypt(struct aead_request *req) { - return p10_aes_gcm_crypt(req, 1); + return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 1); } static int p10_aes_gcm_decrypt(struct aead_request *req) { - return p10_aes_gcm_crypt(req, 0); + return p10_aes_gcm_crypt(req, req->iv, req->assoclen, 0); } -static struct aead_alg gcm_aes_alg = { +static struct aead_alg gcm_aes_algs[] = {{ .ivsize = GCM_IV_SIZE, .maxauthsize = 16, @@ -321,23 +382,57 @@ static struct aead_alg gcm_aes_alg = { .encrypt = p10_aes_gcm_encrypt, .decrypt = p10_aes_gcm_decrypt, - .base.cra_name = "gcm(aes)", - .base.cra_driver_name = "aes_gcm_p10", + .base.cra_name = "__gcm(aes)", + .base.cra_driver_name = "__aes_gcm_p10", .base.cra_priority = 2100, .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx), + .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx)+ + 4 * sizeof(u64[2]), .base.cra_module = THIS_MODULE, -}; + .base.cra_flags = CRYPTO_ALG_INTERNAL, +}, { + .ivsize = GCM_RFC4106_IV_SIZE, + .maxauthsize = 16, + .setkey = rfc4106_setkey, + .setauthsize = rfc4106_setauthsize, + .encrypt = rfc4106_encrypt, + .decrypt = rfc4106_decrypt, + + .base.cra_name = "__rfc4106(gcm(aes))", + .base.cra_driver_name = "__rfc4106_aes_gcm_p10", + .base.cra_priority = 2100, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct p10_aes_gcm_ctx) + + 4 * sizeof(u64[2]), + .base.cra_module = THIS_MODULE, + .base.cra_flags = CRYPTO_ALG_INTERNAL, +}}; + +static struct simd_aead_alg *p10_simd_aeads[ARRAY_SIZE(gcm_aes_algs)]; static int __init p10_init(void) { - return crypto_register_aead(&gcm_aes_alg); + int ret; + + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return 0; + + ret = simd_register_aeads_compat(gcm_aes_algs, + ARRAY_SIZE(gcm_aes_algs), + p10_simd_aeads); + if (ret) { + simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs), + p10_simd_aeads); + return ret; + } + return 0; } static void __exit p10_exit(void) { - crypto_unregister_aead(&gcm_aes_alg); + simd_unregister_aeads(gcm_aes_algs, ARRAY_SIZE(gcm_aes_algs), + p10_simd_aeads); } -module_cpu_feature_match(PPC_MODULE_FEATURE_P10, p10_init); +module_init(p10_init); module_exit(p10_exit); diff --git a/arch/powerpc/crypto/aes-gcm-p10.S b/arch/powerpc/crypto/aes-gcm-p10.S index a51f4b265308..89f50eef3512 100644 --- a/arch/powerpc/crypto/aes-gcm-p10.S +++ b/arch/powerpc/crypto/aes-gcm-p10.S @@ -1,42 +1,42 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ - # - # Accelerated AES-GCM stitched implementation for ppc64le. - # - # Copyright 2022- IBM Inc. All rights reserved - # - #=================================================================================== - # Written by Danny Tsen <dtsen@linux.ibm.com> - # - # GHASH is based on the Karatsuba multiplication method. - # - # Xi xor X1 - # - # X1 * H^4 + X2 * H^3 + x3 * H^2 + X4 * H = - # (X1.h * H4.h + xX.l * H4.l + X1 * H4) + - # (X2.h * H3.h + X2.l * H3.l + X2 * H3) + - # (X3.h * H2.h + X3.l * H2.l + X3 * H2) + - # (X4.h * H.h + X4.l * H.l + X4 * H) - # - # Xi = v0 - # H Poly = v2 - # Hash keys = v3 - v14 - # ( H.l, H, H.h) - # ( H^2.l, H^2, H^2.h) - # ( H^3.l, H^3, H^3.h) - # ( H^4.l, H^4, H^4.h) - # - # v30 is IV - # v31 - counter 1 - # - # AES used, - # vs0 - vs14 for round keys - # v15, v16, v17, v18, v19, v20, v21, v22 for 8 blocks (encrypted) - # - # This implementation uses stitched AES-GCM approach to improve overall performance. - # AES is implemented with 8x blocks and GHASH is using 2 4x blocks. - # - # =================================================================================== - # +# +# Accelerated AES-GCM stitched implementation for ppc64le. +# +# Copyright 2024- IBM Inc. +# +#=================================================================================== +# Written by Danny Tsen <dtsen@us.ibm.com> +# +# GHASH is based on the Karatsuba multiplication method. +# +# Xi xor X1 +# +# X1 * H^4 + X2 * H^3 + x3 * H^2 + X4 * H = +# (X1.h * H4.h + xX.l * H4.l + X1 * H4) + +# (X2.h * H3.h + X2.l * H3.l + X2 * H3) + +# (X3.h * H2.h + X3.l * H2.l + X3 * H2) + +# (X4.h * H.h + X4.l * H.l + X4 * H) +# +# Xi = v0 +# H Poly = v2 +# Hash keys = v3 - v14 +# ( H.l, H, H.h) +# ( H^2.l, H^2, H^2.h) +# ( H^3.l, H^3, H^3.h) +# ( H^4.l, H^4, H^4.h) +# +# v30 is IV +# v31 - counter 1 +# +# AES used, +# vs0 - round key 0 +# v15, v16, v17, v18, v19, v20, v21, v22 for 8 blocks (encrypted) +# +# This implementation uses stitched AES-GCM approach to improve overall performance. +# AES is implemented with 8x blocks and GHASH is using 2 4x blocks. +# +# =================================================================================== +# #include <asm/ppc_asm.h> #include <linux/linkage.h> @@ -44,483 +44,224 @@ .machine "any" .text - # 4x loops - # v15 - v18 - input states - # vs1 - vs9 - round keys - # -.macro Loop_aes_middle4x - xxlor 19+32, 1, 1 - xxlor 20+32, 2, 2 - xxlor 21+32, 3, 3 - xxlor 22+32, 4, 4 - - vcipher 15, 15, 19 - vcipher 16, 16, 19 - vcipher 17, 17, 19 - vcipher 18, 18, 19 - - vcipher 15, 15, 20 - vcipher 16, 16, 20 - vcipher 17, 17, 20 - vcipher 18, 18, 20 - - vcipher 15, 15, 21 - vcipher 16, 16, 21 - vcipher 17, 17, 21 - vcipher 18, 18, 21 - - vcipher 15, 15, 22 - vcipher 16, 16, 22 - vcipher 17, 17, 22 - vcipher 18, 18, 22 - - xxlor 19+32, 5, 5 - xxlor 20+32, 6, 6 - xxlor 21+32, 7, 7 - xxlor 22+32, 8, 8 - - vcipher 15, 15, 19 - vcipher 16, 16, 19 - vcipher 17, 17, 19 - vcipher 18, 18, 19 - - vcipher 15, 15, 20 - vcipher 16, 16, 20 - vcipher 17, 17, 20 - vcipher 18, 18, 20 - - vcipher 15, 15, 21 - vcipher 16, 16, 21 - vcipher 17, 17, 21 - vcipher 18, 18, 21 - - vcipher 15, 15, 22 - vcipher 16, 16, 22 - vcipher 17, 17, 22 - vcipher 18, 18, 22 - - xxlor 23+32, 9, 9 - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 +.macro SAVE_GPR GPR OFFSET FRAME + std \GPR,\OFFSET(\FRAME) .endm - # 8x loops - # v15 - v22 - input states - # vs1 - vs9 - round keys - # -.macro Loop_aes_middle8x - xxlor 23+32, 1, 1 - xxlor 24+32, 2, 2 - xxlor 25+32, 3, 3 - xxlor 26+32, 4, 4 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - vcipher 15, 15, 25 - vcipher 16, 16, 25 - vcipher 17, 17, 25 - vcipher 18, 18, 25 - vcipher 19, 19, 25 - vcipher 20, 20, 25 - vcipher 21, 21, 25 - vcipher 22, 22, 25 - - vcipher 15, 15, 26 - vcipher 16, 16, 26 - vcipher 17, 17, 26 - vcipher 18, 18, 26 - vcipher 19, 19, 26 - vcipher 20, 20, 26 - vcipher 21, 21, 26 - vcipher 22, 22, 26 - - xxlor 23+32, 5, 5 - xxlor 24+32, 6, 6 - xxlor 25+32, 7, 7 - xxlor 26+32, 8, 8 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - vcipher 15, 15, 25 - vcipher 16, 16, 25 - vcipher 17, 17, 25 - vcipher 18, 18, 25 - vcipher 19, 19, 25 - vcipher 20, 20, 25 - vcipher 21, 21, 25 - vcipher 22, 22, 25 - - vcipher 15, 15, 26 - vcipher 16, 16, 26 - vcipher 17, 17, 26 - vcipher 18, 18, 26 - vcipher 19, 19, 26 - vcipher 20, 20, 26 - vcipher 21, 21, 26 - vcipher 22, 22, 26 - - xxlor 23+32, 9, 9 - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 +.macro SAVE_VRS VRS OFFSET FRAME + stxv \VRS+32, \OFFSET(\FRAME) .endm -.macro Loop_aes_middle_1x - xxlor 19+32, 1, 1 - xxlor 20+32, 2, 2 - xxlor 21+32, 3, 3 - xxlor 22+32, 4, 4 - - vcipher 15, 15, 19 - vcipher 15, 15, 20 - vcipher 15, 15, 21 - vcipher 15, 15, 22 - - xxlor 19+32, 5, 5 - xxlor 20+32, 6, 6 - xxlor 21+32, 7, 7 - xxlor 22+32, 8, 8 - - vcipher 15, 15, 19 - vcipher 15, 15, 20 - vcipher 15, 15, 21 - vcipher 15, 15, 22 - - xxlor 19+32, 9, 9 - vcipher 15, 15, 19 +.macro RESTORE_GPR GPR OFFSET FRAME + ld \GPR,\OFFSET(\FRAME) .endm - # - # Compute 4x hash values based on Karatsuba method. - # -.macro ppc_aes_gcm_ghash - vxor 15, 15, 0 - - vpmsumd 23, 12, 15 # H4.L * X.L - vpmsumd 24, 9, 16 - vpmsumd 25, 6, 17 - vpmsumd 26, 3, 18 - - vxor 23, 23, 24 - vxor 23, 23, 25 - vxor 23, 23, 26 # L - - vpmsumd 24, 13, 15 # H4.L * X.H + H4.H * X.L - vpmsumd 25, 10, 16 # H3.L * X1.H + H3.H * X1.L - vpmsumd 26, 7, 17 - vpmsumd 27, 4, 18 - - vxor 24, 24, 25 - vxor 24, 24, 26 - vxor 24, 24, 27 # M - - # sum hash and reduction with H Poly - vpmsumd 28, 23, 2 # reduction - - vxor 29, 29, 29 - vsldoi 26, 24, 29, 8 # mL - vsldoi 29, 29, 24, 8 # mH - vxor 23, 23, 26 # mL + L - - vsldoi 23, 23, 23, 8 # swap - vxor 23, 23, 28 - - vpmsumd 24, 14, 15 # H4.H * X.H - vpmsumd 25, 11, 16 - vpmsumd 26, 8, 17 - vpmsumd 27, 5, 18 - - vxor 24, 24, 25 - vxor 24, 24, 26 - vxor 24, 24, 27 - - vxor 24, 24, 29 - - # sum hash and reduction with H Poly - vsldoi 27, 23, 23, 8 # swap - vpmsumd 23, 23, 2 - vxor 27, 27, 24 - vxor 23, 23, 27 - - xxlor 32, 23+32, 23+32 # update hash - +.macro RESTORE_VRS VRS OFFSET FRAME + lxv \VRS+32, \OFFSET(\FRAME) .endm - # - # Combine two 4x ghash - # v15 - v22 - input blocks - # -.macro ppc_aes_gcm_ghash2_4x - # first 4x hash - vxor 15, 15, 0 # Xi + X - - vpmsumd 23, 12, 15 # H4.L * X.L - vpmsumd 24, 9, 16 - vpmsumd 25, 6, 17 - vpmsumd 26, 3, 18 - - vxor 23, 23, 24 - vxor 23, 23, 25 - vxor 23, 23, 26 # L - - vpmsumd 24, 13, 15 # H4.L * X.H + H4.H * X.L - vpmsumd 25, 10, 16 # H3.L * X1.H + H3.H * X1.L - vpmsumd 26, 7, 17 - vpmsumd 27, 4, 18 - - vxor 24, 24, 25 - vxor 24, 24, 26 - - # sum hash and reduction with H Poly - vpmsumd 28, 23, 2 # reduction - - vxor 29, 29, 29 - - vxor 24, 24, 27 # M - vsldoi 26, 24, 29, 8 # mL - vsldoi 29, 29, 24, 8 # mH - vxor 23, 23, 26 # mL + L - - vsldoi 23, 23, 23, 8 # swap - vxor 23, 23, 28 +.macro SAVE_REGS + mflr 0 + std 0, 16(1) + stdu 1,-512(1) + + SAVE_GPR 14, 112, 1 + SAVE_GPR 15, 120, 1 + SAVE_GPR 16, 128, 1 + SAVE_GPR 17, 136, 1 + SAVE_GPR 18, 144, 1 + SAVE_GPR 19, 152, 1 + SAVE_GPR 20, 160, 1 + SAVE_GPR 21, 168, 1 + SAVE_GPR 22, 176, 1 + SAVE_GPR 23, 184, 1 + SAVE_GPR 24, 192, 1 + + addi 9, 1, 256 + SAVE_VRS 20, 0, 9 + SAVE_VRS 21, 16, 9 + SAVE_VRS 22, 32, 9 + SAVE_VRS 23, 48, 9 + SAVE_VRS 24, 64, 9 + SAVE_VRS 25, 80, 9 + SAVE_VRS 26, 96, 9 + SAVE_VRS 27, 112, 9 + SAVE_VRS 28, 128, 9 + SAVE_VRS 29, 144, 9 + SAVE_VRS 30, 160, 9 + SAVE_VRS 31, 176, 9 +.endm # SAVE_REGS - vpmsumd 24, 14, 15 # H4.H * X.H - vpmsumd 25, 11, 16 - vpmsumd 26, 8, 17 - vpmsumd 27, 5, 18 +.macro RESTORE_REGS + addi 9, 1, 256 + RESTORE_VRS 20, 0, 9 + RESTORE_VRS 21, 16, 9 + RESTORE_VRS 22, 32, 9 + RESTORE_VRS 23, 48, 9 + RESTORE_VRS 24, 64, 9 + RESTORE_VRS 25, 80, 9 + RESTORE_VRS 26, 96, 9 + RESTORE_VRS 27, 112, 9 + RESTORE_VRS 28, 128, 9 + RESTORE_VRS 29, 144, 9 + RESTORE_VRS 30, 160, 9 + RESTORE_VRS 31, 176, 9 + + RESTORE_GPR 14, 112, 1 + RESTORE_GPR 15, 120, 1 + RESTORE_GPR 16, 128, 1 + RESTORE_GPR 17, 136, 1 + RESTORE_GPR 18, 144, 1 + RESTORE_GPR 19, 152, 1 + RESTORE_GPR 20, 160, 1 + RESTORE_GPR 21, 168, 1 + RESTORE_GPR 22, 176, 1 + RESTORE_GPR 23, 184, 1 + RESTORE_GPR 24, 192, 1 + + addi 1, 1, 512 + ld 0, 16(1) + mtlr 0 +.endm # RESTORE_REGS + +# 4x loops +.macro AES_CIPHER_4x _VCIPHER ST r + \_VCIPHER \ST, \ST, \r + \_VCIPHER \ST+1, \ST+1, \r + \_VCIPHER \ST+2, \ST+2, \r + \_VCIPHER \ST+3, \ST+3, \r +.endm - vxor 24, 24, 25 - vxor 24, 24, 26 - vxor 24, 24, 27 # H +# 8x loops +.macro AES_CIPHER_8x _VCIPHER ST r + \_VCIPHER \ST, \ST, \r + \_VCIPHER \ST+1, \ST+1, \r + \_VCIPHER \ST+2, \ST+2, \r + \_VCIPHER \ST+3, \ST+3, \r + \_VCIPHER \ST+4, \ST+4, \r + \_VCIPHER \ST+5, \ST+5, \r + \_VCIPHER \ST+6, \ST+6, \r + \_VCIPHER \ST+7, \ST+7, \r +.endm - vxor 24, 24, 29 # H + mH +.macro LOOP_8AES_STATE + xxlor 32+23, 1, 1 + xxlor 32+24, 2, 2 + xxlor 32+25, 3, 3 + xxlor 32+26, 4, 4 + AES_CIPHER_8x vcipher, 15, 23 + AES_CIPHER_8x vcipher, 15, 24 + AES_CIPHER_8x vcipher, 15, 25 + AES_CIPHER_8x vcipher, 15, 26 + xxlor 32+23, 5, 5 + xxlor 32+24, 6, 6 + xxlor 32+25, 7, 7 + xxlor 32+26, 8, 8 + AES_CIPHER_8x vcipher, 15, 23 + AES_CIPHER_8x vcipher, 15, 24 + AES_CIPHER_8x vcipher, 15, 25 + AES_CIPHER_8x vcipher, 15, 26 +.endm - # sum hash and reduction with H Poly - vsldoi 27, 23, 23, 8 # swap - vpmsumd 23, 23, 2 - vxor 27, 27, 24 - vxor 27, 23, 27 # 1st Xi - - # 2nd 4x hash - vpmsumd 24, 9, 20 - vpmsumd 25, 6, 21 - vpmsumd 26, 3, 22 - vxor 19, 19, 27 # Xi + X - vpmsumd 23, 12, 19 # H4.L * X.L - - vxor 23, 23, 24 - vxor 23, 23, 25 - vxor 23, 23, 26 # L - - vpmsumd 24, 13, 19 # H4.L * X.H + H4.H * X.L - vpmsumd 25, 10, 20 # H3.L * X1.H + H3.H * X1.L - vpmsumd 26, 7, 21 - vpmsumd 27, 4, 22 - - vxor 24, 24, 25 - vxor 24, 24, 26 +# +# PPC_GHASH4x(H, S1, S2, S3, S4): Compute 4x hash values based on Karatsuba method. +# H: returning digest +# S#: states +# +# S1 should xor with the previous digest +# +# Xi = v0 +# H Poly = v2 +# Hash keys = v3 - v14 +# Scratch: v23 - v29 +# +.macro PPC_GHASH4x H S1 S2 S3 S4 + + vpmsumd 23, 12, \S1 # H4.L * X.L + vpmsumd 24, 9, \S2 + vpmsumd 25, 6, \S3 + vpmsumd 26, 3, \S4 + + vpmsumd 27, 13, \S1 # H4.L * X.H + H4.H * X.L + vpmsumd 28, 10, \S2 # H3.L * X1.H + H3.H * X1.L + + vxor 23, 23, 24 + vxor 23, 23, 25 + vxor 23, 23, 26 # L + + vxor 24, 27, 28 + vpmsumd 25, 7, \S3 + vpmsumd 26, 4, \S4 + + vxor 24, 24, 25 + vxor 24, 24, 26 # M # sum hash and reduction with H Poly - vpmsumd 28, 23, 2 # reduction - - vxor 29, 29, 29 + vpmsumd 28, 23, 2 # reduction - vxor 24, 24, 27 # M - vsldoi 26, 24, 29, 8 # mL - vsldoi 29, 29, 24, 8 # mH - vxor 23, 23, 26 # mL + L + vxor 1, 1, 1 + vsldoi 25, 24, 1, 8 # mL + vsldoi 1, 1, 24, 8 # mH + vxor 23, 23, 25 # mL + L - vsldoi 23, 23, 23, 8 # swap - vxor 23, 23, 28 + # This performs swap and xor like, + # vsldoi 23, 23, 23, 8 # swap + # vxor 23, 23, 28 + xxlor 32+25, 10, 10 + vpermxor 23, 23, 28, 25 - vpmsumd 24, 14, 19 # H4.H * X.H - vpmsumd 25, 11, 20 - vpmsumd 26, 8, 21 - vpmsumd 27, 5, 22 + vpmsumd 26, 14, \S1 # H4.H * X.H + vpmsumd 27, 11, \S2 + vpmsumd 28, 8, \S3 + vpmsumd 29, 5, \S4 - vxor 24, 24, 25 - vxor 24, 24, 26 - vxor 24, 24, 27 # H + vxor 24, 26, 27 + vxor 24, 24, 28 + vxor 24, 24, 29 - vxor 24, 24, 29 # H + mH + vxor 24, 24, 1 # sum hash and reduction with H Poly - vsldoi 27, 23, 23, 8 # swap - vpmsumd 23, 23, 2 - vxor 27, 27, 24 - vxor 23, 23, 27 - - xxlor 32, 23+32, 23+32 # update hash - + vsldoi 25, 23, 23, 8 # swap + vpmsumd 23, 23, 2 + vxor 27, 25, 24 + vxor \H, 23, 27 .endm - # - # Compute update single hash - # -.macro ppc_update_hash_1x - vxor 28, 28, 0 - - vxor 19, 19, 19 +# +# Compute update single ghash +# scratch: v1, v22..v27 +# +.macro PPC_GHASH1x H S1 - vpmsumd 22, 3, 28 # L - vpmsumd 23, 4, 28 # M - vpmsumd 24, 5, 28 # H + vxor 1, 1, 1 - vpmsumd 27, 22, 2 # reduction + vpmsumd 22, 3, \S1 # L + vpmsumd 23, 4, \S1 # M + vpmsumd 24, 5, \S1 # H - vsldoi 25, 23, 19, 8 # mL - vsldoi 26, 19, 23, 8 # mH - vxor 22, 22, 25 # LL + LL - vxor 24, 24, 26 # HH + HH + vpmsumd 27, 22, 2 # reduction - vsldoi 22, 22, 22, 8 # swap - vxor 22, 22, 27 + vsldoi 25, 23, 1, 8 # mL + vsldoi 26, 1, 23, 8 # mH + vxor 22, 22, 25 # LL + LL + vxor 24, 24, 26 # HH + HH - vsldoi 20, 22, 22, 8 # swap - vpmsumd 22, 22, 2 # reduction - vxor 20, 20, 24 - vxor 22, 22, 20 + xxlor 32+25, 10, 10 + vpermxor 22, 22, 27, 25 - vmr 0, 22 # update hash - -.endm - -.macro SAVE_REGS - stdu 1,-640(1) - mflr 0 - - std 14,112(1) - std 15,120(1) - std 16,128(1) - std 17,136(1) - std 18,144(1) - std 19,152(1) - std 20,160(1) - std 21,168(1) - li 9, 256 - stvx 20, 9, 1 - addi 9, 9, 16 - stvx 21, 9, 1 - addi 9, 9, 16 - stvx 22, 9, 1 - addi 9, 9, 16 - stvx 23, 9, 1 - addi 9, 9, 16 - stvx 24, 9, 1 - addi 9, 9, 16 - stvx 25, 9, 1 - addi 9, 9, 16 - stvx 26, 9, 1 - addi 9, 9, 16 - stvx 27, 9, 1 - addi 9, 9, 16 - stvx 28, 9, 1 - addi 9, 9, 16 - stvx 29, 9, 1 - addi 9, 9, 16 - stvx 30, 9, 1 - addi 9, 9, 16 - stvx 31, 9, 1 - stxv 14, 464(1) - stxv 15, 480(1) - stxv 16, 496(1) - stxv 17, 512(1) - stxv 18, 528(1) - stxv 19, 544(1) - stxv 20, 560(1) - stxv 21, 576(1) - stxv 22, 592(1) - std 0, 656(1) -.endm - -.macro RESTORE_REGS - lxv 14, 464(1) - lxv 15, 480(1) - lxv 16, 496(1) - lxv 17, 512(1) - lxv 18, 528(1) - lxv 19, 544(1) - lxv 20, 560(1) - lxv 21, 576(1) - lxv 22, 592(1) - li 9, 256 - lvx 20, 9, 1 - addi 9, 9, 16 - lvx 21, 9, 1 - addi 9, 9, 16 - lvx 22, 9, 1 - addi 9, 9, 16 - lvx 23, 9, 1 - addi 9, 9, 16 - lvx 24, 9, 1 - addi 9, 9, 16 - lvx 25, 9, 1 - addi 9, 9, 16 - lvx 26, 9, 1 - addi 9, 9, 16 - lvx 27, 9, 1 - addi 9, 9, 16 - lvx 28, 9, 1 - addi 9, 9, 16 - lvx 29, 9, 1 - addi 9, 9, 16 - lvx 30, 9, 1 - addi 9, 9, 16 - lvx 31, 9, 1 - - ld 0, 656(1) - ld 14,112(1) - ld 15,120(1) - ld 16,128(1) - ld 17,136(1) - ld 18,144(1) - ld 19,152(1) - ld 20,160(1) - ld 21,168(1) - - mtlr 0 - addi 1, 1, 640 + vsldoi 23, 22, 22, 8 # swap + vpmsumd 22, 22, 2 # reduction + vxor 23, 23, 24 + vxor \H, 22, 23 .endm +# +# LOAD_HASH_TABLE +# Xi = v0 +# H Poly = v2 +# Hash keys = v3 - v14 +# .macro LOAD_HASH_TABLE # Load Xi lxvb16x 32, 0, 8 # load Xi @@ -557,657 +298,434 @@ lxvd2x 14+32, 10, 8 # H^4h .endm - # - # aes_p10_gcm_encrypt (const void *inp, void *out, size_t len, - # const char *rk, unsigned char iv[16], void *Xip); - # - # r3 - inp - # r4 - out - # r5 - len - # r6 - AES round keys - # r7 - iv and other data - # r8 - Xi, HPoli, hash keys - # - # rounds is at offset 240 in rk - # Xi is at 0 in gcm_table (Xip). - # -_GLOBAL(aes_p10_gcm_encrypt) -.align 5 - - SAVE_REGS - - LOAD_HASH_TABLE - - # initialize ICB: GHASH( IV ), IV - r7 - lxvb16x 30+32, 0, 7 # load IV - v30 - - mr 12, 5 # length - li 11, 0 # block index - - # counter 1 - vxor 31, 31, 31 - vspltisb 22, 1 - vsldoi 31, 31, 22,1 # counter 1 - - # load round key to VSR - lxv 0, 0(6) - lxv 1, 0x10(6) - lxv 2, 0x20(6) - lxv 3, 0x30(6) - lxv 4, 0x40(6) - lxv 5, 0x50(6) - lxv 6, 0x60(6) - lxv 7, 0x70(6) - lxv 8, 0x80(6) - lxv 9, 0x90(6) - lxv 10, 0xa0(6) - - # load rounds - 10 (128), 12 (192), 14 (256) - lwz 9,240(6) - - # - # vxor state, state, w # addroundkey - xxlor 32+29, 0, 0 - vxor 15, 30, 29 # IV + round key - add round key 0 - - cmpdi 9, 10 - beq Loop_aes_gcm_8x - - # load 2 more round keys (v11, v12) - lxv 11, 0xb0(6) - lxv 12, 0xc0(6) - - cmpdi 9, 12 - beq Loop_aes_gcm_8x - - # load 2 more round keys (v11, v12, v13, v14) - lxv 13, 0xd0(6) - lxv 14, 0xe0(6) - cmpdi 9, 14 - beq Loop_aes_gcm_8x - - b aes_gcm_out - -.align 5 -Loop_aes_gcm_8x: - mr 14, 3 - mr 9, 4 - - # - # check partial block - # -Continue_partial_check: - ld 15, 56(7) - cmpdi 15, 0 - beq Continue - bgt Final_block - cmpdi 15, 16 - blt Final_block - -Continue: - # n blcoks - li 10, 128 - divdu 10, 12, 10 # n 128 bytes-blocks - cmpdi 10, 0 - beq Loop_last_block - - vaddudm 30, 30, 31 # IV + counter - vxor 16, 30, 29 - vaddudm 30, 30, 31 - vxor 17, 30, 29 - vaddudm 30, 30, 31 - vxor 18, 30, 29 - vaddudm 30, 30, 31 - vxor 19, 30, 29 - vaddudm 30, 30, 31 - vxor 20, 30, 29 - vaddudm 30, 30, 31 - vxor 21, 30, 29 - vaddudm 30, 30, 31 - vxor 22, 30, 29 - - mtctr 10 - - li 15, 16 - li 16, 32 - li 17, 48 - li 18, 64 - li 19, 80 - li 20, 96 - li 21, 112 - - lwz 10, 240(6) - -Loop_8x_block: - - lxvb16x 15, 0, 14 # load block - lxvb16x 16, 15, 14 # load block - lxvb16x 17, 16, 14 # load block - lxvb16x 18, 17, 14 # load block - lxvb16x 19, 18, 14 # load block - lxvb16x 20, 19, 14 # load block - lxvb16x 21, 20, 14 # load block - lxvb16x 22, 21, 14 # load block - addi 14, 14, 128 - - Loop_aes_middle8x - - xxlor 23+32, 10, 10 - - cmpdi 10, 10 - beq Do_next_ghash - - # 192 bits - xxlor 24+32, 11, 11 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - xxlor 23+32, 12, 12 - - cmpdi 10, 12 - beq Do_next_ghash - - # 256 bits - xxlor 24+32, 13, 13 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - xxlor 23+32, 14, 14 - - cmpdi 10, 14 - beq Do_next_ghash - b aes_gcm_out - -Do_next_ghash: - - # - # last round - vcipherlast 15, 15, 23 - vcipherlast 16, 16, 23 - - xxlxor 47, 47, 15 - stxvb16x 47, 0, 9 # store output - xxlxor 48, 48, 16 - stxvb16x 48, 15, 9 # store output - - vcipherlast 17, 17, 23 - vcipherlast 18, 18, 23 - - xxlxor 49, 49, 17 - stxvb16x 49, 16, 9 # store output - xxlxor 50, 50, 18 - stxvb16x 50, 17, 9 # store output - - vcipherlast 19, 19, 23 - vcipherlast 20, 20, 23 - - xxlxor 51, 51, 19 - stxvb16x 51, 18, 9 # store output - xxlxor 52, 52, 20 - stxvb16x 52, 19, 9 # store output - - vcipherlast 21, 21, 23 - vcipherlast 22, 22, 23 - - xxlxor 53, 53, 21 - stxvb16x 53, 20, 9 # store output - xxlxor 54, 54, 22 - stxvb16x 54, 21, 9 # store output - - addi 9, 9, 128 - - # ghash here - ppc_aes_gcm_ghash2_4x - - xxlor 27+32, 0, 0 - vaddudm 30, 30, 31 # IV + counter - vmr 29, 30 - vxor 15, 30, 27 # add round key - vaddudm 30, 30, 31 - vxor 16, 30, 27 - vaddudm 30, 30, 31 - vxor 17, 30, 27 - vaddudm 30, 30, 31 - vxor 18, 30, 27 - vaddudm 30, 30, 31 - vxor 19, 30, 27 - vaddudm 30, 30, 31 - vxor 20, 30, 27 - vaddudm 30, 30, 31 - vxor 21, 30, 27 - vaddudm 30, 30, 31 - vxor 22, 30, 27 - - addi 12, 12, -128 - addi 11, 11, 128 - - bdnz Loop_8x_block - - vmr 30, 29 - stxvb16x 30+32, 0, 7 # update IV - -Loop_last_block: - cmpdi 12, 0 - beq aes_gcm_out - - # loop last few blocks +################################################################################ +# Compute AES and ghash one block at a time. +# r23: AES rounds +# v30: current IV +# vs0: roundkey 0 +# +################################################################################ +SYM_FUNC_START_LOCAL(aes_gcm_crypt_1x) + + cmpdi 5, 16 + bge __More_1x + blr +__More_1x: li 10, 16 - divdu 10, 12, 10 - - mtctr 10 - - lwz 10, 240(6) - - cmpdi 12, 16 - blt Final_block - -Next_rem_block: - lxvb16x 15, 0, 14 # load block - - Loop_aes_middle_1x - - xxlor 23+32, 10, 10 - - cmpdi 10, 10 - beq Do_next_1x - - # 192 bits - xxlor 24+32, 11, 11 - - vcipher 15, 15, 23 - vcipher 15, 15, 24 - - xxlor 23+32, 12, 12 + divdu 12, 5, 10 + + xxlxor 32+15, 32+30, 0 + + # Pre-load 8 AES rounds to scratch vectors. + xxlor 32+16, 1, 1 + xxlor 32+17, 2, 2 + xxlor 32+18, 3, 3 + xxlor 32+19, 4, 4 + xxlor 32+20, 5, 5 + xxlor 32+21, 6, 6 + xxlor 32+28, 7, 7 + xxlor 32+29, 8, 8 + lwz 23, 240(6) # n rounds + addi 22, 23, -9 # remaing AES rounds - cmpdi 10, 12 - beq Do_next_1x - - # 256 bits - xxlor 24+32, 13, 13 - - vcipher 15, 15, 23 - vcipher 15, 15, 24 - - xxlor 23+32, 14, 14 - - cmpdi 10, 14 - beq Do_next_1x - -Do_next_1x: - vcipherlast 15, 15, 23 - - xxlxor 47, 47, 15 - stxvb16x 47, 0, 9 # store output - addi 14, 14, 16 - addi 9, 9, 16 - - vmr 28, 15 - ppc_update_hash_1x - - addi 12, 12, -16 - addi 11, 11, 16 - xxlor 19+32, 0, 0 - vaddudm 30, 30, 31 # IV + counter - vxor 15, 30, 19 # add round key - - bdnz Next_rem_block - - li 15, 0 - std 15, 56(7) # clear partial? - stxvb16x 30+32, 0, 7 # update IV cmpdi 12, 0 - beq aes_gcm_out - -Final_block: - lwz 10, 240(6) - Loop_aes_middle_1x - - xxlor 23+32, 10, 10 - - cmpdi 10, 10 - beq Do_final_1x - - # 192 bits - xxlor 24+32, 11, 11 - - vcipher 15, 15, 23 - vcipher 15, 15, 24 - - xxlor 23+32, 12, 12 - - cmpdi 10, 12 - beq Do_final_1x - - # 256 bits - xxlor 24+32, 13, 13 - - vcipher 15, 15, 23 - vcipher 15, 15, 24 + bgt __Loop_1x + blr - xxlor 23+32, 14, 14 +__Loop_1x: + mtctr 22 + addi 10, 6, 144 + vcipher 15, 15, 16 + vcipher 15, 15, 17 + vcipher 15, 15, 18 + vcipher 15, 15, 19 + vcipher 15, 15, 20 + vcipher 15, 15, 21 + vcipher 15, 15, 28 + vcipher 15, 15, 29 - cmpdi 10, 14 - beq Do_final_1x +__Loop_aes_1state: + lxv 32+1, 0(10) + vcipher 15, 15, 1 + addi 10, 10, 16 + bdnz __Loop_aes_1state + lxv 32+1, 0(10) # last round key + lxvb16x 11, 0, 14 # load input block + vcipherlast 15, 15, 1 + + xxlxor 32+15, 32+15, 11 + stxvb16x 32+15, 0, 9 # store output + addi 14, 14, 16 + addi 9, 9, 16 -Do_final_1x: - vcipherlast 15, 15, 23 + cmpdi 24, 0 # decrypt? + bne __Encrypt_1x + xxlor 15+32, 11, 11 +__Encrypt_1x: + vxor 15, 15, 0 + PPC_GHASH1x 0, 15 - # check partial block - li 21, 0 # encrypt - ld 15, 56(7) # partial? - cmpdi 15, 0 - beq Normal_block - bl Do_partial_block + addi 5, 5, -16 + addi 11, 11, 16 + vadduwm 30, 30, 31 # IV + counter + xxlxor 32+15, 32+30, 0 + addi 12, 12, -1 cmpdi 12, 0 - ble aes_gcm_out + bgt __Loop_1x - b Continue_partial_check - -Normal_block: - lxvb16x 15, 0, 14 # load last block - xxlxor 47, 47, 15 - - # create partial block mask - li 15, 16 - sub 15, 15, 12 # index to the mask - - vspltisb 16, -1 # first 16 bytes - 0xffff...ff - vspltisb 17, 0 # second 16 bytes - 0x0000...00 - li 10, 192 - stvx 16, 10, 1 + stxvb16x 32+30, 0, 7 # update IV + stxvb16x 32+0, 0, 8 # update Xi + blr +SYM_FUNC_END(aes_gcm_crypt_1x) + +################################################################################ +# Process a normal partial block when we come here. +# Compute partial mask, Load and store partial block to stack. +# Update partial_len and pblock. +# pblock is (encrypted ^ AES state) for encrypt +# and (input ^ AES state) for decrypt. +# +################################################################################ +SYM_FUNC_START_LOCAL(__Process_partial) + + # create partial mask + vspltisb 16, -1 + li 12, 16 + sub 12, 12, 5 + sldi 12, 12, 3 + mtvsrdd 32+17, 0, 12 + vslo 16, 16, 17 # partial block mask + + lxvb16x 11, 0, 14 # load partial block + xxland 11, 11, 32+16 + + # AES crypt partial + xxlxor 32+15, 32+30, 0 + lwz 23, 240(6) # n rounds + addi 22, 23, -1 # loop - 1 + mtctr 22 + addi 10, 6, 16 + +__Loop_aes_pstate: + lxv 32+1, 0(10) + vcipher 15, 15, 1 addi 10, 10, 16 - stvx 17, 10, 1 - - addi 10, 1, 192 - lxvb16x 16, 15, 10 # load partial block mask - xxland 47, 47, 16 - - vmr 28, 15 - ppc_update_hash_1x + bdnz __Loop_aes_pstate + lxv 32+1, 0(10) # last round key + vcipherlast 15, 15, 1 - # * should store only the remaining bytes. - bl Write_partial_block - - stxvb16x 30+32, 0, 7 # update IV - std 12, 56(7) # update partial? - li 16, 16 + xxlxor 32+15, 32+15, 11 + vand 15, 15, 16 - stxvb16x 32, 0, 8 # write out Xi - stxvb16x 32, 16, 8 # write out Xi - b aes_gcm_out - - # - # Compute data mask - # -.macro GEN_MASK _mask _start _end - vspltisb 16, -1 # first 16 bytes - 0xffff...ff - vspltisb 17, 0 # second 16 bytes - 0x0000...00 - li 10, 192 - stxvb16x 17+32, 10, 1 - add 10, 10, \_start - stxvb16x 16+32, 10, 1 - add 10, 10, \_end - stxvb16x 17+32, 10, 1 - - addi 10, 1, 192 - lxvb16x \_mask, 0, 10 # load partial block mask -.endm + # AES crypt output v15 + # Write partial + li 10, 224 + stxvb16x 15+32, 10, 1 # write v15 to stack + addi 10, 1, 223 + addi 12, 9, -1 + mtctr 5 # partial block len +__Write_partial: + lbzu 22, 1(10) + stbu 22, 1(12) + bdnz __Write_partial + + cmpdi 24, 0 # decrypt? + bne __Encrypt_partial + xxlor 32+15, 11, 11 # decrypt using the input block +__Encrypt_partial: + #vxor 15, 15, 0 # ^ previous hash + #PPC_GHASH1x 0, 15 + + add 14, 14, 5 + add 9, 9, 5 + std 5, 56(7) # update partial + sub 11, 11, 5 + li 5, 0 # done last byte - # - # Handle multiple partial blocks for encrypt and decrypt - # operations. - # -SYM_FUNC_START_LOCAL(Do_partial_block) - add 17, 15, 5 - cmpdi 17, 16 - bgt Big_block - GEN_MASK 18, 15, 5 - b _Partial -SYM_FUNC_END(Do_partial_block) -Big_block: + # + # Don't increase IV since this is the last partial. + # It should get updated in gcm_update if no more data blocks. + #vadduwm 30, 30, 31 # increase IV + stxvb16x 32+30, 0, 7 # update IV + li 10, 64 + stxvb16x 32+0, 0, 8 # Update X1 + stxvb16x 32+15, 10, 7 # Update pblock + blr +SYM_FUNC_END(__Process_partial) + +################################################################################ +# Combine partial blocks and ghash when we come here. +# +# The partial block has to be shifted to the right location to encrypt/decrypt +# and compute ghash if combing the previous partial block is needed. +# - Compute ghash for a full block. Clear Partial_len and pblock. Update IV. +# Write Xi. +# - Don't compute ghash if not full block. gcm_update will take care of it +# is the last block. Update Partial_len and pblock. +# +################################################################################ +SYM_FUNC_START_LOCAL(__Combine_partial) + + ld 12, 56(7) + mr 21, 5 # these bytes to be processed + + li 17, 0 li 16, 16 - GEN_MASK 18, 15, 16 - -_Partial: - lxvb16x 17+32, 0, 14 # load last block - sldi 16, 15, 3 - mtvsrdd 32+16, 0, 16 - vsro 17, 17, 16 - xxlxor 47, 47, 17+32 - xxland 47, 47, 18 - - vxor 0, 0, 0 # clear Xi - vmr 28, 15 - - cmpdi 21, 0 # encrypt/decrypt ops? - beq Skip_decrypt - xxland 32+28, 32+17, 18 - -Skip_decrypt: - - ppc_update_hash_1x + sub 22, 16, 12 # bytes to complete a block + sub 17, 22, 5 # remaining bytes in a block + cmpdi 5, 16 + ble __Inp_msg_less16 + li 17, 0 + mr 21, 22 + b __Combine_continue +__Inp_msg_less16: + cmpd 22, 5 + bgt __Combine_continue + li 17, 0 + mr 21, 22 # these bytes to be processed + +__Combine_continue: + # load msg and shift to the proper location and mask + vspltisb 16, -1 + sldi 15, 12, 3 + mtvsrdd 32+17, 0, 15 + vslo 16, 16, 17 + vsro 16, 16, 17 + sldi 15, 17, 3 + mtvsrdd 32+17, 0, 15 + vsro 16, 16, 17 + vslo 16, 16, 17 # mask + + lxvb16x 32+19, 0, 14 # load partial block + sldi 15, 12, 3 + mtvsrdd 32+17, 0, 15 + vsro 19, 19, 17 # 0x00..xxxx??..?? + sldi 15, 17, 3 + mtvsrdd 32+17, 0, 15 + vsro 19, 19, 17 # 0x00..xxxx + vslo 19, 19, 17 # shift back to form 0x00..xxxx00..00 + + # AES crypt partial + xxlxor 32+15, 32+30, 0 + lwz 23, 240(6) # n rounds + addi 22, 23, -1 # loop - 1 + mtctr 22 + addi 10, 6, 16 + +__Loop_aes_cpstate: + lxv 32+1, 0(10) + vcipher 15, 15, 1 + addi 10, 10, 16 + bdnz __Loop_aes_cpstate + lxv 32+1, 0(10) # last round key + vcipherlast 15, 15, 1 - li 16, 16 - lxvb16x 32+29, 16, 8 - vxor 0, 0, 29 - stxvb16x 32, 0, 8 # save Xi - stxvb16x 32, 16, 8 # save Xi - - # store partial block - # loop the rest of the stream if any - sldi 16, 15, 3 - mtvsrdd 32+16, 0, 16 - vslo 15, 15, 16 - #stxvb16x 15+32, 0, 9 # last block + vxor 15, 15, 19 + vand 15, 15, 16 - li 16, 16 - sub 17, 16, 15 # 16 - partial - - add 16, 15, 5 - cmpdi 16, 16 - bgt Larger_16 - mr 17, 5 -Larger_16: - - # write partial - li 10, 192 - stxvb16x 15+32, 10, 1 # save current block - - addi 10, 9, -1 - addi 16, 1, 191 - mtctr 17 # move partial byte count - -Write_last_partial: - lbzu 18, 1(16) - stbu 18, 1(10) - bdnz Write_last_partial - # Complete loop partial - - add 14, 14, 17 - add 9, 9, 17 - sub 12, 12, 17 - add 11, 11, 17 - - add 15, 15, 5 - cmpdi 15, 16 - blt Save_partial - - vaddudm 30, 30, 31 - stxvb16x 30+32, 0, 7 # update IV - xxlor 32+29, 0, 0 - vxor 15, 30, 29 # IV + round key - add round key 0 - li 15, 0 - std 15, 56(7) # partial done - clear - b Partial_done -Save_partial: - std 15, 56(7) # partial - -Partial_done: + # AES crypt output v15 + # Write partial + li 10, 224 + stxvb16x 15+32, 10, 1 # write v15 to stack + addi 10, 1, 223 + add 10, 10, 12 # add offset + addi 15, 9, -1 + mtctr 21 # partial block len +__Write_combine_partial: + lbzu 22, 1(10) + stbu 22, 1(15) + bdnz __Write_combine_partial + + add 14, 14, 21 + add 11, 11, 21 + add 9, 9, 21 + sub 5, 5, 21 + + # Encrypt/Decrypt? + cmpdi 24, 0 # decrypt? + bne __Encrypt_combine_partial + vmr 15, 19 # decrypt using the input block + +__Encrypt_combine_partial: + # + # Update partial flag and combine ghash. +__Update_partial_ghash: + li 10, 64 + lxvb16x 32+17, 10, 7 # load previous pblock + add 12, 12, 21 # combined pprocessed + vxor 15, 15, 17 # combined pblock + + cmpdi 12, 16 + beq __Clear_partial_flag + std 12, 56(7) # update partial len + stxvb16x 32+15, 10, 7 # Update current pblock blr - # - # Write partial block - # r9 - output - # r12 - remaining bytes - # v15 - partial input data - # -SYM_FUNC_START_LOCAL(Write_partial_block) - li 10, 192 - stxvb16x 15+32, 10, 1 # last block - - addi 10, 9, -1 - addi 16, 1, 191 - - mtctr 12 # remaining bytes - li 15, 0 - -Write_last_byte: - lbzu 14, 1(16) - stbu 14, 1(10) - bdnz Write_last_byte +__Clear_partial_flag: + li 12, 0 + std 12, 56(7) + # Update IV and ghash here + vadduwm 30, 30, 31 # increase IV + stxvb16x 32+30, 0, 7 # update IV + + # v15 either is either (input blockor encrypted)^(AES state) + vxor 15, 15, 0 + PPC_GHASH1x 0, 15 + stxvb16x 32+0, 10, 7 # update pblock for debug? + stxvb16x 32+0, 0, 8 # update Xi blr -SYM_FUNC_END(Write_partial_block) +SYM_FUNC_END(__Combine_partial) -aes_gcm_out: - # out = state - stxvb16x 32, 0, 8 # write out Xi - add 3, 11, 12 # return count +################################################################################ +# gcm_update(iv, Xi) - compute last hash +# +################################################################################ +SYM_FUNC_START(gcm_update) - RESTORE_REGS - blr + ld 10, 56(3) + cmpdi 10, 0 + beq __no_update - # - # 8x Decrypt - # -_GLOBAL(aes_p10_gcm_decrypt) -.align 5 + lxvb16x 32, 0, 4 # load Xi + # load Hash - h^4, h^3, h^2, h + li 10, 32 + lxvd2x 2+32, 10, 4 # H Poli + li 10, 48 + lxvd2x 3+32, 10, 4 # Hl + li 10, 64 + lxvd2x 4+32, 10, 4 # H + li 10, 80 + lxvd2x 5+32, 10, 4 # Hh + + addis 11, 2, permx@toc@ha + addi 11, 11, permx@toc@l + lxv 10, 0(11) # vs10: vpermxor vector + + li 9, 64 + lxvb16x 32+6, 9, 3 # load pblock + vxor 6, 6, 0 + + vxor 1, 1, 1 + vpmsumd 12, 3, 6 # L + vpmsumd 13, 4, 6 # M + vpmsumd 14, 5, 6 # H + vpmsumd 17, 12, 2 # reduction + vsldoi 15, 13, 1, 8 # mL + vsldoi 16, 1, 13, 8 # mH + vxor 12, 12, 15 # LL + LL + vxor 14, 14, 16 # HH + HH + xxlor 32+15, 10, 10 + vpermxor 12, 12, 17, 15 + vsldoi 13, 12, 12, 8 # swap + vpmsumd 12, 12, 2 # reduction + vxor 13, 13, 14 + vxor 7, 12, 13 + + #vxor 0, 0, 0 + #stxvb16x 32+0, 9, 3 + li 10, 0 + std 10, 56(3) + stxvb16x 32+7, 0, 4 + +__no_update: + blr +SYM_FUNC_END(gcm_update) + +################################################################################ +# aes_p10_gcm_encrypt (const void *inp, void *out, size_t len, +# const char *rk, unsigned char iv[16], void *Xip); +# +# r3 - inp +# r4 - out +# r5 - len +# r6 - AES round keys +# r7 - iv and other data +# r8 - Xi, HPoli, hash keys +# +# rounds is at offset 240 in rk +# Xi is at 0 in gcm_table (Xip). +# +################################################################################ +SYM_FUNC_START(aes_p10_gcm_encrypt) + + cmpdi 5, 0 + ble __Invalid_msg_len SAVE_REGS - LOAD_HASH_TABLE # initialize ICB: GHASH( IV ), IV - r7 lxvb16x 30+32, 0, 7 # load IV - v30 - mr 12, 5 # length - li 11, 0 # block index + mr 14, 3 + mr 9, 4 # counter 1 vxor 31, 31, 31 vspltisb 22, 1 vsldoi 31, 31, 22,1 # counter 1 - # load round key to VSR - lxv 0, 0(6) - lxv 1, 0x10(6) - lxv 2, 0x20(6) - lxv 3, 0x30(6) - lxv 4, 0x40(6) - lxv 5, 0x50(6) - lxv 6, 0x60(6) - lxv 7, 0x70(6) - lxv 8, 0x80(6) - lxv 9, 0x90(6) - lxv 10, 0xa0(6) + addis 11, 2, permx@toc@ha + addi 11, 11, permx@toc@l + lxv 10, 0(11) # vs10: vpermxor vector + li 11, 0 + + # load 9 round keys to VSR + lxv 0, 0(6) # round key 0 + lxv 1, 16(6) # round key 1 + lxv 2, 32(6) # round key 2 + lxv 3, 48(6) # round key 3 + lxv 4, 64(6) # round key 4 + lxv 5, 80(6) # round key 5 + lxv 6, 96(6) # round key 6 + lxv 7, 112(6) # round key 7 + lxv 8, 128(6) # round key 8 # load rounds - 10 (128), 12 (192), 14 (256) - lwz 9,240(6) + lwz 23, 240(6) # n rounds + li 24, 1 # encrypt +__Process_encrypt: # - # vxor state, state, w # addroundkey - xxlor 32+29, 0, 0 - vxor 15, 30, 29 # IV + round key - add round key 0 - - cmpdi 9, 10 - beq Loop_aes_gcm_8x_dec - - # load 2 more round keys (v11, v12) - lxv 11, 0xb0(6) - lxv 12, 0xc0(6) - - cmpdi 9, 12 - beq Loop_aes_gcm_8x_dec - - # load 2 more round keys (v11, v12, v13, v14) - lxv 13, 0xd0(6) - lxv 14, 0xe0(6) - cmpdi 9, 14 - beq Loop_aes_gcm_8x_dec + # Process different blocks + # + ld 12, 56(7) + cmpdi 12, 0 + bgt __Do_combine_enc + cmpdi 5, 128 + blt __Process_more_enc + +# +# Process 8x AES/GCM blocks +# +__Process_8x_enc: + # 8x blcoks + li 10, 128 + divdu 12, 5, 10 # n 128 bytes-blocks - b aes_gcm_out + addi 12, 12, -1 # loop - 1 -.align 5 -Loop_aes_gcm_8x_dec: - mr 14, 3 - mr 9, 4 + vmr 15, 30 # first state: IV + vadduwm 16, 15, 31 # state + counter + vadduwm 17, 16, 31 + vadduwm 18, 17, 31 + vadduwm 19, 18, 31 + vadduwm 20, 19, 31 + vadduwm 21, 20, 31 + vadduwm 22, 21, 31 + xxlor 9, 32+22, 32+22 # save last state - # - # check partial block - # -Continue_partial_check_dec: - ld 15, 56(7) - cmpdi 15, 0 - beq Continue_dec - bgt Final_block_dec - cmpdi 15, 16 - blt Final_block_dec - -Continue_dec: - # n blcoks - li 10, 128 - divdu 10, 12, 10 # n 128 bytes-blocks - cmpdi 10, 0 - beq Loop_last_block_dec - - vaddudm 30, 30, 31 # IV + counter - vxor 16, 30, 29 - vaddudm 30, 30, 31 - vxor 17, 30, 29 - vaddudm 30, 30, 31 - vxor 18, 30, 29 - vaddudm 30, 30, 31 - vxor 19, 30, 29 - vaddudm 30, 30, 31 - vxor 20, 30, 29 - vaddudm 30, 30, 31 - vxor 21, 30, 29 - vaddudm 30, 30, 31 - vxor 22, 30, 29 - - mtctr 10 + # vxor state, state, w # addroundkey + xxlor 32+29, 0, 0 + vxor 15, 15, 29 # IV + round key - add round key 0 + vxor 16, 16, 29 + vxor 17, 17, 29 + vxor 18, 18, 29 + vxor 19, 19, 29 + vxor 20, 20, 29 + vxor 21, 21, 29 + vxor 22, 22, 29 li 15, 16 li 16, 32 @@ -1217,305 +735,502 @@ Continue_dec: li 20, 96 li 21, 112 - lwz 10, 240(6) - -Loop_8x_block_dec: - - lxvb16x 15, 0, 14 # load block - lxvb16x 16, 15, 14 # load block - lxvb16x 17, 16, 14 # load block - lxvb16x 18, 17, 14 # load block - lxvb16x 19, 18, 14 # load block - lxvb16x 20, 19, 14 # load block - lxvb16x 21, 20, 14 # load block - lxvb16x 22, 21, 14 # load block - addi 14, 14, 128 - - Loop_aes_middle8x - - xxlor 23+32, 10, 10 - - cmpdi 10, 10 - beq Do_next_ghash_dec - - # 192 bits - xxlor 24+32, 11, 11 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - xxlor 23+32, 12, 12 - - cmpdi 10, 12 - beq Do_next_ghash_dec - - # 256 bits - xxlor 24+32, 13, 13 - - vcipher 15, 15, 23 - vcipher 16, 16, 23 - vcipher 17, 17, 23 - vcipher 18, 18, 23 - vcipher 19, 19, 23 - vcipher 20, 20, 23 - vcipher 21, 21, 23 - vcipher 22, 22, 23 - - vcipher 15, 15, 24 - vcipher 16, 16, 24 - vcipher 17, 17, 24 - vcipher 18, 18, 24 - vcipher 19, 19, 24 - vcipher 20, 20, 24 - vcipher 21, 21, 24 - vcipher 22, 22, 24 - - xxlor 23+32, 14, 14 - - cmpdi 10, 14 - beq Do_next_ghash_dec - b aes_gcm_out + # + # Pre-compute first 8 AES state and leave 1/3/5 more rounds + # for the loop. + # + addi 22, 23, -9 # process 8 keys + mtctr 22 # AES key loop + addi 10, 6, 144 -Do_next_ghash_dec: + LOOP_8AES_STATE # process 8 AES keys - # - # last round - vcipherlast 15, 15, 23 - vcipherlast 16, 16, 23 - - xxlxor 47, 47, 15 - stxvb16x 47, 0, 9 # store output - xxlxor 48, 48, 16 - stxvb16x 48, 15, 9 # store output - - vcipherlast 17, 17, 23 - vcipherlast 18, 18, 23 - - xxlxor 49, 49, 17 - stxvb16x 49, 16, 9 # store output - xxlxor 50, 50, 18 - stxvb16x 50, 17, 9 # store output - - vcipherlast 19, 19, 23 - vcipherlast 20, 20, 23 - - xxlxor 51, 51, 19 - stxvb16x 51, 18, 9 # store output - xxlxor 52, 52, 20 - stxvb16x 52, 19, 9 # store output - - vcipherlast 21, 21, 23 - vcipherlast 22, 22, 23 - - xxlxor 53, 53, 21 - stxvb16x 53, 20, 9 # store output - xxlxor 54, 54, 22 - stxvb16x 54, 21, 9 # store output - - addi 9, 9, 128 - - xxlor 15+32, 15, 15 - xxlor 16+32, 16, 16 - xxlor 17+32, 17, 17 - xxlor 18+32, 18, 18 - xxlor 19+32, 19, 19 - xxlor 20+32, 20, 20 - xxlor 21+32, 21, 21 - xxlor 22+32, 22, 22 +__PreLoop_aes_state: + lxv 32+1, 0(10) # round key + AES_CIPHER_8x vcipher 15 1 + addi 10, 10, 16 + bdnz __PreLoop_aes_state + lxv 32+1, 0(10) # last round key (v1) + + cmpdi 12, 0 # Only one loop (8 block) + beq __Finish_ghash + +# +# Loop 8x blocks and compute ghash +# +__Loop_8x_block_enc: + vcipherlast 15, 15, 1 + vcipherlast 16, 16, 1 + vcipherlast 17, 17, 1 + vcipherlast 18, 18, 1 + vcipherlast 19, 19, 1 + vcipherlast 20, 20, 1 + vcipherlast 21, 21, 1 + vcipherlast 22, 22, 1 + + lxvb16x 32+23, 0, 14 # load block + lxvb16x 32+24, 15, 14 # load block + lxvb16x 32+25, 16, 14 # load block + lxvb16x 32+26, 17, 14 # load block + lxvb16x 32+27, 18, 14 # load block + lxvb16x 32+28, 19, 14 # load block + lxvb16x 32+29, 20, 14 # load block + lxvb16x 32+30, 21, 14 # load block + addi 14, 14, 128 + + vxor 15, 15, 23 + vxor 16, 16, 24 + vxor 17, 17, 25 + vxor 18, 18, 26 + vxor 19, 19, 27 + vxor 20, 20, 28 + vxor 21, 21, 29 + vxor 22, 22, 30 + + stxvb16x 47, 0, 9 # store output + stxvb16x 48, 15, 9 # store output + stxvb16x 49, 16, 9 # store output + stxvb16x 50, 17, 9 # store output + stxvb16x 51, 18, 9 # store output + stxvb16x 52, 19, 9 # store output + stxvb16x 53, 20, 9 # store output + stxvb16x 54, 21, 9 # store output + addi 9, 9, 128 # ghash here - ppc_aes_gcm_ghash2_4x - - xxlor 27+32, 0, 0 - vaddudm 30, 30, 31 # IV + counter - vmr 29, 30 - vxor 15, 30, 27 # add round key - vaddudm 30, 30, 31 - vxor 16, 30, 27 - vaddudm 30, 30, 31 - vxor 17, 30, 27 - vaddudm 30, 30, 31 - vxor 18, 30, 27 - vaddudm 30, 30, 31 - vxor 19, 30, 27 - vaddudm 30, 30, 31 - vxor 20, 30, 27 - vaddudm 30, 30, 31 - vxor 21, 30, 27 - vaddudm 30, 30, 31 - vxor 22, 30, 27 - - addi 12, 12, -128 + vxor 15, 15, 0 + PPC_GHASH4x 0, 15, 16, 17, 18 + + vxor 19, 19, 0 + PPC_GHASH4x 0, 19, 20, 21, 22 + + xxlor 32+15, 9, 9 # last state + vadduwm 15, 15, 31 # state + counter + vadduwm 16, 15, 31 + vadduwm 17, 16, 31 + vadduwm 18, 17, 31 + vadduwm 19, 18, 31 + vadduwm 20, 19, 31 + vadduwm 21, 20, 31 + vadduwm 22, 21, 31 + xxlor 9, 32+22, 32+22 # save last state + + xxlor 32+27, 0, 0 # restore roundkey 0 + vxor 15, 15, 27 # IV + round key - add round key 0 + vxor 16, 16, 27 + vxor 17, 17, 27 + vxor 18, 18, 27 + vxor 19, 19, 27 + vxor 20, 20, 27 + vxor 21, 21, 27 + vxor 22, 22, 27 + + addi 5, 5, -128 addi 11, 11, 128 - bdnz Loop_8x_block_dec - - vmr 30, 29 - stxvb16x 30+32, 0, 7 # update IV - -Loop_last_block_dec: - cmpdi 12, 0 - beq aes_gcm_out - - # loop last few blocks - li 10, 16 - divdu 10, 12, 10 - - mtctr 10 - - lwz 10, 240(6) - - cmpdi 12, 16 - blt Final_block_dec - -Next_rem_block_dec: - lxvb16x 15, 0, 14 # load block - - Loop_aes_middle_1x - - xxlor 23+32, 10, 10 + LOOP_8AES_STATE # process 8 AES keys + mtctr 22 # AES key loop + addi 10, 6, 144 +__LastLoop_aes_state: + lxv 32+1, 0(10) # round key + AES_CIPHER_8x vcipher 15 1 + addi 10, 10, 16 + bdnz __LastLoop_aes_state + lxv 32+1, 0(10) # last round key (v1) - cmpdi 10, 10 - beq Do_next_1x_dec + addi 12, 12, -1 + cmpdi 12, 0 + bne __Loop_8x_block_enc + +__Finish_ghash: + vcipherlast 15, 15, 1 + vcipherlast 16, 16, 1 + vcipherlast 17, 17, 1 + vcipherlast 18, 18, 1 + vcipherlast 19, 19, 1 + vcipherlast 20, 20, 1 + vcipherlast 21, 21, 1 + vcipherlast 22, 22, 1 + + lxvb16x 32+23, 0, 14 # load block + lxvb16x 32+24, 15, 14 # load block + lxvb16x 32+25, 16, 14 # load block + lxvb16x 32+26, 17, 14 # load block + lxvb16x 32+27, 18, 14 # load block + lxvb16x 32+28, 19, 14 # load block + lxvb16x 32+29, 20, 14 # load block + lxvb16x 32+30, 21, 14 # load block + addi 14, 14, 128 + + vxor 15, 15, 23 + vxor 16, 16, 24 + vxor 17, 17, 25 + vxor 18, 18, 26 + vxor 19, 19, 27 + vxor 20, 20, 28 + vxor 21, 21, 29 + vxor 22, 22, 30 + + stxvb16x 47, 0, 9 # store output + stxvb16x 48, 15, 9 # store output + stxvb16x 49, 16, 9 # store output + stxvb16x 50, 17, 9 # store output + stxvb16x 51, 18, 9 # store output + stxvb16x 52, 19, 9 # store output + stxvb16x 53, 20, 9 # store output + stxvb16x 54, 21, 9 # store output + addi 9, 9, 128 + + vxor 15, 15, 0 + PPC_GHASH4x 0, 15, 16, 17, 18 + + vxor 19, 19, 0 + PPC_GHASH4x 0, 19, 20, 21, 22 + + xxlor 30+32, 9, 9 # last ctr + vadduwm 30, 30, 31 # increase ctr + stxvb16x 32+30, 0, 7 # update IV + stxvb16x 32+0, 0, 8 # update Xi + + addi 5, 5, -128 + addi 11, 11, 128 - # 192 bits - xxlor 24+32, 11, 11 + # + # Done 8x blocks + # - vcipher 15, 15, 23 - vcipher 15, 15, 24 + cmpdi 5, 0 + beq aes_gcm_out - xxlor 23+32, 12, 12 +__Process_more_enc: + li 24, 1 # encrypt + bl aes_gcm_crypt_1x + cmpdi 5, 0 + beq aes_gcm_out - cmpdi 10, 12 - beq Do_next_1x_dec + bl __Process_partial + cmpdi 5, 0 + beq aes_gcm_out +__Do_combine_enc: + bl __Combine_partial + cmpdi 5, 0 + bgt __Process_encrypt + b aes_gcm_out - # 256 bits - xxlor 24+32, 13, 13 +SYM_FUNC_END(aes_p10_gcm_encrypt) - vcipher 15, 15, 23 - vcipher 15, 15, 24 +################################################################################ +# aes_p10_gcm_decrypt (const void *inp, void *out, size_t len, +# const char *rk, unsigned char iv[16], void *Xip); +# 8x Decrypt +# +################################################################################ +SYM_FUNC_START(aes_p10_gcm_decrypt) - xxlor 23+32, 14, 14 + cmpdi 5, 0 + ble __Invalid_msg_len - cmpdi 10, 14 - beq Do_next_1x_dec + SAVE_REGS + LOAD_HASH_TABLE -Do_next_1x_dec: - vcipherlast 15, 15, 23 + # initialize ICB: GHASH( IV ), IV - r7 + lxvb16x 30+32, 0, 7 # load IV - v30 - xxlxor 47, 47, 15 - stxvb16x 47, 0, 9 # store output - addi 14, 14, 16 - addi 9, 9, 16 + mr 14, 3 + mr 9, 4 - xxlor 28+32, 15, 15 - #vmr 28, 15 - ppc_update_hash_1x + # counter 1 + vxor 31, 31, 31 + vspltisb 22, 1 + vsldoi 31, 31, 22,1 # counter 1 - addi 12, 12, -16 - addi 11, 11, 16 - xxlor 19+32, 0, 0 - vaddudm 30, 30, 31 # IV + counter - vxor 15, 30, 19 # add round key + addis 11, 2, permx@toc@ha + addi 11, 11, permx@toc@l + lxv 10, 0(11) # vs10: vpermxor vector + li 11, 0 + + # load 9 round keys to VSR + lxv 0, 0(6) # round key 0 + lxv 1, 16(6) # round key 1 + lxv 2, 32(6) # round key 2 + lxv 3, 48(6) # round key 3 + lxv 4, 64(6) # round key 4 + lxv 5, 80(6) # round key 5 + lxv 6, 96(6) # round key 6 + lxv 7, 112(6) # round key 7 + lxv 8, 128(6) # round key 8 - bdnz Next_rem_block_dec + # load rounds - 10 (128), 12 (192), 14 (256) + lwz 23, 240(6) # n rounds + li 24, 0 # decrypt - li 15, 0 - std 15, 56(7) # clear partial? - stxvb16x 30+32, 0, 7 # update IV +__Process_decrypt: + # + # Process different blocks + # + ld 12, 56(7) cmpdi 12, 0 - beq aes_gcm_out - -Final_block_dec: - lwz 10, 240(6) - Loop_aes_middle_1x - - xxlor 23+32, 10, 10 - - cmpdi 10, 10 - beq Do_final_1x_dec + bgt __Do_combine_dec + cmpdi 5, 128 + blt __Process_more_dec + +# +# Process 8x AES/GCM blocks +# +__Process_8x_dec: + # 8x blcoks + li 10, 128 + divdu 12, 5, 10 # n 128 bytes-blocks - # 192 bits - xxlor 24+32, 11, 11 + addi 12, 12, -1 # loop - 1 - vcipher 15, 15, 23 - vcipher 15, 15, 24 + vmr 15, 30 # first state: IV + vadduwm 16, 15, 31 # state + counter + vadduwm 17, 16, 31 + vadduwm 18, 17, 31 + vadduwm 19, 18, 31 + vadduwm 20, 19, 31 + vadduwm 21, 20, 31 + vadduwm 22, 21, 31 + xxlor 9, 32+22, 32+22 # save last state - xxlor 23+32, 12, 12 + # vxor state, state, w # addroundkey + xxlor 32+29, 0, 0 + vxor 15, 15, 29 # IV + round key - add round key 0 + vxor 16, 16, 29 + vxor 17, 17, 29 + vxor 18, 18, 29 + vxor 19, 19, 29 + vxor 20, 20, 29 + vxor 21, 21, 29 + vxor 22, 22, 29 - cmpdi 10, 12 - beq Do_final_1x_dec + li 15, 16 + li 16, 32 + li 17, 48 + li 18, 64 + li 19, 80 + li 20, 96 + li 21, 112 - # 256 bits - xxlor 24+32, 13, 13 + # + # Pre-compute first 8 AES state and leave 1/3/5 more rounds + # for the loop. + # + addi 22, 23, -9 # process 8 keys + mtctr 22 # AES key loop + addi 10, 6, 144 - vcipher 15, 15, 23 - vcipher 15, 15, 24 + LOOP_8AES_STATE # process 8 AES keys - xxlor 23+32, 14, 14 +__PreLoop_aes_state_dec: + lxv 32+1, 0(10) # round key + AES_CIPHER_8x vcipher 15 1 + addi 10, 10, 16 + bdnz __PreLoop_aes_state_dec + lxv 32+1, 0(10) # last round key (v1) + + cmpdi 12, 0 # Only one loop (8 block) + beq __Finish_ghash_dec + +# +# Loop 8x blocks and compute ghash +# +__Loop_8x_block_dec: + vcipherlast 15, 15, 1 + vcipherlast 16, 16, 1 + vcipherlast 17, 17, 1 + vcipherlast 18, 18, 1 + vcipherlast 19, 19, 1 + vcipherlast 20, 20, 1 + vcipherlast 21, 21, 1 + vcipherlast 22, 22, 1 + + lxvb16x 32+23, 0, 14 # load block + lxvb16x 32+24, 15, 14 # load block + lxvb16x 32+25, 16, 14 # load block + lxvb16x 32+26, 17, 14 # load block + lxvb16x 32+27, 18, 14 # load block + lxvb16x 32+28, 19, 14 # load block + lxvb16x 32+29, 20, 14 # load block + lxvb16x 32+30, 21, 14 # load block + addi 14, 14, 128 + + vxor 15, 15, 23 + vxor 16, 16, 24 + vxor 17, 17, 25 + vxor 18, 18, 26 + vxor 19, 19, 27 + vxor 20, 20, 28 + vxor 21, 21, 29 + vxor 22, 22, 30 + + stxvb16x 47, 0, 9 # store output + stxvb16x 48, 15, 9 # store output + stxvb16x 49, 16, 9 # store output + stxvb16x 50, 17, 9 # store output + stxvb16x 51, 18, 9 # store output + stxvb16x 52, 19, 9 # store output + stxvb16x 53, 20, 9 # store output + stxvb16x 54, 21, 9 # store output + + addi 9, 9, 128 + + vmr 15, 23 + vmr 16, 24 + vmr 17, 25 + vmr 18, 26 + vmr 19, 27 + vmr 20, 28 + vmr 21, 29 + vmr 22, 30 - cmpdi 10, 14 - beq Do_final_1x_dec + # ghash here + vxor 15, 15, 0 + PPC_GHASH4x 0, 15, 16, 17, 18 + + vxor 19, 19, 0 + PPC_GHASH4x 0, 19, 20, 21, 22 + + xxlor 32+15, 9, 9 # last state + vadduwm 15, 15, 31 # state + counter + vadduwm 16, 15, 31 + vadduwm 17, 16, 31 + vadduwm 18, 17, 31 + vadduwm 19, 18, 31 + vadduwm 20, 19, 31 + vadduwm 21, 20, 31 + vadduwm 22, 21, 31 + xxlor 9, 32+22, 32+22 # save last state + + xxlor 32+27, 0, 0 # restore roundkey 0 + vxor 15, 15, 27 # IV + round key - add round key 0 + vxor 16, 16, 27 + vxor 17, 17, 27 + vxor 18, 18, 27 + vxor 19, 19, 27 + vxor 20, 20, 27 + vxor 21, 21, 27 + vxor 22, 22, 27 + + addi 5, 5, -128 + addi 11, 11, 128 -Do_final_1x_dec: - vcipherlast 15, 15, 23 + LOOP_8AES_STATE # process 8 AES keys + mtctr 22 # AES key loop + addi 10, 6, 144 +__LastLoop_aes_state_dec: + lxv 32+1, 0(10) # round key + AES_CIPHER_8x vcipher 15 1 + addi 10, 10, 16 + bdnz __LastLoop_aes_state_dec + lxv 32+1, 0(10) # last round key (v1) - # check partial block - li 21, 1 # decrypt - ld 15, 56(7) # partial? - cmpdi 15, 0 - beq Normal_block_dec - bl Do_partial_block + addi 12, 12, -1 cmpdi 12, 0 - ble aes_gcm_out - - b Continue_partial_check_dec + bne __Loop_8x_block_dec + +__Finish_ghash_dec: + vcipherlast 15, 15, 1 + vcipherlast 16, 16, 1 + vcipherlast 17, 17, 1 + vcipherlast 18, 18, 1 + vcipherlast 19, 19, 1 + vcipherlast 20, 20, 1 + vcipherlast 21, 21, 1 + vcipherlast 22, 22, 1 + + lxvb16x 32+23, 0, 14 # load block + lxvb16x 32+24, 15, 14 # load block + lxvb16x 32+25, 16, 14 # load block + lxvb16x 32+26, 17, 14 # load block + lxvb16x 32+27, 18, 14 # load block + lxvb16x 32+28, 19, 14 # load block + lxvb16x 32+29, 20, 14 # load block + lxvb16x 32+30, 21, 14 # load block + addi 14, 14, 128 + + vxor 15, 15, 23 + vxor 16, 16, 24 + vxor 17, 17, 25 + vxor 18, 18, 26 + vxor 19, 19, 27 + vxor 20, 20, 28 + vxor 21, 21, 29 + vxor 22, 22, 30 + + stxvb16x 47, 0, 9 # store output + stxvb16x 48, 15, 9 # store output + stxvb16x 49, 16, 9 # store output + stxvb16x 50, 17, 9 # store output + stxvb16x 51, 18, 9 # store output + stxvb16x 52, 19, 9 # store output + stxvb16x 53, 20, 9 # store output + stxvb16x 54, 21, 9 # store output + addi 9, 9, 128 + + #vmr 15, 23 + vxor 15, 23, 0 + vmr 16, 24 + vmr 17, 25 + vmr 18, 26 + vmr 19, 27 + vmr 20, 28 + vmr 21, 29 + vmr 22, 30 + + #vxor 15, 15, 0 + PPC_GHASH4x 0, 15, 16, 17, 18 + + vxor 19, 19, 0 + PPC_GHASH4x 0, 19, 20, 21, 22 + + xxlor 30+32, 9, 9 # last ctr + vadduwm 30, 30, 31 # increase ctr + stxvb16x 32+30, 0, 7 # update IV + stxvb16x 32+0, 0, 8 # update Xi + + addi 5, 5, -128 + addi 11, 11, 128 -Normal_block_dec: - lxvb16x 15, 0, 14 # load last block - xxlxor 47, 47, 15 + # + # Done 8x blocks + # - # create partial block mask - li 15, 16 - sub 15, 15, 12 # index to the mask + cmpdi 5, 0 + beq aes_gcm_out - vspltisb 16, -1 # first 16 bytes - 0xffff...ff - vspltisb 17, 0 # second 16 bytes - 0x0000...00 - li 10, 192 - stvx 16, 10, 1 - addi 10, 10, 16 - stvx 17, 10, 1 +__Process_more_dec: + li 24, 0 # decrypt + bl aes_gcm_crypt_1x + cmpdi 5, 0 + beq aes_gcm_out - addi 10, 1, 192 - lxvb16x 16, 15, 10 # load partial block mask - xxland 47, 47, 16 + bl __Process_partial + cmpdi 5, 0 + beq aes_gcm_out +__Do_combine_dec: + bl __Combine_partial + cmpdi 5, 0 + bgt __Process_decrypt + b aes_gcm_out +SYM_FUNC_END(aes_p10_gcm_decrypt) - xxland 32+28, 15, 16 - #vmr 28, 15 - ppc_update_hash_1x +SYM_FUNC_START_LOCAL(aes_gcm_out) - # * should store only the remaining bytes. - bl Write_partial_block + mr 3, 11 # return count - stxvb16x 30+32, 0, 7 # update IV - std 12, 56(7) # update partial? - li 16, 16 + RESTORE_REGS + blr - stxvb16x 32, 0, 8 # write out Xi - stxvb16x 32, 16, 8 # write out Xi - b aes_gcm_out +__Invalid_msg_len: + li 3, 0 + blr +SYM_FUNC_END(aes_gcm_out) + +SYM_DATA_START_LOCAL(PERMX) +.align 4 +# for vector permute and xor +permx: +.long 0x4c5d6e7f, 0x08192a3b, 0xc4d5e6f7, 0x8091a2b3 +SYM_DATA_END(permx) diff --git a/arch/powerpc/crypto/curve25519-ppc64le-core.c b/arch/powerpc/crypto/curve25519-ppc64le-core.c index 4e3e44ea4484..f7810be0b292 100644 --- a/arch/powerpc/crypto/curve25519-ppc64le-core.c +++ b/arch/powerpc/crypto/curve25519-ppc64le-core.c @@ -295,5 +295,6 @@ module_exit(curve25519_mod_exit); MODULE_ALIAS_CRYPTO("curve25519"); MODULE_ALIAS_CRYPTO("curve25519-ppc64le"); +MODULE_DESCRIPTION("PPC64le Curve25519 scalar multiplication with 51 bits limbs"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Danny Tsen <dtsen@us.ibm.com>"); diff --git a/arch/powerpc/crypto/poly1305-p10-glue.c b/arch/powerpc/crypto/poly1305-p10-glue.c index 95dd708573ee..369686e9370b 100644 --- a/arch/powerpc/crypto/poly1305-p10-glue.c +++ b/arch/powerpc/crypto/poly1305-p10-glue.c @@ -14,7 +14,7 @@ #include <crypto/internal/poly1305.h> #include <crypto/internal/simd.h> #include <linux/cpufeature.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/simd.h> #include <asm/switch_to.h> diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h index 2bc53c646ccd..f48e644900a2 100644 --- a/arch/powerpc/include/asm/asm-compat.h +++ b/arch/powerpc/include/asm/asm-compat.h @@ -26,19 +26,23 @@ #define PPC_MIN_STKFRM 112 #ifdef __BIG_ENDIAN__ -#define LHZX_BE stringify_in_c(lhzx) #define LWZX_BE stringify_in_c(lwzx) #define LDX_BE stringify_in_c(ldx) #define STWX_BE stringify_in_c(stwx) #define STDX_BE stringify_in_c(stdx) #else -#define LHZX_BE stringify_in_c(lhbrx) #define LWZX_BE stringify_in_c(lwbrx) #define LDX_BE stringify_in_c(ldbrx) #define STWX_BE stringify_in_c(stwbrx) #define STDX_BE stringify_in_c(stdbrx) #endif +#ifdef CONFIG_CC_IS_CLANG +#define DS_FORM_CONSTRAINT "Z<>" +#else +#define DS_FORM_CONSTRAINT "YZ<>" +#endif + #else /* 32-bit */ /* operations for longs and pointers */ diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index 5bf6a4d49268..d1ea554c33ed 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -11,6 +11,7 @@ #include <asm/cmpxchg.h> #include <asm/barrier.h> #include <asm/asm-const.h> +#include <asm/asm-compat.h> /* * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with @@ -197,7 +198,7 @@ static __inline__ s64 arch_atomic64_read(const atomic64_t *v) if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) __asm__ __volatile__("ld %0,0(%1)" : "=r"(t) : "b"(&v->counter)); else - __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); + __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : DS_FORM_CONSTRAINT (v->counter)); return t; } @@ -208,7 +209,7 @@ static __inline__ void arch_atomic64_set(atomic64_t *v, s64 i) if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) __asm__ __volatile__("std %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); else - __asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); + __asm__ __volatile__("std%U0%X0 %1,%0" : "=" DS_FORM_CONSTRAINT (v->counter) : "r"(i)); } #define ATOMIC64_OP(op, asm_op) \ diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 52971ee30717..42c3af90d1f0 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -196,7 +196,8 @@ void unmap_kernel_page(unsigned long va); #endif #define MODULES_END ALIGN_DOWN(PAGE_OFFSET, SZ_256M) -#define MODULES_VADDR (MODULES_END - SZ_256M) +#define MODULES_SIZE (CONFIG_MODULES_SIZE * SZ_1M) +#define MODULES_VADDR (MODULES_END - MODULES_SIZE) #ifndef __ASSEMBLY__ #include <linux/sched.h> diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index c654c376ef8b..c3efacab4b94 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h @@ -75,6 +75,26 @@ remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot)) /* + * With 4K page size the real_pte machinery is all nops. + */ +#define __real_pte(e, p, o) ((real_pte_t){(e)}) +#define __rpte_to_pte(r) ((r).pte) +#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT) + +#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ + do { \ + index = 0; \ + shift = mmu_psize_defs[psize].shift; \ + +#define pte_iterate_hashed_end() } while(0) + +/* + * We expect this to be called only for user addresses or kernel virtual + * addresses other than the linear mapping. + */ +#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K + +/* * 4K PTE format is different from 64K PTE format. Saving the hash_slot is just * a matter of returning the PTE bits that need to be modified. On 64K PTE, * things are a little more involved and hence needs many more parameters to diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 519b1743a0f4..6d98e6f08d4d 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -330,32 +330,6 @@ static inline unsigned long pud_leaf_size(pud_t pud) #ifndef __ASSEMBLY__ -/* - * This is the default implementation of various PTE accessors, it's - * used in all cases except Book3S with 64K pages where we have a - * concept of sub-pages - */ -#ifndef __real_pte - -#define __real_pte(e, p, o) ((real_pte_t){(e)}) -#define __rpte_to_pte(r) ((r).pte) -#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT) - -#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ - do { \ - index = 0; \ - shift = mmu_psize_defs[psize].shift; \ - -#define pte_iterate_hashed_end() } while(0) - -/* - * We expect this to be called only for user addresses or kernel virtual - * addresses other than the linear mapping. - */ -#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K - -#endif /* __real_pte */ - static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long clr, unsigned long set, int huge) @@ -1124,6 +1098,7 @@ extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); extern pud_t pfn_pud(unsigned long pfn, pgprot_t pgprot); extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); extern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot); +extern pud_t pud_modify(pud_t pud, pgprot_t newprot); extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd); extern void set_pud_at(struct mm_struct *mm, unsigned long addr, @@ -1384,6 +1359,8 @@ static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, #define __HAVE_ARCH_PMDP_INVALIDATE extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); +extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp); #define pmd_move_must_withdraw pmd_move_must_withdraw struct spinlock; diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 0e29ccf903d0..e7f14720f630 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h @@ -76,6 +76,43 @@ int patch_instruction(u32 *addr, ppc_inst_t instr); int raw_patch_instruction(u32 *addr, ppc_inst_t instr); int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr); +/* + * The data patching functions patch_uint() and patch_ulong(), etc., must be + * called on aligned addresses. + * + * The instruction patching functions patch_instruction() and similar must be + * called on addresses satisfying instruction alignment requirements. + */ + +#ifdef CONFIG_PPC64 + +int patch_uint(void *addr, unsigned int val); +int patch_ulong(void *addr, unsigned long val); + +#define patch_u64 patch_ulong + +#else + +static inline int patch_uint(void *addr, unsigned int val) +{ + if (!IS_ALIGNED((unsigned long)addr, sizeof(unsigned int))) + return -EINVAL; + + return patch_instruction(addr, ppc_inst(val)); +} + +static inline int patch_ulong(void *addr, unsigned long val) +{ + if (!IS_ALIGNED((unsigned long)addr, sizeof(unsigned long))) + return -EINVAL; + + return patch_instruction(addr, ppc_inst(val)); +} + +#endif + +#define patch_u32 patch_uint + static inline unsigned long patch_site_addr(s32 *site) { return (unsigned long)site + *site; diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 91a9fd53254f..5e34611de9ef 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -308,6 +308,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option, bool include_passed); int eeh_pe_configure(struct eeh_pe *pe); int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func, unsigned long addr, unsigned long mask); +int eeh_pe_inject_mmio_error(struct pci_dev *pdev); /** * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index 559560286e6d..0edfb874eb02 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -32,42 +32,21 @@ struct dyn_arch_ftrace { int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); #define ftrace_init_nop ftrace_init_nop -struct ftrace_regs { - struct pt_regs regs; -}; +#include <linux/ftrace_regs.h> static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs) { /* We clear regs.msr in ftrace_call */ - return fregs->regs.msr ? &fregs->regs : NULL; + return arch_ftrace_regs(fregs)->regs.msr ? &arch_ftrace_regs(fregs)->regs : NULL; } static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip) { - regs_set_return_ip(&fregs->regs, ip); + regs_set_return_ip(&arch_ftrace_regs(fregs)->regs, ip); } -static __always_inline unsigned long -ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs) -{ - return instruction_pointer(&fregs->regs); -} - -#define ftrace_regs_get_argument(fregs, n) \ - regs_get_kernel_argument(&(fregs)->regs, n) -#define ftrace_regs_get_stack_pointer(fregs) \ - kernel_stack_pointer(&(fregs)->regs) -#define ftrace_regs_return_value(fregs) \ - regs_return_value(&(fregs)->regs) -#define ftrace_regs_set_return_value(fregs, ret) \ - regs_set_return_value(&(fregs)->regs, ret) -#define ftrace_override_function_with_return(fregs) \ - override_function_with_return(&(fregs)->regs) -#define ftrace_regs_query_register_offset(name) \ - regs_query_register_offset(name) - struct ftrace_ops; #define ftrace_graph_func ftrace_graph_func diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h index 2d6c886b40f4..23638d4e73ac 100644 --- a/arch/powerpc/include/asm/interrupt.h +++ b/arch/powerpc/include/asm/interrupt.h @@ -177,7 +177,7 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs) if (user_mode(regs)) { kuap_lock(); - CT_WARN_ON(ct_state() != CONTEXT_USER); + CT_WARN_ON(ct_state() != CT_STATE_USER); user_exit_irqoff(); account_cpu_user_entry(); @@ -189,8 +189,8 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs) * so avoid recursion. */ if (TRAP(regs) != INTERRUPT_PROGRAM) - CT_WARN_ON(ct_state() != CONTEXT_KERNEL && - ct_state() != CONTEXT_IDLE); + CT_WARN_ON(ct_state() != CT_STATE_KERNEL && + ct_state() != CT_STATE_IDLE); INT_SOFT_MASK_BUG_ON(regs, is_implicit_soft_masked(regs)); INT_SOFT_MASK_BUG_ON(regs, arch_irq_disabled_regs(regs) && search_kernel_restart_table(regs->nip)); diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h index 17a77d47ed6d..42a51a993d94 100644 --- a/arch/powerpc/include/asm/mman.h +++ b/arch/powerpc/include/asm/mman.h @@ -6,7 +6,7 @@ #include <uapi/asm/mman.h> -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) && !defined(BUILD_VDSO) #include <asm/cputable.h> #include <linux/mm.h> diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 37bffa0f7918..a157ab513347 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -116,9 +116,6 @@ static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea) } #endif -extern int use_cop(unsigned long acop, struct mm_struct *mm); -extern void drop_cop(unsigned long acop, struct mm_struct *mm); - #ifdef CONFIG_PPC_BOOK3S_64 static inline void inc_mm_active_cpus(struct mm_struct *mm) { @@ -260,15 +257,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, extern void arch_exit_mmap(struct mm_struct *mm); -static inline void arch_unmap(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - unsigned long vdso_base = (unsigned long)mm->context.vdso; - - if (start <= vdso_base && vdso_base < end) - mm->context.vdso = NULL; -} - #ifdef CONFIG_PPC_MEM_KEYS bool arch_vma_access_permitted(struct vm_area_struct *vma, bool write, bool execute, bool foreign); diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h index da827d2d0866..d99863cd6cde 100644 --- a/arch/powerpc/include/asm/mmzone.h +++ b/arch/powerpc/include/asm/mmzone.h @@ -20,12 +20,6 @@ #ifdef CONFIG_NUMA -extern struct pglist_data *node_data[]; -/* - * Return a pointer to the node data for node n. - */ -#define NODE_DATA(nid) (node_data[nid]) - /* * Following are specific to this numa platform. */ diff --git a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h index a756a1e59c54..2986f9ba40b8 100644 --- a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h @@ -170,8 +170,9 @@ #define mmu_linear_psize MMU_PAGE_8M -#define MODULES_VADDR (PAGE_OFFSET - SZ_256M) #define MODULES_END PAGE_OFFSET +#define MODULES_SIZE (CONFIG_MODULES_SIZE * SZ_1M) +#define MODULES_VADDR (MODULES_END - MODULES_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index 9508399dd036..b481738c4bb5 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -52,7 +52,7 @@ #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) #define pgd_ERROR(e) \ - pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) + pr_err("%s:%d: bad pgd %08llx.\n", __FILE__, __LINE__, (unsigned long long)pgd_val(e)) /* * This is the bottom of the PKMAP area with HIGHMEM or an arbitrary @@ -170,7 +170,7 @@ static inline void pmd_clear(pmd_t *pmdp) #define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) #else #define pmd_page_vaddr(pmd) \ - ((const void *)(pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1))) + ((const void *)((unsigned long)pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1))) #define pmd_pfn(pmd) (__pa(pmd_val(pmd)) >> PAGE_SHIFT) #endif diff --git a/arch/powerpc/include/asm/nohash/pgalloc.h b/arch/powerpc/include/asm/nohash/pgalloc.h index d06efac6d7aa..bb5f3e8ea912 100644 --- a/arch/powerpc/include/asm/nohash/pgalloc.h +++ b/arch/powerpc/include/asm/nohash/pgalloc.h @@ -19,8 +19,14 @@ static inline void tlb_flush_pgtable(struct mmu_gather *tlb, static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), + pgd_t *pgd = kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), pgtable_gfp_flags(mm, GFP_KERNEL)); + +#if defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_BOOK3S_603) + memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, + (MAX_PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); +#endif + return pgd; } static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 83d0a4fc5f75..af9a2628d1df 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -21,8 +21,7 @@ * page size. When using 64K pages however, whether we are really supporting * 64K pages in HW or not is irrelevant to those definitions. */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) +#include <vdso/page.h> #ifndef __ASSEMBLY__ #ifndef CONFIG_HUGETLB_PAGE @@ -42,13 +41,6 @@ extern unsigned int hpage_shift; #endif /* - * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we - * assign PAGE_MASK to a larger type it gets extended the way we want - * (i.e. with 1s in the high bits) - */ -#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) - -/* * KERNELBASE is the virtual address of the start of the kernel, it's often * the same as PAGE_OFFSET, but _might not be_. * diff --git a/arch/powerpc/include/asm/percpu.h b/arch/powerpc/include/asm/percpu.h index 634970ce13c6..ecf5ac70cfae 100644 --- a/arch/powerpc/include/asm/percpu.h +++ b/arch/powerpc/include/asm/percpu.h @@ -23,7 +23,7 @@ DECLARE_STATIC_KEY_FALSE(__percpu_first_chunk_is_paged); (static_key_enabled(&__percpu_first_chunk_is_paged.key)) #else #define percpu_first_chunk_is_paged false -#endif /* CONFIG_PPC64 && CONFIG_SMP */ +#endif #include <asm-generic/percpu.h> diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 5995614e9062..af0f46e2373b 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -102,8 +102,8 @@ struct power_pmu { int __init register_power_pmu(struct power_pmu *pmu); struct pt_regs; -extern unsigned long perf_misc_flags(struct pt_regs *regs); -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_arch_misc_flags(struct pt_regs *regs); +extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); extern unsigned long int read_bhrb(int n); /* @@ -111,7 +111,7 @@ extern unsigned long int read_bhrb(int n); * if we have hardware PMU support. */ #ifdef CONFIG_PPC_PERF_CTRS -#define perf_misc_flags(regs) perf_misc_flags(regs) +#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs) #endif /* diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h index 7b3d4c592a10..f3086e39e7d2 100644 --- a/arch/powerpc/include/asm/pgtable-types.h +++ b/arch/powerpc/include/asm/pgtable-types.h @@ -49,16 +49,22 @@ static inline unsigned long pud_val(pud_t x) #endif /* CONFIG_PPC64 */ /* PGD level */ -#if defined(CONFIG_PPC_E500) && defined(CONFIG_PTE_64BIT) +#if defined(CONFIG_PPC_85xx) && defined(CONFIG_PTE_64BIT) typedef struct { unsigned long long pgd; } pgd_t; + +static inline unsigned long long pgd_val(pgd_t x) +{ + return x.pgd; +} #else typedef struct { unsigned long pgd; } pgd_t; -#endif -#define __pgd(x) ((pgd_t) { (x) }) + static inline unsigned long pgd_val(pgd_t x) { return x.pgd; } +#endif +#define __pgd(x) ((pgd_t) { (x) }) /* Page protection bits */ typedef struct { unsigned long pgprot; } pgprot_t; diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 264a6c09517a..2f72ad885332 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -65,6 +65,7 @@ static inline unsigned long pte_pfn(pte_t pte) /* * Select all bits except the pfn */ +#define pte_pgprot pte_pgprot static inline pgprot_t pte_pgprot(pte_t pte) { unsigned long pte_flags; diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 065ffd1b2f8a..04406162fc5a 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -397,6 +397,7 @@ inline uint16_t pseries_errorlog_length(struct pseries_errorlog *sect) #define PSERIES_HP_ELOG_RESOURCE_SLOT 3 #define PSERIES_HP_ELOG_RESOURCE_PHB 4 #define PSERIES_HP_ELOG_RESOURCE_PMEM 6 +#define PSERIES_HP_ELOG_RESOURCE_DT 7 #define PSERIES_HP_ELOG_ACTION_ADD 1 #define PSERIES_HP_ELOG_ACTION_REMOVE 2 diff --git a/arch/powerpc/include/asm/systemcfg.h b/arch/powerpc/include/asm/systemcfg.h new file mode 100644 index 000000000000..2f9b1d6a5c98 --- /dev/null +++ b/arch/powerpc/include/asm/systemcfg.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _SYSTEMCFG_H +#define _SYSTEMCFG_H + +/* + * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM + * Copyright (C) 2005 Benjamin Herrenschmidy <benh@kernel.crashing.org>, + * IBM Corp. + */ + +#ifdef CONFIG_PPC64 + +/* + * If the major version changes we are incompatible. + * Minor version changes are a hint. + */ +#define SYSTEMCFG_MAJOR 1 +#define SYSTEMCFG_MINOR 1 + +#include <linux/types.h> + +struct systemcfg { + __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ + struct { /* Systemcfg version numbers */ + __u32 major; /* Major number 0x10 */ + __u32 minor; /* Minor number 0x14 */ + } version; + + /* Note about the platform flags: it now only contains the lpar + * bit. The actual platform number is dead and buried + */ + __u32 platform; /* Platform flags 0x18 */ + __u32 processor; /* Processor type 0x1C */ + __u64 processorCount; /* # of physical processors 0x20 */ + __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */ + __u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */ + __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ + __u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */ + __u64 stamp_xsec; /* (NU) 0x48 */ + __u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */ + __u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */ + __u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */ + __u32 dcache_size; /* L1 d-cache size 0x60 */ + __u32 dcache_line_size; /* L1 d-cache line size 0x64 */ + __u32 icache_size; /* L1 i-cache size 0x68 */ + __u32 icache_line_size; /* L1 i-cache line size 0x6C */ +}; + +extern struct systemcfg *systemcfg; + +#endif /* CONFIG_PPC64 */ +#endif /* _SYSTEMCFG_H */ diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 15c5691dd218..6ebca2996f18 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -226,6 +226,10 @@ static inline int arch_within_stack_frames(const void * const stack, return BAD_STACK; } +#ifdef CONFIG_PPC32 +extern void *emergency_ctx[]; +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index fd594bf6c6a9..4f5a46a77fa2 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -6,6 +6,7 @@ #include <asm/page.h> #include <asm/extable.h> #include <asm/kup.h> +#include <asm/asm-compat.h> #ifdef __powerpc64__ /* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */ @@ -92,12 +93,6 @@ __pu_failed: \ : label) #endif -#ifdef CONFIG_CC_IS_CLANG -#define DS_FORM_CONSTRAINT "Z<>" -#else -#define DS_FORM_CONSTRAINT "YZ<>" -#endif - #ifdef __powerpc64__ #ifdef CONFIG_PPC_KERNEL_PREFIXED #define __put_user_asm2_goto(x, ptr, label) \ diff --git a/arch/powerpc/include/asm/vdso/getrandom.h b/arch/powerpc/include/asm/vdso/getrandom.h new file mode 100644 index 000000000000..501d6bb14e8a --- /dev/null +++ b/arch/powerpc/include/asm/vdso/getrandom.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France + */ +#ifndef _ASM_POWERPC_VDSO_GETRANDOM_H +#define _ASM_POWERPC_VDSO_GETRANDOM_H + +#ifndef __ASSEMBLY__ + +static __always_inline int do_syscall_3(const unsigned long _r0, const unsigned long _r3, + const unsigned long _r4, const unsigned long _r5) +{ + register long r0 asm("r0") = _r0; + register unsigned long r3 asm("r3") = _r3; + register unsigned long r4 asm("r4") = _r4; + register unsigned long r5 asm("r5") = _r5; + register int ret asm ("r3"); + + asm volatile( + " sc\n" + " bns+ 1f\n" + " neg %0, %0\n" + "1:\n" + : "=r" (ret), "+r" (r4), "+r" (r5), "+r" (r0) + : "r" (r3) + : "memory", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr"); + + return ret; +} + +/** + * getrandom_syscall - Invoke the getrandom() syscall. + * @buffer: Destination buffer to fill with random bytes. + * @len: Size of @buffer in bytes. + * @flags: Zero or more GRND_* flags. + * Returns: The number of bytes written to @buffer, or a negative value indicating an error. + */ +static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsigned int flags) +{ + return do_syscall_3(__NR_getrandom, (unsigned long)buffer, + (unsigned long)len, (unsigned long)flags); +} + +static __always_inline struct vdso_rng_data *__arch_get_vdso_rng_data(void) +{ + return NULL; +} + +ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, + size_t opaque_len, const struct vdso_rng_data *vd); + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_VDSO_GETRANDOM_H */ diff --git a/arch/powerpc/include/asm/vdso/vsyscall.h b/arch/powerpc/include/asm/vdso/vsyscall.h index 48cf23f1e273..48560a119559 100644 --- a/arch/powerpc/include/asm/vdso/vsyscall.h +++ b/arch/powerpc/include/asm/vdso/vsyscall.h @@ -4,12 +4,8 @@ #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <asm/vdso_datapage.h> -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ static __always_inline struct vdso_data *__arch_get_k_vdso_data(void) { @@ -17,6 +13,12 @@ struct vdso_data *__arch_get_k_vdso_data(void) } #define __arch_get_k_vdso_data __arch_get_k_vdso_data +static __always_inline +struct vdso_rng_data *__arch_get_k_vdso_rng_data(void) +{ + return &vdso_data->rng_data; +} + /* The asm-generic header needs to be included after the definitions above */ #include <asm-generic/vdso/vsyscall.h> diff --git a/arch/powerpc/include/asm/vdso_datapage.h b/arch/powerpc/include/asm/vdso_datapage.h index a585c8e538ff..a9686310be2c 100644 --- a/arch/powerpc/include/asm/vdso_datapage.h +++ b/arch/powerpc/include/asm/vdso_datapage.h @@ -9,29 +9,6 @@ * IBM Corp. */ - -/* - * Note about this structure: - * - * This structure was historically called systemcfg and exposed to - * userland via /proc/ppc64/systemcfg. Unfortunately, this became an - * ABI issue as some proprietary software started relying on being able - * to mmap() it, thus we have to keep the base layout at least for a - * few kernel versions. - * - * However, since ppc32 doesn't suffer from this backward handicap, - * a simpler version of the data structure is used there with only the - * fields actually used by the vDSO. - * - */ - -/* - * If the major version changes we are incompatible. - * Minor version changes are a hint. - */ -#define SYSTEMCFG_MAJOR 1 -#define SYSTEMCFG_MINOR 1 - #ifndef __ASSEMBLY__ #include <linux/unistd.h> @@ -40,41 +17,10 @@ #define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32) -/* - * So here is the ppc64 backward compatible version - */ - #ifdef CONFIG_PPC64 struct vdso_arch_data { - __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ - struct { /* Systemcfg version numbers */ - __u32 major; /* Major number 0x10 */ - __u32 minor; /* Minor number 0x14 */ - } version; - - /* Note about the platform flags: it now only contains the lpar - * bit. The actual platform number is dead and buried - */ - __u32 platform; /* Platform flags 0x18 */ - __u32 processor; /* Processor type 0x1C */ - __u64 processorCount; /* # of physical processors 0x20 */ - __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */ - __u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */ - __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ - __u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */ - __u64 stamp_xsec; /* (NU) 0x48 */ - __u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */ - __u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */ - __u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */ - __u32 dcache_size; /* L1 d-cache size 0x60 */ - __u32 dcache_line_size; /* L1 d-cache line size 0x64 */ - __u32 icache_size; /* L1 i-cache size 0x68 */ - __u32 icache_line_size; /* L1 i-cache line size 0x6C */ - - /* those additional ones don't have to be located anywhere - * special as they were not part of the original systemcfg - */ + __u64 tb_ticks_per_sec; /* Timebase tics / sec */ __u32 dcache_block_size; /* L1 d-cache block size */ __u32 icache_block_size; /* L1 i-cache block size */ __u32 dcache_log_block_size; /* L1 d-cache log block size */ @@ -83,18 +29,17 @@ struct vdso_arch_data { __u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat syscalls */ struct vdso_data data[CS_BASES]; + struct vdso_rng_data rng_data; }; #else /* CONFIG_PPC64 */ -/* - * And here is the simpler 32 bits version - */ struct vdso_arch_data { - __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ + __u64 tb_ticks_per_sec; /* Timebase tics / sec */ __u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */ __u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */ struct vdso_data data[CS_BASES]; + struct vdso_rng_data rng_data; }; #endif /* CONFIG_PPC64 */ @@ -111,6 +56,21 @@ extern struct vdso_arch_data *vdso_data; addi \ptr, \ptr, (_vdso_datapage - 999b)@l .endm +#include <asm/asm-offsets.h> +#include <asm/page.h> + +.macro get_realdatapage ptr scratch + get_datapage \ptr +#ifdef CONFIG_TIME_NS + lwz \scratch, VDSO_CLOCKMODE_OFFSET(\ptr) + xoris \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@h + xori \scratch, \scratch, VDSO_CLOCKMODE_TIMENS@l + cntlzw \scratch, \scratch + rlwinm \scratch, \scratch, PAGE_SHIFT - 5, 1 << PAGE_SHIFT + add \ptr, \ptr, \scratch +#endif +.endm + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1784b6a6ca1d..f43c1198768c 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -139,6 +139,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_OPTPROBES) += optprobes.o optprobes_head.o obj-$(CONFIG_KPROBES_ON_FTRACE) += kprobes-ftrace.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-$(CONFIG_RETHOOK) += rethook.o obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o obj-$(CONFIG_ARCH_HAS_DMA_SET_MASK) += dma-mask.o diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 23733282de4d..131a8cc10dbe 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -335,6 +335,7 @@ int main(void) /* datapage offsets for use by vdso */ OFFSET(VDSO_DATA_OFFSET, vdso_arch_data, data); + OFFSET(VDSO_RNG_DATA_OFFSET, vdso_arch_data, rng_data); OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec); #ifdef CONFIG_PPC64 OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size); @@ -346,6 +347,8 @@ int main(void) #else OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, syscall_map); #endif + OFFSET(VDSO_CLOCKMODE_OFFSET, vdso_arch_data, data[0].clock_mode); + DEFINE(VDSO_CLOCKMODE_TIMENS, VDSO_CLOCKMODE_TIMENS); #ifdef CONFIG_BUG DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index f502337dd37d..0fcc463b02e2 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -735,7 +735,7 @@ static const struct sysfs_ops cache_index_ops = { .show = cache_index_show, }; -static struct kobj_type cache_index_type = { +static const struct kobj_type cache_index_type = { .release = cache_index_release, .sysfs_ops = &cache_index_ops, .default_groups = cache_index_default_groups, diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index af4263594eb2..1bee15c013e7 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -867,7 +867,7 @@ bool __init dt_cpu_ftrs_init(void *fdt) using_dt_cpu_ftrs = false; /* Setup and verify the FDT, if it fails we just bail */ - if (!early_init_dt_verify(fdt)) + if (!early_init_dt_verify(fdt, __pa(fdt))) return false; if (!of_scan_flat_dt(fdt_find_cpu_features, NULL)) diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index d03f17987fca..83fe99861eb1 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -1537,10 +1537,6 @@ int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func, if (!eeh_ops || !eeh_ops->err_inject) return -ENOENT; - /* Check on PCI error type */ - if (type != EEH_ERR_TYPE_32 && type != EEH_ERR_TYPE_64) - return -EINVAL; - /* Check on PCI error function */ if (func < EEH_ERR_FUNC_MIN || func > EEH_ERR_FUNC_MAX) return -EINVAL; @@ -1578,6 +1574,104 @@ static int proc_eeh_show(struct seq_file *m, void *v) } #endif /* CONFIG_PROC_FS */ +static int eeh_break_device(struct pci_dev *pdev) +{ + struct resource *bar = NULL; + void __iomem *mapped; + u16 old, bit; + int i, pos; + + /* Do we have an MMIO BAR to disable? */ + for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { + struct resource *r = &pdev->resource[i]; + + if (!r->flags || !r->start) + continue; + if (r->flags & IORESOURCE_IO) + continue; + if (r->flags & IORESOURCE_UNSET) + continue; + + bar = r; + break; + } + + if (!bar) { + pci_err(pdev, "Unable to find Memory BAR to cause EEH with\n"); + return -ENXIO; + } + + pci_err(pdev, "Going to break: %pR\n", bar); + + if (pdev->is_virtfn) { +#ifndef CONFIG_PCI_IOV + return -ENXIO; +#else + /* + * VFs don't have a per-function COMMAND register, so the best + * we can do is clear the Memory Space Enable bit in the PF's + * SRIOV control reg. + * + * Unfortunately, this requires that we have a PF (i.e doesn't + * work for a passed-through VF) and it has the potential side + * effect of also causing an EEH on every other VF under the + * PF. Oh well. + */ + pdev = pdev->physfn; + if (!pdev) + return -ENXIO; /* passed through VFs have no PF */ + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); + pos += PCI_SRIOV_CTRL; + bit = PCI_SRIOV_CTRL_MSE; +#endif /* !CONFIG_PCI_IOV */ + } else { + bit = PCI_COMMAND_MEMORY; + pos = PCI_COMMAND; + } + + /* + * Process here is: + * + * 1. Disable Memory space. + * + * 2. Perform an MMIO to the device. This should result in an error + * (CA / UR) being raised by the device which results in an EEH + * PE freeze. Using the in_8() accessor skips the eeh detection hook + * so the freeze hook so the EEH Detection machinery won't be + * triggered here. This is to match the usual behaviour of EEH + * where the HW will asynchronously freeze a PE and it's up to + * the kernel to notice and deal with it. + * + * 3. Turn Memory space back on. This is more important for VFs + * since recovery will probably fail if we don't. For normal + * the COMMAND register is reset as a part of re-initialising + * the device. + * + * Breaking stuff is the point so who cares if it's racy ;) + */ + pci_read_config_word(pdev, pos, &old); + + mapped = ioremap(bar->start, PAGE_SIZE); + if (!mapped) { + pci_err(pdev, "Unable to map MMIO BAR %pR\n", bar); + return -ENXIO; + } + + pci_write_config_word(pdev, pos, old & ~bit); + in_8(mapped); + pci_write_config_word(pdev, pos, old); + + iounmap(mapped); + + return 0; +} + +int eeh_pe_inject_mmio_error(struct pci_dev *pdev) +{ + return eeh_break_device(pdev); +} + #ifdef CONFIG_DEBUG_FS @@ -1682,7 +1776,6 @@ static ssize_t eeh_force_recover_write(struct file *filp, static const struct file_operations eeh_force_recover_fops = { .open = simple_open, - .llseek = no_llseek, .write = eeh_force_recover_write, }; @@ -1726,104 +1819,10 @@ static ssize_t eeh_dev_check_write(struct file *filp, static const struct file_operations eeh_dev_check_fops = { .open = simple_open, - .llseek = no_llseek, .write = eeh_dev_check_write, .read = eeh_debugfs_dev_usage, }; -static int eeh_debugfs_break_device(struct pci_dev *pdev) -{ - struct resource *bar = NULL; - void __iomem *mapped; - u16 old, bit; - int i, pos; - - /* Do we have an MMIO BAR to disable? */ - for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { - struct resource *r = &pdev->resource[i]; - - if (!r->flags || !r->start) - continue; - if (r->flags & IORESOURCE_IO) - continue; - if (r->flags & IORESOURCE_UNSET) - continue; - - bar = r; - break; - } - - if (!bar) { - pci_err(pdev, "Unable to find Memory BAR to cause EEH with\n"); - return -ENXIO; - } - - pci_err(pdev, "Going to break: %pR\n", bar); - - if (pdev->is_virtfn) { -#ifndef CONFIG_PCI_IOV - return -ENXIO; -#else - /* - * VFs don't have a per-function COMMAND register, so the best - * we can do is clear the Memory Space Enable bit in the PF's - * SRIOV control reg. - * - * Unfortunately, this requires that we have a PF (i.e doesn't - * work for a passed-through VF) and it has the potential side - * effect of also causing an EEH on every other VF under the - * PF. Oh well. - */ - pdev = pdev->physfn; - if (!pdev) - return -ENXIO; /* passed through VFs have no PF */ - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); - pos += PCI_SRIOV_CTRL; - bit = PCI_SRIOV_CTRL_MSE; -#endif /* !CONFIG_PCI_IOV */ - } else { - bit = PCI_COMMAND_MEMORY; - pos = PCI_COMMAND; - } - - /* - * Process here is: - * - * 1. Disable Memory space. - * - * 2. Perform an MMIO to the device. This should result in an error - * (CA / UR) being raised by the device which results in an EEH - * PE freeze. Using the in_8() accessor skips the eeh detection hook - * so the freeze hook so the EEH Detection machinery won't be - * triggered here. This is to match the usual behaviour of EEH - * where the HW will asynchronously freeze a PE and it's up to - * the kernel to notice and deal with it. - * - * 3. Turn Memory space back on. This is more important for VFs - * since recovery will probably fail if we don't. For normal - * the COMMAND register is reset as a part of re-initialising - * the device. - * - * Breaking stuff is the point so who cares if it's racy ;) - */ - pci_read_config_word(pdev, pos, &old); - - mapped = ioremap(bar->start, PAGE_SIZE); - if (!mapped) { - pci_err(pdev, "Unable to map MMIO BAR %pR\n", bar); - return -ENXIO; - } - - pci_write_config_word(pdev, pos, old & ~bit); - in_8(mapped); - pci_write_config_word(pdev, pos, old); - - iounmap(mapped); - - return 0; -} - static ssize_t eeh_dev_break_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos) @@ -1835,7 +1834,7 @@ static ssize_t eeh_dev_break_write(struct file *filp, if (IS_ERR(pdev)) return PTR_ERR(pdev); - ret = eeh_debugfs_break_device(pdev); + ret = eeh_break_device(pdev); pci_dev_put(pdev); if (ret < 0) @@ -1846,7 +1845,6 @@ static ssize_t eeh_dev_break_write(struct file *filp, static const struct file_operations eeh_dev_break_fops = { .open = simple_open, - .llseek = no_llseek, .write = eeh_dev_break_write, .read = eeh_debugfs_dev_usage, }; @@ -1893,7 +1891,6 @@ static ssize_t eeh_dev_can_recover(struct file *filp, static const struct file_operations eeh_dev_can_recover_fops = { .open = simple_open, - .llseek = no_llseek, .write = eeh_dev_can_recover, .read = eeh_debugfs_dev_usage, }; diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index eaf2f167c342..195b075d116c 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1989,13 +1989,6 @@ INT_DEFINE_END(system_call) INTERRUPT_TO_KERNEL #endif -#ifdef CONFIG_PPC_FAST_ENDIAN_SWITCH -BEGIN_FTR_SECTION - cmpdi r0,0x1ebe - beq- 1f -END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) -#endif - /* We reach here with PACA in r13, r13 in r9. */ mfspr r11,SPRN_SRR0 mfspr r12,SPRN_SRR1 @@ -2015,16 +2008,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) b system_call_common #endif .endif - -#ifdef CONFIG_PPC_FAST_ENDIAN_SWITCH - /* Fast LE/BE switch system call */ -1: mfspr r12,SPRN_SRR1 - xori r12,r12,MSR_LE - mtspr SPRN_SRR1,r12 - mr r13,r9 - RFI_TO_USER /* return to userspace */ - b . /* prevent speculative execution */ -#endif .endm EXC_REAL_BEGIN(system_call, 0xc00, 0x100) diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index ac74321b1192..56c5ebe21b99 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -40,16 +40,6 @@ #include "head_32.h" -.macro compare_to_kernel_boundary scratch, addr -#if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000 -/* By simply checking Address >= 0x80000000, we know if its a kernel address */ - not. \scratch, \addr -#else - rlwinm \scratch, \addr, 16, 0xfff8 - cmpli cr0, \scratch, PAGE_OFFSET@h -#endif -.endm - #define PAGE_SHIFT_512K 19 #define PAGE_SHIFT_8M 23 @@ -199,18 +189,7 @@ instruction_counter: mfspr r10, SPRN_SRR0 /* Get effective address of fault */ INVALIDATE_ADJACENT_PAGES_CPU15(r10, r11) mtspr SPRN_MD_EPN, r10 -#ifdef CONFIG_EXECMEM - mfcr r11 - compare_to_kernel_boundary r10, r10 -#endif mfspr r10, SPRN_M_TWB /* Get level 1 table */ -#ifdef CONFIG_EXECMEM - blt+ 3f - rlwinm r10, r10, 0, 20, 31 - oris r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha -3: - mtcr r11 -#endif lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */ mtspr SPRN_MD_TWC, r11 mfspr r10, SPRN_MD_TWC @@ -248,19 +227,12 @@ instruction_counter: START_EXCEPTION(INTERRUPT_DATA_TLB_MISS_8xx, DataStoreTLBMiss) mtspr SPRN_SPRG_SCRATCH2, r10 mtspr SPRN_M_TW, r11 - mfcr r11 /* If we are faulting a kernel address, we have to use the * kernel page tables. */ mfspr r10, SPRN_MD_EPN - compare_to_kernel_boundary r10, r10 mfspr r10, SPRN_M_TWB /* Get level 1 table */ - blt+ 3f - rlwinm r10, r10, 0, 20, 31 - oris r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha -3: - mtcr r11 lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r10) /* Get level 1 entry */ mtspr SPRN_MD_TWC, r11 @@ -332,15 +304,19 @@ instruction_counter: cmpwi cr1, r11, RPN_PATTERN beq- cr1, FixupDAR /* must be a buggy dcbX, icbi insn. */ DARFixed:/* Return from dcbx instruction bug workaround */ + mfspr r11, SPRN_DSISR + rlwinm r11, r11, 0, DSISR_NOHPTE + cmpwi cr1, r11, 0 + beq+ cr1, .Ldtlbie + mfspr r11, SPRN_DAR + tlbie r11 + rlwinm r11, r11, 16, 0xffff + cmplwi cr1, r11, TASK_SIZE@h + bge- cr1, FixupPGD +.Ldtlbie: EXCEPTION_PROLOG_1 /* 0x300 is DataAccess exception, needed by bad_page_fault() */ EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataTLBError handle_dar_dsisr=1 - lwz r4, _DAR(r11) - lwz r5, _DSISR(r11) - andis. r10,r5,DSISR_NOHPTE@h - beq+ .Ldtlbie - tlbie r4 -.Ldtlbie: prepare_transfer_to_handler bl do_page_fault b interrupt_return @@ -394,6 +370,30 @@ DARFixed:/* Return from dcbx instruction bug workaround */ __HEAD . = 0x2000 +FixupPGD: + mtspr SPRN_M_TW, r10 + mfspr r10, SPRN_DAR + mtspr SPRN_MD_EPN, r10 + mfspr r11, SPRN_M_TWB /* Get level 1 table */ + lwz r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ + cmpwi cr1, r10, 0 + bne cr1, 1f + + rlwinm r10, r11, 0, 20, 31 + oris r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha + lwz r10, (swapper_pg_dir - PAGE_OFFSET)@l(r10) /* Get the level 1 entry */ + cmpwi cr1, r10, 0 + beq cr1, 1f + stw r10, (swapper_pg_dir - PAGE_OFFSET)@l(r11) /* Set the level 1 entry */ + mfspr r10, SPRN_M_TW + mtcr r10 + mfspr r10, SPRN_SPRG_SCRATCH0 + mfspr r11, SPRN_SPRG_SCRATCH1 + rfi +1: + mfspr r10, SPRN_M_TW + b .Ldtlbie + /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions * by decoding the registers used by the dcbx instruction and adding them. * DAR is set to the calculated address. @@ -404,7 +404,7 @@ FixupDAR:/* Entry point for dcbx workaround. */ mfspr r10, SPRN_SRR0 mtspr SPRN_MD_EPN, r10 rlwinm r11, r10, 16, 0xfff8 - cmpli cr1, r11, PAGE_OFFSET@h + cmpli cr1, r11, TASK_SIZE@h mfspr r11, SPRN_M_TWB /* Get level 1 table */ blt+ cr1, 3f @@ -494,6 +494,7 @@ FixupDAR:/* Entry point for dcbx workaround. */ bctr /* jump into table */ 152: mfdar r11 + mtdar r10 mtctr r11 /* restore ctr reg from DAR */ mfspr r11, SPRN_SPRG_THREAD stw r10, DAR(r11) @@ -587,6 +588,10 @@ start_here: lis r0, (MD_TWAM | MD_RSV4I)@h mtspr SPRN_MD_CTR, r0 #endif +#ifndef CONFIG_PIN_TLB_TEXT + li r0, 0 + mtspr SPRN_MI_CTR, r0 +#endif #if !defined(CONFIG_PIN_TLB_DATA) && !defined(CONFIG_PIN_TLB_IMMR) lis r0, MD_TWAM@h mtspr SPRN_MD_CTR, r0 @@ -683,6 +688,7 @@ SYM_FUNC_START_LOCAL(initial_mmu) blr SYM_FUNC_END(initial_mmu) +#ifdef CONFIG_PIN_TLB _GLOBAL(mmu_pin_tlb) lis r9, (1f - PAGE_OFFSET)@h ori r9, r9, (1f - PAGE_OFFSET)@l @@ -704,6 +710,7 @@ _GLOBAL(mmu_pin_tlb) mtspr SPRN_MD_CTR, r6 tlbia +#ifdef CONFIG_PIN_TLB_TEXT LOAD_REG_IMMEDIATE(r5, 28 << 8) LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET) LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED) @@ -724,6 +731,7 @@ _GLOBAL(mmu_pin_tlb) bdnzt lt, 2b lis r0, MI_RSV4I@h mtspr SPRN_MI_CTR, r0 +#endif LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM) #ifdef CONFIG_PIN_TLB_DATA @@ -783,3 +791,4 @@ _GLOBAL(mmu_pin_tlb) mtspr SPRN_SRR1, r10 mtspr SPRN_SRR0, r11 rfi +#endif diff --git a/arch/powerpc/kernel/head_book3s_32.S b/arch/powerpc/kernel/head_book3s_32.S index 57196883a00e..cb2bca76be53 100644 --- a/arch/powerpc/kernel/head_book3s_32.S +++ b/arch/powerpc/kernel/head_book3s_32.S @@ -411,39 +411,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) */ . = INTERRUPT_INST_TLB_MISS_603 InstructionTLBMiss: -/* - * r0: userspace flag (later scratch) - * r1: linux style pte ( later becomes ppc hardware pte ) - * r2: ptr to linux-style pte - * r3: fault address - */ /* Get PTE (linux-style) and check access */ - mfspr r3,SPRN_IMISS -#ifdef CONFIG_EXECMEM - lis r1, TASK_SIZE@h /* check if kernel address */ - cmplw 0,r1,r3 -#endif + mfspr r0,SPRN_IMISS mfspr r2, SPRN_SDR1 li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC rlwinm r2, r2, 28, 0xfffff000 + rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ + lwz r2,0(r2) /* get pmd entry */ #ifdef CONFIG_EXECMEM - li r0, 3 - bgt- 112f - lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r0, 0 - addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ + rlwinm r3, r0, 4, 0xf + subi r3, r3, (TASK_SIZE >> 28) & 0xf #endif -112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ - lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ beq- InstructionAddressInvalid /* return if no mapping */ - rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ + rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ lwz r2,0(r2) /* get linux-style pte */ andc. r1,r1,r2 /* check access & ~permission */ bne- InstructionAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ #ifdef CONFIG_EXECMEM - rlwimi r2, r0, 0, 31, 31 /* userspace ? -> PP lsb */ + rlwimi r2, r3, 1, 31, 31 /* userspace ? -> PP lsb */ #endif ori r1, r1, 0xe06 /* clear out reserved bits */ andc r1, r2, r1 /* PP = user? 1 : 0 */ @@ -451,7 +438,7 @@ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 - tlbli r3 + tlbli r0 mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ mtcrf 0x80,r3 rfi @@ -480,35 +467,24 @@ InstructionAddressInvalid: */ . = INTERRUPT_DATA_LOAD_TLB_MISS_603 DataLoadTLBMiss: -/* - * r0: userspace flag (later scratch) - * r1: linux style pte ( later becomes ppc hardware pte ) - * r2: ptr to linux-style pte - * r3: fault address - */ /* Get PTE (linux-style) and check access */ - mfspr r3,SPRN_DMISS - lis r1, TASK_SIZE@h /* check if kernel address */ - cmplw 0,r1,r3 + mfspr r0,SPRN_DMISS mfspr r2, SPRN_SDR1 - li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ - rlwinm r2, r2, 28, 0xfffff000 - li r0, 3 - bgt- 112f - lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r0, 0 - addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ -112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ - lwz r2,0(r2) /* get pmd entry */ + rlwinm r1, r2, 28, 0xfffff000 + rlwimi r1,r0,12,20,29 /* insert top 10 bits of address */ + lwz r2,0(r1) /* get pmd entry */ + rlwinm r3, r0, 4, 0xf rlwinm. r2,r2,0,0,19 /* extract address of pte page */ - beq- DataAddressInvalid /* return if no mapping */ - rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ + subi r3, r3, (TASK_SIZE >> 28) & 0xf + beq- 2f /* bail if no mapping */ +1: rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ lwz r2,0(r2) /* get linux-style pte */ + li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ andc. r1,r1,r2 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ rlwinm r1,r2,32-9,30,30 /* _PAGE_WRITE -> PP msb */ - rlwimi r2,r0,0,30,31 /* userspace ? -> PP */ + rlwimi r2,r3,2,30,31 /* userspace ? -> PP */ rlwimi r1,r2,32-3,24,24 /* _PAGE_WRITE -> _PAGE_DIRTY */ xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */ ori r1,r1,0xe04 /* clear out reserved bits */ @@ -518,25 +494,35 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mtspr SPRN_RPA,r1 BEGIN_MMU_FTR_SECTION - li r0,1 + li r3,1 mfspr r1,SPRN_SPRG_603_LRU - rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ - slw r0,r0,r2 - xor r1,r0,r1 - srw r0,r1,r2 + rlwinm r2,r0,20,27,31 /* Get Address bits 15:19 */ + slw r3,r3,r2 + xor r1,r3,r1 + srw r3,r1,r2 mtspr SPRN_SPRG_603_LRU,r1 mfspr r2,SPRN_SRR1 - rlwimi r2,r0,31-14,14,14 + rlwimi r2,r3,31-14,14,14 mtspr SPRN_SRR1,r2 mtcrf 0x80,r2 - tlbld r3 + tlbld r0 rfi MMU_FTR_SECTION_ELSE mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ mtcrf 0x80,r2 - tlbld r3 + tlbld r0 rfi ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) + +2: lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha + addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ + rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ + lwz r2,0(r2) /* get pmd entry */ + cmpwi cr0,r2,0 + beq- DataAddressInvalid /* return if no mapping */ + stw r2,0(r1) + rlwinm. r2,r2,0,0,19 /* extract address of pte page */ + b 1b DataAddressInvalid: mfspr r3,SPRN_SRR1 rlwinm r1,r3,9,6,6 /* Get load/store bit */ @@ -560,34 +546,24 @@ DataAddressInvalid: */ . = INTERRUPT_DATA_STORE_TLB_MISS_603 DataStoreTLBMiss: -/* - * r0: userspace flag (later scratch) - * r1: linux style pte ( later becomes ppc hardware pte ) - * r2: ptr to linux-style pte - * r3: fault address - */ /* Get PTE (linux-style) and check access */ - mfspr r3,SPRN_DMISS - lis r1, TASK_SIZE@h /* check if kernel address */ - cmplw 0,r1,r3 + mfspr r0,SPRN_DMISS mfspr r2, SPRN_SDR1 - li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED - rlwinm r2, r2, 28, 0xfffff000 - li r0, 3 - bgt- 112f - lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r0, 0 - addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ -112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ - lwz r2,0(r2) /* get pmd entry */ + rlwinm r1, r2, 28, 0xfffff000 + rlwimi r1,r0,12,20,29 /* insert top 10 bits of address */ + lwz r2,0(r1) /* get pmd entry */ + rlwinm r3, r0, 4, 0xf rlwinm. r2,r2,0,0,19 /* extract address of pte page */ - beq- DataAddressInvalid /* return if no mapping */ - rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ + subi r3, r3, (TASK_SIZE >> 28) & 0xf + beq- 2f /* bail if no mapping */ +1: + rlwimi r2,r0,22,20,29 /* insert next 10 bits of address */ lwz r2,0(r2) /* get linux-style pte */ + li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED andc. r1,r1,r2 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ - rlwimi r2,r0,0,31,31 /* userspace ? -> PP lsb */ + rlwimi r2,r3,1,31,31 /* userspace ? -> PP lsb */ li r1,0xe06 /* clear out reserved bits & PP msb */ andc r1,r2,r1 /* PP = user? 1: 0 */ BEGIN_FTR_SECTION @@ -597,26 +573,36 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ mtcrf 0x80,r2 BEGIN_MMU_FTR_SECTION - li r0,1 + li r3,1 mfspr r1,SPRN_SPRG_603_LRU - rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ - slw r0,r0,r2 - xor r1,r0,r1 - srw r0,r1,r2 + rlwinm r2,r0,20,27,31 /* Get Address bits 15:19 */ + slw r3,r3,r2 + xor r1,r3,r1 + srw r3,r1,r2 mtspr SPRN_SPRG_603_LRU,r1 mfspr r2,SPRN_SRR1 - rlwimi r2,r0,31-14,14,14 + rlwimi r2,r3,31-14,14,14 mtspr SPRN_SRR1,r2 mtcrf 0x80,r2 - tlbld r3 + tlbld r0 rfi MMU_FTR_SECTION_ELSE mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ mtcrf 0x80,r2 - tlbld r3 + tlbld r0 rfi ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) +2: lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha + addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ + rlwimi r2,r0,12,20,29 /* insert top 10 bits of address */ + lwz r2,0(r2) /* get pmd entry */ + cmpwi cr0,r2,0 + beq- DataAddressInvalid /* return if no mapping */ + stw r2,0(r1) + rlwinm r2,r2,0,0,19 /* extract address of pte page */ + b 1b + #ifndef CONFIG_ALTIVEC #define altivec_assist_exception unknown_exception #endif diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c index eca293794a1e..af62ec974b97 100644 --- a/arch/powerpc/kernel/interrupt.c +++ b/arch/powerpc/kernel/interrupt.c @@ -266,7 +266,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3, unsigned long ret = 0; bool is_not_scv = !IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !scv; - CT_WARN_ON(ct_state() == CONTEXT_USER); + CT_WARN_ON(ct_state() == CT_STATE_USER); kuap_assert_locked(); @@ -344,7 +344,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs) BUG_ON(regs_is_unrecoverable(regs)); BUG_ON(arch_irq_disabled_regs(regs)); - CT_WARN_ON(ct_state() == CONTEXT_USER); + CT_WARN_ON(ct_state() == CT_STATE_USER); /* * We don't need to restore AMR on the way back to userspace for KUAP. @@ -386,7 +386,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) if (!IS_ENABLED(CONFIG_PPC_BOOK3E_64) && TRAP(regs) != INTERRUPT_PROGRAM && TRAP(regs) != INTERRUPT_PERFMON) - CT_WARN_ON(ct_state() == CONTEXT_USER); + CT_WARN_ON(ct_state() == CT_STATE_USER); kuap = kuap_get_and_assert_locked(); diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 14c5ddec3056..f8aa91bc3b17 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -228,16 +228,6 @@ static nokprobe_inline void set_current_kprobe(struct kprobe *p, struct pt_regs kcb->kprobe_saved_msr = regs->msr; } -void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) -{ - ri->ret_addr = (kprobe_opcode_t *)regs->link; - ri->fp = NULL; - - /* Replace the return addr with trampoline addr */ - regs->link = (unsigned long)__kretprobe_trampoline; -} -NOKPROBE_SYMBOL(arch_prepare_kretprobe); - static int try_to_emulate(struct kprobe *p, struct pt_regs *regs) { int ret; @@ -395,49 +385,6 @@ no_kprobe: NOKPROBE_SYMBOL(kprobe_handler); /* - * Function return probe trampoline: - * - init_kprobes() establishes a probepoint here - * - When the probed function returns, this probe - * causes the handlers to fire - */ -asm(".global __kretprobe_trampoline\n" - ".type __kretprobe_trampoline, @function\n" - "__kretprobe_trampoline:\n" - "nop\n" - "blr\n" - ".size __kretprobe_trampoline, .-__kretprobe_trampoline\n"); - -/* - * Called when the probe at kretprobe trampoline is hit - */ -static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) -{ - unsigned long orig_ret_address; - - orig_ret_address = __kretprobe_trampoline_handler(regs, NULL); - /* - * We get here through one of two paths: - * 1. by taking a trap -> kprobe_handler() -> here - * 2. by optprobe branch -> optimized_callback() -> opt_pre_handler() -> here - * - * When going back through (1), we need regs->nip to be setup properly - * as it is used to determine the return address from the trap. - * For (2), since nip is not honoured with optprobes, we instead setup - * the link register properly so that the subsequent 'blr' in - * __kretprobe_trampoline jumps back to the right instruction. - * - * For nip, we should set the address to the previous instruction since - * we end up emulating it in kprobe_handler(), which increments the nip - * again. - */ - regs_set_return_ip(regs, orig_ret_address - 4); - regs->link = orig_ret_address; - - return 0; -} -NOKPROBE_SYMBOL(trampoline_probe_handler); - -/* * Called after single-stepping. p->addr is the address of the * instruction whose first byte has been replaced by the "breakpoint" * instruction. To avoid the SMP problems that can occur when we @@ -539,19 +486,9 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr) } NOKPROBE_SYMBOL(kprobe_fault_handler); -static struct kprobe trampoline_p = { - .addr = (kprobe_opcode_t *) &__kretprobe_trampoline, - .pre_handler = trampoline_probe_handler -}; - -int __init arch_init_kprobes(void) -{ - return register_kprobe(&trampoline_p); -} - int arch_trampoline_kprobe(struct kprobe *p) { - if (p->addr == (kprobe_opcode_t *)&__kretprobe_trampoline) + if (p->addr == (kprobe_opcode_t *)&arch_rethook_trampoline) return 1; return 0; diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 7112adc597a8..e9bab599d0c2 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -651,12 +651,11 @@ static inline int create_stub(const Elf64_Shdr *sechdrs, // func_desc_t is 8 bytes if ABIv2, else 16 bytes desc = func_desc(addr); for (i = 0; i < sizeof(func_desc_t) / sizeof(u32); i++) { - if (patch_instruction(((u32 *)&entry->funcdata) + i, - ppc_inst(((u32 *)(&desc))[i]))) + if (patch_u32(((u32 *)&entry->funcdata) + i, ((u32 *)&desc)[i])) return 0; } - if (patch_instruction(&entry->magic, ppc_inst(STUB_MAGIC))) + if (patch_u32(&entry->magic, STUB_MAGIC)) return 0; return 1; diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index e385d3164648..f9c6568a9137 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -73,7 +73,7 @@ static const char *nvram_os_partitions[] = { }; static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason); + struct kmsg_dump_detail *detail); static struct kmsg_dumper nvram_kmsg_dumper = { .dump = oops_to_nvram @@ -643,7 +643,7 @@ void __init nvram_init_oops_partition(int rtas_partition_exists) * partition. If that's too much, go back and capture uncompressed text. */ static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason) + struct kmsg_dump_detail *detail) { struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; static unsigned int oops_count = 0; @@ -655,7 +655,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; int rc = -1; - switch (reason) { + switch (detail->reason) { case KMSG_DUMP_SHUTDOWN: /* These are almost always orderly shutdowns. */ return; @@ -671,7 +671,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, break; default: pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", - __func__, (int) reason); + __func__, (int) detail->reason); return; } diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 004fae2044a3..c0b351d61058 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -56,7 +56,7 @@ static unsigned long can_optimize(struct kprobe *p) * has a 'nop' instruction, which can be emulated. * So further checks can be skipped. */ - if (p->addr == (kprobe_opcode_t *)&__kretprobe_trampoline) + if (p->addr == (kprobe_opcode_t *)&arch_rethook_trampoline) return addr + sizeof(kprobe_opcode_t); /* diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c index b109cd7b5d01..3816a2bf2b84 100644 --- a/arch/powerpc/kernel/proc_powerpc.c +++ b/arch/powerpc/kernel/proc_powerpc.c @@ -4,6 +4,7 @@ */ #include <linux/init.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/proc_fs.h> #include <linux/kernel.h> @@ -12,9 +13,10 @@ #include <asm/machdep.h> #include <asm/vdso_datapage.h> #include <asm/rtas.h> +#include <asm/systemcfg.h> #include <linux/uaccess.h> -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG static loff_t page_map_seek(struct file *file, loff_t off, int whence) { @@ -33,10 +35,9 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) return -EINVAL; - remap_pfn_range(vma, vma->vm_start, - __pa(pde_data(file_inode(file))) >> PAGE_SHIFT, - PAGE_SIZE, vma->vm_page_prot); - return 0; + return remap_pfn_range(vma, vma->vm_start, + __pa(pde_data(file_inode(file))) >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot); } static const struct proc_ops page_map_proc_ops = { @@ -45,13 +46,35 @@ static const struct proc_ops page_map_proc_ops = { .proc_mmap = page_map_mmap, }; +static union { + struct systemcfg data; + u8 page[PAGE_SIZE]; +} systemcfg_data_store __page_aligned_data; +struct systemcfg *systemcfg = &systemcfg_data_store.data; static int __init proc_ppc64_init(void) { struct proc_dir_entry *pde; + strcpy((char *)systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); + systemcfg->version.major = SYSTEMCFG_MAJOR; + systemcfg->version.minor = SYSTEMCFG_MINOR; + systemcfg->processor = mfspr(SPRN_PVR); + /* + * Fake the old platform number for pSeries and add + * in LPAR bit if necessary + */ + systemcfg->platform = 0x100; + if (firmware_has_feature(FW_FEATURE_LPAR)) + systemcfg->platform |= 1; + systemcfg->physicalMemorySize = memblock_phys_mem_size(); + systemcfg->dcache_size = ppc64_caches.l1d.size; + systemcfg->dcache_line_size = ppc64_caches.l1d.line_size; + systemcfg->icache_size = ppc64_caches.l1i.size; + systemcfg->icache_line_size = ppc64_caches.l1i.line_size; + pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL, - &page_map_proc_ops, vdso_data); + &page_map_proc_ops, systemcfg); if (!pde) return 1; proc_set_size(pde, PAGE_SIZE); @@ -60,7 +83,7 @@ static int __init proc_ppc64_init(void) } __initcall(proc_ppc64_init); -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64_PROC_SYSTEMCFG */ /* * Create the ppc64 and ppc64/rtas directories early. This allows us to diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3b506d4c55f3..ff61a3e7984c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -72,8 +72,6 @@ #define TM_DEBUG(x...) do { } while(0) #endif -extern unsigned long _get_SP(void); - #ifdef CONFIG_PPC_TRANSACTIONAL_MEM /* * Are we running in "Suspend disabled" mode? If so we have to block any @@ -2177,10 +2175,10 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, return 0; } +#ifdef CONFIG_PPC64 static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p, unsigned long nbytes) { -#ifdef CONFIG_PPC64 unsigned long stack_page; unsigned long cpu = task_cpu(p); @@ -2208,10 +2206,26 @@ static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p, if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes) return 1; # endif -#endif return 0; } +#else +static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p, + unsigned long nbytes) +{ + unsigned long stack_page; + unsigned long cpu = task_cpu(p); + + if (!IS_ENABLED(CONFIG_VMAP_STACK)) + return 0; + + stack_page = (unsigned long)emergency_ctx[cpu] - THREAD_SIZE; + if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + + return 0; +} +#endif /* * validate the stack frame of a particular minimum size, used for when we are diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 0be07ed407c7..88cbe432cad5 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -791,7 +791,7 @@ void __init early_init_devtree(void *params) DBG(" -> early_init_devtree(%px)\n", params); /* Too early to BUG_ON(), do it by hand */ - if (!early_init_dt_verify(params)) + if (!early_init_dt_verify(params, __pa(params))) panic("BUG: Failed verifying flat device tree, bad version?"); of_scan_flat_dt(early_init_dt_scan_model, NULL); diff --git a/arch/powerpc/kernel/rethook.c b/arch/powerpc/kernel/rethook.c new file mode 100644 index 000000000000..5f5f47ae82cf --- /dev/null +++ b/arch/powerpc/kernel/rethook.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PowerPC implementation of rethook. This depends on kprobes. + */ + +#include <linux/kprobes.h> +#include <linux/rethook.h> + +/* + * Function return trampoline: + * - init_kprobes() establishes a probepoint here + * - When the probed function returns, this probe + * causes the handlers to fire + */ +asm(".global arch_rethook_trampoline\n" + ".type arch_rethook_trampoline, @function\n" + "arch_rethook_trampoline:\n" + "nop\n" + "blr\n" + ".size arch_rethook_trampoline, .-arch_rethook_trampoline\n"); + +/* + * Called when the probe at kretprobe trampoline is hit + */ +static int trampoline_rethook_handler(struct kprobe *p, struct pt_regs *regs) +{ + return !rethook_trampoline_handler(regs, regs->gpr[1]); +} +NOKPROBE_SYMBOL(trampoline_rethook_handler); + +void arch_rethook_prepare(struct rethook_node *rh, struct pt_regs *regs, bool mcount) +{ + rh->ret_addr = regs->link; + rh->frame = regs->gpr[1]; + + /* Replace the return addr with trampoline addr */ + regs->link = (unsigned long)arch_rethook_trampoline; +} +NOKPROBE_SYMBOL(arch_rethook_prepare); + +/* This is called from rethook_trampoline_handler(). */ +void arch_rethook_fixup_return(struct pt_regs *regs, unsigned long orig_ret_address) +{ + /* + * We get here through one of two paths: + * 1. by taking a trap -> kprobe_handler() -> here + * 2. by optprobe branch -> optimized_callback() -> opt_pre_handler() -> here + * + * When going back through (1), we need regs->nip to be setup properly + * as it is used to determine the return address from the trap. + * For (2), since nip is not honoured with optprobes, we instead setup + * the link register properly so that the subsequent 'blr' in + * arch_rethook_trampoline jumps back to the right instruction. + * + * For nip, we should set the address to the previous instruction since + * we end up emulating it in kprobe_handler(), which increments the nip + * again. + */ + regs_set_return_ip(regs, orig_ret_address - 4); + regs->link = orig_ret_address; +} +NOKPROBE_SYMBOL(arch_rethook_fixup_return); + +static struct kprobe trampoline_p = { + .addr = (kprobe_opcode_t *) &arch_rethook_trampoline, + .pre_handler = trampoline_rethook_handler +}; + +/* rethook initializer */ +int __init arch_init_kprobes(void) +{ + return register_kprobe(&trampoline_p); +} diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index f7e86e09c49f..d31c9799cab2 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1390,21 +1390,14 @@ bool __ref rtas_busy_delay(int status) */ ms = clamp(ms, 1U, 1000U); /* - * The delay hint is an order-of-magnitude suggestion, not - * a minimum. It is fine, possibly even advantageous, for - * us to pause for less time than hinted. For small values, - * use usleep_range() to ensure we don't sleep much longer - * than actually needed. - * - * See Documentation/timers/timers-howto.rst for - * explanation of the threshold used here. In effect we use - * usleep_range() for 9900 and 9901, msleep() for - * 9902-9905. + * The delay hint is an order-of-magnitude suggestion, not a + * minimum. It is fine, possibly even advantageous, for us to + * pause for less time than hinted. To make sure pause time will + * not be way longer than requested independent of HZ + * configuration, use fsleep(). See fsleep() for details of + * used sleeping functions. */ - if (ms <= 20) - usleep_range(ms * 100, ms * 1000); - else - msleep(ms); + fsleep(ms * 1000); break; case RTAS_BUSY: ret = true; diff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c index eb3c053f323f..fbeb1cbac01b 100644 --- a/arch/powerpc/kernel/secvar-sysfs.c +++ b/arch/powerpc/kernel/secvar-sysfs.c @@ -125,7 +125,7 @@ static const struct attribute_group secvar_attr_group = { }; __ATTRIBUTE_GROUPS(secvar_attr); -static struct kobj_type secvar_ktype = { +static const struct kobj_type secvar_ktype = { .sysfs_ops = &kobj_sysfs_ops, .default_groups = secvar_attr_groups, }; diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 943430077375..0b732d3b283b 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -67,6 +67,7 @@ #include <asm/cpu_has_feature.h> #include <asm/kasan.h> #include <asm/mce.h> +#include <asm/systemcfg.h> #include "setup.h" @@ -560,7 +561,9 @@ void __init smp_setup_cpu_maps(void) out: of_node_put(dn); } - vdso_data->processorCount = num_present_cpus(); +#endif +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG + systemcfg->processorCount = num_present_cpus(); #endif /* CONFIG_PPC64 */ /* Initialize CPU <=> thread mapping/ diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 46e6d2cd7a2d..5ac7084eebc0 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -61,6 +61,7 @@ #include <asm/ftrace.h> #include <asm/kup.h> #include <asm/fadump.h> +#include <asm/systemcfg.h> #include <trace/events/ipi.h> @@ -1166,7 +1167,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) cpu_smt_set_num_threads(num_threads, threads_per_core); } -void smp_prepare_boot_cpu(void) +void __init smp_prepare_boot_cpu(void) { BUG_ON(smp_processor_id() != boot_cpuid); #ifdef CONFIG_PPC64 @@ -1186,8 +1187,8 @@ int generic_cpu_disable(void) return -EBUSY; set_cpu_online(cpu, false); -#ifdef CONFIG_PPC64 - vdso_data->processorCount--; +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG + systemcfg->processorCount--; #endif /* Update affinity of all IRQs previously aimed at this CPU */ irq_migrate_all_off_this_cpu(); @@ -1642,10 +1643,12 @@ void start_secondary(void *unused) secondary_cpu_time_init(); -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG if (system_state == SYSTEM_RUNNING) - vdso_data->processorCount++; + systemcfg->processorCount++; +#endif +#ifdef CONFIG_PPC64 vdso_getcpu_init(); #endif set_numa_node(numa_cpu_lookup_table[cpu]); diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index e6a958a5da27..90882b5175cd 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c @@ -21,6 +21,7 @@ #include <asm/processor.h> #include <linux/ftrace.h> #include <asm/kprobes.h> +#include <linux/rethook.h> #include <asm/paca.h> @@ -133,12 +134,13 @@ int __no_sanitize_address arch_stack_walk_reliable(stack_trace_consume_fn consum * arch-dependent code, they are generic. */ ip = ftrace_graph_ret_addr(task, &graph_idx, ip, stack); -#ifdef CONFIG_KPROBES + /* * Mark stacktraces with kretprobed functions on them * as unreliable. */ - if (ip == (unsigned long)__kretprobe_trampoline) +#ifdef CONFIG_RETHOOK + if (ip == (unsigned long)arch_rethook_trampoline) return -EINVAL; #endif diff --git a/arch/powerpc/kernel/static_call.c b/arch/powerpc/kernel/static_call.c index 863a7aa24650..1502b7e439ca 100644 --- a/arch/powerpc/kernel/static_call.c +++ b/arch/powerpc/kernel/static_call.c @@ -17,7 +17,7 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail) mutex_lock(&text_mutex); if (func && !is_short) { - err = patch_instruction(tramp + PPC_SCT_DATA, ppc_inst(target)); + err = patch_ulong(tramp + PPC_SCT_DATA, target); if (err) goto out; } diff --git a/arch/powerpc/kernel/syscall.c b/arch/powerpc/kernel/syscall.c index f6f868e817e6..be159ad4b77b 100644 --- a/arch/powerpc/kernel/syscall.c +++ b/arch/powerpc/kernel/syscall.c @@ -27,7 +27,7 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0) trace_hardirqs_off(); /* finish reconciling */ - CT_WARN_ON(ct_state() == CONTEXT_KERNEL); + CT_WARN_ON(ct_state() == CT_STATE_KERNEL); user_exit_irqoff(); BUG_ON(regs_is_unrecoverable(regs)); diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index ebae8415dfbb..d8b4ab78bef0 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -553,3 +553,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0ff9f038e800..0727332ad86f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -71,11 +71,11 @@ #include <asm/vdso_datapage.h> #include <asm/firmware.h> #include <asm/mce.h> +#include <asm/systemcfg.h> /* powerpc clocksource/clockevent code */ #include <linux/clockchips.h> -#include <linux/timekeeper_internal.h> static u64 timebase_read(struct clocksource *); static struct clocksource clocksource_timebase = { @@ -951,6 +951,9 @@ void __init time_init(void) } vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG + systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; +#endif /* initialise and enable the large decrementer (if we have one) */ set_decrementer_max(); diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index d8d6b4fd9a14..df41f4a7c738 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -421,7 +421,7 @@ int __init ftrace_dyn_arch_init(void) void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - unsigned long sp = fregs->regs.gpr[1]; + unsigned long sp = arch_ftrace_regs(fregs)->regs.gpr[1]; int bit; if (unlikely(ftrace_graph_is_dead())) @@ -439,6 +439,6 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, ftrace_test_recursion_unlock(bit); out: - fregs->regs.link = parent_ip; + arch_ftrace_regs(fregs)->regs.link = parent_ip; } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/powerpc/kernel/trace/ftrace_64_pg.c b/arch/powerpc/kernel/trace/ftrace_64_pg.c index 12fab1803bcf..d3c5552e4984 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_pg.c +++ b/arch/powerpc/kernel/trace/ftrace_64_pg.c @@ -829,7 +829,7 @@ out: void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]); + arch_ftrace_regs(fregs)->regs.link = __prepare_ftrace_return(parent_ip, ip, arch_ftrace_regs(fregs)->regs.gpr[1]); } #else unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 28d6472c380a..edf5cabe5dfd 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -121,7 +121,7 @@ static void pmac_backlight_unblank(void) props = &pmac_backlight->props; props->brightness = props->max_brightness; - props->power = FB_BLANK_UNBLANK; + props->power = BACKLIGHT_POWER_ON; backlight_update_status(pmac_backlight); } mutex_unlock(&pmac_backlight_mutex); diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 7a2ff9010f17..924f7f4fa597 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -16,7 +16,6 @@ #include <linux/user.h> #include <linux/elf.h> #include <linux/security.h> -#include <linux/memblock.h> #include <linux/syscalls.h> #include <linux/time_namespace.h> #include <vdso/datapage.h> @@ -81,6 +80,21 @@ static int vdso64_mremap(const struct vm_special_mapping *sm, struct vm_area_str return vdso_mremap(sm, new_vma, &vdso64_end - &vdso64_start); } +static void vdso_close(const struct vm_special_mapping *sm, struct vm_area_struct *vma) +{ + struct mm_struct *mm = vma->vm_mm; + + /* + * close() is called for munmap() but also for mremap(). In the mremap() + * case the vdso pointer has already been updated by the mremap() hook + * above, so it must not be set to NULL here. + */ + if (vma->vm_start != (unsigned long)mm->context.vdso) + return; + + mm->context.vdso = NULL; +} + static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, struct vm_area_struct *vma, struct vm_fault *vmf); @@ -92,11 +106,13 @@ static struct vm_special_mapping vvar_spec __ro_after_init = { static struct vm_special_mapping vdso32_spec __ro_after_init = { .name = "[vdso]", .mremap = vdso32_mremap, + .close = vdso_close, }; static struct vm_special_mapping vdso64_spec __ro_after_init = { .name = "[vdso]", .mremap = vdso64_mremap, + .close = vdso_close, }; #ifdef CONFIG_TIME_NS @@ -197,13 +213,6 @@ static int __arch_setup_additional_pages(struct linux_binprm *bprm, int uses_int /* Add required alignment. */ vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT); - /* - * Put vDSO base into mm struct. We need to do this before calling - * install_special_mapping or the perf counter mmap tracking code - * will fail to recognise it as a vDSO. - */ - mm->context.vdso = (void __user *)vdso_base + vvar_size; - vma = _install_special_mapping(mm, vdso_base, vvar_size, VM_READ | VM_MAYREAD | VM_IO | VM_DONTDUMP | VM_PFNMAP, &vvar_spec); @@ -223,10 +232,15 @@ static int __arch_setup_additional_pages(struct linux_binprm *bprm, int uses_int vma = _install_special_mapping(mm, vdso_base + vvar_size, vdso_size, VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, vdso_spec); - if (IS_ERR(vma)) + if (IS_ERR(vma)) { do_munmap(mm, vdso_base, vvar_size, NULL); + return PTR_ERR(vma); + } + + // Now that the mappings are in place, set the mm VDSO pointer + mm->context.vdso = (void __user *)vdso_base + vvar_size; - return PTR_ERR_OR_ZERO(vma); + return 0; } int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) @@ -240,8 +254,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) return -EINTR; rc = __arch_setup_additional_pages(bprm, uses_interp); - if (rc) - mm->context.vdso = NULL; mmap_write_unlock(mm); return rc; @@ -336,25 +348,6 @@ static struct page ** __init vdso_setup_pages(void *start, void *end) static int __init vdso_init(void) { #ifdef CONFIG_PPC64 - /* - * Fill up the "systemcfg" stuff for backward compatibility - */ - strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); - vdso_data->version.major = SYSTEMCFG_MAJOR; - vdso_data->version.minor = SYSTEMCFG_MINOR; - vdso_data->processor = mfspr(SPRN_PVR); - /* - * Fake the old platform number for pSeries and add - * in LPAR bit if necessary - */ - vdso_data->platform = 0x100; - if (firmware_has_feature(FW_FEATURE_LPAR)) - vdso_data->platform |= 1; - vdso_data->physicalMemorySize = memblock_phys_mem_size(); - vdso_data->dcache_size = ppc64_caches.l1d.size; - vdso_data->dcache_line_size = ppc64_caches.l1d.line_size; - vdso_data->icache_size = ppc64_caches.l1i.size; - vdso_data->icache_line_size = ppc64_caches.l1i.line_size; vdso_data->dcache_block_size = ppc64_caches.l1d.block_size; vdso_data->icache_block_size = ppc64_caches.l1i.block_size; vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size; diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile index 1425b6edc66b..31ca5a547004 100644 --- a/arch/powerpc/kernel/vdso/Makefile +++ b/arch/powerpc/kernel/vdso/Makefile @@ -8,30 +8,21 @@ include $(srctree)/lib/vdso/Makefile obj-vdso32 = sigtramp32-32.o gettimeofday-32.o datapage-32.o cacheflush-32.o note-32.o getcpu-32.o obj-vdso64 = sigtramp64-64.o gettimeofday-64.o datapage-64.o cacheflush-64.o note-64.o getcpu-64.o +obj-vdso32 += getrandom-32.o vgetrandom-chacha-32.o +obj-vdso64 += getrandom-64.o vgetrandom-chacha-64.o + ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y) - CFLAGS_vgettimeofday-32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) - CFLAGS_vgettimeofday-32.o += $(call cc-option, -fno-stack-protector) - CFLAGS_vgettimeofday-32.o += -DDISABLE_BRANCH_PROFILING - CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables - CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE) - CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc - # This flag is supported by clang for 64-bit but not 32-bit so it will cause - # an unused command line flag warning for this file. - ifdef CONFIG_CC_IS_CLANG - CFLAGS_REMOVE_vgettimeofday-32.o += -fno-stack-clash-protection - endif - CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) - CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) - CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector) - CFLAGS_vgettimeofday-64.o += -DDISABLE_BRANCH_PROFILING - CFLAGS_vgettimeofday-64.o += -ffreestanding -fasynchronous-unwind-tables - CFLAGS_REMOVE_vgettimeofday-64.o = $(CC_FLAGS_FTRACE) # Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true # by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is # compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code # generation is minimal, it will just use r29 instead. - CFLAGS_vgettimeofday-64.o += $(call cc-option, -ffixed-r30) + CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) $(call cc-option, -ffixed-r30) +endif + +ifneq ($(c-getrandom-y),) + CFLAGS_vgetrandom-32.o += -include $(c-getrandom-y) + CFLAGS_vgetrandom-64.o += -include $(c-getrandom-y) endif # Build rules @@ -42,12 +33,18 @@ else VDSOCC := $(CC) endif -targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday-32.o +targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday-32.o vgetrandom-32.o +targets += crtsavres-32.o obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) -targets += $(obj-vdso64) vdso64.so.dbg vgettimeofday-64.o +targets += $(obj-vdso64) vdso64.so.dbg vgettimeofday-64.o vgetrandom-64.o obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) -ccflags-y := -fno-common -fno-builtin +ccflags-y := -fno-common -fno-builtin -DBUILD_VDSO +ccflags-y += $(DISABLE_LATENT_ENTROPY_PLUGIN) +ccflags-y += $(call cc-option, -fno-stack-protector) +ccflags-y += -DDISABLE_BRANCH_PROFILING +ccflags-y += -ffreestanding -fasynchronous-unwind-tables +ccflags-remove-y := $(CC_FLAGS_FTRACE) ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS) ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld) ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) @@ -56,6 +53,12 @@ ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WAR ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS)) CC32FLAGS := -m32 +CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc + # This flag is supported by clang for 64-bit but not 32-bit so it will cause + # an unused command line flag warning for this file. +ifdef CONFIG_CC_IS_CLANG +CC32FLAGSREMOVE += -fno-stack-clash-protection +endif LD32FLAGS := -Wl,-soname=linux-vdso32.so.1 AS32FLAGS := -D__VDSO32__ @@ -68,20 +71,26 @@ targets += vdso64.lds CPPFLAGS_vdso64.lds += -P -C # link rule for the .so file, .lds has to be first -$(obj)/vdso32.so.dbg: $(obj)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday-32.o FORCE +$(obj)/vdso32.so.dbg: $(obj)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday-32.o $(obj)/vgetrandom-32.o $(obj)/crtsavres-32.o FORCE $(call if_changed,vdso32ld_and_check) -$(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday-64.o FORCE +$(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday-64.o $(obj)/vgetrandom-64.o FORCE $(call if_changed,vdso64ld_and_check) # assembly rules for the .S files $(obj-vdso32): %-32.o: %.S FORCE $(call if_changed_dep,vdso32as) +$(obj)/crtsavres-32.o: %-32.o: $(srctree)/arch/powerpc/lib/crtsavres.S FORCE + $(call if_changed_dep,vdso32as) $(obj)/vgettimeofday-32.o: %-32.o: %.c FORCE $(call if_changed_dep,vdso32cc) +$(obj)/vgetrandom-32.o: %-32.o: %.c FORCE + $(call if_changed_dep,vdso32cc) $(obj-vdso64): %-64.o: %.S FORCE $(call if_changed_dep,vdso64as) $(obj)/vgettimeofday-64.o: %-64.o: %.c FORCE $(call if_changed_dep,cc_o_c) +$(obj)/vgetrandom-64.o: %-64.o: %.c FORCE + $(call if_changed_dep,cc_o_c) # Generate VDSO offsets using helper script gen-vdso32sym := $(src)/gen_vdso32_offsets.sh @@ -102,7 +111,7 @@ quiet_cmd_vdso32ld_and_check = VDSO32L $@ quiet_cmd_vdso32as = VDSO32A $@ cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $< quiet_cmd_vdso32cc = VDSO32C $@ - cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $< + cmd_vdso32cc = $(VDSOCC) $(filter-out $(CC32FLAGSREMOVE), $(c_flags)) $(CC32FLAGS) -c -o $@ $< quiet_cmd_vdso64ld_and_check = VDSO64L $@ cmd_vdso64ld_and_check = $(VDSOCC) $(ldflags-y) $(LD64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check) diff --git a/arch/powerpc/kernel/vdso/cacheflush.S b/arch/powerpc/kernel/vdso/cacheflush.S index 0085ae464dac..3b2479bd2f9a 100644 --- a/arch/powerpc/kernel/vdso/cacheflush.S +++ b/arch/powerpc/kernel/vdso/cacheflush.S @@ -30,7 +30,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) #ifdef CONFIG_PPC64 mflr r12 .cfi_register lr,r12 - get_datapage r10 + get_realdatapage r10, r11 mtlr r12 .cfi_restore lr #endif diff --git a/arch/powerpc/kernel/vdso/datapage.S b/arch/powerpc/kernel/vdso/datapage.S index db8e167f0166..2b19b6201a33 100644 --- a/arch/powerpc/kernel/vdso/datapage.S +++ b/arch/powerpc/kernel/vdso/datapage.S @@ -28,7 +28,7 @@ V_FUNCTION_BEGIN(__kernel_get_syscall_map) mflr r12 .cfi_register lr,r12 mr. r4,r3 - get_datapage r3 + get_realdatapage r3, r11 mtlr r12 #ifdef __powerpc64__ addi r3,r3,CFG_SYSCALL_MAP64 @@ -52,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq) .cfi_startproc mflr r12 .cfi_register lr,r12 - get_datapage r3 + get_realdatapage r3, r11 #ifndef __powerpc64__ lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) #endif diff --git a/arch/powerpc/kernel/vdso/getrandom.S b/arch/powerpc/kernel/vdso/getrandom.S new file mode 100644 index 000000000000..f3bbf931931c --- /dev/null +++ b/arch/powerpc/kernel/vdso/getrandom.S @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Userland implementation of getrandom() for processes + * for use in the vDSO + * + * Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France + */ +#include <asm/processor.h> +#include <asm/ppc_asm.h> +#include <asm/vdso.h> +#include <asm/vdso_datapage.h> +#include <asm/asm-offsets.h> +#include <asm/unistd.h> + +/* + * The macro sets two stack frames, one for the caller and one for the callee + * because there are no requirement for the caller to set a stack frame when + * calling VDSO so it may have omitted to set one, especially on PPC64 + */ + +.macro cvdso_call funct + .cfi_startproc + PPC_STLU r1, -PPC_MIN_STKFRM(r1) + .cfi_adjust_cfa_offset PPC_MIN_STKFRM + mflr r0 + PPC_STLU r1, -PPC_MIN_STKFRM(r1) + .cfi_adjust_cfa_offset PPC_MIN_STKFRM + PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) + .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF +#ifdef __powerpc64__ + PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) + .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT +#endif + get_realdatapage r8, r11 + addi r8, r8, VDSO_RNG_DATA_OFFSET + bl CFUNC(DOTSYM(\funct)) + PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) +#ifdef __powerpc64__ + PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) + .cfi_restore r2 +#endif + cmpwi r3, 0 + mtlr r0 + addi r1, r1, 2 * PPC_MIN_STKFRM + .cfi_restore lr + .cfi_def_cfa_offset 0 + crclr so + bgelr+ + crset so + neg r3, r3 + blr + .cfi_endproc +.endm + + .text +V_FUNCTION_BEGIN(__kernel_getrandom) + cvdso_call __c_kernel_getrandom +V_FUNCTION_END(__kernel_getrandom) diff --git a/arch/powerpc/kernel/vdso/gettimeofday.S b/arch/powerpc/kernel/vdso/gettimeofday.S index 48fc6658053a..5540d7021fa2 100644 --- a/arch/powerpc/kernel/vdso/gettimeofday.S +++ b/arch/powerpc/kernel/vdso/gettimeofday.S @@ -38,11 +38,7 @@ .else addi r4, r5, VDSO_DATA_OFFSET .endif -#ifdef __powerpc64__ bl CFUNC(DOTSYM(\funct)) -#else - bl \funct -#endif PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) #ifdef __powerpc64__ PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) @@ -118,16 +114,3 @@ V_FUNCTION_END(__kernel_clock_getres) V_FUNCTION_BEGIN(__kernel_time) cvdso_call __c_kernel_time call_time=1 V_FUNCTION_END(__kernel_time) - -/* Routines for restoring integer registers, called by the compiler. */ -/* Called with r11 pointing to the stack header word of the caller of the */ -/* function, just beyond the end of the integer restore area. */ -#ifndef __powerpc64__ -_GLOBAL(_restgpr_31_x) -_GLOBAL(_rest32gpr_31_x) - lwz r0,4(r11) - lwz r31,-4(r11) - mtlr r0 - mr r1,r11 - blr -#endif diff --git a/arch/powerpc/kernel/vdso/vdso32.lds.S b/arch/powerpc/kernel/vdso/vdso32.lds.S index 426e1ccc6971..7b41d5d256e8 100644 --- a/arch/powerpc/kernel/vdso/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso/vdso32.lds.S @@ -74,6 +74,8 @@ SECTIONS .got : { *(.got) } :text .plt : { *(.plt) } + .rela.dyn : { *(.rela .rela*) } + _end = .; __end = .; PROVIDE(end = .); @@ -87,7 +89,7 @@ SECTIONS *(.branch_lt) *(.data .data.* .gnu.linkonce.d.* .sdata*) *(.bss .sbss .dynbss .dynsbss) - *(.got1 .glink .iplt .rela*) + *(.got1 .glink .iplt) } } @@ -128,6 +130,7 @@ VERSION #if defined(CONFIG_PPC64) || !defined(CONFIG_SMP) __kernel_getcpu; #endif + __kernel_getrandom; local: *; }; diff --git a/arch/powerpc/kernel/vdso/vdso64.lds.S b/arch/powerpc/kernel/vdso/vdso64.lds.S index bda6c8cdd459..9481e4b892ed 100644 --- a/arch/powerpc/kernel/vdso/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso/vdso64.lds.S @@ -69,7 +69,7 @@ SECTIONS .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr .eh_frame : { KEEP (*(.eh_frame)) } :text .gcc_except_table : { *(.gcc_except_table) } - .rela.dyn ALIGN(8) : { *(.rela.dyn) } + .rela.dyn ALIGN(8) : { *(.rela .rela*) } .got ALIGN(8) : { *(.got .toc) } @@ -86,7 +86,7 @@ SECTIONS *(.data .data.* .gnu.linkonce.d.* .sdata*) *(.bss .sbss .dynbss .dynsbss) *(.opd) - *(.glink .iplt .plt .rela*) + *(.glink .iplt .plt) } } @@ -123,6 +123,7 @@ VERSION __kernel_sigtramp_rt64; __kernel_getcpu; __kernel_time; + __kernel_getrandom; local: *; }; diff --git a/arch/powerpc/kernel/vdso/vgetrandom-chacha.S b/arch/powerpc/kernel/vdso/vgetrandom-chacha.S new file mode 100644 index 000000000000..7f9061a9e8b4 --- /dev/null +++ b/arch/powerpc/kernel/vdso/vgetrandom-chacha.S @@ -0,0 +1,365 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France + */ + +#include <linux/linkage.h> + +#include <asm/ppc_asm.h> + +#define dst_bytes r3 +#define key r4 +#define counter r5 +#define nblocks r6 + +#define idx_r0 r0 +#define val4 r4 + +#define const0 0x61707865 +#define const1 0x3320646e +#define const2 0x79622d32 +#define const3 0x6b206574 + +#define key0 r5 +#define key1 r6 +#define key2 r7 +#define key3 r8 +#define key4 r9 +#define key5 r10 +#define key6 r11 +#define key7 r12 + +#define counter0 r14 +#define counter1 r15 + +#define state0 r16 +#define state1 r17 +#define state2 r18 +#define state3 r19 +#define state4 r20 +#define state5 r21 +#define state6 r22 +#define state7 r23 +#define state8 r24 +#define state9 r25 +#define state10 r26 +#define state11 r27 +#define state12 r28 +#define state13 r29 +#define state14 r30 +#define state15 r31 + +.macro quarterround4 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3 a4 b4 c4 d4 + add \a1, \a1, \b1 + add \a2, \a2, \b2 + add \a3, \a3, \b3 + add \a4, \a4, \b4 + xor \d1, \d1, \a1 + xor \d2, \d2, \a2 + xor \d3, \d3, \a3 + xor \d4, \d4, \a4 + rotlwi \d1, \d1, 16 + rotlwi \d2, \d2, 16 + rotlwi \d3, \d3, 16 + rotlwi \d4, \d4, 16 + add \c1, \c1, \d1 + add \c2, \c2, \d2 + add \c3, \c3, \d3 + add \c4, \c4, \d4 + xor \b1, \b1, \c1 + xor \b2, \b2, \c2 + xor \b3, \b3, \c3 + xor \b4, \b4, \c4 + rotlwi \b1, \b1, 12 + rotlwi \b2, \b2, 12 + rotlwi \b3, \b3, 12 + rotlwi \b4, \b4, 12 + add \a1, \a1, \b1 + add \a2, \a2, \b2 + add \a3, \a3, \b3 + add \a4, \a4, \b4 + xor \d1, \d1, \a1 + xor \d2, \d2, \a2 + xor \d3, \d3, \a3 + xor \d4, \d4, \a4 + rotlwi \d1, \d1, 8 + rotlwi \d2, \d2, 8 + rotlwi \d3, \d3, 8 + rotlwi \d4, \d4, 8 + add \c1, \c1, \d1 + add \c2, \c2, \d2 + add \c3, \c3, \d3 + add \c4, \c4, \d4 + xor \b1, \b1, \c1 + xor \b2, \b2, \c2 + xor \b3, \b3, \c3 + xor \b4, \b4, \c4 + rotlwi \b1, \b1, 7 + rotlwi \b2, \b2, 7 + rotlwi \b3, \b3, 7 + rotlwi \b4, \b4, 7 +.endm + +#define QUARTERROUND4(a1,b1,c1,d1,a2,b2,c2,d2,a3,b3,c3,d3,a4,b4,c4,d4) \ + quarterround4 state##a1 state##b1 state##c1 state##d1 \ + state##a2 state##b2 state##c2 state##d2 \ + state##a3 state##b3 state##c3 state##d3 \ + state##a4 state##b4 state##c4 state##d4 + +/* + * Very basic 32 bits implementation of ChaCha20. Produces a given positive number + * of blocks of output with a nonce of 0, taking an input key and 8-byte + * counter. Importantly does not spill to the stack. Its arguments are: + * + * r3: output bytes + * r4: 32-byte key input + * r5: 8-byte counter input/output (saved on stack) + * r6: number of 64-byte blocks to write to output + * + * r0: counter of blocks (initialised with r6) + * r4: Value '4' after key has been read. + * r5-r12: key + * r14-r15: counter + * r16-r31: state + */ +SYM_FUNC_START(__arch_chacha20_blocks_nostack) +#ifdef __powerpc64__ + std counter, -216(r1) + + std r14, -144(r1) + std r15, -136(r1) + std r16, -128(r1) + std r17, -120(r1) + std r18, -112(r1) + std r19, -104(r1) + std r20, -96(r1) + std r21, -88(r1) + std r22, -80(r1) + std r23, -72(r1) + std r24, -64(r1) + std r25, -56(r1) + std r26, -48(r1) + std r27, -40(r1) + std r28, -32(r1) + std r29, -24(r1) + std r30, -16(r1) + std r31, -8(r1) +#else + stwu r1, -96(r1) + stw counter, 20(r1) +#ifdef __BIG_ENDIAN__ + stmw r14, 24(r1) +#else + stw r14, 24(r1) + stw r15, 28(r1) + stw r16, 32(r1) + stw r17, 36(r1) + stw r18, 40(r1) + stw r19, 44(r1) + stw r20, 48(r1) + stw r21, 52(r1) + stw r22, 56(r1) + stw r23, 60(r1) + stw r24, 64(r1) + stw r25, 68(r1) + stw r26, 72(r1) + stw r27, 76(r1) + stw r28, 80(r1) + stw r29, 84(r1) + stw r30, 88(r1) + stw r31, 92(r1) +#endif +#endif /* __powerpc64__ */ + + lwz counter0, 0(counter) + lwz counter1, 4(counter) +#ifdef __powerpc64__ + rldimi counter0, counter1, 32, 0 +#endif + mr idx_r0, nblocks + subi dst_bytes, dst_bytes, 4 + + lwz key0, 0(key) + lwz key1, 4(key) + lwz key2, 8(key) + lwz key3, 12(key) + lwz key4, 16(key) + lwz key5, 20(key) + lwz key6, 24(key) + lwz key7, 28(key) + + li val4, 4 +.Lblock: + li r31, 10 + + lis state0, const0@ha + lis state1, const1@ha + lis state2, const2@ha + lis state3, const3@ha + addi state0, state0, const0@l + addi state1, state1, const1@l + addi state2, state2, const2@l + addi state3, state3, const3@l + + mtctr r31 + + mr state4, key0 + mr state5, key1 + mr state6, key2 + mr state7, key3 + mr state8, key4 + mr state9, key5 + mr state10, key6 + mr state11, key7 + + mr state12, counter0 + mr state13, counter1 + + li state14, 0 + li state15, 0 + +.Lpermute: + QUARTERROUND4( 0, 4, 8,12, 1, 5, 9,13, 2, 6,10,14, 3, 7,11,15) + QUARTERROUND4( 0, 5,10,15, 1, 6,11,12, 2, 7, 8,13, 3, 4, 9,14) + + bdnz .Lpermute + + addis state0, state0, const0@ha + addis state1, state1, const1@ha + addis state2, state2, const2@ha + addis state3, state3, const3@ha + addi state0, state0, const0@l + addi state1, state1, const1@l + addi state2, state2, const2@l + addi state3, state3, const3@l + + add state4, state4, key0 + add state5, state5, key1 + add state6, state6, key2 + add state7, state7, key3 + add state8, state8, key4 + add state9, state9, key5 + add state10, state10, key6 + add state11, state11, key7 + + add state12, state12, counter0 + add state13, state13, counter1 + +#ifdef __BIG_ENDIAN__ + stwbrx state0, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state1, 0, dst_bytes + stwbrx state2, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state3, 0, dst_bytes + stwbrx state4, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state5, 0, dst_bytes + stwbrx state6, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state7, 0, dst_bytes + stwbrx state8, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state9, 0, dst_bytes + stwbrx state10, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state11, 0, dst_bytes + stwbrx state12, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state13, 0, dst_bytes + stwbrx state14, val4, dst_bytes + addi dst_bytes, dst_bytes, 8 + stwbrx state15, 0, dst_bytes +#else + stw state0, 4(dst_bytes) + stw state1, 8(dst_bytes) + stw state2, 12(dst_bytes) + stw state3, 16(dst_bytes) + stw state4, 20(dst_bytes) + stw state5, 24(dst_bytes) + stw state6, 28(dst_bytes) + stw state7, 32(dst_bytes) + stw state8, 36(dst_bytes) + stw state9, 40(dst_bytes) + stw state10, 44(dst_bytes) + stw state11, 48(dst_bytes) + stw state12, 52(dst_bytes) + stw state13, 56(dst_bytes) + stw state14, 60(dst_bytes) + stwu state15, 64(dst_bytes) +#endif + + subic. idx_r0, idx_r0, 1 /* subi. can't use r0 as source */ + +#ifdef __powerpc64__ + addi counter0, counter0, 1 + srdi counter1, counter0, 32 +#else + addic counter0, counter0, 1 + addze counter1, counter1 +#endif + + bne .Lblock + +#ifdef __powerpc64__ + ld counter, -216(r1) +#else + lwz counter, 20(r1) +#endif + stw counter0, 0(counter) + stw counter1, 4(counter) + + li r6, 0 + li r7, 0 + li r8, 0 + li r9, 0 + li r10, 0 + li r11, 0 + li r12, 0 + +#ifdef __powerpc64__ + ld r14, -144(r1) + ld r15, -136(r1) + ld r16, -128(r1) + ld r17, -120(r1) + ld r18, -112(r1) + ld r19, -104(r1) + ld r20, -96(r1) + ld r21, -88(r1) + ld r22, -80(r1) + ld r23, -72(r1) + ld r24, -64(r1) + ld r25, -56(r1) + ld r26, -48(r1) + ld r27, -40(r1) + ld r28, -32(r1) + ld r29, -24(r1) + ld r30, -16(r1) + ld r31, -8(r1) +#else +#ifdef __BIG_ENDIAN__ + lmw r14, 24(r1) +#else + lwz r14, 24(r1) + lwz r15, 28(r1) + lwz r16, 32(r1) + lwz r17, 36(r1) + lwz r18, 40(r1) + lwz r19, 44(r1) + lwz r20, 48(r1) + lwz r21, 52(r1) + lwz r22, 56(r1) + lwz r23, 60(r1) + lwz r24, 64(r1) + lwz r25, 68(r1) + lwz r26, 72(r1) + lwz r27, 76(r1) + lwz r28, 80(r1) + lwz r29, 84(r1) + lwz r30, 88(r1) + lwz r31, 92(r1) +#endif + addi r1, r1, 96 +#endif /* __powerpc64__ */ + blr +SYM_FUNC_END(__arch_chacha20_blocks_nostack) diff --git a/arch/powerpc/kernel/vdso/vgetrandom.c b/arch/powerpc/kernel/vdso/vgetrandom.c new file mode 100644 index 000000000000..5f855d45fb7b --- /dev/null +++ b/arch/powerpc/kernel/vdso/vgetrandom.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Powerpc userspace implementation of getrandom() + * + * Copyright (C) 2024 Christophe Leroy <christophe.leroy@csgroup.eu>, CS GROUP France + */ +#include <linux/time.h> +#include <linux/types.h> + +ssize_t __c_kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, + size_t opaque_len, const struct vdso_rng_data *vd) +{ + return __cvdso_getrandom_data(vd, buffer, len, flags, opaque_state, opaque_len); +} diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 3ff3de9a52ac..742aa58a7c7e 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -115,31 +115,26 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, struct iommu_table_group *table_group; long i; struct kvmppc_spapr_tce_iommu_table *stit; - struct fd f; + CLASS(fd, f)(tablefd); - f = fdget(tablefd); - if (!f.file) + if (fd_empty(f)) return -EBADF; rcu_read_lock(); list_for_each_entry_rcu(stt, &kvm->arch.spapr_tce_tables, list) { - if (stt == f.file->private_data) { + if (stt == fd_file(f)->private_data) { found = true; break; } } rcu_read_unlock(); - if (!found) { - fdput(f); + if (!found) return -EINVAL; - } table_group = iommu_group_get_iommudata(grp); - if (WARN_ON(!table_group)) { - fdput(f); + if (WARN_ON(!table_group)) return -EFAULT; - } for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) { struct iommu_table *tbltmp = table_group->tables[i]; @@ -160,10 +155,8 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, break; } } - if (!tbl) { - fdput(f); + if (!tbl) return -EINVAL; - } rcu_read_lock(); list_for_each_entry_rcu(stit, &stt->iommu_tables, next) { @@ -174,7 +167,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, /* stit is being destroyed */ iommu_tce_table_put(tbl); rcu_read_unlock(); - fdput(f); return -ENOTTY; } /* @@ -182,7 +174,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, * its KVM reference counter and can return. */ rcu_read_unlock(); - fdput(f); return 0; } rcu_read_unlock(); @@ -190,7 +181,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, stit = kzalloc(sizeof(*stit), GFP_KERNEL); if (!stit) { iommu_tce_table_put(tbl); - fdput(f); return -ENOMEM; } @@ -199,7 +189,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, list_add_rcu(&stit->next, &stt->iommu_tables); - fdput(f); return 0; } diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 8f7d7e37bc8c..ad8dc4ccdaab 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -1922,14 +1922,22 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, r = EMULATE_FAIL; if (cpu_has_feature(CPU_FTR_ARCH_300)) { - if (cause == FSCR_MSGP_LG) + switch (cause) { + case FSCR_MSGP_LG: r = kvmppc_emulate_doorbell_instr(vcpu); - if (cause == FSCR_PM_LG) + break; + case FSCR_PM_LG: r = kvmppc_pmu_unavailable(vcpu); - if (cause == FSCR_EBB_LG) + break; + case FSCR_EBB_LG: r = kvmppc_ebb_unavailable(vcpu); - if (cause == FSCR_TM_LG) + break; + case FSCR_TM_LG: r = kvmppc_tm_unavailable(vcpu); + break; + default: + break; + } } if (r == EMULATE_FAIL) { kvmppc_core_queue_program(vcpu, SRR1_PROGILL | @@ -4049,7 +4057,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) /* Return to whole-core mode if we split the core earlier */ if (cmd_bit) { unsigned long hid0 = mfspr(SPRN_HID0); - unsigned long loops = 0; hid0 &= ~HID0_POWER8_DYNLPARDIS; stat_bit = HID0_POWER8_2LPARMODE | HID0_POWER8_4LPARMODE; @@ -4061,7 +4068,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) if (!(hid0 & stat_bit)) break; cpu_relax(); - ++loops; } split_info.do_nap = 0; } @@ -4892,6 +4898,18 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, BOOK3S_INTERRUPT_EXTERNAL, 0); else lpcr |= LPCR_MER; + } else { + /* + * L1's copy of L2's LPCR (vcpu->arch.vcore->lpcr) can get its MER bit + * unexpectedly set - for e.g. during NMI handling when all register + * states are synchronized from L0 to L1. L1 needs to inform L0 about + * MER=1 only when there are pending external interrupts. + * In the above if check, MER bit is set if there are pending + * external interrupts. Hence, explicity mask off MER bit + * here as otherwise it may generate spurious interrupts in L2 KVM + * causing an endless loop, which results in L2 guest getting hung. + */ + lpcr &= ~LPCR_MER; } } else if (vcpu->arch.pending_exceptions || vcpu->arch.doorbell_request || diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 5e6c7b527677..b3b37ea77849 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -1933,69 +1933,59 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, #endif #ifdef CONFIG_KVM_MPIC case KVM_CAP_IRQ_MPIC: { - struct fd f; + CLASS(fd, f)(cap->args[0]); struct kvm_device *dev; r = -EBADF; - f = fdget(cap->args[0]); - if (!f.file) + if (fd_empty(f)) break; r = -EPERM; - dev = kvm_device_from_filp(f.file); + dev = kvm_device_from_filp(fd_file(f)); if (dev) r = kvmppc_mpic_connect_vcpu(dev, vcpu, cap->args[1]); - fdput(f); break; } #endif #ifdef CONFIG_KVM_XICS case KVM_CAP_IRQ_XICS: { - struct fd f; + CLASS(fd, f)(cap->args[0]); struct kvm_device *dev; r = -EBADF; - f = fdget(cap->args[0]); - if (!f.file) + if (fd_empty(f)) break; r = -EPERM; - dev = kvm_device_from_filp(f.file); + dev = kvm_device_from_filp(fd_file(f)); if (dev) { if (xics_on_xive()) r = kvmppc_xive_connect_vcpu(dev, vcpu, cap->args[1]); else r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]); } - - fdput(f); break; } #endif /* CONFIG_KVM_XICS */ #ifdef CONFIG_KVM_XIVE case KVM_CAP_PPC_IRQ_XIVE: { - struct fd f; + CLASS(fd, f)(cap->args[0]); struct kvm_device *dev; r = -EBADF; - f = fdget(cap->args[0]); - if (!f.file) + if (fd_empty(f)) break; r = -ENXIO; - if (!xive_enabled()) { - fdput(f); + if (!xive_enabled()) break; - } r = -EPERM; - dev = kvm_device_from_filp(f.file); + dev = kvm_device_from_filp(fd_file(f)); if (dev) r = kvmppc_xive_native_connect_vcpu(dev, vcpu, cap->args[1]); - - fdput(f); break; } #endif /* CONFIG_KVM_XIVE */ diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index 0d1f3ee91115..acdab294b340 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -20,15 +20,14 @@ #include <asm/code-patching.h> #include <asm/inst.h> -static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr) +static int __patch_mem(void *exec_addr, unsigned long val, void *patch_addr, bool is_dword) { - if (!ppc_inst_prefixed(instr)) { - u32 val = ppc_inst_val(instr); + if (!IS_ENABLED(CONFIG_PPC64) || likely(!is_dword)) { + /* For big endian correctness: plain address would use the wrong half */ + u32 val32 = val; - __put_kernel_nofault(patch_addr, &val, u32, failed); + __put_kernel_nofault(patch_addr, &val32, u32, failed); } else { - u64 val = ppc_inst_as_ulong(instr); - __put_kernel_nofault(patch_addr, &val, u64, failed); } @@ -44,7 +43,10 @@ failed: int raw_patch_instruction(u32 *addr, ppc_inst_t instr) { - return __patch_instruction(addr, instr, addr); + if (ppc_inst_prefixed(instr)) + return __patch_mem(addr, ppc_inst_as_ulong(instr), addr, true); + else + return __patch_mem(addr, ppc_inst_val(instr), addr, false); } struct patch_context { @@ -276,7 +278,7 @@ static void unmap_patch_area(unsigned long addr) flush_tlb_kernel_range(addr, addr + PAGE_SIZE); } -static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) +static int __do_patch_mem_mm(void *addr, unsigned long val, bool is_dword) { int err; u32 *patch_addr; @@ -305,7 +307,7 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) orig_mm = start_using_temp_mm(patching_mm); - err = __patch_instruction(addr, instr, patch_addr); + err = __patch_mem(addr, val, patch_addr, is_dword); /* context synchronisation performed by __patch_instruction (isync or exception) */ stop_using_temp_mm(patching_mm, orig_mm); @@ -322,7 +324,7 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) return err; } -static int __do_patch_instruction(u32 *addr, ppc_inst_t instr) +static int __do_patch_mem(void *addr, unsigned long val, bool is_dword) { int err; u32 *patch_addr; @@ -339,7 +341,7 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t instr) if (radix_enabled()) asm volatile("ptesync": : :"memory"); - err = __patch_instruction(addr, instr, patch_addr); + err = __patch_mem(addr, val, patch_addr, is_dword); pte_clear(&init_mm, text_poke_addr, pte); flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE); @@ -347,7 +349,7 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t instr) return err; } -int patch_instruction(u32 *addr, ppc_inst_t instr) +static int patch_mem(void *addr, unsigned long val, bool is_dword) { int err; unsigned long flags; @@ -359,19 +361,57 @@ int patch_instruction(u32 *addr, ppc_inst_t instr) */ if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX) || !static_branch_likely(&poking_init_done)) - return raw_patch_instruction(addr, instr); + return __patch_mem(addr, val, addr, is_dword); local_irq_save(flags); if (mm_patch_enabled()) - err = __do_patch_instruction_mm(addr, instr); + err = __do_patch_mem_mm(addr, val, is_dword); else - err = __do_patch_instruction(addr, instr); + err = __do_patch_mem(addr, val, is_dword); local_irq_restore(flags); return err; } + +#ifdef CONFIG_PPC64 + +int patch_instruction(u32 *addr, ppc_inst_t instr) +{ + if (ppc_inst_prefixed(instr)) + return patch_mem(addr, ppc_inst_as_ulong(instr), true); + else + return patch_mem(addr, ppc_inst_val(instr), false); +} NOKPROBE_SYMBOL(patch_instruction); +int patch_uint(void *addr, unsigned int val) +{ + if (!IS_ALIGNED((unsigned long)addr, sizeof(unsigned int))) + return -EINVAL; + + return patch_mem(addr, val, false); +} +NOKPROBE_SYMBOL(patch_uint); + +int patch_ulong(void *addr, unsigned long val) +{ + if (!IS_ALIGNED((unsigned long)addr, sizeof(unsigned long))) + return -EINVAL; + + return patch_mem(addr, val, true); +} +NOKPROBE_SYMBOL(patch_ulong); + +#else + +int patch_instruction(u32 *addr, ppc_inst_t instr) +{ + return patch_mem(addr, ppc_inst_val(instr), false); +} +NOKPROBE_SYMBOL(patch_instruction) + +#endif + static int patch_memset64(u64 *addr, u64 val, size_t count) { for (u64 *end = addr + count; addr < end; addr++) diff --git a/arch/powerpc/lib/crtsavres.S b/arch/powerpc/lib/crtsavres.S index 7e5e1c28e56a..8967903c15e9 100644 --- a/arch/powerpc/lib/crtsavres.S +++ b/arch/powerpc/lib/crtsavres.S @@ -46,7 +46,7 @@ .section ".text" -#ifndef CONFIG_PPC64 +#ifndef __powerpc64__ /* Routines for saving integer registers, called by the compiler. */ /* Called with r11 pointing to the stack header word of the caller of the */ diff --git a/arch/powerpc/lib/qspinlock.c b/arch/powerpc/lib/qspinlock.c index 5de4dd549f6e..bcc7e4dff8c3 100644 --- a/arch/powerpc/lib/qspinlock.c +++ b/arch/powerpc/lib/qspinlock.c @@ -697,7 +697,15 @@ again: } release: - qnodesp->count--; /* release the node */ + /* + * Clear the lock before releasing the node, as another CPU might see stale + * values if an interrupt occurs after we increment qnodesp->count + * but before node->lock is initialized. The barrier ensures that + * there are no further stores to the node after it has been released. + */ + node->lock = NULL; + barrier(); + qnodesp->count--; } void queued_spin_lock_slowpath(struct qspinlock *lock) diff --git a/arch/powerpc/lib/test-code-patching.c b/arch/powerpc/lib/test-code-patching.c index f76030087f98..8cd3b32f805b 100644 --- a/arch/powerpc/lib/test-code-patching.c +++ b/arch/powerpc/lib/test-code-patching.c @@ -438,6 +438,46 @@ static void __init test_multi_instruction_patching(void) vfree(buf); } +static void __init test_data_patching(void) +{ + void *buf; + u32 *addr32; + + buf = vzalloc(PAGE_SIZE); + check(buf); + if (!buf) + return; + + addr32 = buf + 128; + + addr32[1] = 0xA0A1A2A3; + addr32[2] = 0xB0B1B2B3; + + check(!patch_uint(&addr32[1], 0xC0C1C2C3)); + + check(addr32[0] == 0); + check(addr32[1] == 0xC0C1C2C3); + check(addr32[2] == 0xB0B1B2B3); + check(addr32[3] == 0); + + /* Unaligned patch_ulong() should fail */ + if (IS_ENABLED(CONFIG_PPC64)) + check(patch_ulong(&addr32[1], 0xD0D1D2D3) == -EINVAL); + + check(!patch_ulong(&addr32[2], 0xD0D1D2D3)); + + check(addr32[0] == 0); + check(addr32[1] == 0xC0C1C2C3); + check(*(unsigned long *)(&addr32[2]) == 0xD0D1D2D3); + + if (!IS_ENABLED(CONFIG_PPC64)) + check(addr32[3] == 0); + + check(addr32[4] == 0); + + vfree(buf); +} + static int __init test_code_patching(void) { pr_info("Running code patching self-tests ...\n"); @@ -448,6 +488,7 @@ static int __init test_code_patching(void) test_translate_branch(); test_prefixed_patching(); test_multi_instruction_patching(); + test_data_patching(); return 0; } diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c index 625fe7d08e06..2db167f4233f 100644 --- a/arch/powerpc/mm/book3s32/mmu.c +++ b/arch/powerpc/mm/book3s32/mmu.c @@ -223,6 +223,8 @@ int mmu_mark_initmem_nx(void) update_bats(); + BUILD_BUG_ON(ALIGN_DOWN(MODULES_VADDR, SZ_256M) < TASK_SIZE); + for (i = TASK_SIZE >> 28; i < 16; i++) { /* Do not set NX on VM space for modules */ if (is_module_segment(i << 28)) diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index 6727a15ab94f..e1eadd03f133 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c @@ -125,7 +125,7 @@ int mmu_ci_restrictions; #endif static u8 *linear_map_hash_slots; static unsigned long linear_map_hash_count; -struct mmu_hash_ops mmu_hash_ops; +struct mmu_hash_ops mmu_hash_ops __ro_after_init; EXPORT_SYMBOL(mmu_hash_ops); /* diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c index f4d8d3c40e5c..5a4a75369043 100644 --- a/arch/powerpc/mm/book3s64/pgtable.c +++ b/arch/powerpc/mm/book3s64/pgtable.c @@ -176,6 +176,17 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, return __pmd(old_pmd); } +pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp) +{ + unsigned long old_pud; + + VM_WARN_ON_ONCE(!pud_present(*pudp)); + old_pud = pud_hugepage_update(vma->vm_mm, address, pudp, _PAGE_PRESENT, _PAGE_INVALID); + flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE); + return __pud(old_pud); +} + pmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp, int full) { @@ -259,6 +270,15 @@ pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) pmdv &= _HPAGE_CHG_MASK; return pmd_set_protbits(__pmd(pmdv), newprot); } + +pud_t pud_modify(pud_t pud, pgprot_t newprot) +{ + unsigned long pudv; + + pudv = pud_val(pud); + pudv &= _HPAGE_CHG_MASK; + return pud_set_protbits(__pud(pudv), newprot); +} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ /* For use by kexec, called with MMU off */ diff --git a/arch/powerpc/mm/book3s64/slice.c b/arch/powerpc/mm/book3s64/slice.c index ef3ce37f1bb3..87307d0fc3b8 100644 --- a/arch/powerpc/mm/book3s64/slice.c +++ b/arch/powerpc/mm/book3s64/slice.c @@ -637,10 +637,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, + vm_flags_t vm_flags) { if (radix_enabled()) - return generic_get_unmapped_area(filp, addr, len, pgoff, flags); + return generic_get_unmapped_area(filp, addr, len, pgoff, flags, vm_flags); return slice_get_unmapped_area(addr, len, flags, mm_ctx_user_psize(¤t->mm->context), 0); @@ -650,10 +651,11 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, const unsigned long len, const unsigned long pgoff, - const unsigned long flags) + const unsigned long flags, + vm_flags_t vm_flags) { if (radix_enabled()) - return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags); + return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags, vm_flags); return slice_get_unmapped_area(addr0, len, flags, mm_ctx_user_psize(¤t->mm->context), 1); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index da21cb018984..1221c561b43a 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -216,7 +216,7 @@ static int __init mark_nonram_nosave(void) * everything else. GFP_DMA32 page allocations automatically fall back to * ZONE_DMA. * - * By using 31-bit unconditionally, we can exploit zone_dma_bits to inform the + * By using 31-bit unconditionally, we can exploit zone_dma_limit to inform the * generic DMA mapping code. 32-bit only devices (if not handled by an IOMMU * anyway) will take a first dip into ZONE_NORMAL and get otherwise served by * ZONE_DMA. @@ -230,6 +230,7 @@ void __init paging_init(void) { unsigned long long total_ram = memblock_phys_mem_size(); phys_addr_t top_of_ram = memblock_end_of_DRAM(); + int zone_dma_bits; #ifdef CONFIG_HIGHMEM unsigned long v = __fix_to_virt(FIX_KMAP_END); @@ -256,6 +257,8 @@ void __init paging_init(void) else zone_dma_bits = 31; + zone_dma_limit = DMA_BIT_MASK(zone_dma_bits); + #ifdef CONFIG_ZONE_DMA max_zone_pfns[ZONE_DMA] = min(max_low_pfn, 1UL << (zone_dma_bits - PAGE_SHIFT)); @@ -410,6 +413,18 @@ EXPORT_SYMBOL_GPL(walk_system_ram_range); #ifdef CONFIG_EXECMEM static struct execmem_info execmem_info __ro_after_init; +#if defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_BOOK3S_603) +static void prealloc_execmem_pgtable(void) +{ + unsigned long va; + + for (va = ALIGN_DOWN(MODULES_VADDR, PGDIR_SIZE); va < MODULES_END; va += PGDIR_SIZE) + pte_alloc_kernel(pmd_off_k(va), va); +} +#else +static void prealloc_execmem_pgtable(void) { } +#endif + struct execmem_info __init *execmem_arch_setup(void) { pgprot_t kprobes_prot = strict_module_rwx_enabled() ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; @@ -441,6 +456,8 @@ struct execmem_info __init *execmem_arch_setup(void) end = VMALLOC_END; #endif + prealloc_execmem_pgtable(); + execmem_info = (struct execmem_info){ .ranges = { [EXECMEM_DEFAULT] = { diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c index 388bba0ab3e7..8b54f12d1889 100644 --- a/arch/powerpc/mm/nohash/8xx.c +++ b/arch/powerpc/mm/nohash/8xx.c @@ -150,11 +150,11 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top) mmu_mapin_immr(); - mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_TEXT, true); + mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_X, true); if (debug_pagealloc_enabled_or_kfence()) { top = boundary; } else { - mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL_TEXT, true); + mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL_X, true); mmu_mapin_ram_chunk(einittext8, top, PAGE_KERNEL, true); } @@ -177,7 +177,8 @@ int mmu_mark_initmem_nx(void) if (!debug_pagealloc_enabled_or_kfence()) err = mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false); - mmu_pin_tlb(block_mapped_ram, false); + if (IS_ENABLED(CONFIG_PIN_TLB_TEXT)) + mmu_pin_tlb(block_mapped_ram, false); return err; } @@ -206,6 +207,8 @@ void __init setup_initial_memory_limit(phys_addr_t first_memblock_base, /* 8xx can only access 32MB at the moment */ memblock_set_current_limit(min_t(u64, first_memblock_size, SZ_32M)); + + BUILD_BUG_ON(ALIGN_DOWN(MODULES_VADDR, PGDIR_SIZE) < TASK_SIZE); } int pud_clear_huge(pud_t *pud) diff --git a/arch/powerpc/mm/nohash/tlb_64e.c b/arch/powerpc/mm/nohash/tlb_64e.c index 113edf76d3ce..d26656b07b72 100644 --- a/arch/powerpc/mm/nohash/tlb_64e.c +++ b/arch/powerpc/mm/nohash/tlb_64e.c @@ -33,7 +33,7 @@ * though this will probably be made common with other nohash * implementations at some point */ -int mmu_pte_psize; /* Page size used for PTE pages */ +static int mmu_pte_psize; /* Page size used for PTE pages */ int mmu_vmemmap_psize; /* Page size used for the virtual mem map */ int book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ unsigned long linear_map_top; /* Top of linear mapping */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index aa89899f0c1a..3c1da08304d0 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -43,11 +43,9 @@ static char *cmdline __initdata; int numa_cpu_lookup_table[NR_CPUS]; cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; -struct pglist_data *node_data[MAX_NUMNODES]; EXPORT_SYMBOL(numa_cpu_lookup_table); EXPORT_SYMBOL(node_to_cpumask_map); -EXPORT_SYMBOL(node_data); static int primary_domain_index; static int n_mem_addr_cells, n_mem_size_cells; @@ -1095,27 +1093,9 @@ void __init dump_numa_cpu_topology(void) static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) { u64 spanned_pages = end_pfn - start_pfn; - const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES); - u64 nd_pa; - void *nd; - int tnid; - - nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); - if (!nd_pa) - panic("Cannot allocate %zu bytes for node %d data\n", - nd_size, nid); - - nd = __va(nd_pa); - - /* report and initialize */ - pr_info(" NODE_DATA [mem %#010Lx-%#010Lx]\n", - nd_pa, nd_pa + nd_size - 1); - tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); - if (tnid != nid) - pr_info(" NODE_DATA(%d) on node %d\n", nid, tnid); - - node_data[nid] = nd; - memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); + + alloc_node_data(nid); + NODE_DATA(nid)->node_id = nid; NODE_DATA(nid)->node_start_pfn = start_pfn; NODE_DATA(nid)->node_spanned_pages = spanned_pages; diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c index 8c31802f97e8..e89f64a0f24a 100644 --- a/arch/powerpc/mm/pgtable-frag.c +++ b/arch/powerpc/mm/pgtable-frag.c @@ -136,10 +136,10 @@ void pte_fragment_free(unsigned long *table, int kernel) #ifdef CONFIG_TRANSPARENT_HUGEPAGE void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable) { - struct page *page; + struct folio *folio; - page = virt_to_page(pgtable); - SetPageActive(page); + folio = virt_to_folio(pgtable); + folio_set_active(folio); pte_fragment_free((unsigned long *)pgtable, 0); } #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index ab0656115424..7316396e452d 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -297,6 +297,12 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, } #if defined(CONFIG_PPC_8xx) + +#if defined(CONFIG_SPLIT_PTE_PTLOCKS) || defined(CONFIG_SPLIT_PMD_PTLOCKS) +/* We need the same lock to protect the PMD table and the two PTE tables. */ +#error "8M hugetlb folios are incompatible with split page table locks" +#endif + static void __set_huge_pte_at(pmd_t *pmd, pte_t *ptep, pte_basic_t val) { pte_basic_t *entry = (pte_basic_t *)ptep; diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index 6b4434dd0ff3..26aa26482c9a 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -51,7 +51,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re lr = regs->link; sp = regs->gpr[1]; - perf_callchain_store(entry, perf_instruction_pointer(regs)); + perf_callchain_store(entry, perf_arch_instruction_pointer(regs)); if (!validate_sp(sp, current)) return; diff --git a/arch/powerpc/perf/callchain_32.c b/arch/powerpc/perf/callchain_32.c index ea8cfe3806dc..ddcc2d8aa64a 100644 --- a/arch/powerpc/perf/callchain_32.c +++ b/arch/powerpc/perf/callchain_32.c @@ -139,7 +139,7 @@ void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, long level = 0; unsigned int __user *fp, *uregs; - next_ip = perf_instruction_pointer(regs); + next_ip = perf_arch_instruction_pointer(regs); lr = regs->link; sp = regs->gpr[1]; perf_callchain_store(entry, next_ip); diff --git a/arch/powerpc/perf/callchain_64.c b/arch/powerpc/perf/callchain_64.c index 488e8a21a11e..115d1c105e8a 100644 --- a/arch/powerpc/perf/callchain_64.c +++ b/arch/powerpc/perf/callchain_64.c @@ -74,7 +74,7 @@ void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, struct signal_frame_64 __user *sigframe; unsigned long __user *fp, *uregs; - next_ip = perf_instruction_pointer(regs); + next_ip = perf_arch_instruction_pointer(regs); lr = regs->link; sp = regs->gpr[1]; perf_callchain_store(entry, next_ip); diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 42867469752d..dc01aa604cc1 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -2332,7 +2332,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val, * Called from generic code to get the misc flags (i.e. processor mode) * for an event_id. */ -unsigned long perf_misc_flags(struct pt_regs *regs) +unsigned long perf_arch_misc_flags(struct pt_regs *regs) { u32 flags = perf_get_misc_flags(regs); @@ -2346,7 +2346,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs) * Called from generic code to get the instruction pointer * for an event_id. */ -unsigned long perf_instruction_pointer(struct pt_regs *regs) +unsigned long perf_arch_instruction_pointer(struct pt_regs *regs) { unsigned long siar = mfspr(SPRN_SIAR); diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index 164cbcd4588e..e7b7bdaad341 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c @@ -95,7 +95,7 @@ static int avr_probe(struct i2c_client *client) } static const struct i2c_device_id avr_id[] = { - { "akebono-avr", 0 }, + { "akebono-avr" }, { } }; diff --git a/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c b/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c index 4a25b6b48615..9668b052cd4b 100644 --- a/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c +++ b/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c @@ -504,7 +504,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_lpbfifo_match); static struct platform_driver mpc512x_lpbfifo_driver = { .probe = mpc512x_lpbfifo_probe, - .remove_new = mpc512x_lpbfifo_remove, + .remove = mpc512x_lpbfifo_remove, .driver = { .name = DRV_NAME, .of_match_table = mpc512x_lpbfifo_match, diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 2bd6abcdc113..1ea591ec6083 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -644,7 +644,6 @@ static int mpc52xx_wdt_release(struct inode *inode, struct file *file) static const struct file_operations mpc52xx_wdt_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .write = mpc52xx_wdt_write, .unlocked_ioctl = mpc52xx_wdt_ioctl, .compat_ioctl = compat_ptr_ioctl, diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c index 34ce21f42623..e635b27ee718 100644 --- a/arch/powerpc/platforms/85xx/sgy_cts1000.c +++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c @@ -143,7 +143,7 @@ static struct platform_driver gpio_halt_driver = { .of_match_table = gpio_halt_match, }, .probe = gpio_halt_probe, - .remove_new = gpio_halt_remove, + .remove = gpio_halt_remove, }; module_platform_driver(gpio_halt_driver); diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index a14d9d8997a4..8623aebfac48 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -195,6 +195,13 @@ config PIN_TLB_IMMR CONFIG_PIN_TLB_DATA is also selected, it will reduce CONFIG_PIN_TLB_DATA to 24 Mbytes. +config PIN_TLB_TEXT + bool "Pinned TLB for TEXT" + depends on PIN_TLB + default y + help + This pins kernel text with 8M pages. + endmenu endmenu diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 4b0d7d4f88f6..1453ccc900c4 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -84,11 +84,8 @@ config PPC_BOOK3S_64 bool "Server processors" select PPC_FPU select PPC_HAVE_PMU_SUPPORT - select HAVE_ARCH_TRANSPARENT_HUGEPAGE - select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_SPLIT_PMD_PTLOCK - select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE select ARCH_SUPPORTS_HUGETLBFS select ARCH_SUPPORTS_NUMA_BALANCING select HAVE_MOVE_PMD @@ -108,6 +105,14 @@ config PPC_BOOK3E_64 endchoice +config PPC_THP + def_bool y + depends on PPC_BOOK3S_64 + depends on PPC_RADIX_MMU || (PPC_64S_HASH_MMU && PAGE_SIZE_64KB) + select HAVE_ARCH_TRANSPARENT_HUGEPAGE + select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD + select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE + choice prompt "CPU selection" help diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 28dc86744cac..d243f7fd8982 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -112,7 +112,7 @@ static void axon_msi_cascade(struct irq_desc *desc) pr_devel("axon_msi: woff %x roff %x msi %x\n", write_offset, msic->read_offset, msi); - if (msi < nr_irqs && irq_get_chip_data(msi) == msic) { + if (msi < irq_get_nr_irqs() && irq_get_chip_data(msi) == msic) { generic_handle_irq(msi); msic->fifo_virt[idx] = cpu_to_le32(0xffffffff); } else { diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c index 87ad7d563cfa..000894e07b02 100644 --- a/arch/powerpc/platforms/cell/spu_syscalls.c +++ b/arch/powerpc/platforms/cell/spu_syscalls.c @@ -36,6 +36,9 @@ static inline struct spufs_calls *spufs_calls_get(void) static inline void spufs_calls_put(struct spufs_calls *calls) { + if (!calls) + return; + BUG_ON(calls != spufs_calls); /* we don't need to rcu this, as we hold a reference to the module */ @@ -53,82 +56,55 @@ static inline void spufs_calls_put(struct spufs_calls *calls) { } #endif /* CONFIG_SPU_FS_MODULE */ +DEFINE_CLASS(spufs_calls, struct spufs_calls *, spufs_calls_put(_T), spufs_calls_get(), void) + SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags, umode_t, mode, int, neighbor_fd) { - long ret; - struct spufs_calls *calls; - - calls = spufs_calls_get(); + CLASS(spufs_calls, calls)(); if (!calls) return -ENOSYS; if (flags & SPU_CREATE_AFFINITY_SPU) { - struct fd neighbor = fdget(neighbor_fd); - ret = -EBADF; - if (neighbor.file) { - ret = calls->create_thread(name, flags, mode, neighbor.file); - fdput(neighbor); - } - } else - ret = calls->create_thread(name, flags, mode, NULL); - - spufs_calls_put(calls); - return ret; + CLASS(fd, neighbor)(neighbor_fd); + if (fd_empty(neighbor)) + return -EBADF; + return calls->create_thread(name, flags, mode, fd_file(neighbor)); + } else { + return calls->create_thread(name, flags, mode, NULL); + } } SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus) { - long ret; - struct fd arg; - struct spufs_calls *calls; - - calls = spufs_calls_get(); + CLASS(spufs_calls, calls)(); if (!calls) return -ENOSYS; - ret = -EBADF; - arg = fdget(fd); - if (arg.file) { - ret = calls->spu_run(arg.file, unpc, ustatus); - fdput(arg); - } + CLASS(fd, arg)(fd); + if (fd_empty(arg)) + return -EBADF; - spufs_calls_put(calls); - return ret; + return calls->spu_run(fd_file(arg), unpc, ustatus); } #ifdef CONFIG_COREDUMP int elf_coredump_extra_notes_size(void) { - struct spufs_calls *calls; - int ret; - - calls = spufs_calls_get(); + CLASS(spufs_calls, calls)(); if (!calls) return 0; - ret = calls->coredump_extra_notes_size(); - - spufs_calls_put(calls); - - return ret; + return calls->coredump_extra_notes_size(); } int elf_coredump_extra_notes_write(struct coredump_params *cprm) { - struct spufs_calls *calls; - int ret; - - calls = spufs_calls_get(); + CLASS(spufs_calls, calls)(); if (!calls) return 0; - ret = calls->coredump_extra_notes_write(cprm); - - spufs_calls_put(calls); - - return ret; + return calls->coredump_extra_notes_write(cprm); } #endif diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 18daafbe2e65..301ee7d8b7df 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -73,9 +73,7 @@ static struct spu_context *coredump_next_context(int *fd) return NULL; *fd = n - 1; - rcu_read_lock(); - file = lookup_fdget_rcu(*fd); - rcu_read_unlock(); + file = fget_raw(*fd); if (file) { ctx = SPUFS_I(file_inode(file))->i_ctx; get_spu_context(ctx); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7f4e0db8eb08..d5a2c77bc908 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -453,7 +453,6 @@ static const struct file_operations spufs_cntl_fops = { .release = spufs_cntl_release, .read = simple_attr_read, .write = simple_attr_write, - .llseek = no_llseek, .mmap = spufs_cntl_mmap, }; @@ -634,7 +633,6 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf, static const struct file_operations spufs_mbox_fops = { .open = spufs_pipe_open, .read = spufs_mbox_read, - .llseek = no_llseek, }; static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, @@ -664,7 +662,6 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, static const struct file_operations spufs_mbox_stat_fops = { .open = spufs_pipe_open, .read = spufs_mbox_stat_read, - .llseek = no_llseek, }; /* low-level ibox access function */ @@ -769,7 +766,6 @@ static const struct file_operations spufs_ibox_fops = { .open = spufs_pipe_open, .read = spufs_ibox_read, .poll = spufs_ibox_poll, - .llseek = no_llseek, }; static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, @@ -797,7 +793,6 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, static const struct file_operations spufs_ibox_stat_fops = { .open = spufs_pipe_open, .read = spufs_ibox_stat_read, - .llseek = no_llseek, }; /* low-level mailbox write */ @@ -901,7 +896,6 @@ static const struct file_operations spufs_wbox_fops = { .open = spufs_pipe_open, .write = spufs_wbox_write, .poll = spufs_wbox_poll, - .llseek = no_llseek, }; static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, @@ -929,7 +923,6 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, static const struct file_operations spufs_wbox_stat_fops = { .open = spufs_pipe_open, .read = spufs_wbox_stat_read, - .llseek = no_llseek, }; static int spufs_signal1_open(struct inode *inode, struct file *file) @@ -1056,7 +1049,6 @@ static const struct file_operations spufs_signal1_fops = { .read = spufs_signal1_read, .write = spufs_signal1_write, .mmap = spufs_signal1_mmap, - .llseek = no_llseek, }; static const struct file_operations spufs_signal1_nosched_fops = { @@ -1064,7 +1056,6 @@ static const struct file_operations spufs_signal1_nosched_fops = { .release = spufs_signal1_release, .write = spufs_signal1_write, .mmap = spufs_signal1_mmap, - .llseek = no_llseek, }; static int spufs_signal2_open(struct inode *inode, struct file *file) @@ -1195,7 +1186,6 @@ static const struct file_operations spufs_signal2_fops = { .read = spufs_signal2_read, .write = spufs_signal2_write, .mmap = spufs_signal2_mmap, - .llseek = no_llseek, }; static const struct file_operations spufs_signal2_nosched_fops = { @@ -1203,7 +1193,6 @@ static const struct file_operations spufs_signal2_nosched_fops = { .release = spufs_signal2_release, .write = spufs_signal2_write, .mmap = spufs_signal2_mmap, - .llseek = no_llseek, }; /* @@ -1343,7 +1332,6 @@ static const struct file_operations spufs_mss_fops = { .open = spufs_mss_open, .release = spufs_mss_release, .mmap = spufs_mss_mmap, - .llseek = no_llseek, }; static vm_fault_t @@ -1401,7 +1389,6 @@ static const struct file_operations spufs_psmap_fops = { .open = spufs_psmap_open, .release = spufs_psmap_release, .mmap = spufs_psmap_mmap, - .llseek = no_llseek, }; @@ -1732,7 +1719,6 @@ static const struct file_operations spufs_mfc_fops = { .flush = spufs_mfc_flush, .fsync = spufs_mfc_fsync, .mmap = spufs_mfc_mmap, - .llseek = no_llseek, }; static int spufs_npc_set(void *data, u64 val) @@ -2102,7 +2088,6 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, static const struct file_operations spufs_dma_info_fops = { .open = spufs_info_open, .read = spufs_dma_info_read, - .llseek = no_llseek, }; static void spufs_get_proxydma_info(struct spu_context *ctx, @@ -2159,7 +2144,6 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, static const struct file_operations spufs_proxydma_info_fops = { .open = spufs_info_open, .read = spufs_proxydma_info_read, - .llseek = no_llseek, }; static int spufs_show_tid(struct seq_file *s, void *private) @@ -2442,7 +2426,6 @@ static const struct file_operations spufs_switch_log_fops = { .read = spufs_switch_log_read, .poll = spufs_switch_log_poll, .release = spufs_switch_log_release, - .llseek = no_llseek, }; /** diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 5c4f1a9ca154..6f4a41a9352a 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c @@ -14,7 +14,7 @@ #include <linux/ioport.h> #include <linux/device.h> #include <linux/platform_device.h> -#include <linux/mv643xx.h> +#include <linux/mv643xx_eth.h> #include <linux/pci.h> #define PEGASOS2_MARVELL_REGBASE (0xf1000000) @@ -25,12 +25,15 @@ #define PEGASOS2_SRAM_BASE_ETH_PORT0 (PEGASOS2_SRAM_BASE) #define PEGASOS2_SRAM_BASE_ETH_PORT1 (PEGASOS2_SRAM_BASE_ETH_PORT0 + (PEGASOS2_SRAM_SIZE / 2) ) - #define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4) #define PEGASOS2_SRAM_TXRING_SIZE (PEGASOS2_SRAM_SIZE/4) #undef BE_VERBOSE +#define MV64340_BASE_ADDR_ENABLE 0x278 +#define MV64340_INTEGRATED_SRAM_BASE_ADDR 0x268 +#define MV64340_SRAM_CONFIG 0x380 + static struct resource mv643xx_eth_shared_resources[] = { [0] = { .name = "ethernet shared base", diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h index 4f358b55c341..8ddbaa4ebd0b 100644 --- a/arch/powerpc/platforms/maple/maple.h +++ b/arch/powerpc/platforms/maple/maple.h @@ -7,7 +7,6 @@ extern int maple_set_rtc_time(struct rtc_time *tm); extern void maple_get_rtc_time(struct rtc_time *tm); extern time64_t maple_get_boot_time(void); -extern void maple_calibrate_decr(void); extern void maple_pci_init(void); extern void maple_pci_irq_fixup(struct pci_dev *dev); extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 4e983af32949..e4538d471256 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(of, gpio_mdio_match); static struct platform_driver gpio_mdio_driver = { .probe = gpio_mdio_probe, - .remove_new = gpio_mdio_remove, + .remove = gpio_mdio_remove, .driver = { .name = "gpio-mdio-bitbang", .of_match_table = gpio_mdio_match, diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 018c30665e1b..6f6743b8e48d 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h @@ -5,7 +5,6 @@ extern time64_t pas_get_boot_time(void); extern void pas_pci_init(void); struct pci_dev; -extern void pas_pci_irq_fixup(struct pci_dev *dev); extern void pas_pci_dma_dev_setup(struct pci_dev *dev); void __iomem *__init pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset); diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 085e0ad20eba..8253de737373 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -313,7 +313,7 @@ static void __init uninorth_install_pfunc(void) /* * Install handlers for the hwclock child if any */ - for (np = NULL; (np = of_get_next_child(uninorth_node, np)) != NULL;) + for_each_child_of_node(uninorth_node, np) if (of_node_name_eq(np, "hw-clock")) { unin_hwclock = np; break; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 15644be31990..d21b681f52fb 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -827,7 +827,7 @@ static int smp_core99_kick_cpu(int nr) mdelay(1); /* Restore our exception vector */ - patch_instruction(vector, ppc_inst(save_vector)); + patch_uint(vector, save_vector); local_irq_restore(flags); if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index af3a5d37a149..db3370d1673c 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -99,7 +99,6 @@ static ssize_t pnv_eeh_ei_write(struct file *filp, static const struct file_operations pnv_eeh_ei_fops = { .open = simple_open, - .llseek = no_llseek, .write = pnv_eeh_ei_write, }; @@ -860,7 +859,7 @@ static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option) int64_t rc; /* Hot reset to the bus if firmware cannot handle */ - if (!dn || !of_get_property(dn, "ibm,reset-by-firmware", NULL)) + if (!dn || !of_property_present(dn, "ibm,reset-by-firmware")) return __pnv_eeh_bridge_reset(pdev, option); pr_debug("%s: FW reset PCI bus %04x:%02x with option %d\n", diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c index 16c5860f1372..608e4b68c5ea 100644 --- a/arch/powerpc/platforms/powernv/opal-dump.c +++ b/arch/powerpc/platforms/powernv/opal-dump.c @@ -210,7 +210,7 @@ static struct attribute *dump_default_attrs[] = { }; ATTRIBUTE_GROUPS(dump_default); -static struct kobj_type dump_ktype = { +static const struct kobj_type dump_ktype = { .sysfs_ops = &dump_sysfs_ops, .release = &dump_release, .default_groups = dump_default_groups, diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 554fdd7f88b8..5db1e733143b 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c @@ -146,7 +146,7 @@ static struct attribute *elog_default_attrs[] = { }; ATTRIBUTE_GROUPS(elog_default); -static struct kobj_type elog_ktype = { +static const struct kobj_type elog_ktype = { .sysfs_ops = &elog_sysfs_ops, .release = &elog_release, .default_groups = elog_default_groups, diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c index 56a1f7ce78d2..d92759c21fae 100644 --- a/arch/powerpc/platforms/powernv/opal-irqchip.c +++ b/arch/powerpc/platforms/powernv/opal-irqchip.c @@ -282,6 +282,7 @@ int __init opal_event_init(void) name, NULL); if (rc) { pr_warn("Error %d requesting OPAL irq %d\n", rc, (int)r->start); + kfree(name); continue; } } diff --git a/arch/powerpc/platforms/powernv/opal-kmsg.c b/arch/powerpc/platforms/powernv/opal-kmsg.c index 6c3bc4b4da98..bb4218fa796e 100644 --- a/arch/powerpc/platforms/powernv/opal-kmsg.c +++ b/arch/powerpc/platforms/powernv/opal-kmsg.c @@ -20,13 +20,13 @@ * message, it just ensures that OPAL completely flushes the console buffer. */ static void kmsg_dump_opal_console_flush(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason) + struct kmsg_dump_detail *detail) { /* * Outside of a panic context the pollers will continue to run, * so we don't need to do any special flushing. */ - if (reason != KMSG_DUMP_PANIC) + if (detail->reason != KMSG_DUMP_PANIC) return; opal_flush_console(0); diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index a16f07cdab26..8a7f39e106bd 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c @@ -393,7 +393,7 @@ void __init opal_lpc_init(void) for_each_compatible_node(np, NULL, "ibm,power8-lpc") { if (!of_device_is_available(np)) continue; - if (!of_get_property(np, "primary", NULL)) + if (!of_property_present(np, "primary")) continue; opal_lpc_chip_id = of_get_ibm_chip_id(np); of_node_put(np); diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c index 24f04f20d3e8..dc246ed4b7b4 100644 --- a/arch/powerpc/platforms/powernv/opal-prd.c +++ b/arch/powerpc/platforms/powernv/opal-prd.c @@ -443,7 +443,7 @@ static struct platform_driver opal_prd_driver = { .of_match_table = opal_prd_match, }, .probe = opal_prd_probe, - .remove_new = opal_prd_remove, + .remove = opal_prd_remove, }; module_platform_driver(opal_prd_driver); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 957f2b47a3c0..93fba1f8661f 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -274,7 +274,6 @@ int pnv_pci_cfg_write(struct pci_dn *pdn, int where, int size, u32 val); extern struct iommu_table *pnv_pci_table_alloc(int nid); -extern void pnv_pci_init_ioda_hub(struct device_node *np); extern void pnv_pci_init_ioda2_phb(struct device_node *np); extern void pnv_pci_init_npu2_opencapi_phb(struct device_node *np); extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev); diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 8f14f0581a21..2e9da58195f5 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -36,6 +36,7 @@ #include <asm/kexec.h> #include <asm/reg.h> #include <asm/powernv.h> +#include <asm/systemcfg.h> #include "powernv.h" @@ -136,7 +137,9 @@ static int pnv_smp_cpu_disable(void) * the generic fixup_irqs. --BenH. */ set_cpu_online(cpu, false); - vdso_data->processorCount--; +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG + systemcfg->processorCount--; +#endif if (cpu == boot_cpuid) boot_cpuid = cpumask_any(cpu_online_mask); if (xive_enabled()) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 47f8eabd1bee..213aa26dc8b3 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -23,6 +23,7 @@ #include <linux/uaccess.h> #include <asm/rtas.h> #include <asm/rtas-work-area.h> +#include <asm/prom.h> static struct workqueue_struct *pseries_hp_wq; @@ -250,11 +251,8 @@ int dlpar_detach_node(struct device_node *dn) struct device_node *child; int rc; - child = of_get_next_child(dn, NULL); - while (child) { + for_each_child_of_node(dn, child) dlpar_detach_node(child); - child = of_get_next_child(dn, child); - } rc = of_detach_node(dn); if (rc) @@ -264,6 +262,20 @@ int dlpar_detach_node(struct device_node *dn) return 0; } +static int dlpar_changeset_attach_cc_nodes(struct of_changeset *ocs, + struct device_node *dn) +{ + int rc; + + rc = of_changeset_attach_node(ocs, dn); + + if (!rc && dn->child) + rc = dlpar_changeset_attach_cc_nodes(ocs, dn->child); + if (!rc && dn->sibling) + rc = dlpar_changeset_attach_cc_nodes(ocs, dn->sibling); + + return rc; +} #define DR_ENTITY_SENSE 9003 #define DR_ENTITY_PRESENT 1 @@ -330,27 +342,206 @@ int dlpar_unisolate_drc(u32 drc_index) return 0; } -int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) +static struct device_node * +get_device_node_with_drc_index(u32 index) +{ + struct device_node *np = NULL; + u32 node_index; + int rc; + + for_each_node_with_property(np, "ibm,my-drc-index") { + rc = of_property_read_u32(np, "ibm,my-drc-index", + &node_index); + if (rc) { + pr_err("%s: %pOF: of_property_read_u32 %s: %d\n", + __func__, np, "ibm,my-drc-index", rc); + of_node_put(np); + return NULL; + } + + if (index == node_index) + break; + } + + return np; +} + +static struct device_node * +get_device_node_with_drc_info(u32 index) +{ + struct device_node *np = NULL; + struct of_drc_info drc; + struct property *info; + const __be32 *value; + u32 node_index; + int i, j, count; + + for_each_node_with_property(np, "ibm,drc-info") { + info = of_find_property(np, "ibm,drc-info", NULL); + if (info == NULL) { + /* XXX can this happen? */ + of_node_put(np); + return NULL; + } + value = of_prop_next_u32(info, NULL, &count); + if (value == NULL) + continue; + value++; + for (i = 0; i < count; i++) { + if (of_read_drc_info_cell(&info, &value, &drc)) + break; + if (index > drc.last_drc_index) + continue; + node_index = drc.drc_index_start; + for (j = 0; j < drc.num_sequential_elems; j++) { + if (index == node_index) + return np; + node_index += drc.sequential_inc; + } + } + } + + return NULL; +} + +static int dlpar_hp_dt_add(u32 index) +{ + struct device_node *np, *nodes; + struct of_changeset ocs; + int rc; + + /* + * Do not add device node(s) if already exists in the + * device tree. + */ + np = get_device_node_with_drc_index(index); + if (np) { + pr_err("%s: Adding device node for index (%d), but " + "already exists in the device tree\n", + __func__, index); + rc = -EINVAL; + goto out; + } + + np = get_device_node_with_drc_info(index); + + if (!np) + return -EIO; + + /* Next, configure the connector. */ + nodes = dlpar_configure_connector(cpu_to_be32(index), np); + if (!nodes) { + rc = -EIO; + goto out; + } + + /* + * Add the new nodes from dlpar_configure_connector() onto + * the device-tree. + */ + of_changeset_init(&ocs); + rc = dlpar_changeset_attach_cc_nodes(&ocs, nodes); + + if (!rc) + rc = of_changeset_apply(&ocs); + else + dlpar_free_cc_nodes(nodes); + + of_changeset_destroy(&ocs); + +out: + of_node_put(np); + return rc; +} + +static int changeset_detach_node_recursive(struct of_changeset *ocs, + struct device_node *node) { + struct device_node *child; int rc; - /* pseries error logs are in BE format, convert to cpu type */ - switch (hp_elog->id_type) { - case PSERIES_HP_ELOG_ID_DRC_COUNT: - hp_elog->_drc_u.drc_count = - be32_to_cpu(hp_elog->_drc_u.drc_count); + for_each_child_of_node(node, child) { + rc = changeset_detach_node_recursive(ocs, child); + if (rc) { + of_node_put(child); + return rc; + } + } + + return of_changeset_detach_node(ocs, node); +} + +static int dlpar_hp_dt_remove(u32 drc_index) +{ + struct device_node *np; + struct of_changeset ocs; + u32 index; + int rc = 0; + + /* + * Prune all nodes with a matching index. + */ + of_changeset_init(&ocs); + + for_each_node_with_property(np, "ibm,my-drc-index") { + rc = of_property_read_u32(np, "ibm,my-drc-index", &index); + if (rc) { + pr_err("%s: %pOF: of_property_read_u32 %s: %d\n", + __func__, np, "ibm,my-drc-index", rc); + of_node_put(np); + goto out; + } + + if (index == drc_index) { + rc = changeset_detach_node_recursive(&ocs, np); + if (rc) { + of_node_put(np); + goto out; + } + } + } + + rc = of_changeset_apply(&ocs); + +out: + of_changeset_destroy(&ocs); + return rc; +} + +static int dlpar_hp_dt(struct pseries_hp_errorlog *phpe) +{ + u32 drc_index; + int rc; + + if (phpe->id_type != PSERIES_HP_ELOG_ID_DRC_INDEX) + return -EINVAL; + + drc_index = be32_to_cpu(phpe->_drc_u.drc_index); + + lock_device_hotplug(); + + switch (phpe->action) { + case PSERIES_HP_ELOG_ACTION_ADD: + rc = dlpar_hp_dt_add(drc_index); break; - case PSERIES_HP_ELOG_ID_DRC_INDEX: - hp_elog->_drc_u.drc_index = - be32_to_cpu(hp_elog->_drc_u.drc_index); + case PSERIES_HP_ELOG_ACTION_REMOVE: + rc = dlpar_hp_dt_remove(drc_index); + break; + default: + pr_err("Invalid action (%d) specified\n", phpe->action); + rc = -EINVAL; break; - case PSERIES_HP_ELOG_ID_DRC_IC: - hp_elog->_drc_u.ic.count = - be32_to_cpu(hp_elog->_drc_u.ic.count); - hp_elog->_drc_u.ic.index = - be32_to_cpu(hp_elog->_drc_u.ic.index); } + unlock_device_hotplug(); + + return rc; +} + +int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) +{ + int rc; + switch (hp_elog->resource) { case PSERIES_HP_ELOG_RESOURCE_MEM: rc = dlpar_memory(hp_elog); @@ -361,6 +552,9 @@ int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) case PSERIES_HP_ELOG_RESOURCE_PMEM: rc = dlpar_hp_pmem(hp_elog); break; + case PSERIES_HP_ELOG_RESOURCE_DT: + rc = dlpar_hp_dt(hp_elog); + break; default: pr_warn_ratelimited("Invalid resource (%d) specified\n", @@ -413,6 +607,8 @@ static int dlpar_parse_resource(char **cmd, struct pseries_hp_errorlog *hp_elog) hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM; } else if (sysfs_streq(arg, "cpu")) { hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_CPU; + } else if (sysfs_streq(arg, "dt")) { + hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_DT; } else { pr_err("Invalid resource specified.\n"); return -EINVAL; @@ -554,7 +750,7 @@ dlpar_store_out: static ssize_t dlpar_show(const struct class *class, const struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", "memory,cpu"); + return sprintf(buf, "%s\n", "memory,cpu,dt"); } static CLASS_ATTR_RW(dlpar); diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 3f1cdccebc9c..8cb9d36ea491 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c @@ -325,7 +325,6 @@ static const struct file_operations dtl_fops = { .open = dtl_file_open, .release = dtl_file_release, .read = dtl_file_read, - .llseek = no_llseek, }; static struct dentry *dtl_dir; diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index b1ae0c0d1187..1893f66371fa 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -784,6 +784,43 @@ static int pseries_notify_resume(struct eeh_dev *edev) } #endif +/** + * pseries_eeh_err_inject - Inject specified error to the indicated PE + * @pe: the indicated PE + * @type: error type + * @func: specific error type + * @addr: address + * @mask: address mask + * The routine is called to inject specified error, which is + * determined by @type and @func, to the indicated PE + */ +static int pseries_eeh_err_inject(struct eeh_pe *pe, int type, int func, + unsigned long addr, unsigned long mask) +{ + struct eeh_dev *pdev; + + /* Check on PCI error type */ + if (type != EEH_ERR_TYPE_32 && type != EEH_ERR_TYPE_64) + return -EINVAL; + + switch (func) { + case EEH_ERR_FUNC_LD_MEM_ADDR: + case EEH_ERR_FUNC_LD_MEM_DATA: + case EEH_ERR_FUNC_ST_MEM_ADDR: + case EEH_ERR_FUNC_ST_MEM_DATA: + /* injects a MMIO error for all pdev's belonging to PE */ + pci_lock_rescan_remove(); + list_for_each_entry(pdev, &pe->edevs, entry) + eeh_pe_inject_mmio_error(pdev->pdev); + pci_unlock_rescan_remove(); + break; + default: + return -ERANGE; + } + + return 0; +} + static struct eeh_ops pseries_eeh_ops = { .name = "pseries", .probe = pseries_eeh_probe, @@ -792,7 +829,7 @@ static struct eeh_ops pseries_eeh_ops = { .reset = pseries_eeh_reset, .get_log = pseries_eeh_get_log, .configure_bridge = pseries_eeh_configure_bridge, - .err_inject = NULL, + .err_inject = pseries_eeh_err_inject, .read_config = pseries_eeh_read_config, .write_config = pseries_eeh_write_config, .next_error = NULL, diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index e62835a12d73..bc6926dbf148 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -33,6 +33,7 @@ #include <asm/xive.h> #include <asm/plpar_wrappers.h> #include <asm/topology.h> +#include <asm/systemcfg.h> #include "pseries.h" @@ -83,7 +84,9 @@ static int pseries_cpu_disable(void) int cpu = smp_processor_id(); set_cpu_online(cpu, false); - vdso_data->processorCount--; +#ifdef CONFIG_PPC64_PROC_SYSTEMCFG + systemcfg->processorCount--; +#endif /*fix boot_cpuid here*/ if (cpu == boot_cpuid) @@ -757,7 +760,7 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog) u32 drc_index; int rc; - drc_index = hp_elog->_drc_u.drc_index; + drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index); lock_device_hotplug(); diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 3fe3ddb30c04..38dc4f7c9296 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -817,16 +817,16 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) case PSERIES_HP_ELOG_ACTION_ADD: switch (hp_elog->id_type) { case PSERIES_HP_ELOG_ID_DRC_COUNT: - count = hp_elog->_drc_u.drc_count; + count = be32_to_cpu(hp_elog->_drc_u.drc_count); rc = dlpar_memory_add_by_count(count); break; case PSERIES_HP_ELOG_ID_DRC_INDEX: - drc_index = hp_elog->_drc_u.drc_index; + drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index); rc = dlpar_memory_add_by_index(drc_index); break; case PSERIES_HP_ELOG_ID_DRC_IC: - count = hp_elog->_drc_u.ic.count; - drc_index = hp_elog->_drc_u.ic.index; + count = be32_to_cpu(hp_elog->_drc_u.ic.count); + drc_index = be32_to_cpu(hp_elog->_drc_u.ic.index); rc = dlpar_memory_add_by_ic(count, drc_index); break; default: @@ -838,16 +838,16 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) case PSERIES_HP_ELOG_ACTION_REMOVE: switch (hp_elog->id_type) { case PSERIES_HP_ELOG_ID_DRC_COUNT: - count = hp_elog->_drc_u.drc_count; + count = be32_to_cpu(hp_elog->_drc_u.drc_count); rc = dlpar_memory_remove_by_count(count); break; case PSERIES_HP_ELOG_ID_DRC_INDEX: - drc_index = hp_elog->_drc_u.drc_index; + drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index); rc = dlpar_memory_remove_by_index(drc_index); break; case PSERIES_HP_ELOG_ID_DRC_IC: - count = hp_elog->_drc_u.ic.count; - drc_index = hp_elog->_drc_u.ic.index; + count = be32_to_cpu(hp_elog->_drc_u.ic.count); + drc_index = be32_to_cpu(hp_elog->_drc_u.ic.index); rc = dlpar_memory_remove_by_ic(count, drc_index); break; default: diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 62da20f9700a..cc22924f159f 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c @@ -29,7 +29,6 @@ #include <asm/firmware.h> #include <asm/rtas.h> #include <asm/time.h> -#include <asm/vdso_datapage.h> #include <asm/vio.h> #include <asm/mmu.h> #include <asm/machdep.h> @@ -530,7 +529,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { - partition_potential_processors = vdso_data->processorCount; + partition_potential_processors = num_possible_cpus(); } else { partition_potential_processors = be32_to_cpup(lrdrp + 4); } @@ -553,7 +552,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) } else { /* non SPLPAR case */ seq_printf(m, "system_active_processors=%d\n", - partition_potential_processors); + partition_active_processors); seq_printf(m, "system_potential_processors=%d\n", partition_potential_processors); diff --git a/arch/powerpc/platforms/pseries/papr-vpd.c b/arch/powerpc/platforms/pseries/papr-vpd.c index c29e85db5f35..1574176e3ffc 100644 --- a/arch/powerpc/platforms/pseries/papr-vpd.c +++ b/arch/powerpc/platforms/pseries/papr-vpd.c @@ -156,10 +156,7 @@ static int vpd_blob_extend(struct vpd_blob *blob, const char *data, size_t len) const char *old_ptr = blob->data; char *new_ptr; - new_ptr = old_ptr ? - kvrealloc(old_ptr, old_len, new_len, GFP_KERNEL_ACCOUNT) : - kvmalloc(len, GFP_KERNEL_ACCOUNT); - + new_ptr = kvrealloc(old_ptr, new_len, GFP_KERNEL_ACCOUNT); if (!new_ptr) return -ENOMEM; diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index f6a70bc92e83..9e297f88adc5 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -19,7 +19,7 @@ #include <uapi/linux/papr_pdsm.h> #include <linux/papr_scm.h> #include <asm/mce.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/perf_event.h> #define BIND_ANY_ADDR (~0ul) @@ -1509,7 +1509,7 @@ static const struct of_device_id papr_scm_match[] = { static struct platform_driver papr_scm_driver = { .probe = papr_scm_probe, - .remove_new = papr_scm_remove, + .remove = papr_scm_remove, .driver = { .name = "papr_scm", .of_match_table = papr_scm_match, diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c index 4a595493d28a..b1667ed05f98 100644 --- a/arch/powerpc/platforms/pseries/plpks.c +++ b/arch/powerpc/platforms/pseries/plpks.c @@ -683,7 +683,7 @@ void __init plpks_early_init_devtree(void) out: fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw"); // Since we've cleared the password, we must update the FDT checksum - early_init_dt_verify(fdt); + early_init_dt_verify(fdt, __pa(fdt)); } static __init int pseries_plpks_init(void) diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c index 3c290b9ed01b..0f1d45f32e4a 100644 --- a/arch/powerpc/platforms/pseries/pmem.c +++ b/arch/powerpc/platforms/pseries/pmem.c @@ -121,7 +121,7 @@ int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog) return -EINVAL; } - drc_index = hp_elog->_drc_u.drc_index; + drc_index = be32_to_cpu(hp_elog->_drc_u.drc_index); lock_device_hotplug(); diff --git a/arch/powerpc/platforms/pseries/vas-sysfs.c b/arch/powerpc/platforms/pseries/vas-sysfs.c index f9f682724e77..9e05a0e99cad 100644 --- a/arch/powerpc/platforms/pseries/vas-sysfs.c +++ b/arch/powerpc/platforms/pseries/vas-sysfs.c @@ -162,13 +162,13 @@ static const struct sysfs_ops vas_sysfs_ops = { .store = vas_type_store, }; -static struct kobj_type vas_def_attr_type = { +static const struct kobj_type vas_def_attr_type = { .release = vas_type_release, .sysfs_ops = &vas_sysfs_ops, .default_groups = vas_def_capab_groups, }; -static struct kobj_type vas_qos_attr_type = { +static const struct kobj_type vas_qos_attr_type = { .release = vas_type_release, .sysfs_ops = &vas_sysfs_ops, .default_groups = vas_qos_capab_groups, diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index e205135ae1fe..1aa0cb097c9c 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -603,7 +603,7 @@ static struct platform_driver fsl_of_msi_driver = { .of_match_table = fsl_of_msi_ids, }, .probe = fsl_of_msi_probe, - .remove_new = fsl_of_msi_remove, + .remove = fsl_of_msi_remove, }; static __init int fsl_of_msi_init(void) diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 737f97fd67d7..2511e586fe31 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -193,7 +193,7 @@ static void pmi_of_remove(struct platform_device *dev) static struct platform_driver pmi_of_platform_driver = { .probe = pmi_of_probe, - .remove_new = pmi_of_remove, + .remove = pmi_of_remove, .driver = { .name = "pmi", .of_match_table = pmi_match, diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index bd4813bad317..e6cddbb2305f 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -3543,7 +3543,7 @@ scanhex(unsigned long *vp) } } else if (c == '$') { int i; - for (i=0; i<63; i++) { + for (i = 0; i < (KSYM_NAME_LEN - 1); i++) { c = inchar(); if (isspace(c) || c == '\0') { termch = c; diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 0f3cd7c3a436..ff1e353b0d6f 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -13,6 +13,7 @@ config 32BIT config RISCV def_bool y select ACPI_GENERIC_GSI if ACPI + select ACPI_MCFG if (ACPI && PCI) select ACPI_PPTT if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ACPI_SPCR_TABLE if ACPI @@ -38,6 +39,7 @@ config RISCV select ARCH_HAS_MMIOWB select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_PMEM_API + select ARCH_HAS_PREEMPT_LAZY select ARCH_HAS_PREPARE_SYNC_CORE_CMD select ARCH_HAS_PTE_DEVMAP if 64BIT && MMU select ARCH_HAS_PTE_SPECIAL @@ -49,7 +51,7 @@ config RISCV select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_UBSAN - select ARCH_HAS_VDSO_DATA + select ARCH_HAS_VDSO_TIME_DATA select ARCH_KEEP_MEMBLOCK if ACPI select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if 64BIT && MMU select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX @@ -64,10 +66,12 @@ config RISCV select ARCH_SUPPORTS_LTO_CLANG_THIN if LLD_VERSION >= 140000 select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU select ARCH_SUPPORTS_PER_VMA_LOCK if MMU + select ARCH_SUPPORTS_RT select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK select ARCH_USE_CMPXCHG_LOCKREF if 64BIT select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS + select ARCH_USE_SYM_ANNOTATIONS select ARCH_USES_CFI_TRAPS if CFI_CLANG select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if MMU select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU @@ -92,6 +96,7 @@ config RISCV select GENERIC_ATOMIC64 if !64BIT select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CPU_DEVICES + select GENERIC_CPU_VULNERABILITIES select GENERIC_EARLY_IOREMAP select GENERIC_ENTRY select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO @@ -156,6 +161,7 @@ config RISCV select HAVE_KERNEL_LZO if !XIP_KERNEL && !EFI_ZBOOT select HAVE_KERNEL_UNCOMPRESSED if !XIP_KERNEL && !EFI_ZBOOT select HAVE_KERNEL_ZSTD if !XIP_KERNEL && !EFI_ZBOOT + select HAVE_KERNEL_XZ if !XIP_KERNEL && !EFI_ZBOOT select HAVE_KPROBES if !XIP_KERNEL select HAVE_KRETPROBES if !XIP_KERNEL # https://github.com/ClangBuiltLinux/linux/issues/1881 @@ -172,7 +178,7 @@ config RISCV select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RETHOOK if !XIP_KERNEL select HAVE_RSEQ - select HAVE_RUST if 64BIT + select HAVE_RUST if RUSTC_SUPPORTS_RISCV && CC_IS_CLANG select HAVE_SAMPLE_FTRACE_DIRECT select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_STACKPROTECTOR @@ -188,6 +194,7 @@ config RISCV select OF_EARLY_FLATTREE select OF_IRQ select PCI_DOMAINS_GENERIC if PCI + select PCI_ECAM if (ACPI && PCI) select PCI_MSI if PCI select RISCV_ALTERNATIVE if !XIP_KERNEL select RISCV_APLIC @@ -200,8 +207,16 @@ config RISCV select THREAD_INFO_IN_TASK select TRACE_IRQFLAGS_SUPPORT select UACCESS_MEMCPY if !MMU + select USER_STACKTRACE_SUPPORT select ZONE_DMA32 if 64BIT +config RUSTC_SUPPORTS_RISCV + def_bool y + depends on 64BIT + # Shadow call stack requires rustc version 1.82+ due to use of the + # -Zsanitizer=shadow-call-stack flag. + depends on !SHADOW_CALL_STACK || RUSTC_VERSION >= 108200 + config CLANG_SUPPORTS_DYNAMIC_FTRACE def_bool CC_IS_CLANG # https://github.com/ClangBuiltLinux/linux/issues/1817 @@ -319,6 +334,11 @@ config GENERIC_HWEIGHT config FIX_EARLYCON_MEM def_bool MMU +config ILLEGAL_POINTER_VALUE + hex + default 0 if 32BIT + default 0xdead000000000000 if 64BIT + config PGTABLE_LEVELS int default 5 if 64BIT @@ -552,8 +572,8 @@ config RISCV_ISA_SVPBMT config TOOLCHAIN_HAS_V bool default y - depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64iv) - depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32iv) + depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64imv) + depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32imv) depends on LLD_VERSION >= 140000 || LD_VERSION >= 23800 depends on AS_HAS_OPTION_ARCH @@ -758,8 +778,7 @@ config IRQ_STACKS config THREAD_SIZE_ORDER int "Kernel stack size (in power-of-two numbers of page size)" if VMAP_STACK && EXPERT range 0 4 - default 1 if 32BIT && !KASAN - default 3 if 64BIT && KASAN + default 1 if 32BIT default 2 help Specify the Pages of thread stack size (from 4KB to 64KB), which also @@ -880,6 +899,9 @@ config ARCH_SUPPORTS_KEXEC_PURGATORY config ARCH_SUPPORTS_CRASH_DUMP def_bool y +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION def_bool CRASH_RESERVE diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 6fe682139d2e..d469db9f46f4 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -159,6 +159,7 @@ boot-image-$(CONFIG_KERNEL_LZ4) := Image.lz4 boot-image-$(CONFIG_KERNEL_LZMA) := Image.lzma boot-image-$(CONFIG_KERNEL_LZO) := Image.lzo boot-image-$(CONFIG_KERNEL_ZSTD) := Image.zst +boot-image-$(CONFIG_KERNEL_XZ) := Image.xz ifdef CONFIG_RISCV_M_MODE boot-image-$(CONFIG_ARCH_CANAAN) := loader.bin endif @@ -183,12 +184,12 @@ endif vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg -BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst loader loader.bin xipImage vmlinuz.efi +BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader loader.bin xipImage vmlinuz.efi all: $(notdir $(KBUILD_IMAGE)) loader.bin: loader -Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst loader xipImage vmlinuz.efi: Image +Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader xipImage vmlinuz.efi: Image $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ @@ -225,6 +226,7 @@ define archhelp echo ' Image.lzma - Compressed kernel image (arch/riscv/boot/Image.lzma)' echo ' Image.lzo - Compressed kernel image (arch/riscv/boot/Image.lzo)' echo ' Image.zst - Compressed kernel image (arch/riscv/boot/Image.zst)' + echo ' Image.xz - Compressed kernel image (arch/riscv/boot/Image.xz)' echo ' vmlinuz.efi - Compressed EFI kernel image (arch/riscv/boot/vmlinuz.efi)' echo ' Default when CONFIG_EFI_ZBOOT=y' echo ' xipImage - Execute-in-place kernel image (arch/riscv/boot/xipImage)' diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index 4e9e7a28bf9b..b25d524ce5eb 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -64,6 +64,9 @@ $(obj)/Image.lzo: $(obj)/Image FORCE $(obj)/Image.zst: $(obj)/Image FORCE $(call if_changed,zstd) +$(obj)/Image.xz: $(obj)/Image FORCE + $(call if_changed,xzkern) + $(obj)/loader.bin: $(obj)/loader FORCE $(call if_changed,objcopy) diff --git a/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts b/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts index aa361f3a86bb..7b5f57853690 100644 --- a/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts +++ b/arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dts @@ -43,6 +43,15 @@ clock-frequency = <25000000>; }; +&sdhci0 { + status = "okay"; + bus-width = <4>; + no-1-8-v; + no-mmc; + no-sdio; + disable-wp; +}; + &uart0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi index 891932ae470f..b724fb6d9689 100644 --- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi +++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi @@ -297,6 +297,22 @@ status = "disabled"; }; + dmac: dma-controller@4330000 { + compatible = "snps,axi-dma-1.01a"; + reg = <0x04330000 0x1000>; + interrupts = <29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk CLK_SDMA_AXI>, <&clk CLK_SDMA_AXI>; + clock-names = "core-clk", "cfgr-clk"; + #dma-cells = <1>; + dma-channels = <8>; + snps,block-size = <1024 1024 1024 1024 + 1024 1024 1024 1024>; + snps,priority = <0 1 2 3 4 5 6 7>; + snps,dma-masters = <2>; + snps,data-width = <4>; + status = "disabled"; + }; + plic: interrupt-controller@70000000 { reg = <0x70000000 0x4000000>; interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>; diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts index 80cb017974d8..a3f9d6f22566 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts +++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts @@ -26,6 +26,83 @@ clock-frequency = <25000000>; }; +&emmc { + bus-width = <4>; + no-sdio; + no-sd; + non-removable; + wp-inverted; + status = "okay"; +}; + +&i2c1 { + status = "okay"; + + mcu: syscon@17 { + compatible = "sophgo,sg2042-hwmon-mcu"; + reg = <0x17>; + #thermal-sensor-cells = <1>; + }; +}; + +&sd { + bus-width = <4>; + no-sdio; + no-mmc; + wp-inverted; + status = "okay"; +}; + &uart0 { status = "okay"; }; + +/ { + thermal-zones { + soc-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&mcu 0>; + + trips { + soc_active1: soc-active1 { + temperature = <30000>; + hysteresis = <8000>; + type = "active"; + }; + + soc_active2: soc-active2 { + temperature = <58000>; + hysteresis = <12000>; + type = "active"; + }; + + soc_active3: soc-active3 { + temperature = <70000>; + hysteresis = <10000>; + type = "active"; + }; + + soc_hot: soc-hot { + temperature = <80000>; + hysteresis = <5000>; + type = "hot"; + }; + }; + }; + + board-thermal { + polling-delay-passive = <1000>; + polling-delay = <1000>; + thermal-sensors = <&mcu 1>; + + trips { + board_active: board-active { + temperature = <75000>; + hysteresis = <8000>; + type = "active"; + }; + }; + }; + }; +}; diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index 34c802bd3f9b..e62ac51ac55a 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -44,8 +44,127 @@ compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; + interrupt-parent = <&intc>; ranges; + i2c0: i2c@7030005000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30005000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C0>; + status = "disabled"; + }; + + i2c1: i2c@7030006000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30006000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <102 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C1>; + status = "disabled"; + }; + + i2c2: i2c@7030007000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30007000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <103 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C2>; + status = "disabled"; + }; + + i2c3: i2c@7030008000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30008000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <104 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C3>; + status = "disabled"; + }; + + gpio0: gpio@7030009000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x30009000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port0a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <96 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@703000a000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x3000a000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port1a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <97 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio2: gpio@703000b000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x3000b000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port2a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <98 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + pllclk: clock-controller@70300100c0 { compatible = "sophgo,sg2042-pll"; reg = <0x70 0x300100c0 0x0 0x40>; @@ -388,7 +507,6 @@ uart0: serial@7040000000 { compatible = "snps,dw-apb-uart"; reg = <0x00000070 0x40000000 0x00000000 0x00001000>; - interrupt-parent = <&intc>; interrupts = <112 IRQ_TYPE_LEVEL_HIGH>; clock-frequency = <500000000>; clocks = <&clkgen GATE_CLK_UART_500M>, @@ -399,5 +517,33 @@ resets = <&rstgen RST_UART0>; status = "disabled"; }; + + emmc: mmc@704002a000 { + compatible = "sophgo,sg2042-dwcmshc"; + reg = <0x70 0x4002a000 0x0 0x1000>; + interrupt-parent = <&intc>; + interrupts = <134 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkgen GATE_CLK_EMMC_100M>, + <&clkgen GATE_CLK_AXI_EMMC>, + <&clkgen GATE_CLK_100K_EMMC>; + clock-names = "core", + "bus", + "timer"; + status = "disabled"; + }; + + sd: mmc@704002b000 { + compatible = "sophgo,sg2042-dwcmshc"; + reg = <0x70 0x4002b000 0x0 0x1000>; + interrupt-parent = <&intc>; + interrupts = <136 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkgen GATE_CLK_SD_100M>, + <&clkgen GATE_CLK_AXI_SD>, + <&clkgen GATE_CLK_100K_SD>; + clock-names = "core", + "bus", + "timer"; + status = "disabled"; + }; }; }; diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi index ca2d44d59d48..d6c55f1cc96a 100644 --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi @@ -128,7 +128,6 @@ assigned-clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>, <&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>; assigned-clock-rates = <49500000>, <198000000>; - status = "okay"; ports { #address-cells = <1>; @@ -151,7 +150,6 @@ &csi2rx { assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>; assigned-clock-rates = <297000000>; - status = "okay"; ports { #address-cells = <1>; @@ -365,6 +363,12 @@ }; }; +&syscrg { + assigned-clocks = <&syscrg JH7110_SYSCLK_CPU_CORE>, + <&pllclk JH7110_PLLCLK_PLL0_OUT>; + assigned-clock-rates = <500000000>, <1500000000>; +}; + &sysgpio { i2c0_pins: i2c0-0 { i2c-pins { diff --git a/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts index b720cdd15ed6..8e39fdc73ecb 100644 --- a/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts +++ b/arch/riscv/boot/dts/starfive/jh7110-pine64-star64.dts @@ -44,8 +44,7 @@ }; &phy0 { - rx-internal-delay-ps = <1900>; - tx-internal-delay-ps = <1500>; + rx-internal-delay-ps = <1500>; motorcomm,rx-clk-drv-microamp = <2910>; motorcomm,rx-data-drv-microamp = <2910>; motorcomm,tx-clk-adj-enabled; diff --git a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts index d9b4de9e4757..497d961456f3 100644 --- a/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts +++ b/arch/riscv/boot/dts/thead/th1520-beaglev-ahead.dts @@ -23,6 +23,7 @@ serial3 = &uart3; serial4 = &uart4; serial5 = &uart5; + spi0 = &spi0; }; chosen { @@ -44,18 +45,6 @@ clock-frequency = <32768>; }; -&apb_clk { - clock-frequency = <62500000>; -}; - -&sdhci_clk { - clock-frequency = <198000000>; -}; - -&uart_sclk { - clock-frequency = <100000000>; -}; - &dmac0 { status = "okay"; }; @@ -79,3 +68,7 @@ &uart0 { status = "okay"; }; + +&spi0 { + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi index 1365d3a512a3..78977bdbbe3d 100644 --- a/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi +++ b/arch/riscv/boot/dts/thead/th1520-lichee-module-4a.dtsi @@ -25,18 +25,6 @@ clock-frequency = <32768>; }; -&apb_clk { - clock-frequency = <62500000>; -}; - -&sdhci_clk { - clock-frequency = <198000000>; -}; - -&uart_sclk { - clock-frequency = <100000000>; -}; - &dmac0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts index 9a3884a73e13..7738d2895c5a 100644 --- a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts +++ b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts @@ -20,6 +20,7 @@ serial3 = &uart3; serial4 = &uart4; serial5 = &uart5; + spi0 = &spi0; }; chosen { @@ -30,3 +31,7 @@ &uart0 { status = "okay"; }; + +&spi0 { + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi index 3c9974062c20..6992060e6a54 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -5,6 +5,7 @@ */ #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clock/thead,th1520-clk-ap.h> / { compatible = "thead,th1520"; @@ -215,25 +216,6 @@ #clock-cells = <0>; }; - apb_clk: apb-clk-clock { - compatible = "fixed-clock"; - clock-output-names = "apb_clk"; - #clock-cells = <0>; - }; - - uart_sclk: uart-sclk-clock { - compatible = "fixed-clock"; - clock-output-names = "uart_sclk"; - #clock-cells = <0>; - }; - - sdhci_clk: sdhci-clock { - compatible = "fixed-clock"; - clock-frequency = <198000000>; - clock-output-names = "sdhci_clk"; - #clock-cells = <0>; - }; - soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -264,11 +246,22 @@ <&cpu3_intc 3>, <&cpu3_intc 7>; }; + spi0: spi@ffe700c000 { + compatible = "thead,th1520-spi", "snps,dw-apb-ssi"; + reg = <0xff 0xe700c000 0x0 0x1000>; + interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk CLK_SPI>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + uart0: serial@ffe7014000 { compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7014000 0x0 0x100>; interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART0_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -278,7 +271,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe7080000 0x0 0x10000>; interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -287,7 +280,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe7090000 0x0 0x10000>; interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -296,7 +289,7 @@ compatible = "thead,th1520-dwcmshc"; reg = <0xff 0xe70a0000 0x0 0x10000>; interrupts = <71 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; + clocks = <&clk CLK_EMMC_SDIO>; clock-names = "core"; status = "disabled"; }; @@ -305,7 +298,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7f00000 0x0 0x100>; interrupts = <37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART1_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -315,7 +309,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xe7f04000 0x0 0x100>; interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART3_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -326,6 +321,7 @@ reg = <0xff 0xe7f34000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; + clocks = <&clk CLK_GPIO2>; portc: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; @@ -344,6 +340,7 @@ reg = <0xff 0xe7f38000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; + clocks = <&clk CLK_GPIO3>; portd: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; @@ -362,6 +359,7 @@ reg = <0xff 0xec005000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; + clocks = <&clk CLK_GPIO0>; porta: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; @@ -380,6 +378,7 @@ reg = <0xff 0xec006000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; + clocks = <&clk CLK_GPIO1>; portb: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; @@ -397,17 +396,25 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xec010000 0x0 0x4000>; interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART2_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; }; + clk: clock-controller@ffef010000 { + compatible = "thead,th1520-clk-ap"; + reg = <0xff 0xef010000 0x0 0x1000>; + clocks = <&osc>; + #clock-cells = <1>; + }; + dmac0: dma-controller@ffefc00000 { compatible = "snps,axi-dma-1.01a"; reg = <0xff 0xefc00000 0x0 0x1000>; interrupts = <27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&apb_clk>, <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>, <&clk CLK_PERI_APB_PCLK>; clock-names = "core-clk", "cfgr-clk"; #dma-cells = <1>; dma-channels = <4>; @@ -422,7 +429,7 @@ timer0: timer@ffefc32000 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32000 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -431,7 +438,7 @@ timer1: timer@ffefc32014 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32014 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -440,7 +447,7 @@ timer2: timer@ffefc32028 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc32028 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -449,7 +456,7 @@ timer3: timer@ffefc3203c { compatible = "snps,dw-apb-timer"; reg = <0xff 0xefc3203c 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -459,7 +466,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xf7f08000 0x0 0x4000>; interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART4_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -469,7 +477,8 @@ compatible = "snps,dw-apb-uart"; reg = <0xff 0xf7f0c000 0x0 0x4000>; interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&uart_sclk>; + clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART5_PCLK>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -478,7 +487,7 @@ timer4: timer@ffffc33000 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33000 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -487,7 +496,7 @@ timer5: timer@ffffc33014 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33014 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -496,7 +505,7 @@ timer6: timer@ffffc33028 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33028 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -505,7 +514,7 @@ timer7: timer@ffffc3303c { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc3303c 0x0 0x14>; - clocks = <&apb_clk>; + clocks = <&clk CLK_PERI_APB_PCLK>; clock-names = "timer"; interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index 0d678325444f..1d5e13b148f2 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -137,12 +137,10 @@ CONFIG_VIRTIO_NET=y CONFIG_MACB=y CONFIG_E1000E=y CONFIG_R8169=y -CONFIG_RAVB=y CONFIG_STMMAC_ETH=m CONFIG_MICREL_PHY=y CONFIG_MICROSEMI_PHY=y CONFIG_MOTORCOMM_PHY=y -CONFIG_CAN_RCAR_CANFD=m CONFIG_INPUT_MOUSEDEV=y CONFIG_KEYBOARD_SUN4I_LRADC=m CONFIG_SERIAL_8250=y @@ -150,29 +148,30 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_EARLYCON_RISCV_SBI=y -CONFIG_SERIAL_SH_SCI=y CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y CONFIG_HW_RANDOM_JH7110=m CONFIG_I2C=y CONFIG_I2C_CHARDEV=m +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_MV64XXX=m -CONFIG_I2C_RIIC=y CONFIG_SPI=y CONFIG_SPI_CADENCE_QUADSPI=m CONFIG_SPI_PL022=m -CONFIG_SPI_RSPI=m CONFIG_SPI_SIFIVE=y CONFIG_SPI_SUN6I=y # CONFIG_PTP_1588_CLOCK is not set +CONFIG_PINCTRL_SOPHGO_CV1800B=y +CONFIG_PINCTRL_SOPHGO_CV1812H=y +CONFIG_PINCTRL_SOPHGO_SG2000=y +CONFIG_PINCTRL_SOPHGO_SG2002=y CONFIG_GPIO_SIFIVE=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_SENSORS_SFCTEMP=m CONFIG_CPU_THERMAL=y CONFIG_DEVFREQ_THERMAL=y -CONFIG_RZG2L_THERMAL=y CONFIG_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=y CONFIG_MFD_AXP20X_I2C=y @@ -201,11 +200,11 @@ CONFIG_USB=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y +# CONFIG_USB_XHCI_RCAR is not set CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_RENESAS_USBHS=m CONFIG_USB_STORAGE=y CONFIG_USB_UAS=y CONFIG_USB_CDNS_SUPPORT=m @@ -217,7 +216,6 @@ CONFIG_USB_MUSB_HDRC=m CONFIG_USB_MUSB_SUNXI=m CONFIG_NOP_USB_XCEIV=m CONFIG_USB_GADGET=y -CONFIG_USB_RENESAS_USBHS_UDC=m CONFIG_USB_CONFIGFS=m CONFIG_USB_CONFIGFS_SERIAL=y CONFIG_USB_CONFIGFS_ACM=y @@ -235,7 +233,6 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_OF_DWCMSHC=y CONFIG_MMC_SDHCI_CADENCE=y CONFIG_MMC_SPI=y -CONFIG_MMC_SDHI=y CONFIG_MMC_DW=y CONFIG_MMC_DW_STARFIVE=y CONFIG_MMC_SUNXI=y @@ -249,16 +246,18 @@ CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_INPUT=y CONFIG_VIRTIO_MMIO=y CONFIG_CLK_SOPHGO_CV1800=y +CONFIG_CLK_SOPHGO_SG2042_PLL=y +CONFIG_CLK_SOPHGO_SG2042_CLKGEN=y +CONFIG_CLK_SOPHGO_SG2042_RPGATE=y CONFIG_SUN8I_DE2_CCU=m -CONFIG_RENESAS_OSTM=y CONFIG_SUN50I_IOMMU=y CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_CTRL=y CONFIG_RPMSG_VIRTIO=y CONFIG_PM_DEVFREQ=y CONFIG_IIO=y +CONFIG_THEAD_C900_ACLINT_SSWI=y CONFIG_PHY_SUN4I_USB=m -CONFIG_PHY_RCAR_GEN3_USB2=y CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m CONFIG_PHY_STARFIVE_JH7110_PCIE=m CONFIG_PHY_STARFIVE_JH7110_USB=m @@ -303,7 +302,6 @@ CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_WQ_WATCHDOG=y -CONFIG_DEBUG_TIMEKEEPING=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig index af9601da4643..87ff5a1233af 100644 --- a/arch/riscv/configs/nommu_k210_defconfig +++ b/arch/riscv/configs/nommu_k210_defconfig @@ -58,6 +58,7 @@ CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y # CONFIG_SPI_MEM is not set diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig index dd460c649152..95cbd574f291 100644 --- a/arch/riscv/configs/nommu_k210_sdcard_defconfig +++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig @@ -50,6 +50,7 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_DESIGNWARE_CORE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y # CONFIG_SPI_MEM is not set diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile index 8a2739485123..f0da9d7b39c3 100644 --- a/arch/riscv/errata/Makefile +++ b/arch/riscv/errata/Makefile @@ -2,6 +2,12 @@ ifdef CONFIG_RELOCATABLE KBUILD_CFLAGS += -fno-pie endif +ifdef CONFIG_RISCV_ALTERNATIVE_EARLY +ifdef CONFIG_FORTIFY_SOURCE +KBUILD_CFLAGS += -D__NO_FORTIFY +endif +endif + obj-$(CONFIG_ERRATA_ANDES) += andes/ obj-$(CONFIG_ERRATA_SIFIVE) += sifive/ obj-$(CONFIG_ERRATA_THEAD) += thead/ diff --git a/arch/riscv/errata/sifive/errata_cip_453.S b/arch/riscv/errata/sifive/errata_cip_453.S index f1b9623fe1de..b1f7b636fe9a 100644 --- a/arch/riscv/errata/sifive/errata_cip_453.S +++ b/arch/riscv/errata/sifive/errata_cip_453.S @@ -21,7 +21,7 @@ 1: .endm -ENTRY(sifive_cip_453_page_fault_trp) +SYM_FUNC_START(sifive_cip_453_page_fault_trp) ADD_SIGN_EXT a0, t0, t1 #ifdef CONFIG_MMU la t0, do_page_fault @@ -29,10 +29,10 @@ ENTRY(sifive_cip_453_page_fault_trp) la t0, do_trap_unknown #endif jr t0 -END(sifive_cip_453_page_fault_trp) +SYM_FUNC_END(sifive_cip_453_page_fault_trp) -ENTRY(sifive_cip_453_insn_fault_trp) +SYM_FUNC_START(sifive_cip_453_insn_fault_trp) ADD_SIGN_EXT a0, t0, t1 la t0, do_trap_insn_fault jr t0 -END(sifive_cip_453_insn_fault_trp) +SYM_FUNC_END(sifive_cip_453_insn_fault_trp) diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index 5c589770f2a8..1461af12da6e 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -5,6 +5,7 @@ syscall-y += syscall_table_64.h generic-y += early_ioremap.h generic-y += flat.h generic-y += kvm_para.h +generic-y += mmzone.h generic-y += parport.h generic-y += spinlock.h generic-y += spinlock_types.h diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h index e0a1f84404f3..6e13695120bc 100644 --- a/arch/riscv/include/asm/acpi.h +++ b/arch/riscv/include/asm/acpi.h @@ -91,10 +91,8 @@ static inline void acpi_get_cbo_block_size(struct acpi_table_header *table, #endif /* CONFIG_ACPI */ #ifdef CONFIG_ACPI_NUMA -int acpi_numa_get_nid(unsigned int cpu); void acpi_map_cpus_to_nodes(void); #else -static inline int acpi_numa_get_nid(unsigned int cpu) { return NUMA_NO_NODE; } static inline void acpi_map_cpus_to_nodes(void) { } #endif /* CONFIG_ACPI_NUMA */ diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h index 71af9ecfcfcb..fae152ea0508 100644 --- a/arch/riscv/include/asm/bitops.h +++ b/arch/riscv/include/asm/bitops.h @@ -222,44 +222,44 @@ legacy: #define __NOT(x) (~(x)) /** - * test_and_set_bit - Set a bit and return its old value + * arch_test_and_set_bit - Set a bit and return its old value * @nr: Bit to set * @addr: Address to count from * * This operation may be reordered on other architectures than x86. */ -static inline int test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int arch_test_and_set_bit(int nr, volatile unsigned long *addr) { return __test_and_op_bit(or, __NOP, nr, addr); } /** - * test_and_clear_bit - Clear a bit and return its old value + * arch_test_and_clear_bit - Clear a bit and return its old value * @nr: Bit to clear * @addr: Address to count from * * This operation can be reordered on other architectures other than x86. */ -static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int arch_test_and_clear_bit(int nr, volatile unsigned long *addr) { return __test_and_op_bit(and, __NOT, nr, addr); } /** - * test_and_change_bit - Change a bit and return its old value + * arch_test_and_change_bit - Change a bit and return its old value * @nr: Bit to change * @addr: Address to count from * * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int arch_test_and_change_bit(int nr, volatile unsigned long *addr) { return __test_and_op_bit(xor, __NOP, nr, addr); } /** - * set_bit - Atomically set a bit in memory + * arch_set_bit - Atomically set a bit in memory * @nr: the bit to set * @addr: the address to start counting from * @@ -270,13 +270,13 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void set_bit(int nr, volatile unsigned long *addr) +static inline void arch_set_bit(int nr, volatile unsigned long *addr) { __op_bit(or, __NOP, nr, addr); } /** - * clear_bit - Clears a bit in memory + * arch_clear_bit - Clears a bit in memory * @nr: Bit to clear * @addr: Address to start counting from * @@ -284,13 +284,13 @@ static inline void set_bit(int nr, volatile unsigned long *addr) * on non x86 architectures, so if you are writing portable code, * make sure not to rely on its reordering guarantees. */ -static inline void clear_bit(int nr, volatile unsigned long *addr) +static inline void arch_clear_bit(int nr, volatile unsigned long *addr) { __op_bit(and, __NOT, nr, addr); } /** - * change_bit - Toggle a bit in memory + * arch_change_bit - Toggle a bit in memory * @nr: Bit to change * @addr: Address to start counting from * @@ -298,40 +298,40 @@ static inline void clear_bit(int nr, volatile unsigned long *addr) * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void change_bit(int nr, volatile unsigned long *addr) +static inline void arch_change_bit(int nr, volatile unsigned long *addr) { __op_bit(xor, __NOP, nr, addr); } /** - * test_and_set_bit_lock - Set a bit and return its old value, for lock + * arch_test_and_set_bit_lock - Set a bit and return its old value, for lock * @nr: Bit to set * @addr: Address to count from * * This operation is atomic and provides acquire barrier semantics. * It can be used to implement bit locks. */ -static inline int test_and_set_bit_lock( +static inline int arch_test_and_set_bit_lock( unsigned long nr, volatile unsigned long *addr) { return __test_and_op_bit_ord(or, __NOP, nr, addr, .aq); } /** - * clear_bit_unlock - Clear a bit in memory, for unlock + * arch_clear_bit_unlock - Clear a bit in memory, for unlock * @nr: the bit to set * @addr: the address to start counting from * * This operation is atomic and provides release barrier semantics. */ -static inline void clear_bit_unlock( +static inline void arch_clear_bit_unlock( unsigned long nr, volatile unsigned long *addr) { __op_bit_ord(and, __NOT, nr, addr, .rl); } /** - * __clear_bit_unlock - Clear a bit in memory, for unlock + * arch___clear_bit_unlock - Clear a bit in memory, for unlock * @nr: the bit to set * @addr: the address to start counting from * @@ -345,13 +345,13 @@ static inline void clear_bit_unlock( * non-atomic property here: it's a lot more instructions and we still have to * provide release semantics anyway. */ -static inline void __clear_bit_unlock( +static inline void arch___clear_bit_unlock( unsigned long nr, volatile unsigned long *addr) { - clear_bit_unlock(nr, addr); + arch_clear_bit_unlock(nr, addr); } -static inline bool xor_unlock_is_negative_byte(unsigned long mask, +static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask, volatile unsigned long *addr) { unsigned long res; @@ -369,6 +369,9 @@ static inline bool xor_unlock_is_negative_byte(unsigned long mask, #undef __NOT #undef __AMO +#include <asm-generic/bitops/instrumented-atomic.h> +#include <asm-generic/bitops/instrumented-lock.h> + #include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/le.h> #include <asm-generic/bitops/ext2-atomic.h> diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h index ce79c558a4c8..8de73f91bfa3 100644 --- a/arch/riscv/include/asm/cacheflush.h +++ b/arch/riscv/include/asm/cacheflush.h @@ -46,7 +46,23 @@ do { \ } while (0) #ifdef CONFIG_64BIT -#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end) +extern u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1]; +extern char _end[]; +#define flush_cache_vmap flush_cache_vmap +static inline void flush_cache_vmap(unsigned long start, unsigned long end) +{ + if (is_vmalloc_or_module_addr((void *)start)) { + int i; + + /* + * We don't care if concurrently a cpu resets this value since + * the only place this can happen is in handle_exception() where + * an sfence.vma is emitted. + */ + for (i = 0; i < ARRAY_SIZE(new_vmalloc); ++i) + new_vmalloc[i] = -1ULL; + } +} #define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end) #endif diff --git a/arch/riscv/include/asm/exec.h b/arch/riscv/include/asm/exec.h new file mode 100644 index 000000000000..07d9942682e0 --- /dev/null +++ b/arch/riscv/include/asm/exec.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ASM_EXEC_H +#define __ASM_EXEC_H + +extern unsigned long arch_align_stack(unsigned long sp); + +#endif /* __ASM_EXEC_H */ diff --git a/arch/riscv/include/asm/fence.h b/arch/riscv/include/asm/fence.h index 6bcd80325dfc..182db7930edc 100644 --- a/arch/riscv/include/asm/fence.h +++ b/arch/riscv/include/asm/fence.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef _ASM_RISCV_FENCE_H #define _ASM_RISCV_FENCE_H diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h index 2cddd79ff21b..3d66437a1029 100644 --- a/arch/riscv/include/asm/ftrace.h +++ b/arch/riscv/include/asm/ftrace.h @@ -125,8 +125,12 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS #define arch_ftrace_get_regs(regs) NULL +#define HAVE_ARCH_FTRACE_REGS struct ftrace_ops; -struct ftrace_regs { +struct ftrace_regs; +#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs)) + +struct __arch_ftrace_regs { unsigned long epc; unsigned long ra; unsigned long sp; @@ -150,42 +154,42 @@ struct ftrace_regs { static __always_inline unsigned long ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs) { - return fregs->epc; + return arch_ftrace_regs(fregs)->epc; } static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long pc) { - fregs->epc = pc; + arch_ftrace_regs(fregs)->epc = pc; } static __always_inline unsigned long ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs) { - return fregs->sp; + return arch_ftrace_regs(fregs)->sp; } static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n) { if (n < 8) - return fregs->args[n]; + return arch_ftrace_regs(fregs)->args[n]; return 0; } static __always_inline unsigned long ftrace_regs_get_return_value(const struct ftrace_regs *fregs) { - return fregs->a0; + return arch_ftrace_regs(fregs)->a0; } static __always_inline void ftrace_regs_set_return_value(struct ftrace_regs *fregs, unsigned long ret) { - fregs->a0 = ret; + arch_ftrace_regs(fregs)->a0 = ret; } static __always_inline void ftrace_override_function_with_return(struct ftrace_regs *fregs) { - fregs->epc = fregs->ra; + arch_ftrace_regs(fregs)->epc = arch_ftrace_regs(fregs)->ra; } int ftrace_regs_query_register_offset(const char *name); @@ -196,7 +200,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) { - fregs->t1 = addr; + arch_ftrace_regs(fregs)->t1 = addr; } #endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 5a0bd27fd11a..46d9de54179e 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -92,6 +92,7 @@ #define RISCV_ISA_EXT_ZCF 83 #define RISCV_ISA_EXT_ZCMOP 84 #define RISCV_ISA_EXT_ZAWRS 85 +#define RISCV_ISA_EXT_SVVPTC 86 #define RISCV_ISA_EXT_XLINUXENVCFG 127 diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h index 8e10a94430a2..7b038f3b7cb0 100644 --- a/arch/riscv/include/asm/irq.h +++ b/arch/riscv/include/asm/irq.h @@ -12,8 +12,68 @@ #include <asm-generic/irq.h> +#define INVALID_CONTEXT UINT_MAX + +#ifdef CONFIG_SMP +void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu); +#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace +#endif + void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void)); struct fwnode_handle *riscv_get_intc_hwnode(void); +#ifdef CONFIG_ACPI + +enum riscv_irqchip_type { + ACPI_RISCV_IRQCHIP_INTC = 0x00, + ACPI_RISCV_IRQCHIP_IMSIC = 0x01, + ACPI_RISCV_IRQCHIP_PLIC = 0x02, + ACPI_RISCV_IRQCHIP_APLIC = 0x03, +}; + +int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base, + u32 *id, u32 *nr_irqs, u32 *nr_idcs); +struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi); +unsigned long acpi_rintc_index_to_hartid(u32 index); +unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id, unsigned int ctxt_idx); +unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id); +unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx); +int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res); + +#else +static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base, + u32 *id, u32 *nr_irqs, u32 *nr_idcs) +{ + return 0; +} + +static inline unsigned long acpi_rintc_index_to_hartid(u32 index) +{ + return INVALID_HARTID; +} + +static inline unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id, + unsigned int ctxt_idx) +{ + return INVALID_HARTID; +} + +static inline unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id) +{ + return INVALID_CONTEXT; +} + +static inline unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx) +{ + return INVALID_CONTEXT; +} + +static inline int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res) +{ + return 0; +} + +#endif /* CONFIG_ACPI */ + #endif /* _ASM_RISCV_IRQ_H */ diff --git a/arch/riscv/include/asm/kvm_vcpu_pmu.h b/arch/riscv/include/asm/kvm_vcpu_pmu.h index fa0f535bbbf0..1d85b6617508 100644 --- a/arch/riscv/include/asm/kvm_vcpu_pmu.h +++ b/arch/riscv/include/asm/kvm_vcpu_pmu.h @@ -10,6 +10,7 @@ #define __KVM_VCPU_RISCV_PMU_H #include <linux/perf/riscv_pmu.h> +#include <asm/kvm_vcpu_insn.h> #include <asm/sbi.h> #ifdef CONFIG_RISCV_PMU_SBI @@ -64,11 +65,11 @@ struct kvm_pmu { #if defined(CONFIG_32BIT) #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ -{.base = CSR_CYCLEH, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, \ -{.base = CSR_CYCLE, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, +{.base = CSR_CYCLEH, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, \ +{.base = CSR_CYCLE, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, #else #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ -{.base = CSR_CYCLE, .count = 31, .func = kvm_riscv_vcpu_pmu_read_hpm }, +{.base = CSR_CYCLE, .count = 32, .func = kvm_riscv_vcpu_pmu_read_hpm }, #endif int kvm_riscv_vcpu_pmu_incr_fw(struct kvm_vcpu *vcpu, unsigned long fid); @@ -104,8 +105,20 @@ void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu); struct kvm_pmu { }; +static inline int kvm_riscv_vcpu_pmu_read_legacy(struct kvm_vcpu *vcpu, unsigned int csr_num, + unsigned long *val, unsigned long new_val, + unsigned long wr_mask) +{ + if (csr_num == CSR_CYCLE || csr_num == CSR_INSTRET) { + *val = 0; + return KVM_INSN_CONTINUE_NEXT_SEPC; + } else { + return KVM_INSN_ILLEGAL_TRAP; + } +} + #define KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS \ -{.base = 0, .count = 0, .func = NULL }, +{.base = CSR_CYCLE, .count = 3, .func = kvm_riscv_vcpu_pmu_read_legacy }, static inline void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu) {} static inline int kvm_riscv_vcpu_pmu_incr_fw(struct kvm_vcpu *vcpu, unsigned long fid) diff --git a/arch/riscv/include/asm/mmzone.h b/arch/riscv/include/asm/mmzone.h deleted file mode 100644 index fa17e01d9ab2..000000000000 --- a/arch/riscv/include/asm/mmzone.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_MMZONE_H -#define __ASM_MMZONE_H - -#ifdef CONFIG_NUMA - -#include <asm/numa.h> - -extern struct pglist_data *node_data[]; -#define NODE_DATA(nid) (node_data[(nid)]) - -#endif /* CONFIG_NUMA */ -#endif /* __ASM_MMZONE_H */ diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 7ede2111c591..9875399827c7 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -12,9 +12,7 @@ #include <linux/pfn.h> #include <linux/const.h> -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE - 1)) +#include <vdso/page.h> #define HPAGE_SHIFT PMD_SHIFT #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) @@ -112,11 +110,13 @@ struct kernel_mapping { /* Offset between linear mapping virtual address and kernel load address */ unsigned long va_pa_offset; /* Offset between kernel mapping virtual address and kernel load address */ - unsigned long va_kernel_pa_offset; - unsigned long va_kernel_xip_pa_offset; #ifdef CONFIG_XIP_KERNEL + unsigned long va_kernel_xip_text_pa_offset; + unsigned long va_kernel_xip_data_pa_offset; uintptr_t xiprom; uintptr_t xiprom_sz; +#else + unsigned long va_kernel_pa_offset; #endif }; @@ -134,12 +134,18 @@ extern phys_addr_t phys_ram_base; #else void *linear_mapping_pa_to_va(unsigned long x); #endif + +#ifdef CONFIG_XIP_KERNEL #define kernel_mapping_pa_to_va(y) ({ \ unsigned long _y = (unsigned long)(y); \ - (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \ - (void *)(_y + kernel_map.va_kernel_xip_pa_offset) : \ - (void *)(_y + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \ + (_y < phys_ram_base) ? \ + (void *)(_y + kernel_map.va_kernel_xip_text_pa_offset) : \ + (void *)(_y + kernel_map.va_kernel_xip_data_pa_offset); \ }) +#else +#define kernel_mapping_pa_to_va(y) ((void *)((unsigned long)(y) + kernel_map.va_kernel_pa_offset)) +#endif + #define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x) #ifndef CONFIG_DEBUG_VIRTUAL @@ -147,12 +153,17 @@ void *linear_mapping_pa_to_va(unsigned long x); #else phys_addr_t linear_mapping_va_to_pa(unsigned long x); #endif + +#ifdef CONFIG_XIP_KERNEL #define kernel_mapping_va_to_pa(y) ({ \ unsigned long _y = (unsigned long)(y); \ - (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \ - (_y - kernel_map.va_kernel_xip_pa_offset) : \ - (_y - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \ + (_y < kernel_map.virt_addr + kernel_map.xiprom_sz) ? \ + (_y - kernel_map.va_kernel_xip_text_pa_offset) : \ + (_y - kernel_map.va_kernel_xip_data_pa_offset); \ }) +#else +#define kernel_mapping_va_to_pa(y) ((unsigned long)(y) - kernel_map.va_kernel_pa_offset) +#endif #define __va_to_pa_nodebug(x) ({ \ unsigned long _x = x; \ diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 089f3c9f56a3..e79f15293492 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -107,13 +107,6 @@ #endif -#ifdef CONFIG_XIP_KERNEL -#define XIP_OFFSET SZ_32M -#define XIP_OFFSET_MASK (SZ_32M - 1) -#else -#define XIP_OFFSET 0 -#endif - #ifndef __ASSEMBLY__ #include <asm/page.h> @@ -142,11 +135,14 @@ #ifdef CONFIG_XIP_KERNEL #define XIP_FIXUP(addr) ({ \ + extern char _sdata[], _start[], _end[]; \ + uintptr_t __rom_start_data = CONFIG_XIP_PHYS_ADDR \ + + (uintptr_t)&_sdata - (uintptr_t)&_start; \ + uintptr_t __rom_end_data = CONFIG_XIP_PHYS_ADDR \ + + (uintptr_t)&_end - (uintptr_t)&_start; \ uintptr_t __a = (uintptr_t)(addr); \ - (__a >= CONFIG_XIP_PHYS_ADDR && \ - __a < CONFIG_XIP_PHYS_ADDR + XIP_OFFSET * 2) ? \ - __a - CONFIG_XIP_PHYS_ADDR + CONFIG_PHYS_RAM_BASE - XIP_OFFSET :\ - __a; \ + (__a >= __rom_start_data && __a < __rom_end_data) ? \ + __a - __rom_start_data + CONFIG_PHYS_RAM_BASE : __a; \ }) #else #define XIP_FIXUP(addr) (addr) @@ -501,6 +497,9 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, unsigned long address, pte_t *ptep, unsigned int nr) { + asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1) + : : : : svvptc); + /* * The kernel assumes that TLBs don't cache invalid entries, but * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a @@ -510,6 +509,13 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, */ while (nr--) local_flush_tlb_page(address + nr * PAGE_SIZE); + +svvptc:; + /* + * Svvptc guarantees that the new valid pte will be visible within + * a bounded timeframe, so when the uarch does not cache invalid + * entries, we don't have to do anything. + */ } #define update_mmu_cache(vma, addr, ptep) \ update_mmu_cache_range(NULL, vma, addr, ptep, 1) diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 8702b8721a27..efa1b3519b23 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -14,36 +14,14 @@ #include <asm/ptrace.h> -/* - * addr is a hint to the maximum userspace address that mmap should provide, so - * this macro needs to return the largest address space available so that - * mmap_end < addr, being mmap_end the top of that address space. - * See Documentation/arch/riscv/vm-layout.rst for more details. - */ #define arch_get_mmap_end(addr, len, flags) \ ({ \ - unsigned long mmap_end; \ - typeof(addr) _addr = (addr); \ - if ((_addr) == 0 || is_compat_task() || \ - ((_addr + len) > BIT(VA_BITS - 1))) \ - mmap_end = STACK_TOP_MAX; \ - else \ - mmap_end = (_addr + len); \ - mmap_end; \ + STACK_TOP_MAX; \ }) #define arch_get_mmap_base(addr, base) \ ({ \ - unsigned long mmap_base; \ - typeof(addr) _addr = (addr); \ - typeof(base) _base = (base); \ - unsigned long rnd_gap = DEFAULT_MAP_WINDOW - (_base); \ - if ((_addr) == 0 || is_compat_task() || \ - ((_addr + len) > BIT(VA_BITS - 1))) \ - mmap_base = (_base); \ - else \ - mmap_base = (_addr + len) - rnd_gap; \ - mmap_base; \ + base; \ }) #ifdef CONFIG_64BIT diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 7cffd4ffecd0..98f631b051db 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -9,6 +9,7 @@ #include <linux/types.h> #include <linux/cpumask.h> +#include <linux/jump_label.h> #ifdef CONFIG_RISCV_SBI enum sbi_ext_id { @@ -158,6 +159,7 @@ struct riscv_pmu_snapshot_data { #define RISCV_PMU_RAW_EVENT_MASK GENMASK_ULL(47, 0) #define RISCV_PMU_RAW_EVENT_IDX 0x20000 +#define RISCV_PLAT_FW_EVENT 0xFFFF /** General pmu event codes specified in SBI PMU extension */ enum sbi_pmu_hw_generic_events_t { @@ -304,6 +306,7 @@ struct sbiret { }; void sbi_init(void); +long __sbi_base_ecall(int fid); struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, @@ -373,7 +376,23 @@ static inline unsigned long sbi_mk_version(unsigned long major, | (minor & SBI_SPEC_VERSION_MINOR_MASK); } -int sbi_err_map_linux_errno(int err); +static inline int sbi_err_map_linux_errno(int err) +{ + switch (err) { + case SBI_SUCCESS: + return 0; + case SBI_ERR_DENIED: + return -EPERM; + case SBI_ERR_INVALID_PARAM: + return -EINVAL; + case SBI_ERR_INVALID_ADDRESS: + return -EFAULT; + case SBI_ERR_NOT_SUPPORTED: + case SBI_ERR_FAILURE: + default: + return -ENOTSUPP; + }; +} extern bool sbi_debug_console_available; int sbi_debug_console_write(const char *bytes, unsigned int num_bytes); diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h index ec11001c3fe0..ab92fc84e1fc 100644 --- a/arch/riscv/include/asm/set_memory.h +++ b/arch/riscv/include/asm/set_memory.h @@ -46,7 +46,7 @@ bool kernel_page_present(struct page *page); #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_STRICT_KERNEL_RWX +#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_XIP_KERNEL) #ifdef CONFIG_64BIT #define SECTION_ALIGN (1 << 21) #else diff --git a/arch/riscv/include/asm/sparsemem.h b/arch/riscv/include/asm/sparsemem.h index 63acaecc3374..2f901a410586 100644 --- a/arch/riscv/include/asm/sparsemem.h +++ b/arch/riscv/include/asm/sparsemem.h @@ -7,7 +7,7 @@ #ifdef CONFIG_64BIT #define MAX_PHYSMEM_BITS 56 #else -#define MAX_PHYSMEM_BITS 34 +#define MAX_PHYSMEM_BITS 32 #endif /* CONFIG_64BIT */ #define SECTION_SIZE_BITS 27 #endif /* CONFIG_SPARSEMEM */ diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h index a96b1fea24fe..5ba77f60bf0b 100644 --- a/arch/riscv/include/asm/string.h +++ b/arch/riscv/include/asm/string.h @@ -19,6 +19,7 @@ extern asmlinkage void *__memcpy(void *, const void *, size_t); extern asmlinkage void *memmove(void *, const void *, size_t); extern asmlinkage void *__memmove(void *, const void *, size_t); +#if !(defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) #define __HAVE_ARCH_STRCMP extern asmlinkage int strcmp(const char *cs, const char *ct); @@ -27,6 +28,7 @@ extern asmlinkage __kernel_size_t strlen(const char *); #define __HAVE_ARCH_STRNCMP extern asmlinkage int strncmp(const char *cs, const char *ct, size_t count); +#endif /* For those files which don't want to check by kasan. */ #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h index fca5c6be2b81..f5916a70879a 100644 --- a/arch/riscv/include/asm/thread_info.h +++ b/arch/riscv/include/asm/thread_info.h @@ -13,7 +13,12 @@ #include <linux/sizes.h> /* thread information allocation */ -#define THREAD_SIZE_ORDER CONFIG_THREAD_SIZE_ORDER +#ifdef CONFIG_KASAN +#define KASAN_STACK_ORDER 1 +#else +#define KASAN_STACK_ORDER 0 +#endif +#define THREAD_SIZE_ORDER (CONFIG_THREAD_SIZE_ORDER + KASAN_STACK_ORDER) #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) /* @@ -61,6 +66,13 @@ struct thread_info { void *scs_base; void *scs_sp; #endif +#ifdef CONFIG_64BIT + /* + * Used in handle_exception() to save a0, a1 and a2 before knowing if we + * can access the kernel stack. + */ + unsigned long a0, a1, a2; +#endif }; #ifdef CONFIG_SHADOW_CALL_STACK @@ -95,9 +107,10 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); * - pending work-to-be-done flags are in lowest half-word * - other flags in upper half-word(s) */ -#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ -#define TIF_SIGPENDING 2 /* signal pending */ -#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_NEED_RESCHED 0 /* rescheduling necessary */ +#define TIF_NEED_RESCHED_LAZY 1 /* Lazy rescheduling needed */ +#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ +#define TIF_SIGPENDING 3 /* signal pending */ #define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */ #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ #define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */ @@ -105,15 +118,12 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); #define TIF_32BIT 11 /* compat-mode 32bit process */ #define TIF_RISCV_V_DEFER_RESTORE 12 /* restore Vector before returing to user */ +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) #define _TIF_UPROBE (1 << TIF_UPROBE) #define _TIF_RISCV_V_DEFER_RESTORE (1 << TIF_RISCV_V_DEFER_RESTORE) -#define _TIF_WORK_MASK \ - (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | \ - _TIF_NOTIFY_SIGNAL | _TIF_UPROBE) - #endif /* _ASM_RISCV_THREAD_INFO_H */ diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h index 61183688bdd5..fe1a8bf6902d 100644 --- a/arch/riscv/include/asm/topology.h +++ b/arch/riscv/include/asm/topology.h @@ -4,6 +4,10 @@ #include <linux/arch_topology.h> +#ifdef CONFIG_NUMA +#include <asm/numa.h> +#endif + /* Replace task scheduler's default frequency-invariant accounting */ #define arch_scale_freq_tick topology_scale_freq_tick #define arch_set_freq_scale topology_set_freq_scale diff --git a/arch/riscv/include/asm/vdso/data.h b/arch/riscv/include/asm/vdso/time_data.h index dc2f76f58b76..dfa65228999b 100644 --- a/arch/riscv/include/asm/vdso/data.h +++ b/arch/riscv/include/asm/vdso/time_data.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RISCV_ASM_VDSO_DATA_H -#define __RISCV_ASM_VDSO_DATA_H +#ifndef __RISCV_ASM_VDSO_TIME_DATA_H +#define __RISCV_ASM_VDSO_TIME_DATA_H #include <linux/types.h> #include <vdso/datapage.h> #include <asm/hwprobe.h> -struct arch_vdso_data { +struct arch_vdso_time_data { /* Stash static answers to the hwprobe queries when all CPUs are selected. */ __u64 all_cpu_hwprobe_values[RISCV_HWPROBE_MAX_KEY + 1]; @@ -14,4 +14,4 @@ struct arch_vdso_data { __u8 homogeneous_cpus; }; -#endif /* __RISCV_ASM_VDSO_DATA_H */ +#endif /* __RISCV_ASM_VDSO_TIME_DATA_H */ diff --git a/arch/riscv/include/asm/vdso/vsyscall.h b/arch/riscv/include/asm/vdso/vsyscall.h index 82fd5d83bd60..e8a9c4b53c0c 100644 --- a/arch/riscv/include/asm/vdso/vsyscall.h +++ b/arch/riscv/include/asm/vdso/vsyscall.h @@ -4,14 +4,10 @@ #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> extern struct vdso_data *vdso_data; -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ static __always_inline struct vdso_data *__riscv_get_k_vdso_data(void) { return vdso_data; diff --git a/arch/riscv/include/asm/vmalloc.h b/arch/riscv/include/asm/vmalloc.h index 51f6dfe19745..fefe94dc98e2 100644 --- a/arch/riscv/include/asm/vmalloc.h +++ b/arch/riscv/include/asm/vmalloc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef _ASM_RISCV_VMALLOC_H #define _ASM_RISCV_VMALLOC_H diff --git a/arch/riscv/include/asm/xip_fixup.h b/arch/riscv/include/asm/xip_fixup.h index b65bf6306f69..f3d56299bc22 100644 --- a/arch/riscv/include/asm/xip_fixup.h +++ b/arch/riscv/include/asm/xip_fixup.h @@ -9,18 +9,36 @@ #ifdef CONFIG_XIP_KERNEL .macro XIP_FIXUP_OFFSET reg - REG_L t0, _xip_fixup + /* Fix-up address in Flash into address in RAM early during boot before + * MMU is up. Because generated code "thinks" data is in Flash, but it + * is actually in RAM (actually data is also in Flash, but Flash is + * read-only, thus we need to use the data residing in RAM). + * + * The start of data in Flash is _sdata and the start of data in RAM is + * CONFIG_PHYS_RAM_BASE. So this fix-up essentially does this: + * reg += CONFIG_PHYS_RAM_BASE - _start + */ + li t0, CONFIG_PHYS_RAM_BASE add \reg, \reg, t0 + la t0, _sdata + sub \reg, \reg, t0 .endm .macro XIP_FIXUP_FLASH_OFFSET reg + /* In linker script, at the transition from read-only section to + * writable section, the VMA is increased while LMA remains the same. + * (See in linker script how _sdata, __data_loc and LOAD_OFFSET is + * changed) + * + * Consequently, early during boot before MMU is up, the generated code + * reads the "writable" section at wrong addresses, because VMA is used + * by compiler to generate code, but the data is located in Flash using + * LMA. + */ + la t0, _sdata + sub \reg, \reg, t0 la t0, __data_loc - REG_L t1, _xip_phys_offset - sub \reg, \reg, t1 add \reg, \reg, t0 .endm - -_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET -_xip_phys_offset: .dword CONFIG_XIP_PHYS_ADDR + XIP_OFFSET #else .macro XIP_FIXUP_OFFSET reg .endm diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 06d407f1b30b..69dc8aaab3fb 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -20,17 +20,26 @@ endif ifdef CONFIG_RISCV_ALTERNATIVE_EARLY CFLAGS_alternative.o := -mcmodel=medany CFLAGS_cpufeature.o := -mcmodel=medany +CFLAGS_sbi_ecall.o := -mcmodel=medany ifdef CONFIG_FTRACE CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_sbi_ecall.o = $(CC_FLAGS_FTRACE) endif ifdef CONFIG_RELOCATABLE CFLAGS_alternative.o += -fno-pie CFLAGS_cpufeature.o += -fno-pie +CFLAGS_sbi_ecall.o += -fno-pie endif ifdef CONFIG_KASAN KASAN_SANITIZE_alternative.o := n KASAN_SANITIZE_cpufeature.o := n +KASAN_SANITIZE_sbi_ecall.o := n +endif +ifdef CONFIG_FORTIFY_SOURCE +CFLAGS_alternative.o += -D__NO_FORTIFY +CFLAGS_cpufeature.o += -D__NO_FORTIFY +CFLAGS_sbi_ecall.o += -D__NO_FORTIFY endif endif @@ -88,7 +97,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o -obj-$(CONFIG_RISCV_SBI) += sbi.o +obj-$(CONFIG_RISCV_SBI) += sbi.o sbi_ecall.o ifeq ($(CONFIG_RISCV_SBI), y) obj-$(CONFIG_SMP) += sbi-ipi.o obj-$(CONFIG_SMP) += cpu_ops_sbi.o diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c index ba957aaca5cb..2fd29695a788 100644 --- a/arch/riscv/kernel/acpi.c +++ b/arch/riscv/kernel/acpi.c @@ -210,7 +210,7 @@ void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size) if (!size) return NULL; - return early_ioremap(phys, size); + return early_memremap(phys, size); } void __init __acpi_unmap_table(void __iomem *map, unsigned long size) @@ -218,7 +218,7 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size) if (!map || !size) return; - early_iounmap(map, size); + early_memunmap(map, size); } void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) @@ -311,29 +311,26 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) #ifdef CONFIG_PCI /* - * These interfaces are defined just to enable building ACPI core. - * TODO: Update it with actual implementation when external interrupt - * controller support is added in RISC-V ACPI. + * raw_pci_read/write - Platform-specific PCI config space access. */ -int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, - int reg, int len, u32 *val) +int raw_pci_read(unsigned int domain, unsigned int bus, + unsigned int devfn, int reg, int len, u32 *val) { - return PCIBIOS_DEVICE_NOT_FOUND; -} + struct pci_bus *b = pci_find_bus(domain, bus); -int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, - int reg, int len, u32 val) -{ - return PCIBIOS_DEVICE_NOT_FOUND; + if (!b) + return PCIBIOS_DEVICE_NOT_FOUND; + return b->ops->read(b, devfn, reg, len, val); } -int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) +int raw_pci_write(unsigned int domain, unsigned int bus, + unsigned int devfn, int reg, int len, u32 val) { - return -1; -} + struct pci_bus *b = pci_find_bus(domain, bus); -struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) -{ - return NULL; + if (!b) + return PCIBIOS_DEVICE_NOT_FOUND; + return b->ops->write(b, devfn, reg, len, val); } + #endif /* CONFIG_PCI */ diff --git a/arch/riscv/kernel/acpi_numa.c b/arch/riscv/kernel/acpi_numa.c index ff95aeebee3e..130769e3a99c 100644 --- a/arch/riscv/kernel/acpi_numa.c +++ b/arch/riscv/kernel/acpi_numa.c @@ -30,7 +30,7 @@ static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE }; -int __init acpi_numa_get_nid(unsigned int cpu) +static int __init acpi_numa_get_nid(unsigned int cpu) { return acpi_early_node_map[cpu]; } diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c index b09ca5f944f7..e89455a6a0e5 100644 --- a/arch/riscv/kernel/asm-offsets.c +++ b/arch/riscv/kernel/asm-offsets.c @@ -4,8 +4,6 @@ * Copyright (C) 2017 SiFive */ -#define GENERATING_ASM_OFFSETS - #include <linux/kbuild.h> #include <linux/mm.h> #include <linux/sched.h> @@ -36,6 +34,8 @@ void asm_offsets(void) OFFSET(TASK_THREAD_S9, task_struct, thread.s[9]); OFFSET(TASK_THREAD_S10, task_struct, thread.s[10]); OFFSET(TASK_THREAD_S11, task_struct, thread.s[11]); + + OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu); OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags); OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count); OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp); @@ -43,6 +43,11 @@ void asm_offsets(void) #ifdef CONFIG_SHADOW_CALL_STACK OFFSET(TASK_TI_SCS_SP, task_struct, thread_info.scs_sp); #endif +#ifdef CONFIG_64BIT + OFFSET(TASK_TI_A0, task_struct, thread_info.a0); + OFFSET(TASK_TI_A1, task_struct, thread_info.a1); + OFFSET(TASK_TI_A2, task_struct, thread_info.a2); +#endif OFFSET(TASK_TI_CPU_NUM, task_struct, thread_info.cpu); OFFSET(TASK_THREAD_F0, task_struct, thread.fstate.f[0]); @@ -491,19 +496,19 @@ void asm_offsets(void) OFFSET(STACKFRAME_RA, stackframe, ra); #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS - DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct ftrace_regs), STACK_ALIGN)); - DEFINE(FREGS_EPC, offsetof(struct ftrace_regs, epc)); - DEFINE(FREGS_RA, offsetof(struct ftrace_regs, ra)); - DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp)); - DEFINE(FREGS_S0, offsetof(struct ftrace_regs, s0)); - DEFINE(FREGS_T1, offsetof(struct ftrace_regs, t1)); - DEFINE(FREGS_A0, offsetof(struct ftrace_regs, a0)); - DEFINE(FREGS_A1, offsetof(struct ftrace_regs, a1)); - DEFINE(FREGS_A2, offsetof(struct ftrace_regs, a2)); - DEFINE(FREGS_A3, offsetof(struct ftrace_regs, a3)); - DEFINE(FREGS_A4, offsetof(struct ftrace_regs, a4)); - DEFINE(FREGS_A5, offsetof(struct ftrace_regs, a5)); - DEFINE(FREGS_A6, offsetof(struct ftrace_regs, a6)); - DEFINE(FREGS_A7, offsetof(struct ftrace_regs, a7)); + DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct __arch_ftrace_regs), STACK_ALIGN)); + DEFINE(FREGS_EPC, offsetof(struct __arch_ftrace_regs, epc)); + DEFINE(FREGS_RA, offsetof(struct __arch_ftrace_regs, ra)); + DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp)); + DEFINE(FREGS_S0, offsetof(struct __arch_ftrace_regs, s0)); + DEFINE(FREGS_T1, offsetof(struct __arch_ftrace_regs, t1)); + DEFINE(FREGS_A0, offsetof(struct __arch_ftrace_regs, a0)); + DEFINE(FREGS_A1, offsetof(struct __arch_ftrace_regs, a1)); + DEFINE(FREGS_A2, offsetof(struct __arch_ftrace_regs, a2)); + DEFINE(FREGS_A3, offsetof(struct __arch_ftrace_regs, a3)); + DEFINE(FREGS_A4, offsetof(struct __arch_ftrace_regs, a4)); + DEFINE(FREGS_A5, offsetof(struct __arch_ftrace_regs, a5)); + DEFINE(FREGS_A6, offsetof(struct __arch_ftrace_regs, a6)); + DEFINE(FREGS_A7, offsetof(struct __arch_ftrace_regs, a7)); #endif } diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index d6c108c50cba..2d40736fc37c 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -71,12 +71,16 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, this_leaf->type = type; } +int init_cache_level(unsigned int cpu) +{ + return init_of_cache_level(cpu); +} + int populate_cache_leaves(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf = this_cpu_ci->info_list; - struct device_node *np = of_cpu_device_node_get(cpu); - struct device_node *prev = NULL; + struct device_node *np, *prev; int levels = 1, level = 1; if (!acpi_disabled) { @@ -100,6 +104,10 @@ int populate_cache_leaves(unsigned int cpu) return 0; } + np = of_cpu_device_node_get(cpu); + if (!np) + return -ENOENT; + if (of_property_read_bool(np, "cache-size")) ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level); if (of_property_read_bool(np, "i-cache-size")) diff --git a/arch/riscv/kernel/cpu-hotplug.c b/arch/riscv/kernel/cpu-hotplug.c index 28b58fc5ad19..a1e38ecfc8be 100644 --- a/arch/riscv/kernel/cpu-hotplug.c +++ b/arch/riscv/kernel/cpu-hotplug.c @@ -58,7 +58,7 @@ void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu) if (cpu_ops->cpu_is_stopped) ret = cpu_ops->cpu_is_stopped(cpu); if (ret) - pr_warn("CPU%d may not have stopped: %d\n", cpu, ret); + pr_warn("CPU%u may not have stopped: %d\n", cpu, ret); } /* diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index b427188b28fc..3a8eeaa9310c 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -381,6 +381,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { __RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL), __RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT), __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT), + __RISCV_ISA_EXT_DATA(svvptc, RISCV_ISA_EXT_SVVPTC), }; const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext); diff --git a/arch/riscv/kernel/efi-header.S b/arch/riscv/kernel/efi-header.S index 515b2dfbca75..c5f17c2710b5 100644 --- a/arch/riscv/kernel/efi-header.S +++ b/arch/riscv/kernel/efi-header.S @@ -64,7 +64,7 @@ extra_header_fields: .long efi_header_end - _start // SizeOfHeaders .long 0 // CheckSum .short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem - .short 0 // DllCharacteristics + .short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT // DllCharacteristics .quad 0 // SizeOfStackReserve .quad 0 // SizeOfStackCommit .quad 0 // SizeOfHeapReserve diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c index 11c0d2e0becf..3c37661801f9 100644 --- a/arch/riscv/kernel/elf_kexec.c +++ b/arch/riscv/kernel/elf_kexec.c @@ -451,6 +451,12 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, *(u32 *)loc = CLEAN_IMM(CJTYPE, *(u32 *)loc) | ENCODE_CJTYPE_IMM(val - addr); break; + case R_RISCV_ADD16: + *(u16 *)loc += val; + break; + case R_RISCV_SUB16: + *(u16 *)loc -= val; + break; case R_RISCV_ADD32: *(u32 *)loc += val; break; diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index ac2e908d4418..c200d329d4bd 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -19,6 +19,79 @@ .section .irqentry.text, "ax" +.macro new_vmalloc_check + REG_S a0, TASK_TI_A0(tp) + csrr a0, CSR_CAUSE + /* Exclude IRQs */ + blt a0, zero, _new_vmalloc_restore_context_a0 + + REG_S a1, TASK_TI_A1(tp) + /* Only check new_vmalloc if we are in page/protection fault */ + li a1, EXC_LOAD_PAGE_FAULT + beq a0, a1, _new_vmalloc_kernel_address + li a1, EXC_STORE_PAGE_FAULT + beq a0, a1, _new_vmalloc_kernel_address + li a1, EXC_INST_PAGE_FAULT + bne a0, a1, _new_vmalloc_restore_context_a1 + +_new_vmalloc_kernel_address: + /* Is it a kernel address? */ + csrr a0, CSR_TVAL + bge a0, zero, _new_vmalloc_restore_context_a1 + + /* Check if a new vmalloc mapping appeared that could explain the trap */ + REG_S a2, TASK_TI_A2(tp) + /* + * Computes: + * a0 = &new_vmalloc[BIT_WORD(cpu)] + * a1 = BIT_MASK(cpu) + */ + REG_L a2, TASK_TI_CPU(tp) + /* + * Compute the new_vmalloc element position: + * (cpu / 64) * 8 = (cpu >> 6) << 3 + */ + srli a1, a2, 6 + slli a1, a1, 3 + la a0, new_vmalloc + add a0, a0, a1 + /* + * Compute the bit position in the new_vmalloc element: + * bit_pos = cpu % 64 = cpu - (cpu / 64) * 64 = cpu - (cpu >> 6) << 6 + * = cpu - ((cpu >> 6) << 3) << 3 + */ + slli a1, a1, 3 + sub a1, a2, a1 + /* Compute the "get mask": 1 << bit_pos */ + li a2, 1 + sll a1, a2, a1 + + /* Check the value of new_vmalloc for this cpu */ + REG_L a2, 0(a0) + and a2, a2, a1 + beq a2, zero, _new_vmalloc_restore_context + + /* Atomically reset the current cpu bit in new_vmalloc */ + amoxor.d a0, a1, (a0) + + /* Only emit a sfence.vma if the uarch caches invalid entries */ + ALTERNATIVE("sfence.vma", "nop", 0, RISCV_ISA_EXT_SVVPTC, 1) + + REG_L a0, TASK_TI_A0(tp) + REG_L a1, TASK_TI_A1(tp) + REG_L a2, TASK_TI_A2(tp) + csrw CSR_SCRATCH, x0 + sret + +_new_vmalloc_restore_context: + REG_L a2, TASK_TI_A2(tp) +_new_vmalloc_restore_context_a1: + REG_L a1, TASK_TI_A1(tp) +_new_vmalloc_restore_context_a0: + REG_L a0, TASK_TI_A0(tp) +.endm + + SYM_CODE_START(handle_exception) /* * If coming from userspace, preserve the user thread pointer and load @@ -30,6 +103,20 @@ SYM_CODE_START(handle_exception) .Lrestore_kernel_tpsp: csrr tp, CSR_SCRATCH + +#ifdef CONFIG_64BIT + /* + * The RISC-V kernel does not eagerly emit a sfence.vma after each + * new vmalloc mapping, which may result in exceptions: + * - if the uarch caches invalid entries, the new mapping would not be + * observed by the page table walker and an invalidation is needed. + * - if the uarch does not cache invalid entries, a reordered access + * could "miss" the new mapping and traps: in that case, we only need + * to retry the access, no sfence.vma is required. + */ + new_vmalloc_check +#endif + REG_S sp, TASK_TI_KERNEL_SP(tp) #ifdef CONFIG_VMAP_STACK @@ -239,8 +326,8 @@ SYM_CODE_START(ret_from_fork) jalr s0 1: move a0, sp /* pt_regs */ - la ra, ret_from_exception - tail syscall_exit_to_user_mode + call syscall_exit_to_user_mode + j ret_from_exception SYM_CODE_END(ret_from_fork) #ifdef CONFIG_IRQ_STACKS diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index 4b95c574fd04..5081ad886841 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c @@ -214,7 +214,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - prepare_ftrace_return(&fregs->ra, ip, fregs->s0); + prepare_ftrace_return(&arch_ftrace_regs(fregs)->ra, ip, arch_ftrace_regs(fregs)->s0); } #else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ extern void ftrace_graph_call(void); diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c index 906f9a3a5d65..1cd461f3d872 100644 --- a/arch/riscv/kernel/module.c +++ b/arch/riscv/kernel/module.c @@ -787,8 +787,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, int res; unsigned int num_relocations = sechdrs[relsec].sh_size / sizeof(*rel); struct hlist_head *relocation_hashtable; - struct list_head used_buckets_list; unsigned int hashtable_bits; + LIST_HEAD(used_buckets_list); hashtable_bits = initialize_relocation_hashtable(num_relocations, &relocation_hashtable); @@ -796,8 +796,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, if (!relocation_hashtable) return -ENOMEM; - INIT_LIST_HEAD(&used_buckets_list); - pr_debug("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c index 3348a61de7d9..c7468af77c66 100644 --- a/arch/riscv/kernel/perf_callchain.c +++ b/arch/riscv/kernel/perf_callchain.c @@ -6,37 +6,9 @@ #include <asm/stacktrace.h> -/* - * Get the return address for a single stackframe and return a pointer to the - * next frame tail. - */ -static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry, - unsigned long fp, unsigned long reg_ra) +static bool fill_callchain(void *entry, unsigned long pc) { - struct stackframe buftail; - unsigned long ra = 0; - unsigned long __user *user_frame_tail = - (unsigned long __user *)(fp - sizeof(struct stackframe)); - - /* Check accessibility of one struct frame_tail beyond */ - if (!access_ok(user_frame_tail, sizeof(buftail))) - return 0; - if (__copy_from_user_inatomic(&buftail, user_frame_tail, - sizeof(buftail))) - return 0; - - if (reg_ra != 0) - ra = reg_ra; - else - ra = buftail.ra; - - fp = buftail.fp; - if (ra != 0) - perf_callchain_store(entry, ra); - else - return 0; - - return fp; + return perf_callchain_store(entry, pc) == 0; } /* @@ -56,19 +28,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry, void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { - unsigned long fp = 0; - - fp = regs->s0; - perf_callchain_store(entry, regs->epc); - - fp = user_backtrace(entry, fp, regs->ra); - while (fp && !(fp & 0x3) && entry->nr < entry->max_stack) - fp = user_backtrace(entry, fp, 0); -} - -static bool fill_callchain(void *entry, unsigned long pc) -{ - return perf_callchain_store(entry, pc) == 0; + arch_stack_walk_user(fill_callchain, entry, regs); } void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, diff --git a/arch/riscv/kernel/pi/Makefile b/arch/riscv/kernel/pi/Makefile index 50bc5ef7dd2f..81d69d45c06c 100644 --- a/arch/riscv/kernel/pi/Makefile +++ b/arch/riscv/kernel/pi/Makefile @@ -5,6 +5,7 @@ KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \ -Os -DDISABLE_BRANCH_PROFILING $(DISABLE_STACKLEAK_PLUGIN) \ $(call cc-option,-mbranch-protection=none) \ -I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \ + -include $(srctree)/include/linux/hidden.h \ -D__DISABLE_EXPORTS -ffreestanding \ -fno-asynchronous-unwind-tables -fno-unwind-tables \ $(call cc-option,-fno-addrsig) @@ -15,7 +16,12 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) KBUILD_CFLAGS += -mcmodel=medany CFLAGS_cmdline_early.o += -D__NO_FORTIFY +CFLAGS_fdt_early.o += -D__NO_FORTIFY +# lib/string.c already defines __NO_FORTIFY +CFLAGS_ctype.o += -D__NO_FORTIFY +CFLAGS_lib-fdt.o += -D__NO_FORTIFY CFLAGS_lib-fdt_ro.o += -D__NO_FORTIFY +CFLAGS_archrandom_early.o += -D__NO_FORTIFY $(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_ \ --remove-section=.note.gnu.property \ @@ -32,5 +38,5 @@ $(obj)/string.o: $(srctree)/lib/string.c FORCE $(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE $(call if_changed_rule,cc_o_c) -obj-y := cmdline_early.pi.o fdt_early.pi.o string.pi.o ctype.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o +obj-y := cmdline_early.pi.o fdt_early.pi.o string.pi.o ctype.pi.o lib-fdt.pi.o lib-fdt_ro.pi.o archrandom_early.pi.o extra-y := $(patsubst %.pi.o,%.o,$(obj-y)) diff --git a/arch/riscv/kernel/pi/archrandom_early.c b/arch/riscv/kernel/pi/archrandom_early.c new file mode 100644 index 000000000000..3f05d3cf3b7b --- /dev/null +++ b/arch/riscv/kernel/pi/archrandom_early.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <asm/csr.h> +#include <linux/processor.h> + +#include "pi.h" + +/* + * To avoid rewriting code include asm/archrandom.h and create macros + * for the functions that won't be included. + */ +#undef riscv_has_extension_unlikely +#define riscv_has_extension_likely(...) false +#undef pr_err_once +#define pr_err_once(...) + +#include <asm/archrandom.h> + +u64 get_kaslr_seed_zkr(const uintptr_t dtb_pa) +{ + unsigned long seed = 0; + + if (!fdt_early_match_extension_isa((const void *)dtb_pa, "zkr")) + return 0; + + if (!csr_seed_long(&seed)) + return 0; + + return seed; +} diff --git a/arch/riscv/kernel/pi/cmdline_early.c b/arch/riscv/kernel/pi/cmdline_early.c index f6d4dedffb84..fbcdc9e4e143 100644 --- a/arch/riscv/kernel/pi/cmdline_early.c +++ b/arch/riscv/kernel/pi/cmdline_early.c @@ -6,15 +6,9 @@ #include <asm/pgtable.h> #include <asm/setup.h> -static char early_cmdline[COMMAND_LINE_SIZE]; +#include "pi.h" -/* - * Declare the functions that are exported (but prefixed) here so that LLVM - * does not complain it lacks the 'static' keyword (which, if added, makes - * LLVM complain because the function is actually unused in this file). - */ -u64 set_satp_mode_from_cmdline(uintptr_t dtb_pa); -bool set_nokaslr_from_cmdline(uintptr_t dtb_pa); +static char early_cmdline[COMMAND_LINE_SIZE]; static char *get_early_cmdline(uintptr_t dtb_pa) { diff --git a/arch/riscv/kernel/pi/fdt_early.c b/arch/riscv/kernel/pi/fdt_early.c index 899610e042ab..9bdee2fafe47 100644 --- a/arch/riscv/kernel/pi/fdt_early.c +++ b/arch/riscv/kernel/pi/fdt_early.c @@ -2,13 +2,9 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/libfdt.h> +#include <linux/ctype.h> -/* - * Declare the functions that are exported (but prefixed) here so that LLVM - * does not complain it lacks the 'static' keyword (which, if added, makes - * LLVM complain because the function is actually unused in this file). - */ -u64 get_kaslr_seed(uintptr_t dtb_pa); +#include "pi.h" u64 get_kaslr_seed(uintptr_t dtb_pa) { @@ -28,3 +24,162 @@ u64 get_kaslr_seed(uintptr_t dtb_pa) *prop = 0; return ret; } + +/** + * fdt_device_is_available - check if a device is available for use + * + * @fdt: pointer to the device tree blob + * @node: offset of the node whose property to find + * + * Returns true if the status property is absent or set to "okay" or "ok", + * false otherwise + */ +static bool fdt_device_is_available(const void *fdt, int node) +{ + const char *status; + int statlen; + + status = fdt_getprop(fdt, node, "status", &statlen); + if (!status) + return true; + + if (statlen > 0) { + if (!strcmp(status, "okay") || !strcmp(status, "ok")) + return true; + } + + return false; +} + +/* Copy of fdt_nodename_eq_ */ +static int fdt_node_name_eq(const void *fdt, int offset, + const char *s) +{ + int olen; + int len = strlen(s); + const char *p = fdt_get_name(fdt, offset, &olen); + + if (!p || olen < len) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +/** + * isa_string_contains - check if isa string contains an extension + * + * @isa_str: isa string to search + * @ext_name: the extension to search for + * + * Returns true if the extension is in the given isa string, + * false otherwise + */ +static bool isa_string_contains(const char *isa_str, const char *ext_name) +{ + size_t i, single_end, len = strlen(ext_name); + char ext_end; + + /* Error must contain rv32/64 */ + if (strlen(isa_str) < 4) + return false; + + if (len == 1) { + single_end = strcspn(isa_str, "sSxXzZ"); + /* Search for single chars between rv32/64 and multi-letter extensions */ + for (i = 4; i < single_end; i++) { + if (tolower(isa_str[i]) == ext_name[0]) + return true; + } + return false; + } + + /* Skip to start of multi-letter extensions */ + isa_str = strpbrk(isa_str, "sSxXzZ"); + while (isa_str) { + if (strncasecmp(isa_str, ext_name, len) == 0) { + ext_end = isa_str[len]; + /* Check if matches the whole extension. */ + if (ext_end == '\0' || ext_end == '_') + return true; + } + /* Multi-letter extensions must be split from other multi-letter + * extensions with an "_", the end of a multi-letter extension will + * either be the null character or the "_" at the start of the next + * multi-letter extension. + */ + isa_str = strchr(isa_str, '_'); + if (isa_str) + isa_str++; + } + + return false; +} + +/** + * early_cpu_isa_ext_available - check if cpu node has an extension + * + * @fdt: pointer to the device tree blob + * @node: offset of the cpu node + * @ext_name: the extension to search for + * + * Returns true if the cpu node has the extension, + * false otherwise + */ +static bool early_cpu_isa_ext_available(const void *fdt, int node, const char *ext_name) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, node, "riscv,isa-extensions", &len); + if (prop && fdt_stringlist_contains(prop, len, ext_name)) + return true; + + prop = fdt_getprop(fdt, node, "riscv,isa", &len); + if (prop && isa_string_contains(prop, ext_name)) + return true; + + return false; +} + +/** + * fdt_early_match_extension_isa - check if all cpu nodes have an extension + * + * @fdt: pointer to the device tree blob + * @ext_name: the extension to search for + * + * Returns true if the all available the cpu nodes have the extension, + * false otherwise + */ +bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name) +{ + int node, parent; + bool ret = false; + + parent = fdt_path_offset(fdt, "/cpus"); + if (parent < 0) + return false; + + fdt_for_each_subnode(node, fdt, parent) { + if (!fdt_node_name_eq(fdt, node, "cpu")) + continue; + + if (!fdt_device_is_available(fdt, node)) + continue; + + if (!early_cpu_isa_ext_available(fdt, node, ext_name)) + return false; + + ret = true; + } + + return ret; +} diff --git a/arch/riscv/kernel/pi/pi.h b/arch/riscv/kernel/pi/pi.h new file mode 100644 index 000000000000..21141d84fea6 --- /dev/null +++ b/arch/riscv/kernel/pi/pi.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _RISCV_PI_H_ +#define _RISCV_PI_H_ + +#include <linux/types.h> + +/* + * The following functions are exported (but prefixed). Declare them here so + * that LLVM does not complain it lacks the 'static' keyword (which, if + * added, makes LLVM complain because the function is unused). + */ + +u64 get_kaslr_seed(uintptr_t dtb_pa); +u64 get_kaslr_seed_zkr(const uintptr_t dtb_pa); +bool set_nokaslr_from_cmdline(uintptr_t dtb_pa); +u64 set_satp_mode_from_cmdline(uintptr_t dtb_pa); + +bool fdt_early_match_extension_isa(const void *fdt, const char *ext_name); + +#endif /* _RISCV_PI_H_ */ diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index e4bc61c4e58a..e3142d8a6e28 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -15,6 +15,7 @@ #include <linux/tick.h> #include <linux/ptrace.h> #include <linux/uaccess.h> +#include <linux/personality.h> #include <asm/unistd.h> #include <asm/processor.h> @@ -26,6 +27,7 @@ #include <asm/cpuidle.h> #include <asm/vector.h> #include <asm/cpufeature.h> +#include <asm/exec.h> #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) #include <linux/stackprotector.h> @@ -99,6 +101,13 @@ void show_regs(struct pt_regs *regs) dump_backtrace(regs, NULL, KERN_DEFAULT); } +unsigned long arch_align_stack(unsigned long sp) +{ + if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) + sp -= get_random_u32_below(PAGE_SIZE); + return sp & ~0xf; +} + #ifdef CONFIG_COMPAT static bool compat_mode_supported __read_mostly; diff --git a/arch/riscv/kernel/riscv_ksyms.c b/arch/riscv/kernel/riscv_ksyms.c index a72879b4249a..5ab1c7e1a6ed 100644 --- a/arch/riscv/kernel/riscv_ksyms.c +++ b/arch/riscv/kernel/riscv_ksyms.c @@ -12,9 +12,6 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memmove); diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 837bdab2601b..1989b8cade1b 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -14,9 +14,6 @@ #include <asm/smp.h> #include <asm/tlbflush.h> -#define CREATE_TRACE_POINTS -#include <asm/trace.h> - /* default SBI version is 0.1 */ unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT; EXPORT_SYMBOL(sbi_spec_version); @@ -27,55 +24,6 @@ static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask, unsigned long start, unsigned long size, unsigned long arg4, unsigned long arg5) __ro_after_init; -struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1, - unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5, - int fid, int ext) -{ - struct sbiret ret; - - trace_sbi_call(ext, fid); - - register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); - register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); - register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); - register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); - register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4); - register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5); - register uintptr_t a6 asm ("a6") = (uintptr_t)(fid); - register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); - asm volatile ("ecall" - : "+r" (a0), "+r" (a1) - : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) - : "memory"); - ret.error = a0; - ret.value = a1; - - trace_sbi_return(ext, ret.error, ret.value); - - return ret; -} -EXPORT_SYMBOL(__sbi_ecall); - -int sbi_err_map_linux_errno(int err) -{ - switch (err) { - case SBI_SUCCESS: - return 0; - case SBI_ERR_DENIED: - return -EPERM; - case SBI_ERR_INVALID_PARAM: - return -EINVAL; - case SBI_ERR_INVALID_ADDRESS: - return -EFAULT; - case SBI_ERR_NOT_SUPPORTED: - case SBI_ERR_FAILURE: - default: - return -ENOTSUPP; - }; -} -EXPORT_SYMBOL(sbi_err_map_linux_errno); - #ifdef CONFIG_RISCV_SBI_V01 static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mask) { @@ -535,17 +483,6 @@ long sbi_probe_extension(int extid) } EXPORT_SYMBOL(sbi_probe_extension); -static long __sbi_base_ecall(int fid) -{ - struct sbiret ret; - - ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0); - if (!ret.error) - return ret.value; - else - return sbi_err_map_linux_errno(ret.error); -} - static inline long sbi_get_spec_version(void) { return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION); diff --git a/arch/riscv/kernel/sbi_ecall.c b/arch/riscv/kernel/sbi_ecall.c new file mode 100644 index 000000000000..24aabb4fbde3 --- /dev/null +++ b/arch/riscv/kernel/sbi_ecall.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Rivos Inc. */ + +#include <asm/sbi.h> +#define CREATE_TRACE_POINTS +#include <asm/trace.h> + +long __sbi_base_ecall(int fid) +{ + struct sbiret ret; + + ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0); + if (!ret.error) + return ret.value; + else + return sbi_err_map_linux_errno(ret.error); +} +EXPORT_SYMBOL(__sbi_base_ecall); + +struct sbiret __sbi_ecall(unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5, + int fid, int ext) +{ + struct sbiret ret; + + trace_sbi_call(ext, fid); + + register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); + register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); + register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); + register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4); + register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5); + register uintptr_t a6 asm ("a6") = (uintptr_t)(fid); + register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); + asm volatile ("ecall" + : "+r" (a0), "+r" (a1) + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) + : "memory"); + ret.error = a0; + ret.value = a1; + + trace_sbi_return(ext, ret.error, ret.value); + + return ret; +} +EXPORT_SYMBOL(__sbi_ecall); diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index a2cde65b69e9..26c886db4fb3 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -227,7 +227,7 @@ static void __init init_resources(void) static void __init parse_dtb(void) { /* Early scan of device tree from init memory */ - if (early_init_dt_scan(dtb_early_va)) { + if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) { const char *name = of_flat_dt_get_machine_name(); if (name) { diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 8e6eb64459af..c180a647a30e 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -13,6 +13,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/kexec.h> +#include <linux/kgdb.h> #include <linux/percpu.h> #include <linux/profile.h> #include <linux/smp.h> @@ -21,6 +22,7 @@ #include <linux/delay.h> #include <linux/irq.h> #include <linux/irq_work.h> +#include <linux/nmi.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> @@ -33,6 +35,8 @@ enum ipi_message_type { IPI_CPU_CRASH_STOP, IPI_IRQ_WORK, IPI_TIMER, + IPI_CPU_BACKTRACE, + IPI_KGDB_ROUNDUP, IPI_MAX }; @@ -113,6 +117,7 @@ void arch_irq_work_raise(void) static irqreturn_t handle_IPI(int irq, void *data) { + unsigned int cpu = smp_processor_id(); int ipi = irq - ipi_virq_base; switch (ipi) { @@ -126,7 +131,7 @@ static irqreturn_t handle_IPI(int irq, void *data) ipi_stop(); break; case IPI_CPU_CRASH_STOP: - ipi_cpu_crash_stop(smp_processor_id(), get_irq_regs()); + ipi_cpu_crash_stop(cpu, get_irq_regs()); break; case IPI_IRQ_WORK: irq_work_run(); @@ -136,8 +141,14 @@ static irqreturn_t handle_IPI(int irq, void *data) tick_receive_broadcast(); break; #endif + case IPI_CPU_BACKTRACE: + nmi_cpu_backtrace(get_irq_regs()); + break; + case IPI_KGDB_ROUNDUP: + kgdb_nmicallback(cpu, get_irq_regs()); + break; default: - pr_warn("CPU%d: unhandled IPI%d\n", smp_processor_id(), ipi); + pr_warn("CPU%d: unhandled IPI%d\n", cpu, ipi); break; } @@ -203,6 +214,8 @@ static const char * const ipi_names[] = { [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", [IPI_IRQ_WORK] = "IRQ work interrupts", [IPI_TIMER] = "Timer broadcast interrupts", + [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", + [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts", }; void show_ipi_stats(struct seq_file *p, int prec) @@ -323,3 +336,29 @@ void arch_smp_send_reschedule(int cpu) send_ipi_single(cpu, IPI_RESCHEDULE); } EXPORT_SYMBOL_GPL(arch_smp_send_reschedule); + +static void riscv_backtrace_ipi(cpumask_t *mask) +{ + send_ipi_mask(mask, IPI_CPU_BACKTRACE); +} + +void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) +{ + nmi_trigger_cpumask_backtrace(mask, exclude_cpu, riscv_backtrace_ipi); +} + +#ifdef CONFIG_KGDB +void kgdb_roundup_cpus(void) +{ + int this_cpu = raw_smp_processor_id(); + int cpu; + + for_each_online_cpu(cpu) { + /* No need to roundup ourselves */ + if (cpu == this_cpu) + continue; + + send_ipi_single(cpu, IPI_KGDB_ROUNDUP); + } +} +#endif diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index c6d5de22463f..153a2db4c5fa 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -162,3 +162,46 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry, void { walk_stackframe(task, regs, consume_entry, cookie); } + +/* + * Get the return address for a single stackframe and return a pointer to the + * next frame tail. + */ +static unsigned long unwind_user_frame(stack_trace_consume_fn consume_entry, + void *cookie, unsigned long fp, + unsigned long reg_ra) +{ + struct stackframe buftail; + unsigned long ra = 0; + unsigned long __user *user_frame_tail = + (unsigned long __user *)(fp - sizeof(struct stackframe)); + + /* Check accessibility of one struct frame_tail beyond */ + if (!access_ok(user_frame_tail, sizeof(buftail))) + return 0; + if (__copy_from_user_inatomic(&buftail, user_frame_tail, + sizeof(buftail))) + return 0; + + ra = reg_ra ? : buftail.ra; + + fp = buftail.fp; + if (!ra || !consume_entry(cookie, ra)) + return 0; + + return fp; +} + +void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, + const struct pt_regs *regs) +{ + unsigned long fp = 0; + + fp = regs->s0; + if (!consume_entry(cookie, regs->epc)) + return; + + fp = unwind_user_frame(consume_entry, cookie, fp, regs->ra); + while (fp && !(fp & 0x7)) + fp = unwind_user_frame(consume_entry, cookie, fp, 0); +} diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c index cea0ca2bf2a2..711a31f27c3d 100644 --- a/arch/riscv/kernel/sys_hwprobe.c +++ b/arch/riscv/kernel/sys_hwprobe.c @@ -402,7 +402,7 @@ static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, static int __init init_hwprobe_vdso_data(void) { struct vdso_data *vd = __arch_get_k_vdso_data(); - struct arch_vdso_data *avd = &vd->arch_data; + struct arch_vdso_time_data *avd = &vd->arch_data; u64 id_bitsmash = 0; struct riscv_hwprobe pair; int key; diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c index 192cd5603e95..1b9867136b61 100644 --- a/arch/riscv/kernel/traps_misaligned.c +++ b/arch/riscv/kernel/traps_misaligned.c @@ -136,8 +136,6 @@ #define REG_PTR(insn, pos, regs) \ (ulong *)((ulong)(regs) + REG_OFFSET(insn, pos)) -#define GET_RM(insn) (((insn) >> 12) & 7) - #define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs)) #define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs)) #define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs)) @@ -417,7 +415,7 @@ int handle_misaligned_load(struct pt_regs *regs) val.data_u64 = 0; if (user_mode(regs)) { - if (raw_copy_from_user(&val, (u8 __user *)addr, len)) + if (copy_from_user(&val, (u8 __user *)addr, len)) return -1; } else { memcpy(&val, (u8 *)addr, len); @@ -515,7 +513,7 @@ int handle_misaligned_store(struct pt_regs *regs) return -EOPNOTSUPP; if (user_mode(regs)) { - if (raw_copy_to_user((u8 __user *)addr, &val, len)) + if (copy_to_user((u8 __user *)addr, &val, len)) return -1; } else { memcpy((u8 *)addr, &val, len); diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index 98315b98256d..3ca3ae4277e1 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -23,11 +23,6 @@ enum vvar_pages { VVAR_NR_PAGES, }; -enum rv_vdso_map { - RV_VDSO_MAP_VVAR, - RV_VDSO_MAP_VDSO, -}; - #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) static union vdso_data_store vdso_data_store __page_aligned_data; @@ -38,8 +33,6 @@ struct __vdso_info { const char *vdso_code_start; const char *vdso_code_end; unsigned long vdso_pages; - /* Data Mapping */ - struct vm_special_mapping *dm; /* Code Mapping */ struct vm_special_mapping *cm; }; @@ -92,6 +85,8 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page) return (struct vdso_data *)(vvar_page); } +static const struct vm_special_mapping rv_vvar_map; + /* * The vvar mapping contains data for a specific time namespace, so when a task * changes namespace we must unmap its vvar data for the old namespace. @@ -108,12 +103,8 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) mmap_read_lock(mm); for_each_vma(vmi, vma) { - if (vma_is_special_mapping(vma, vdso_info.dm)) - zap_vma_pages(vma); -#ifdef CONFIG_COMPAT - if (vma_is_special_mapping(vma, compat_vdso_info.dm)) + if (vma_is_special_mapping(vma, &rv_vvar_map)) zap_vma_pages(vma); -#endif } mmap_read_unlock(mm); @@ -155,43 +146,34 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, return vmf_insert_pfn(vma, vmf->address, pfn); } -static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = { - [RV_VDSO_MAP_VVAR] = { - .name = "[vvar]", - .fault = vvar_fault, - }, - [RV_VDSO_MAP_VDSO] = { - .name = "[vdso]", - .mremap = vdso_mremap, - }, +static const struct vm_special_mapping rv_vvar_map = { + .name = "[vvar]", + .fault = vvar_fault, +}; + +static struct vm_special_mapping rv_vdso_map __ro_after_init = { + .name = "[vdso]", + .mremap = vdso_mremap, }; static struct __vdso_info vdso_info __ro_after_init = { .name = "vdso", .vdso_code_start = vdso_start, .vdso_code_end = vdso_end, - .dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR], - .cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO], + .cm = &rv_vdso_map, }; #ifdef CONFIG_COMPAT -static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = { - [RV_VDSO_MAP_VVAR] = { - .name = "[vvar]", - .fault = vvar_fault, - }, - [RV_VDSO_MAP_VDSO] = { - .name = "[vdso]", - .mremap = vdso_mremap, - }, +static struct vm_special_mapping rv_compat_vdso_map __ro_after_init = { + .name = "[vdso]", + .mremap = vdso_mremap, }; static struct __vdso_info compat_vdso_info __ro_after_init = { .name = "compat_vdso", .vdso_code_start = compat_vdso_start, .vdso_code_end = compat_vdso_end, - .dm = &rv_compat_vdso_maps[RV_VDSO_MAP_VVAR], - .cm = &rv_compat_vdso_maps[RV_VDSO_MAP_VDSO], + .cm = &rv_compat_vdso_map, }; #endif @@ -227,7 +209,7 @@ static int __setup_additional_pages(struct mm_struct *mm, } ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE, - (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info->dm); + (VM_READ | VM_MAYREAD | VM_PFNMAP), &rv_vvar_map); if (IS_ERR(ret)) goto up_fail; diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile index f7ef8ad9b550..3f1c4b2d0b06 100644 --- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile @@ -18,6 +18,7 @@ obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o ccflags-y := -fno-stack-protector ccflags-y += -DDISABLE_BRANCH_PROFILING +ccflags-y += -fno-builtin ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y) @@ -45,7 +46,7 @@ $(obj)/vdso.o: $(obj)/vdso.so # link rule for the .so file, .lds has to be first $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE $(call if_changed,vdsold) -LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \ +LDFLAGS_vdso.so.dbg = -shared -soname=linux-vdso.so.1 \ --build-id=sha1 --hash-style=both --eh-frame-hdr # strip rule for the .so file diff --git a/arch/riscv/kernel/vdso/hwprobe.c b/arch/riscv/kernel/vdso/hwprobe.c index 1e926e4b5881..a158c029344f 100644 --- a/arch/riscv/kernel/vdso/hwprobe.c +++ b/arch/riscv/kernel/vdso/hwprobe.c @@ -17,7 +17,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count, unsigned int flags) { const struct vdso_data *vd = __arch_get_vdso_data(); - const struct arch_vdso_data *avd = &vd->arch_data; + const struct arch_vdso_time_data *avd = &vd->arch_data; bool all_cpus = !cpusetsize && !cpus; struct riscv_hwprobe *p = pairs; struct riscv_hwprobe *end = pairs + pair_count; @@ -52,7 +52,7 @@ static int riscv_vdso_get_cpus(struct riscv_hwprobe *pairs, size_t pair_count, unsigned int flags) { const struct vdso_data *vd = __arch_get_vdso_data(); - const struct arch_vdso_data *avd = &vd->arch_data; + const struct arch_vdso_time_data *avd = &vd->arch_data; struct riscv_hwprobe *p = pairs; struct riscv_hwprobe *end = pairs + pair_count; unsigned char *c = (unsigned char *)cpus; diff --git a/arch/riscv/kernel/vendor_extensions/andes.c b/arch/riscv/kernel/vendor_extensions/andes.c index ec688c88456a..51f302b6d503 100644 --- a/arch/riscv/kernel/vendor_extensions/andes.c +++ b/arch/riscv/kernel/vendor_extensions/andes.c @@ -8,7 +8,7 @@ #include <linux/types.h> /* All Andes vendor extensions supported in Linux */ -const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = { +static const struct riscv_isa_ext_data riscv_isa_vendor_ext_andes[] = { __RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_VENDOR_EXT_XANDESPMU), }; diff --git a/arch/riscv/kernel/vmcore_info.c b/arch/riscv/kernel/vmcore_info.c index 6d7a22522d63..d5e448aa90e7 100644 --- a/arch/riscv/kernel/vmcore_info.c +++ b/arch/riscv/kernel/vmcore_info.c @@ -19,6 +19,13 @@ void arch_crash_save_vmcoreinfo(void) #endif #endif vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR); +#ifdef CONFIG_XIP_KERNEL + /* TODO: Communicate with crash-utility developers on the information to + * export. The XIP case is more complicated, because the virtual-physical + * address offset depends on whether the address is in ROM or in RAM. + */ +#else vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n", kernel_map.va_kernel_pa_offset); +#endif } diff --git a/arch/riscv/kernel/vmlinux-xip.lds.S b/arch/riscv/kernel/vmlinux-xip.lds.S index 8c3daa1b0531..a7611789bad5 100644 --- a/arch/riscv/kernel/vmlinux-xip.lds.S +++ b/arch/riscv/kernel/vmlinux-xip.lds.S @@ -14,6 +14,7 @@ #include <asm/page.h> #include <asm/cache.h> #include <asm/thread_info.h> +#include <asm/set_memory.h> OUTPUT_ARCH(riscv) ENTRY(_start) @@ -65,10 +66,10 @@ SECTIONS * From this point, stuff is considered writable and will be copied to RAM */ __data_loc = ALIGN(PAGE_SIZE); /* location in file */ - . = KERNEL_LINK_ADDR + XIP_OFFSET; /* location in memory */ + . = ALIGN(SECTION_ALIGN); /* location in memory */ #undef LOAD_OFFSET -#define LOAD_OFFSET (KERNEL_LINK_ADDR + XIP_OFFSET - (__data_loc & XIP_OFFSET_MASK)) +#define LOAD_OFFSET (KERNEL_LINK_ADDR + _sdata - __data_loc) _sdata = .; /* Start of data section */ _data = .; diff --git a/arch/riscv/kvm/aia_imsic.c b/arch/riscv/kvm/aia_imsic.c index 0a1e859323b4..a8085cd8215e 100644 --- a/arch/riscv/kvm/aia_imsic.c +++ b/arch/riscv/kvm/aia_imsic.c @@ -55,7 +55,7 @@ struct imsic { /* IMSIC SW-file */ struct imsic_mrif *swfile; phys_addr_t swfile_pa; - spinlock_t swfile_extirq_lock; + raw_spinlock_t swfile_extirq_lock; }; #define imsic_vs_csr_read(__c) \ @@ -622,7 +622,7 @@ static void imsic_swfile_extirq_update(struct kvm_vcpu *vcpu) * interruptions between reading topei and updating pending status. */ - spin_lock_irqsave(&imsic->swfile_extirq_lock, flags); + raw_spin_lock_irqsave(&imsic->swfile_extirq_lock, flags); if (imsic_mrif_atomic_read(mrif, &mrif->eidelivery) && imsic_mrif_topei(mrif, imsic->nr_eix, imsic->nr_msis)) @@ -630,7 +630,7 @@ static void imsic_swfile_extirq_update(struct kvm_vcpu *vcpu) else kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_EXT); - spin_unlock_irqrestore(&imsic->swfile_extirq_lock, flags); + raw_spin_unlock_irqrestore(&imsic->swfile_extirq_lock, flags); } static void imsic_swfile_read(struct kvm_vcpu *vcpu, bool clear, @@ -1051,7 +1051,7 @@ int kvm_riscv_vcpu_aia_imsic_init(struct kvm_vcpu *vcpu) } imsic->swfile = page_to_virt(swfile_page); imsic->swfile_pa = page_to_phys(swfile_page); - spin_lock_init(&imsic->swfile_extirq_lock); + raw_spin_lock_init(&imsic->swfile_extirq_lock); /* Setup IO device */ kvm_iodevice_init(&imsic->iodev, &imsic_iodoev_ops); diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c index bab2ec34cd87..f3427f6de608 100644 --- a/arch/riscv/kvm/main.c +++ b/arch/riscv/kvm/main.c @@ -20,7 +20,7 @@ long kvm_arch_dev_ioctl(struct file *filp, return -EINVAL; } -int kvm_arch_hardware_enable(void) +int kvm_arch_enable_virtualization_cpu(void) { csr_write(CSR_HEDELEG, KVM_HEDELEG_DEFAULT); csr_write(CSR_HIDELEG, KVM_HIDELEG_DEFAULT); @@ -35,7 +35,7 @@ int kvm_arch_hardware_enable(void) return 0; } -void kvm_arch_hardware_disable(void) +void kvm_arch_disable_virtualization_cpu(void) { kvm_riscv_aia_disable(); diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c index bcf41d6e0df0..2707a51b082c 100644 --- a/arch/riscv/kvm/vcpu_pmu.c +++ b/arch/riscv/kvm/vcpu_pmu.c @@ -391,19 +391,9 @@ int kvm_riscv_vcpu_pmu_read_hpm(struct kvm_vcpu *vcpu, unsigned int csr_num, static void kvm_pmu_clear_snapshot_area(struct kvm_vcpu *vcpu) { struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); - int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); - if (kvpmu->sdata) { - if (kvpmu->snapshot_addr != INVALID_GPA) { - memset(kvpmu->sdata, 0, snapshot_area_size); - kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, - kvpmu->sdata, snapshot_area_size); - } else { - pr_warn("snapshot address invalid\n"); - } - kfree(kvpmu->sdata); - kvpmu->sdata = NULL; - } + kfree(kvpmu->sdata); + kvpmu->sdata = NULL; kvpmu->snapshot_addr = INVALID_GPA; } diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c index 62f409d4176e..7de128be8db9 100644 --- a/arch/riscv/kvm/vcpu_sbi.c +++ b/arch/riscv/kvm/vcpu_sbi.c @@ -127,8 +127,8 @@ void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run) run->riscv_sbi.args[3] = cp->a3; run->riscv_sbi.args[4] = cp->a4; run->riscv_sbi.args[5] = cp->a5; - run->riscv_sbi.ret[0] = cp->a0; - run->riscv_sbi.ret[1] = cp->a1; + run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED; + run->riscv_sbi.ret[1] = 0; } void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 2b369f51b0a5..8eec6b69a875 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -3,9 +3,11 @@ lib-y += delay.o lib-y += memcpy.o lib-y += memset.o lib-y += memmove.o +ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),) lib-y += strcmp.o lib-y += strlen.o lib-y += strncmp.o +endif lib-y += csum.o ifeq ($(CONFIG_MMU), y) lib-$(CONFIG_RISCV_ISA_V) += uaccess_vector.o diff --git a/arch/riscv/lib/memset.S b/arch/riscv/lib/memset.S index 35f358e70bdb..da23b8347e2d 100644 --- a/arch/riscv/lib/memset.S +++ b/arch/riscv/lib/memset.S @@ -111,3 +111,5 @@ SYM_FUNC_START(__memset) ret SYM_FUNC_END(__memset) SYM_FUNC_ALIAS_WEAK(memset, __memset) +SYM_FUNC_ALIAS(__pi_memset, __memset) +SYM_FUNC_ALIAS(__pi___memset, __memset) diff --git a/arch/riscv/lib/strcmp.S b/arch/riscv/lib/strcmp.S index 687b2bea5c43..57a5c0066231 100644 --- a/arch/riscv/lib/strcmp.S +++ b/arch/riscv/lib/strcmp.S @@ -120,3 +120,5 @@ strcmp_zbb: .option pop #endif SYM_FUNC_END(strcmp) +SYM_FUNC_ALIAS(__pi_strcmp, strcmp) +EXPORT_SYMBOL(strcmp) diff --git a/arch/riscv/lib/strlen.S b/arch/riscv/lib/strlen.S index 8ae3064e45ff..962983b73251 100644 --- a/arch/riscv/lib/strlen.S +++ b/arch/riscv/lib/strlen.S @@ -131,3 +131,4 @@ strlen_zbb: #endif SYM_FUNC_END(strlen) SYM_FUNC_ALIAS(__pi_strlen, strlen) +EXPORT_SYMBOL(strlen) diff --git a/arch/riscv/lib/strncmp.S b/arch/riscv/lib/strncmp.S index aba5b3148621..7b2d0ff9ed6c 100644 --- a/arch/riscv/lib/strncmp.S +++ b/arch/riscv/lib/strncmp.S @@ -136,3 +136,5 @@ strncmp_zbb: .option pop #endif SYM_FUNC_END(strncmp) +SYM_FUNC_ALIAS(__pi_strncmp, strncmp) +EXPORT_SYMBOL(strncmp) diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index a03c994eed3b..b81672729887 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c @@ -158,6 +158,7 @@ void __init riscv_init_cbo_blocksizes(void) #ifdef CONFIG_SMP static void set_icache_stale_mask(void) { + int cpu = get_cpu(); cpumask_t *mask; bool stale_cpu; @@ -168,10 +169,11 @@ static void set_icache_stale_mask(void) * concurrently on different harts. */ mask = ¤t->mm->context.icache_stale_mask; - stale_cpu = cpumask_test_cpu(smp_processor_id(), mask); + stale_cpu = cpumask_test_cpu(cpu, mask); cpumask_setall(mask); - cpumask_assign_cpu(smp_processor_id(), mask, stale_cpu); + cpumask_assign_cpu(cpu, mask, stale_cpu); + put_cpu(); } #endif @@ -239,14 +241,12 @@ int riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long scope) case PR_RISCV_CTX_SW_FENCEI_OFF: switch (scope) { case PR_RISCV_SCOPE_PER_PROCESS: - current->mm->context.force_icache_flush = false; - set_icache_stale_mask(); + current->mm->context.force_icache_flush = false; break; case PR_RISCV_SCOPE_PER_THREAD: - current->thread.force_icache_flush = false; - set_icache_stale_mask(); + current->thread.force_icache_flush = false; break; default: return -EINVAL; diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index eb0649a61b4c..0e8c20adcd98 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -37,6 +37,8 @@ #include "../kernel/head.h" +u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1]; + struct kernel_mapping kernel_map __ro_after_init; EXPORT_SYMBOL(kernel_map); #ifdef CONFIG_XIP_KERNEL @@ -252,7 +254,7 @@ static void __init setup_bootmem(void) * The size of the linear page mapping may restrict the amount of * usable RAM. */ - if (IS_ENABLED(CONFIG_64BIT)) { + if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU)) { max_mapped_addr = __pa(PAGE_OFFSET) + KERN_VIRT_SIZE; memblock_cap_memory_range(phys_ram_base, max_mapped_addr - phys_ram_base); @@ -917,7 +919,7 @@ static void __init relocate_kernel(void) static void __init create_kernel_page_table(pgd_t *pgdir, __always_unused bool early) { - uintptr_t va, end_va; + uintptr_t va, start_va, end_va; /* Map the flash resident part */ end_va = kernel_map.virt_addr + kernel_map.xiprom_sz; @@ -927,10 +929,11 @@ static void __init create_kernel_page_table(pgd_t *pgdir, PMD_SIZE, PAGE_KERNEL_EXEC); /* Map the data in RAM */ + start_va = kernel_map.virt_addr + (uintptr_t)&_sdata - (uintptr_t)&_start; end_va = kernel_map.virt_addr + kernel_map.size; - for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE) + for (va = start_va; va < end_va; va += PMD_SIZE) create_pgd_mapping(pgdir, va, - kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)), + kernel_map.phys_addr + (va - start_va), PMD_SIZE, PAGE_KERNEL); } #else @@ -1048,6 +1051,7 @@ static void __init pt_ops_set_late(void) #ifdef CONFIG_RANDOMIZE_BASE extern bool __init __pi_set_nokaslr_from_cmdline(uintptr_t dtb_pa); extern u64 __init __pi_get_kaslr_seed(uintptr_t dtb_pa); +extern u64 __init __pi_get_kaslr_seed_zkr(const uintptr_t dtb_pa); static int __init print_nokaslr(char *p) { @@ -1068,10 +1072,12 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) #ifdef CONFIG_RANDOMIZE_BASE if (!__pi_set_nokaslr_from_cmdline(dtb_pa)) { - u64 kaslr_seed = __pi_get_kaslr_seed(dtb_pa); + u64 kaslr_seed = __pi_get_kaslr_seed_zkr(dtb_pa); u32 kernel_size = (uintptr_t)(&_end) - (uintptr_t)(&_start); u32 nr_pos; + if (kaslr_seed == 0) + kaslr_seed = __pi_get_kaslr_seed(dtb_pa); /* * Compute the number of positions available: we are limited * by the early page table that only has one PUD and we must @@ -1098,11 +1104,14 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); - kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom; + kernel_map.va_kernel_xip_text_pa_offset = kernel_map.virt_addr - kernel_map.xiprom; + kernel_map.va_kernel_xip_data_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr + + (uintptr_t)&_sdata - (uintptr_t)&_start; #else kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL); kernel_map.phys_addr = (uintptr_t)(&_start); kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr; + kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; #endif #if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL) @@ -1124,15 +1133,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) */ kernel_map.va_pa_offset = IS_ENABLED(CONFIG_64BIT) ? 0UL : PAGE_OFFSET - kernel_map.phys_addr; - kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr; - /* - * The default maximal physical memory size is KERN_VIRT_SIZE for 32-bit - * kernel, whereas for 64-bit kernel, the end of the virtual address - * space is occupied by the modules/BPF/kernel mappings which reduces - * the available size of the linear mapping. - */ - memory_limit = KERN_VIRT_SIZE - (IS_ENABLED(CONFIG_64BIT) ? SZ_4G : 0); + memory_limit = KERN_VIRT_SIZE; /* Sanity check alignment and size */ BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0); diff --git a/arch/riscv/mm/pgtable.c b/arch/riscv/mm/pgtable.c index 533ec9055fa0..4ae67324f992 100644 --- a/arch/riscv/mm/pgtable.c +++ b/arch/riscv/mm/pgtable.c @@ -9,6 +9,9 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, pte_t entry, int dirty) { + asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1) + : : : : svvptc); + if (!pte_same(ptep_get(ptep), entry)) __set_pte_at(vma->vm_mm, ptep, entry); /* @@ -16,6 +19,16 @@ int ptep_set_access_flags(struct vm_area_struct *vma, * the case that the PTE changed and the spurious fault case. */ return true; + +svvptc: + if (!pte_same(ptep_get(ptep), entry)) { + __set_pte_at(vma->vm_mm, ptep, entry); + /* Here only not svadu is impacted */ + flush_tlb_page(vma, address); + return true; + } + + return false; } int ptep_test_and_clear_young(struct vm_area_struct *vma, diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index 99f34409fb60..4cc631fa7039 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -18,6 +18,7 @@ #define RV_MAX_REG_ARGS 8 #define RV_FENTRY_NINSNS 2 #define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4) +#define RV_KCFI_NINSNS (IS_ENABLED(CONFIG_CFI_CLANG) ? 1 : 0) /* imm that allows emit_imm to emit max count insns */ #define RV_MAX_COUNT_IMM 0x7FFF7FF7FF7FF7FF @@ -271,7 +272,8 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx) if (!is_tail_call) emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx); emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA, - is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */ + /* kcfi, fentry and TCC init insns will be skipped on tailcall */ + is_tail_call ? (RV_KCFI_NINSNS + RV_FENTRY_NINSNS + 1) * 4 : 0, ctx); } @@ -548,8 +550,8 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64, rv_lr_w(r0, 0, rd, 0, 0), ctx); jmp_offset = ninsns_rvoff(8); emit(rv_bne(RV_REG_T2, r0, jmp_offset >> 1), ctx); - emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 0) : - rv_sc_w(RV_REG_T3, rs, rd, 0, 0), ctx); + emit(is64 ? rv_sc_d(RV_REG_T3, rs, rd, 0, 1) : + rv_sc_w(RV_REG_T3, rs, rd, 0, 1), ctx); jmp_offset = ninsns_rvoff(-6); emit(rv_bne(RV_REG_T3, 0, jmp_offset >> 1), ctx); emit(rv_fence(0x3, 0x3), ctx); diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile index f11945ee2490..fb9c917c9b45 100644 --- a/arch/riscv/purgatory/Makefile +++ b/arch/riscv/purgatory/Makefile @@ -1,7 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o +ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),) purgatory-y += strcmp.o strlen.o strncmp.o +endif targets += $(purgatory-y) PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index c60e699e99f5..c64b2987d108 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -52,6 +52,13 @@ config KASAN_SHADOW_OFFSET depends on KASAN default 0x1C000000000000 +config GCC_ASM_FLAG_OUTPUT_BROKEN + def_bool CC_IS_GCC && GCC_VERSION < 140200 + help + GCC versions before 14.2.0 may die with an internal + compiler error in some configurations if flag output + operands are used within inline assemblies. + config S390 def_bool y # @@ -70,6 +77,7 @@ config S390 select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_WX select ARCH_HAS_DEVMEM_IS_ALLOWED + select ARCH_HAS_DMA_OPS if PCI select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FORCE_DMA_UNENCRYPTED select ARCH_HAS_FORTIFY_SOURCE @@ -87,7 +95,7 @@ config S390 select ARCH_HAS_STRICT_MODULE_RWX select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_UBSAN - select ARCH_HAS_VDSO_DATA + select ARCH_HAS_VDSO_TIME_DATA select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_INLINE_READ_LOCK select ARCH_INLINE_READ_LOCK_BH @@ -137,7 +145,6 @@ config S390 select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS2 select DCACHE_WORD_ACCESS if !KMSAN - select DMA_OPS if PCI select DYNAMIC_FTRACE if FUNCTION_TRACER select FUNCTION_ALIGNMENT_8B if CC_IS_GCC select FUNCTION_ALIGNMENT_16B if !CC_IS_GCC @@ -224,6 +231,7 @@ config S390 select HAVE_VIRT_CPU_ACCOUNTING_IDLE select IOMMU_HELPER if PCI select IOMMU_SUPPORT if PCI + select LOCK_MM_AND_FIND_VMA select MMU_GATHER_MERGE_VMAS select MMU_GATHER_NO_GATHER select MMU_GATHER_RCU_TABLE_FREE @@ -243,6 +251,7 @@ config S390 select TRACE_IRQFLAGS_SUPPORT select TTY select USER_STACKTRACE_SUPPORT + select VDSO_GETRANDOM select VIRT_CPU_ACCOUNTING select ZONE_DMA # Note: keep the above list sorted alphabetically @@ -275,6 +284,9 @@ config ARCH_SUPPORTS_CRASH_DUMP This option also enables s390 zfcpdump. See also <file:Documentation/arch/s390/zfcpdump.rst> +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + menu "Processor type and features" config HAVE_MARCH_Z10_FEATURES @@ -513,6 +525,26 @@ config SCHED_TOPOLOGY making when dealing with machines that have multi-threading, multiple cores or multiple books. +config SCHED_TOPOLOGY_VERTICAL + def_bool y + bool "Use vertical CPU polarization by default" + depends on SCHED_TOPOLOGY + help + Use vertical CPU polarization by default if available. + The default CPU polarization is horizontal. + +config HIPERDISPATCH_ON + def_bool y + bool "Use hiperdispatch on vertical polarization by default" + depends on SCHED_TOPOLOGY + depends on PROC_SYSCTL + help + Hiperdispatch aims to improve the CPU scheduler's decision + making when using vertical polarization by adjusting CPU + capacities dynamically. Set this option to use hiperdispatch + on vertical polarization by default. This can be overwritten + by sysctl's s390.hiperdispatch attribute later on. + source "kernel/Kconfig.hz" config CERT_STORE @@ -557,17 +589,13 @@ config EXPOLINE If unsure, say N. config EXPOLINE_EXTERN - def_bool y if EXPOLINE - depends on EXPOLINE - depends on CC_IS_GCC && GCC_VERSION >= 110200 - depends on $(success,$(srctree)/arch/s390/tools/gcc-thunk-extern.sh $(CC)) - prompt "Generate expolines as extern functions." + def_bool EXPOLINE && CC_IS_GCC && GCC_VERSION >= 110200 && \ + $(success,$(srctree)/arch/s390/tools/gcc-thunk-extern.sh $(CC)) help - This option is required for some tooling like kpatch. The kernel is - compiled with -mindirect-branch=thunk-extern and requires a newer - compiler. - - If unsure, say N. + Generate expolines as external functions if the compiler supports it. + This option is required for some tooling like kpatch, if expolines + are enabled. The kernel is compiled with + -mindirect-branch=thunk-extern, which requires a newer compiler. choice prompt "Expoline default" diff --git a/arch/s390/Makefile.postlink b/arch/s390/Makefile.postlink new file mode 100644 index 000000000000..df82f5410769 --- /dev/null +++ b/arch/s390/Makefile.postlink @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 +# =========================================================================== +# Post-link s390 pass +# =========================================================================== +# +# 1. Separate relocations from vmlinux into relocs.S. +# 2. Strip relocations from vmlinux. + +PHONY := __archpost +__archpost: + +-include include/config/auto.conf +include $(srctree)/scripts/Kbuild.include + +CMD_RELOCS=arch/s390/tools/relocs +OUT_RELOCS = arch/s390/boot +quiet_cmd_relocs = RELOCS $(OUT_RELOCS)/relocs.S + cmd_relocs = \ + mkdir -p $(OUT_RELOCS); \ + $(CMD_RELOCS) $@ > $(OUT_RELOCS)/relocs.S + +quiet_cmd_strip_relocs = RSTRIP $@ + cmd_strip_relocs = \ + $(OBJCOPY) --remove-section='.rel.*' --remove-section='.rel__*' \ + --remove-section='.rela.*' --remove-section='.rela__*' $@ + +vmlinux: FORCE + $(call cmd,relocs) + $(call cmd,strip_relocs) + +clean: + @rm -f $(OUT_RELOCS)/relocs.S + +PHONY += FORCE clean + +FORCE: + +.PHONY: $(PHONY) diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 4f476884d340..8bc1308ac892 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -11,35 +11,23 @@ KASAN_SANITIZE := n KCSAN_SANITIZE := n KMSAN_SANITIZE := n -KBUILD_AFLAGS := $(KBUILD_AFLAGS_DECOMPRESSOR) -KBUILD_CFLAGS := $(KBUILD_CFLAGS_DECOMPRESSOR) - # -# Use minimum architecture for als.c to be able to print an error +# Use minimum architecture level so it is possible to print an error # message if the kernel is started on a machine which is too old # -ifndef CONFIG_CC_IS_CLANG -CC_FLAGS_MARCH_MINIMUM := -march=z900 -else CC_FLAGS_MARCH_MINIMUM := -march=z10 -endif - -ifneq ($(CC_FLAGS_MARCH),$(CC_FLAGS_MARCH_MINIMUM)) -AFLAGS_REMOVE_head.o += $(CC_FLAGS_MARCH) -AFLAGS_head.o += $(CC_FLAGS_MARCH_MINIMUM) -AFLAGS_REMOVE_mem.o += $(CC_FLAGS_MARCH) -AFLAGS_mem.o += $(CC_FLAGS_MARCH_MINIMUM) -CFLAGS_REMOVE_als.o += $(CC_FLAGS_MARCH) -CFLAGS_als.o += $(CC_FLAGS_MARCH_MINIMUM) -CFLAGS_REMOVE_sclp_early_core.o += $(CC_FLAGS_MARCH) -CFLAGS_sclp_early_core.o += $(CC_FLAGS_MARCH_MINIMUM) -endif + +KBUILD_AFLAGS := $(filter-out $(CC_FLAGS_MARCH),$(KBUILD_AFLAGS_DECOMPRESSOR)) +KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_MARCH),$(KBUILD_CFLAGS_DECOMPRESSOR)) +KBUILD_AFLAGS += $(CC_FLAGS_MARCH_MINIMUM) +KBUILD_CFLAGS += $(CC_FLAGS_MARCH_MINIMUM) CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o -obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o uv.o +obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o +obj-y += uv.o printk.o obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o @@ -109,11 +97,9 @@ OBJCOPYFLAGS_vmlinux.bin := -O binary --remove-section=.comment --remove-section $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -CMD_RELOCS=arch/s390/tools/relocs -quiet_cmd_relocs = RELOCS $@ - cmd_relocs = $(CMD_RELOCS) $< > $@ -$(obj)/relocs.S: vmlinux FORCE - $(call if_changed,relocs) +# relocs.S is created by the vmlinux postlink step. +$(obj)/relocs.S: vmlinux + @true suffix-$(CONFIG_KERNEL_GZIP) := .gz suffix-$(CONFIG_KERNEL_BZIP2) := .bz2 diff --git a/arch/s390/boot/als.c b/arch/s390/boot/als.c index 47c48fbfb563..11e0c3d5dbc8 100644 --- a/arch/s390/boot/als.c +++ b/arch/s390/boot/als.c @@ -9,42 +9,8 @@ #include <asm/sclp.h> #include "boot.h" -/* - * The code within this file will be called very early. It may _not_ - * access anything within the bss section, since that is not cleared - * yet and may contain data (e.g. initrd) that must be saved by other - * code. - * For temporary objects the stack (16k) should be used. - */ - static unsigned long als[] = { FACILITIES_ALS }; -static void u16_to_hex(char *str, u16 val) -{ - int i, num; - - for (i = 1; i <= 4; i++) { - num = (val >> (16 - 4 * i)) & 0xf; - if (num >= 10) - num += 7; - *str++ = '0' + num; - } - *str = '\0'; -} - -static void print_machine_type(void) -{ - static char mach_str[80] = "Detected machine-type number: "; - char type_str[5]; - struct cpuid id; - - get_cpu_id(&id); - u16_to_hex(type_str, id.machine); - strcat(mach_str, type_str); - strcat(mach_str, "\n"); - sclp_early_printk(mach_str); -} - static void u16_to_decimal(char *str, u16 val) { int div = 1; @@ -80,8 +46,7 @@ void print_missing_facilities(void) * z/VM adds a four character prefix. */ if (strlen(als_str) > 70) { - strcat(als_str, "\n"); - sclp_early_printk(als_str); + boot_printk("%s\n", als_str); *als_str = '\0'; } u16_to_decimal(val_str, i * BITS_PER_LONG + j); @@ -89,16 +54,18 @@ void print_missing_facilities(void) first = 0; } } - strcat(als_str, "\n"); - sclp_early_printk(als_str); + boot_printk("%s\n", als_str); } static void facility_mismatch(void) { - sclp_early_printk("The Linux kernel requires more recent processor hardware\n"); - print_machine_type(); + struct cpuid id; + + get_cpu_id(&id); + boot_printk("The Linux kernel requires more recent processor hardware\n"); + boot_printk("Detected machine-type number: %4x\n", id.machine); print_missing_facilities(); - sclp_early_printk("See Principles of Operations for facility bits\n"); + boot_printk("See Principles of Operations for facility bits\n"); disabled_wait(); } diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index 83e2ce050b6c..7521a9d75fa2 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -70,7 +70,7 @@ void print_pgm_check_info(void); unsigned long randomize_within_range(unsigned long size, unsigned long align, unsigned long min, unsigned long max); void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit); -void __printf(1, 2) decompressor_printk(const char *fmt, ...); +void __printf(1, 2) boot_printk(const char *fmt, ...); void print_stacktrace(unsigned long sp); void error(char *m); int get_random(unsigned long limit, unsigned long *value); diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 637c29c3f6e3..0a47b16f6412 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -299,11 +299,11 @@ SYM_CODE_END(startup_normal) # the save area and does disabled wait with a faulty address. # SYM_CODE_START_LOCAL(startup_pgm_check_handler) - stmg %r8,%r15,__LC_SAVE_AREA_SYNC + stmg %r8,%r15,__LC_SAVE_AREA la %r8,4095 stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8) stmg %r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8) - mvc __LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC + mvc __LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA mvc __LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW mvc __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW ni __LC_RETURN_PSW,0xfc # remove IO and EX bits diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 1773b72a6a7b..557462e62cd7 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -215,7 +215,7 @@ static void check_cleared_facilities(void) for (i = 0; i < ARRAY_SIZE(als); i++) { if ((stfle_fac_list[i] & als[i]) != als[i]) { - sclp_early_printk("Warning: The Linux kernel requires facilities cleared via command line option\n"); + boot_printk("Warning: The Linux kernel requires facilities cleared via command line option\n"); print_missing_facilities(); break; } diff --git a/arch/s390/boot/kaslr.c b/arch/s390/boot/kaslr.c index bd3bf5ef472d..f864d2bff775 100644 --- a/arch/s390/boot/kaslr.c +++ b/arch/s390/boot/kaslr.c @@ -32,7 +32,7 @@ struct prng_parm { static int check_prng(void) { if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) { - sclp_early_printk("KASLR disabled: CPU has no PRNG\n"); + boot_printk("KASLR disabled: CPU has no PRNG\n"); return 0; } if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG)) diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c index 5352b3d356da..5abe59fb3bc0 100644 --- a/arch/s390/boot/pgm_check_info.c +++ b/arch/s390/boot/pgm_check_info.c @@ -11,131 +11,19 @@ #include <asm/uv.h> #include "boot.h" -const char hex_asc[] = "0123456789abcdef"; - -static char *as_hex(char *dst, unsigned long val, int pad) -{ - char *p, *end = p = dst + max(pad, (int)__fls(val | 1) / 4 + 1); - - for (*p-- = 0; p >= dst; val >>= 4) - *p-- = hex_asc[val & 0x0f]; - return end; -} - -static char *symstart(char *p) -{ - while (*p) - p--; - return p + 1; -} - -static noinline char *findsym(unsigned long ip, unsigned short *off, unsigned short *len) -{ - /* symbol entries are in a form "10000 c4 startup\0" */ - char *a = _decompressor_syms_start; - char *b = _decompressor_syms_end; - unsigned long start; - unsigned long size; - char *pivot; - char *endp; - - while (a < b) { - pivot = symstart(a + (b - a) / 2); - start = simple_strtoull(pivot, &endp, 16); - size = simple_strtoull(endp + 1, &endp, 16); - if (ip < start) { - b = pivot; - continue; - } - if (ip > start + size) { - a = pivot + strlen(pivot) + 1; - continue; - } - *off = ip - start; - *len = size; - return endp + 1; - } - return NULL; -} - -static noinline char *strsym(void *ip) -{ - static char buf[64]; - unsigned short off; - unsigned short len; - char *p; - - p = findsym((unsigned long)ip, &off, &len); - if (p) { - strncpy(buf, p, sizeof(buf)); - /* reserve 15 bytes for offset/len in symbol+0x1234/0x1234 */ - p = buf + strnlen(buf, sizeof(buf) - 15); - strcpy(p, "+0x"); - p = as_hex(p + 3, off, 0); - strcpy(p, "/0x"); - as_hex(p + 3, len, 0); - } else { - as_hex(buf, (unsigned long)ip, 16); - } - return buf; -} - -void decompressor_printk(const char *fmt, ...) -{ - char buf[1024] = { 0 }; - char *end = buf + sizeof(buf) - 1; /* make sure buf is 0 terminated */ - unsigned long pad; - char *p = buf; - va_list args; - - va_start(args, fmt); - for (; p < end && *fmt; fmt++) { - if (*fmt != '%') { - *p++ = *fmt; - continue; - } - pad = isdigit(*++fmt) ? simple_strtol(fmt, (char **)&fmt, 10) : 0; - switch (*fmt) { - case 's': - p = buf + strlcat(buf, va_arg(args, char *), sizeof(buf)); - break; - case 'p': - if (*++fmt != 'S') - goto out; - p = buf + strlcat(buf, strsym(va_arg(args, void *)), sizeof(buf)); - break; - case 'l': - if (*++fmt != 'x' || end - p <= max(sizeof(long) * 2, pad)) - goto out; - p = as_hex(p, va_arg(args, unsigned long), pad); - break; - case 'x': - if (end - p <= max(sizeof(int) * 2, pad)) - goto out; - p = as_hex(p, va_arg(args, unsigned int), pad); - break; - default: - goto out; - } - } -out: - va_end(args); - sclp_early_printk(buf); -} - void print_stacktrace(unsigned long sp) { struct stack_info boot_stack = { STACK_TYPE_TASK, (unsigned long)_stack_start, (unsigned long)_stack_end }; bool first = true; - decompressor_printk("Call Trace:\n"); + boot_printk("Call Trace:\n"); while (!(sp & 0x7) && on_stack(&boot_stack, sp, sizeof(struct stack_frame))) { struct stack_frame *sf = (struct stack_frame *)sp; - decompressor_printk(first ? "(sp:%016lx [<%016lx>] %pS)\n" : - " sp:%016lx [<%016lx>] %pS\n", - sp, sf->gprs[8], (void *)sf->gprs[8]); + boot_printk(first ? "(sp:%016lx [<%016lx>] %pS)\n" : + " sp:%016lx [<%016lx>] %pS\n", + sp, sf->gprs[8], (void *)sf->gprs[8]); if (sf->back_chain <= sp) break; sp = sf->back_chain; @@ -148,34 +36,30 @@ void print_pgm_check_info(void) unsigned long *gpregs = (unsigned long *)get_lowcore()->gpregs_save_area; struct psw_bits *psw = &psw_bits(get_lowcore()->psw_save_area); - decompressor_printk("Linux version %s\n", kernel_version); + boot_printk("Linux version %s\n", kernel_version); if (!is_prot_virt_guest() && early_command_line[0]) - decompressor_printk("Kernel command line: %s\n", early_command_line); - decompressor_printk("Kernel fault: interruption code %04x ilc:%x\n", - get_lowcore()->pgm_code, get_lowcore()->pgm_ilc >> 1); + boot_printk("Kernel command line: %s\n", early_command_line); + boot_printk("Kernel fault: interruption code %04x ilc:%x\n", + get_lowcore()->pgm_code, get_lowcore()->pgm_ilc >> 1); if (kaslr_enabled()) { - decompressor_printk("Kernel random base: %lx\n", __kaslr_offset); - decompressor_printk("Kernel random base phys: %lx\n", __kaslr_offset_phys); + boot_printk("Kernel random base: %lx\n", __kaslr_offset); + boot_printk("Kernel random base phys: %lx\n", __kaslr_offset_phys); } - decompressor_printk("PSW : %016lx %016lx (%pS)\n", - get_lowcore()->psw_save_area.mask, - get_lowcore()->psw_save_area.addr, - (void *)get_lowcore()->psw_save_area.addr); - decompressor_printk( + boot_printk("PSW : %016lx %016lx (%pS)\n", + get_lowcore()->psw_save_area.mask, + get_lowcore()->psw_save_area.addr, + (void *)get_lowcore()->psw_save_area.addr); + boot_printk( " R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, psw->eaba); - decompressor_printk("GPRS: %016lx %016lx %016lx %016lx\n", - gpregs[0], gpregs[1], gpregs[2], gpregs[3]); - decompressor_printk(" %016lx %016lx %016lx %016lx\n", - gpregs[4], gpregs[5], gpregs[6], gpregs[7]); - decompressor_printk(" %016lx %016lx %016lx %016lx\n", - gpregs[8], gpregs[9], gpregs[10], gpregs[11]); - decompressor_printk(" %016lx %016lx %016lx %016lx\n", - gpregs[12], gpregs[13], gpregs[14], gpregs[15]); + boot_printk("GPRS: %016lx %016lx %016lx %016lx\n", gpregs[0], gpregs[1], gpregs[2], gpregs[3]); + boot_printk(" %016lx %016lx %016lx %016lx\n", gpregs[4], gpregs[5], gpregs[6], gpregs[7]); + boot_printk(" %016lx %016lx %016lx %016lx\n", gpregs[8], gpregs[9], gpregs[10], gpregs[11]); + boot_printk(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]); print_stacktrace(get_lowcore()->gpregs_save_area[15]); - decompressor_printk("Last Breaking-Event-Address:\n"); - decompressor_printk(" [<%016lx>] %pS\n", (unsigned long)get_lowcore()->pgm_last_break, - (void *)get_lowcore()->pgm_last_break); + boot_printk("Last Breaking-Event-Address:\n"); + boot_printk(" [<%016lx>] %pS\n", (unsigned long)get_lowcore()->pgm_last_break, + (void *)get_lowcore()->pgm_last_break); } diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index 4c9ad8258f7e..7617aa2d2f7e 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -9,6 +9,7 @@ #include <asm/sections.h> #include <asm/setup.h> #include <asm/sclp.h> +#include <asm/asm.h> #include <asm/uv.h> #include "decompressor.h" #include "boot.h" @@ -59,13 +60,13 @@ static int __diag260(unsigned long rx1, unsigned long rx2) { unsigned long reg1, reg2, ry; union register_pair rx; + int cc, exception; psw_t old; - int rc; rx.even = rx1; rx.odd = rx2; ry = 0x10; /* storage configuration */ - rc = -1; /* fail */ + exception = 1; asm volatile( " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" " epsw %[reg1],%[reg2]\n" @@ -74,20 +75,22 @@ static int __diag260(unsigned long rx1, unsigned long rx2) " larl %[reg1],1f\n" " stg %[reg1],8(%[psw_pgm])\n" " diag %[rx],%[ry],0x260\n" - " ipm %[rc]\n" - " srl %[rc],28\n" + " lhi %[exc],0\n" "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - : [reg1] "=&d" (reg1), + CC_IPM(cc) + : CC_OUT(cc, cc), + [exc] "+d" (exception), + [reg1] "=&d" (reg1), [reg2] "=&a" (reg2), - [rc] "+&d" (rc), [ry] "+&d" (ry), "+Q" (get_lowcore()->program_new_psw), "=Q" (old) : [rx] "d" (rx.pair), [psw_old] "a" (&old), [psw_pgm] "a" (&get_lowcore()->program_new_psw) - : "cc", "memory"); - return rc == 0 ? ry : -1; + : CC_CLOBBER_LIST("memory")); + cc = exception ? -1 : CC_TRANSFORM(cc); + return cc == 0 ? ry : -1; } static int diag260(void) @@ -109,12 +112,49 @@ static int diag260(void) return 0; } +#define DIAG500_SC_STOR_LIMIT 4 + +static int diag500_storage_limit(unsigned long *max_physmem_end) +{ + unsigned long storage_limit; + unsigned long reg1, reg2; + psw_t old; + + asm volatile( + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" + " epsw %[reg1],%[reg2]\n" + " st %[reg1],0(%[psw_pgm])\n" + " st %[reg2],4(%[psw_pgm])\n" + " larl %[reg1],1f\n" + " stg %[reg1],8(%[psw_pgm])\n" + " lghi 1,%[subcode]\n" + " lghi 2,0\n" + " diag 2,4,0x500\n" + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" + " lgr %[slimit],2\n" + : [reg1] "=&d" (reg1), + [reg2] "=&a" (reg2), + [slimit] "=d" (storage_limit), + "=Q" (get_lowcore()->program_new_psw), + "=Q" (old) + : [psw_old] "a" (&old), + [psw_pgm] "a" (&get_lowcore()->program_new_psw), + [subcode] "i" (DIAG500_SC_STOR_LIMIT) + : "memory", "1", "2"); + if (!storage_limit) + return -EINVAL; + /* Convert inclusive end to exclusive end */ + *max_physmem_end = storage_limit + 1; + return 0; +} + static int tprot(unsigned long addr) { unsigned long reg1, reg2; - int rc = -EFAULT; + int cc, exception; psw_t old; + exception = 1; asm volatile( " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" " epsw %[reg1],%[reg2]\n" @@ -123,19 +163,21 @@ static int tprot(unsigned long addr) " larl %[reg1],1f\n" " stg %[reg1],8(%[psw_pgm])\n" " tprot 0(%[addr]),0\n" - " ipm %[rc]\n" - " srl %[rc],28\n" + " lhi %[exc],0\n" "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" - : [reg1] "=&d" (reg1), + CC_IPM(cc) + : CC_OUT(cc, cc), + [exc] "+d" (exception), + [reg1] "=&d" (reg1), [reg2] "=&a" (reg2), - [rc] "+&d" (rc), "=Q" (get_lowcore()->program_new_psw.addr), "=Q" (old) : [psw_old] "a" (&old), [psw_pgm] "a" (&get_lowcore()->program_new_psw), [addr] "a" (addr) - : "cc", "memory"); - return rc; + : CC_CLOBBER_LIST("memory")); + cc = exception ? -EFAULT : CC_TRANSFORM(cc); + return cc; } static unsigned long search_mem_end(void) @@ -157,7 +199,9 @@ unsigned long detect_max_physmem_end(void) { unsigned long max_physmem_end = 0; - if (!sclp_early_get_memsize(&max_physmem_end)) { + if (!diag500_storage_limit(&max_physmem_end)) { + physmem_info.info_source = MEM_DETECT_DIAG500_STOR_LIMIT; + } else if (!sclp_early_get_memsize(&max_physmem_end)) { physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO; } else { max_physmem_end = search_mem_end(); @@ -170,6 +214,13 @@ void detect_physmem_online_ranges(unsigned long max_physmem_end) { if (!sclp_early_read_storage_info()) { physmem_info.info_source = MEM_DETECT_SCLP_STOR_INFO; + } else if (physmem_info.info_source == MEM_DETECT_DIAG500_STOR_LIMIT) { + unsigned long online_end; + + if (!sclp_early_get_memsize(&online_end)) { + physmem_info.info_source = MEM_DETECT_SCLP_READ_INFO; + add_physmem_online_range(0, online_end); + } } else if (!diag260()) { physmem_info.info_source = MEM_DETECT_DIAG260; } else if (max_physmem_end) { @@ -190,27 +241,27 @@ static void die_oom(unsigned long size, unsigned long align, unsigned long min, enum reserved_range_type t; int i; - decompressor_printk("Linux version %s\n", kernel_version); + boot_printk("Linux version %s\n", kernel_version); if (!is_prot_virt_guest() && early_command_line[0]) - decompressor_printk("Kernel command line: %s\n", early_command_line); - decompressor_printk("Out of memory allocating %lx bytes %lx aligned in range %lx:%lx\n", - size, align, min, max); - decompressor_printk("Reserved memory ranges:\n"); + boot_printk("Kernel command line: %s\n", early_command_line); + boot_printk("Out of memory allocating %lx bytes %lx aligned in range %lx:%lx\n", + size, align, min, max); + boot_printk("Reserved memory ranges:\n"); for_each_physmem_reserved_range(t, range, &start, &end) { - decompressor_printk("%016lx %016lx %s\n", start, end, get_rr_type_name(t)); + boot_printk("%016lx %016lx %s\n", start, end, get_rr_type_name(t)); total_reserved_mem += end - start; } - decompressor_printk("Usable online memory ranges (info source: %s [%x]):\n", - get_physmem_info_source(), physmem_info.info_source); + boot_printk("Usable online memory ranges (info source: %s [%x]):\n", + get_physmem_info_source(), physmem_info.info_source); for_each_physmem_usable_range(i, &start, &end) { - decompressor_printk("%016lx %016lx\n", start, end); + boot_printk("%016lx %016lx\n", start, end); total_mem += end - start; } - decompressor_printk("Usable online memory total: %lx Reserved: %lx Free: %lx\n", - total_mem, total_reserved_mem, - total_mem > total_reserved_mem ? total_mem - total_reserved_mem : 0); + boot_printk("Usable online memory total: %lx Reserved: %lx Free: %lx\n", + total_mem, total_reserved_mem, + total_mem > total_reserved_mem ? total_mem - total_reserved_mem : 0); print_stacktrace(current_frame_address()); - sclp_early_printk("\n\n -- System halted\n"); + boot_printk("\n\n -- System halted\n"); disabled_wait(); } diff --git a/arch/s390/boot/printk.c b/arch/s390/boot/printk.c new file mode 100644 index 000000000000..35f18f2b936e --- /dev/null +++ b/arch/s390/boot/printk.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kernel.h> +#include <linux/stdarg.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <asm/stacktrace.h> +#include <asm/boot_data.h> +#include <asm/lowcore.h> +#include <asm/setup.h> +#include <asm/sclp.h> +#include <asm/uv.h> +#include "boot.h" + +const char hex_asc[] = "0123456789abcdef"; + +static char *as_hex(char *dst, unsigned long val, int pad) +{ + char *p, *end = p = dst + max(pad, (int)__fls(val | 1) / 4 + 1); + + for (*p-- = 0; p >= dst; val >>= 4) + *p-- = hex_asc[val & 0x0f]; + return end; +} + +static char *symstart(char *p) +{ + while (*p) + p--; + return p + 1; +} + +static noinline char *findsym(unsigned long ip, unsigned short *off, unsigned short *len) +{ + /* symbol entries are in a form "10000 c4 startup\0" */ + char *a = _decompressor_syms_start; + char *b = _decompressor_syms_end; + unsigned long start; + unsigned long size; + char *pivot; + char *endp; + + while (a < b) { + pivot = symstart(a + (b - a) / 2); + start = simple_strtoull(pivot, &endp, 16); + size = simple_strtoull(endp + 1, &endp, 16); + if (ip < start) { + b = pivot; + continue; + } + if (ip > start + size) { + a = pivot + strlen(pivot) + 1; + continue; + } + *off = ip - start; + *len = size; + return endp + 1; + } + return NULL; +} + +static noinline char *strsym(void *ip) +{ + static char buf[64]; + unsigned short off; + unsigned short len; + char *p; + + p = findsym((unsigned long)ip, &off, &len); + if (p) { + strncpy(buf, p, sizeof(buf)); + /* reserve 15 bytes for offset/len in symbol+0x1234/0x1234 */ + p = buf + strnlen(buf, sizeof(buf) - 15); + strcpy(p, "+0x"); + p = as_hex(p + 3, off, 0); + strcpy(p, "/0x"); + as_hex(p + 3, len, 0); + } else { + as_hex(buf, (unsigned long)ip, 16); + } + return buf; +} + +void boot_printk(const char *fmt, ...) +{ + char buf[1024] = { 0 }; + char *end = buf + sizeof(buf) - 1; /* make sure buf is 0 terminated */ + unsigned long pad; + char *p = buf; + va_list args; + + va_start(args, fmt); + for (; p < end && *fmt; fmt++) { + if (*fmt != '%') { + *p++ = *fmt; + continue; + } + pad = isdigit(*++fmt) ? simple_strtol(fmt, (char **)&fmt, 10) : 0; + switch (*fmt) { + case 's': + p = buf + strlcat(buf, va_arg(args, char *), sizeof(buf)); + break; + case 'p': + if (*++fmt != 'S') + goto out; + p = buf + strlcat(buf, strsym(va_arg(args, void *)), sizeof(buf)); + break; + case 'l': + if (*++fmt != 'x' || end - p <= max(sizeof(long) * 2, pad)) + goto out; + p = as_hex(p, va_arg(args, unsigned long), pad); + break; + case 'x': + if (end - p <= max(sizeof(int) * 2, pad)) + goto out; + p = as_hex(p, va_arg(args, unsigned int), pad); + break; + default: + goto out; + } + } +out: + va_end(args); + sclp_early_printk(buf); +} diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index c73b5118ad42..abe6e6c0ab98 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -39,10 +39,7 @@ struct machine_info machine; void error(char *x) { - sclp_early_printk("\n\n"); - sclp_early_printk(x); - sclp_early_printk("\n\n -- System halted"); - + boot_printk("\n\n%s\n\n -- System halted", x); disabled_wait(); } @@ -185,12 +182,15 @@ static void kaslr_adjust_got(unsigned long offset) * Merge information from several sources into a single ident_map_size value. * "ident_map_size" represents the upper limit of physical memory we may ever * reach. It might not be all online memory, but also include standby (offline) - * memory. "ident_map_size" could be lower then actual standby or even online + * memory or memory areas reserved for other means (e.g., memory devices such as + * virtio-mem). + * + * "ident_map_size" could be lower then actual standby/reserved or even online * memory present, due to limiting factors. We should never go above this limit. * It is the size of our identity mapping. * * Consider the following factors: - * 1. max_physmem_end - end of physical memory online or standby. + * 1. max_physmem_end - end of physical memory online, standby or reserved. * Always >= end of the last online memory range (get_physmem_online_end()). * 2. CONFIG_MAX_PHYSMEM_BITS - the maximum size of physical memory the * kernel is able to support. @@ -296,7 +296,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size) kernel_start = round_down(kernel_end - kernel_size, THREAD_SIZE); } else if (vmax < __NO_KASLR_END_KERNEL || vsize > __NO_KASLR_END_KERNEL) { kernel_start = round_down(vmax - kernel_size, THREAD_SIZE); - decompressor_printk("The kernel base address is forced to %lx\n", kernel_start); + boot_printk("The kernel base address is forced to %lx\n", kernel_start); } else { kernel_start = __NO_KASLR_START_KERNEL; } @@ -483,7 +483,7 @@ void startup_kernel(void) * __vmlinux_relocs_64_end as the lower range address. However, * .amode31 section is written to by the decompressed kernel - at * that time the contents of .vmlinux.relocs is not needed anymore. - * Conversly, .vmlinux.relocs is read only by the decompressor, even + * Conversely, .vmlinux.relocs is read only by the decompressor, even * before the kernel started. Therefore, in case the two sections * overlap there is no risk of corrupting any data. */ diff --git a/arch/s390/boot/uv.c b/arch/s390/boot/uv.c index 318e6ba95bfd..4568e8f81dac 100644 --- a/arch/s390/boot/uv.c +++ b/arch/s390/boot/uv.c @@ -22,8 +22,8 @@ void uv_query_info(void) if (!test_facility(158)) return; - /* rc==0x100 means that there is additional data we do not process */ - if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != 0x100) + /* Ignore that there might be more data we do not process */ + if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != UVC_RC_MORE_DATA) return; if (IS_ENABLED(CONFIG_KVM)) { @@ -46,7 +46,8 @@ void uv_query_info(void) uv_info.supp_add_secret_req_ver = uvcb.supp_add_secret_req_ver; uv_info.supp_add_secret_pcf = uvcb.supp_add_secret_pcf; uv_info.supp_secret_types = uvcb.supp_secret_types; - uv_info.max_secrets = uvcb.max_secrets; + uv_info.max_assoc_secrets = uvcb.max_assoc_secrets; + uv_info.max_retr_secrets = uvcb.max_retr_secrets; } if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index ea63a7342f5f..d8d227ab82de 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -50,7 +50,6 @@ CONFIG_NUMA=y CONFIG_HZ_100=y CONFIG_CERT_STORE=y CONFIG_EXPOLINE=y -# CONFIG_EXPOLINE_EXTERN is not set CONFIG_EXPOLINE_AUTO=y CONFIG_CHSC_SCH=y CONFIG_VFIO_CCW=m @@ -59,6 +58,7 @@ CONFIG_CMM=m CONFIG_APPLDATA_BASE=y CONFIG_S390_HYPFS_FS=y CONFIG_KVM=m +CONFIG_KVM_S390_UCONTROL=y CONFIG_S390_UNWIND_SELFTEST=m CONFIG_S390_KPROBES_SANITY_TEST=m CONFIG_S390_MODULES_SANITY_TEST=m @@ -94,6 +94,7 @@ CONFIG_BINFMT_MISC=m CONFIG_ZSWAP=y CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y CONFIG_ZSMALLOC_STAT=y +CONFIG_SLAB_BUCKETS=y CONFIG_SLUB_STATS=y # CONFIG_COMPAT_BRK is not set CONFIG_MEMORY_HOTPLUG=y @@ -425,6 +426,13 @@ CONFIG_DEVTMPFS_SAFE=y # CONFIG_FW_LOADER is not set CONFIG_CONNECTOR=y CONFIG_ZRAM=y +CONFIG_ZRAM_BACKEND_LZ4=y +CONFIG_ZRAM_BACKEND_LZ4HC=y +CONFIG_ZRAM_BACKEND_ZSTD=y +CONFIG_ZRAM_BACKEND_DEFLATE=y +CONFIG_ZRAM_BACKEND_842=y +CONFIG_ZRAM_BACKEND_LZO=y +CONFIG_ZRAM_DEF_COMP_DEFLATE=y CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_NBD=m @@ -485,6 +493,7 @@ CONFIG_DM_UEVENT=y CONFIG_DM_FLAKEY=m CONFIG_DM_VERITY=m CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y +CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING=y CONFIG_DM_SWITCH=m CONFIG_DM_INTEGRITY=m CONFIG_DM_VDO=m @@ -534,6 +543,7 @@ CONFIG_NLMON=m CONFIG_MLX4_EN=m CONFIG_MLX5_CORE=m CONFIG_MLX5_CORE_EN=y +# CONFIG_NET_VENDOR_META is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROSEMI is not set @@ -615,6 +625,7 @@ CONFIG_VFIO_PCI=m CONFIG_MLX5_VFIO_PCI=m CONFIG_VIRTIO_PCI=m CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MEM=m CONFIG_VIRTIO_INPUT=y CONFIG_VHOST_NET=m CONFIG_VHOST_VSOCK=m @@ -694,6 +705,7 @@ CONFIG_NFSD=m CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_V4_SECURITY_LABEL=y +# CONFIG_NFSD_LEGACY_CLIENT_TRACKING is not set CONFIG_CIFS=m CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y @@ -739,7 +751,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m @@ -794,8 +805,13 @@ CONFIG_CRYPTO_GHASH_S390=m CONFIG_CRYPTO_AES_S390=m CONFIG_CRYPTO_DES_S390=m CONFIG_CRYPTO_CHACHA_S390=m +CONFIG_CRYPTO_HMAC_S390=m CONFIG_ZCRYPT=m CONFIG_PKEY=m +CONFIG_PKEY_CCA=m +CONFIG_PKEY_EP11=m +CONFIG_PKEY_PCKMO=m +CONFIG_PKEY_UV=m CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_SYSTEM_BLACKLIST_KEYRING=y diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index d8b28ff8ff45..6c2f2bb4fbf8 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -48,7 +48,6 @@ CONFIG_NUMA=y CONFIG_HZ_100=y CONFIG_CERT_STORE=y CONFIG_EXPOLINE=y -# CONFIG_EXPOLINE_EXTERN is not set CONFIG_EXPOLINE_AUTO=y CONFIG_CHSC_SCH=y CONFIG_VFIO_CCW=m @@ -89,6 +88,7 @@ CONFIG_BINFMT_MISC=m CONFIG_ZSWAP=y CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y CONFIG_ZSMALLOC_STAT=y +CONFIG_SLAB_BUCKETS=y # CONFIG_COMPAT_BRK is not set CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTREMOVE=y @@ -416,6 +416,13 @@ CONFIG_DEVTMPFS_SAFE=y # CONFIG_FW_LOADER is not set CONFIG_CONNECTOR=y CONFIG_ZRAM=y +CONFIG_ZRAM_BACKEND_LZ4=y +CONFIG_ZRAM_BACKEND_LZ4HC=y +CONFIG_ZRAM_BACKEND_ZSTD=y +CONFIG_ZRAM_BACKEND_DEFLATE=y +CONFIG_ZRAM_BACKEND_842=y +CONFIG_ZRAM_BACKEND_LZO=y +CONFIG_ZRAM_DEF_COMP_DEFLATE=y CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_NBD=m @@ -476,6 +483,7 @@ CONFIG_DM_UEVENT=y CONFIG_DM_FLAKEY=m CONFIG_DM_VERITY=m CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y +CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING=y CONFIG_DM_SWITCH=m CONFIG_DM_INTEGRITY=m CONFIG_DM_VDO=m @@ -525,6 +533,7 @@ CONFIG_NLMON=m CONFIG_MLX4_EN=m CONFIG_MLX5_CORE=m CONFIG_MLX5_CORE_EN=y +# CONFIG_NET_VENDOR_META is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROSEMI is not set @@ -606,6 +615,7 @@ CONFIG_VFIO_PCI=m CONFIG_MLX5_VFIO_PCI=m CONFIG_VIRTIO_PCI=m CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MEM=m CONFIG_VIRTIO_INPUT=y CONFIG_VHOST_NET=m CONFIG_VHOST_VSOCK=m @@ -682,6 +692,7 @@ CONFIG_NFSD=m CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_V4_SECURITY_LABEL=y +# CONFIG_NFSD_LEGACY_CLIENT_TRACKING is not set CONFIG_CIFS=m CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y @@ -726,7 +737,6 @@ CONFIG_CRYPTO_DH=m CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_ECDSA=m CONFIG_CRYPTO_ECRDSA=m -CONFIG_CRYPTO_SM2=m CONFIG_CRYPTO_CURVE25519=m CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_ANUBIS=m @@ -767,6 +777,7 @@ CONFIG_CRYPTO_LZ4=m CONFIG_CRYPTO_LZ4HC=m CONFIG_CRYPTO_ZSTD=m CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m CONFIG_CRYPTO_USER_API_RNG=m @@ -781,8 +792,13 @@ CONFIG_CRYPTO_GHASH_S390=m CONFIG_CRYPTO_AES_S390=m CONFIG_CRYPTO_DES_S390=m CONFIG_CRYPTO_CHACHA_S390=m +CONFIG_CRYPTO_HMAC_S390=m CONFIG_ZCRYPT=m CONFIG_PKEY=m +CONFIG_PKEY_CCA=m +CONFIG_PKEY_EP11=m +CONFIG_PKEY_PCKMO=m +CONFIG_PKEY_UV=m CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_SYSTEM_BLACKLIST_KEYRING=y diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index 8c2b61363bab..bcbaa069de96 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -49,6 +49,7 @@ CONFIG_ZFCP=y # CONFIG_HVC_IUCV is not set # CONFIG_HW_RANDOM_S390 is not set # CONFIG_HMC_DRV is not set +# CONFIG_S390_UV_UAPI is not set # CONFIG_S390_TAPE is not set # CONFIG_VMCP is not set # CONFIG_MONWRITER is not set diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig index 06ee706b0d78..d3eb3a233693 100644 --- a/arch/s390/crypto/Kconfig +++ b/arch/s390/crypto/Kconfig @@ -132,4 +132,14 @@ config CRYPTO_CHACHA_S390 It is available as of z13. +config CRYPTO_HMAC_S390 + tristate "Keyed-hash message authentication code: HMAC" + depends on S390 + select CRYPTO_HASH + help + s390 specific HMAC hardware support for SHA224, SHA256, SHA384 and + SHA512. + + Architecture: s390 + endmenu diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 1b1cc478fa94..a0cb96937c3d 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_CHACHA_S390) += chacha_s390.o obj-$(CONFIG_S390_PRNG) += prng.o obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o +obj-$(CONFIG_CRYPTO_HMAC_S390) += hmac_s390.o obj-y += arch_random.o crc32-vx_s390-y := crc32-vx.o crc32le-vx.o crc32be-vx.o diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index c6fe5405de4a..8cc02d6e0d0f 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -51,8 +51,13 @@ struct s390_aes_ctx { }; struct s390_xts_ctx { - u8 key[32]; - u8 pcc_key[32]; + union { + u8 keys[64]; + struct { + u8 key[32]; + u8 pcc_key[32]; + }; + }; int key_len; unsigned long fc; struct crypto_skcipher *fallback; @@ -526,6 +531,108 @@ static struct skcipher_alg xts_aes_alg = { .decrypt = xts_aes_decrypt, }; +static int fullxts_aes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct s390_xts_ctx *xts_ctx = crypto_skcipher_ctx(tfm); + unsigned long fc; + int err; + + err = xts_fallback_setkey(tfm, in_key, key_len); + if (err) + return err; + + /* Pick the correct function code based on the key length */ + fc = (key_len == 32) ? CPACF_KM_XTS_128_FULL : + (key_len == 64) ? CPACF_KM_XTS_256_FULL : 0; + + /* Check if the function code is available */ + xts_ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; + if (!xts_ctx->fc) + return 0; + + /* Store double-key */ + memcpy(xts_ctx->keys, in_key, key_len); + xts_ctx->key_len = key_len; + return 0; +} + +static int fullxts_aes_crypt(struct skcipher_request *req, unsigned long modifier) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct s390_xts_ctx *xts_ctx = crypto_skcipher_ctx(tfm); + unsigned int offset, nbytes, n; + struct skcipher_walk walk; + int ret; + struct { + __u8 key[64]; + __u8 tweak[16]; + __u8 nap[16]; + } fxts_param = { + .nap = {0}, + }; + + if (req->cryptlen < AES_BLOCK_SIZE) + return -EINVAL; + + if (unlikely(!xts_ctx->fc || (req->cryptlen % AES_BLOCK_SIZE) != 0)) { + struct skcipher_request *subreq = skcipher_request_ctx(req); + + *subreq = *req; + skcipher_request_set_tfm(subreq, xts_ctx->fallback); + return (modifier & CPACF_DECRYPT) ? + crypto_skcipher_decrypt(subreq) : + crypto_skcipher_encrypt(subreq); + } + + ret = skcipher_walk_virt(&walk, req, false); + if (ret) + return ret; + + offset = xts_ctx->key_len & 0x20; + memcpy(fxts_param.key + offset, xts_ctx->keys, xts_ctx->key_len); + memcpy(fxts_param.tweak, req->iv, AES_BLOCK_SIZE); + fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */ + + while ((nbytes = walk.nbytes) != 0) { + /* only use complete blocks */ + n = nbytes & ~(AES_BLOCK_SIZE - 1); + cpacf_km(xts_ctx->fc | modifier, fxts_param.key + offset, + walk.dst.virt.addr, walk.src.virt.addr, n); + ret = skcipher_walk_done(&walk, nbytes - n); + } + memzero_explicit(&fxts_param, sizeof(fxts_param)); + return ret; +} + +static int fullxts_aes_encrypt(struct skcipher_request *req) +{ + return fullxts_aes_crypt(req, 0); +} + +static int fullxts_aes_decrypt(struct skcipher_request *req) +{ + return fullxts_aes_crypt(req, CPACF_DECRYPT); +} + +static struct skcipher_alg fullxts_aes_alg = { + .base.cra_name = "xts(aes)", + .base.cra_driver_name = "full-xts-aes-s390", + .base.cra_priority = 403, /* aes-xts-s390 + 1 */ + .base.cra_flags = CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct s390_xts_ctx), + .base.cra_module = THIS_MODULE, + .init = xts_fallback_init, + .exit = xts_fallback_exit, + .min_keysize = 2 * AES_MIN_KEY_SIZE, + .max_keysize = 2 * AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = fullxts_aes_set_key, + .encrypt = fullxts_aes_encrypt, + .decrypt = fullxts_aes_decrypt, +}; + static int ctr_aes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { @@ -955,7 +1062,7 @@ static struct aead_alg gcm_aes_aead = { }; static struct crypto_alg *aes_s390_alg; -static struct skcipher_alg *aes_s390_skcipher_algs[4]; +static struct skcipher_alg *aes_s390_skcipher_algs[5]; static int aes_s390_skciphers_num; static struct aead_alg *aes_s390_aead_alg; @@ -1012,6 +1119,13 @@ static int __init aes_s390_init(void) goto out_err; } + if (cpacf_test_func(&km_functions, CPACF_KM_XTS_128_FULL) || + cpacf_test_func(&km_functions, CPACF_KM_XTS_256_FULL)) { + ret = aes_s390_register_skcipher(&fullxts_aes_alg); + if (ret) + goto out_err; + } + if (cpacf_test_func(&km_functions, CPACF_KM_XTS_128) || cpacf_test_func(&km_functions, CPACF_KM_XTS_256)) { ret = aes_s390_register_skcipher(&xts_aes_alg); diff --git a/arch/s390/crypto/hmac_s390.c b/arch/s390/crypto/hmac_s390.c new file mode 100644 index 000000000000..bba9a818dfdc --- /dev/null +++ b/arch/s390/crypto/hmac_s390.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright IBM Corp. 2024 + * + * s390 specific HMAC support. + */ + +#define KMSG_COMPONENT "hmac_s390" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include <asm/cpacf.h> +#include <crypto/sha2.h> +#include <crypto/internal/hash.h> +#include <linux/cpufeature.h> +#include <linux/module.h> + +/* + * KMAC param block layout for sha2 function codes: + * The layout of the param block for the KMAC instruction depends on the + * blocksize of the used hashing sha2-algorithm function codes. The param block + * contains the hash chaining value (cv), the input message bit-length (imbl) + * and the hmac-secret (key). To prevent code duplication, the sizes of all + * these are calculated based on the blocksize. + * + * param-block: + * +-------+ + * | cv | + * +-------+ + * | imbl | + * +-------+ + * | key | + * +-------+ + * + * sizes: + * part | sh2-alg | calculation | size | type + * -----+---------+-------------+------+-------- + * cv | 224/256 | blocksize/2 | 32 | u64[8] + * | 384/512 | | 64 | u128[8] + * imbl | 224/256 | blocksize/8 | 8 | u64 + * | 384/512 | | 16 | u128 + * key | 224/256 | blocksize | 64 | u8[64] + * | 384/512 | | 128 | u8[128] + */ + +#define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE +#define MAX_IMBL_SIZE sizeof(u128) +#define MAX_BLOCK_SIZE SHA512_BLOCK_SIZE + +#define SHA2_CV_SIZE(bs) ((bs) >> 1) +#define SHA2_IMBL_SIZE(bs) ((bs) >> 3) + +#define SHA2_IMBL_OFFSET(bs) (SHA2_CV_SIZE(bs)) +#define SHA2_KEY_OFFSET(bs) (SHA2_CV_SIZE(bs) + SHA2_IMBL_SIZE(bs)) + +struct s390_hmac_ctx { + u8 key[MAX_BLOCK_SIZE]; +}; + +union s390_kmac_gr0 { + unsigned long reg; + struct { + unsigned long : 48; + unsigned long ikp : 1; + unsigned long iimp : 1; + unsigned long ccup : 1; + unsigned long : 6; + unsigned long fc : 7; + }; +}; + +struct s390_kmac_sha2_ctx { + u8 param[MAX_DIGEST_SIZE + MAX_IMBL_SIZE + MAX_BLOCK_SIZE]; + union s390_kmac_gr0 gr0; + u8 buf[MAX_BLOCK_SIZE]; + unsigned int buflen; +}; + +/* + * kmac_sha2_set_imbl - sets the input message bit-length based on the blocksize + */ +static inline void kmac_sha2_set_imbl(u8 *param, unsigned int buflen, + unsigned int blocksize) +{ + u8 *imbl = param + SHA2_IMBL_OFFSET(blocksize); + + switch (blocksize) { + case SHA256_BLOCK_SIZE: + *(u64 *)imbl = (u64)buflen * BITS_PER_BYTE; + break; + case SHA512_BLOCK_SIZE: + *(u128 *)imbl = (u128)buflen * BITS_PER_BYTE; + break; + default: + break; + } +} + +static int hash_key(const u8 *in, unsigned int inlen, + u8 *digest, unsigned int digestsize) +{ + unsigned long func; + union { + struct sha256_paramblock { + u32 h[8]; + u64 mbl; + } sha256; + struct sha512_paramblock { + u64 h[8]; + u128 mbl; + } sha512; + } __packed param; + +#define PARAM_INIT(x, y, z) \ + param.sha##x.h[0] = SHA##y ## _H0; \ + param.sha##x.h[1] = SHA##y ## _H1; \ + param.sha##x.h[2] = SHA##y ## _H2; \ + param.sha##x.h[3] = SHA##y ## _H3; \ + param.sha##x.h[4] = SHA##y ## _H4; \ + param.sha##x.h[5] = SHA##y ## _H5; \ + param.sha##x.h[6] = SHA##y ## _H6; \ + param.sha##x.h[7] = SHA##y ## _H7; \ + param.sha##x.mbl = (z) + + switch (digestsize) { + case SHA224_DIGEST_SIZE: + func = CPACF_KLMD_SHA_256; + PARAM_INIT(256, 224, inlen * 8); + break; + case SHA256_DIGEST_SIZE: + func = CPACF_KLMD_SHA_256; + PARAM_INIT(256, 256, inlen * 8); + break; + case SHA384_DIGEST_SIZE: + func = CPACF_KLMD_SHA_512; + PARAM_INIT(512, 384, inlen * 8); + break; + case SHA512_DIGEST_SIZE: + func = CPACF_KLMD_SHA_512; + PARAM_INIT(512, 512, inlen * 8); + break; + default: + return -EINVAL; + } + +#undef PARAM_INIT + + cpacf_klmd(func, ¶m, in, inlen); + + memcpy(digest, ¶m, digestsize); + + return 0; +} + +static int s390_hmac_sha2_setkey(struct crypto_shash *tfm, + const u8 *key, unsigned int keylen) +{ + struct s390_hmac_ctx *tfm_ctx = crypto_shash_ctx(tfm); + unsigned int ds = crypto_shash_digestsize(tfm); + unsigned int bs = crypto_shash_blocksize(tfm); + + memset(tfm_ctx, 0, sizeof(*tfm_ctx)); + + if (keylen > bs) + return hash_key(key, keylen, tfm_ctx->key, ds); + + memcpy(tfm_ctx->key, key, keylen); + return 0; +} + +static int s390_hmac_sha2_init(struct shash_desc *desc) +{ + struct s390_hmac_ctx *tfm_ctx = crypto_shash_ctx(desc->tfm); + struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc); + unsigned int bs = crypto_shash_blocksize(desc->tfm); + + memcpy(ctx->param + SHA2_KEY_OFFSET(bs), + tfm_ctx->key, bs); + + ctx->buflen = 0; + ctx->gr0.reg = 0; + switch (crypto_shash_digestsize(desc->tfm)) { + case SHA224_DIGEST_SIZE: + ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_224; + break; + case SHA256_DIGEST_SIZE: + ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_256; + break; + case SHA384_DIGEST_SIZE: + ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_384; + break; + case SHA512_DIGEST_SIZE: + ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_512; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int s390_hmac_sha2_update(struct shash_desc *desc, + const u8 *data, unsigned int len) +{ + struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc); + unsigned int bs = crypto_shash_blocksize(desc->tfm); + unsigned int offset, n; + + /* check current buffer */ + offset = ctx->buflen % bs; + ctx->buflen += len; + if (offset + len < bs) + goto store; + + /* process one stored block */ + if (offset) { + n = bs - offset; + memcpy(ctx->buf + offset, data, n); + ctx->gr0.iimp = 1; + _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, bs); + data += n; + len -= n; + offset = 0; + } + /* process as many blocks as possible */ + if (len >= bs) { + n = (len / bs) * bs; + ctx->gr0.iimp = 1; + _cpacf_kmac(&ctx->gr0.reg, ctx->param, data, n); + data += n; + len -= n; + } +store: + /* store incomplete block in buffer */ + if (len) + memcpy(ctx->buf + offset, data, len); + + return 0; +} + +static int s390_hmac_sha2_final(struct shash_desc *desc, u8 *out) +{ + struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc); + unsigned int bs = crypto_shash_blocksize(desc->tfm); + + ctx->gr0.iimp = 0; + kmac_sha2_set_imbl(ctx->param, ctx->buflen, bs); + _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, ctx->buflen % bs); + memcpy(out, ctx->param, crypto_shash_digestsize(desc->tfm)); + + return 0; +} + +static int s390_hmac_sha2_digest(struct shash_desc *desc, + const u8 *data, unsigned int len, u8 *out) +{ + struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc); + unsigned int ds = crypto_shash_digestsize(desc->tfm); + int rc; + + rc = s390_hmac_sha2_init(desc); + if (rc) + return rc; + + ctx->gr0.iimp = 0; + kmac_sha2_set_imbl(ctx->param, len, + crypto_shash_blocksize(desc->tfm)); + _cpacf_kmac(&ctx->gr0.reg, ctx->param, data, len); + memcpy(out, ctx->param, ds); + + return 0; +} + +#define S390_HMAC_SHA2_ALG(x) { \ + .fc = CPACF_KMAC_HMAC_SHA_##x, \ + .alg = { \ + .init = s390_hmac_sha2_init, \ + .update = s390_hmac_sha2_update, \ + .final = s390_hmac_sha2_final, \ + .digest = s390_hmac_sha2_digest, \ + .setkey = s390_hmac_sha2_setkey, \ + .descsize = sizeof(struct s390_kmac_sha2_ctx), \ + .halg = { \ + .digestsize = SHA##x##_DIGEST_SIZE, \ + .base = { \ + .cra_name = "hmac(sha" #x ")", \ + .cra_driver_name = "hmac_s390_sha" #x, \ + .cra_blocksize = SHA##x##_BLOCK_SIZE, \ + .cra_priority = 400, \ + .cra_ctxsize = sizeof(struct s390_hmac_ctx), \ + .cra_module = THIS_MODULE, \ + }, \ + }, \ + }, \ +} + +static struct s390_hmac_alg { + bool registered; + unsigned int fc; + struct shash_alg alg; +} s390_hmac_algs[] = { + S390_HMAC_SHA2_ALG(224), + S390_HMAC_SHA2_ALG(256), + S390_HMAC_SHA2_ALG(384), + S390_HMAC_SHA2_ALG(512), +}; + +static __always_inline void _s390_hmac_algs_unregister(void) +{ + struct s390_hmac_alg *hmac; + int i; + + for (i = ARRAY_SIZE(s390_hmac_algs) - 1; i >= 0; i--) { + hmac = &s390_hmac_algs[i]; + if (!hmac->registered) + continue; + crypto_unregister_shash(&hmac->alg); + } +} + +static int __init hmac_s390_init(void) +{ + struct s390_hmac_alg *hmac; + int i, rc = -ENODEV; + + if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256)) + return -ENODEV; + if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512)) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(s390_hmac_algs); i++) { + hmac = &s390_hmac_algs[i]; + if (!cpacf_query_func(CPACF_KMAC, hmac->fc)) + continue; + + rc = crypto_register_shash(&hmac->alg); + if (rc) { + pr_err("unable to register %s\n", + hmac->alg.halg.base.cra_name); + goto out; + } + hmac->registered = true; + pr_debug("registered %s\n", hmac->alg.halg.base.cra_name); + } + return rc; +out: + _s390_hmac_algs_unregister(); + return rc; +} + +static void __exit hmac_s390_exit(void) +{ + _s390_hmac_algs_unregister(); +} + +module_cpu_feature_match(S390_CPU_FEATURE_MSA, hmac_s390_init); +module_exit(hmac_s390_exit); + +MODULE_DESCRIPTION("S390 HMAC driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c index 99ea3f12c5d2..511093713a6f 100644 --- a/arch/s390/crypto/paes_s390.c +++ b/arch/s390/crypto/paes_s390.c @@ -34,14 +34,22 @@ * is called. As paes can handle different kinds of key blobs * and padding is also possible, the limits need to be generous. */ -#define PAES_MIN_KEYSIZE 16 -#define PAES_MAX_KEYSIZE MAXEP11AESKEYBLOBSIZE +#define PAES_MIN_KEYSIZE 16 +#define PAES_MAX_KEYSIZE MAXEP11AESKEYBLOBSIZE +#define PAES_256_PROTKEY_SIZE (32 + 32) /* key + verification pattern */ +#define PXTS_256_PROTKEY_SIZE (32 + 32 + 32) /* k1 + k2 + verification pattern */ static u8 *ctrblk; static DEFINE_MUTEX(ctrblk_lock); static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; +struct paes_protkey { + u32 type; + u32 len; + u8 protkey[PXTS_256_PROTKEY_SIZE]; +}; + struct key_blob { /* * Small keys will be stored in the keybuf. Larger keys are @@ -55,31 +63,43 @@ struct key_blob { unsigned int keylen; }; -static inline int _key_to_kb(struct key_blob *kb, - const u8 *key, - unsigned int keylen) +/* + * make_clrkey_token() - wrap the raw key ck with pkey clearkey token + * information. + * @returns the size of the clearkey token + */ +static inline u32 make_clrkey_token(const u8 *ck, size_t cklen, u8 *dest) { - struct clearkey_header { + struct clrkey_token { u8 type; u8 res0[3]; u8 version; u8 res1[3]; u32 keytype; u32 len; - } __packed * h; + u8 key[]; + } __packed *token = (struct clrkey_token *)dest; + + token->type = 0x00; + token->version = 0x02; + token->keytype = (cklen - 8) >> 3; + token->len = cklen; + memcpy(token->key, ck, cklen); + + return sizeof(*token) + cklen; +} +static inline int _key_to_kb(struct key_blob *kb, + const u8 *key, + unsigned int keylen) +{ switch (keylen) { case 16: case 24: case 32: /* clear key value, prepare pkey clear key token in keybuf */ memset(kb->keybuf, 0, sizeof(kb->keybuf)); - h = (struct clearkey_header *) kb->keybuf; - h->version = 0x02; /* TOKVER_CLEAR_KEY */ - h->keytype = (keylen - 8) >> 3; - h->len = keylen; - memcpy(kb->keybuf + sizeof(*h), key, keylen); - kb->keylen = sizeof(*h) + keylen; + kb->keylen = make_clrkey_token(key, keylen, kb->keybuf); kb->key = kb->keybuf; break; default: @@ -99,6 +119,40 @@ static inline int _key_to_kb(struct key_blob *kb, return 0; } +static inline int _xts_key_to_kb(struct key_blob *kb, + const u8 *key, + unsigned int keylen) +{ + size_t cklen = keylen / 2; + + memset(kb->keybuf, 0, sizeof(kb->keybuf)); + + switch (keylen) { + case 32: + case 64: + /* clear key value, prepare pkey clear key tokens in keybuf */ + kb->key = kb->keybuf; + kb->keylen = make_clrkey_token(key, cklen, kb->key); + kb->keylen += make_clrkey_token(key + cklen, cklen, + kb->key + kb->keylen); + break; + default: + /* other key material, let pkey handle this */ + if (keylen <= sizeof(kb->keybuf)) { + kb->key = kb->keybuf; + } else { + kb->key = kmalloc(keylen, GFP_KERNEL); + if (!kb->key) + return -ENOMEM; + } + memcpy(kb->key, key, keylen); + kb->keylen = keylen; + break; + } + + return 0; +} + static inline void _free_kb_keybuf(struct key_blob *kb) { if (kb->key && kb->key != kb->keybuf @@ -106,52 +160,53 @@ static inline void _free_kb_keybuf(struct key_blob *kb) kfree_sensitive(kb->key); kb->key = NULL; } + memzero_explicit(kb->keybuf, sizeof(kb->keybuf)); } struct s390_paes_ctx { struct key_blob kb; - struct pkey_protkey pk; + struct paes_protkey pk; spinlock_t pk_lock; unsigned long fc; }; struct s390_pxts_ctx { - struct key_blob kb[2]; - struct pkey_protkey pk[2]; + struct key_blob kb; + struct paes_protkey pk[2]; spinlock_t pk_lock; unsigned long fc; }; -static inline int __paes_keyblob2pkey(struct key_blob *kb, - struct pkey_protkey *pk) +static inline int __paes_keyblob2pkey(const u8 *key, unsigned int keylen, + struct paes_protkey *pk) { - int i, ret = -EIO; + int i, rc = -EIO; /* try three times in case of busy card */ - for (i = 0; ret && i < 3; i++) { - if (ret == -EBUSY && in_task()) { + for (i = 0; rc && i < 3; i++) { + if (rc == -EBUSY && in_task()) { if (msleep_interruptible(1000)) return -EINTR; } - ret = pkey_keyblob2pkey(kb->key, kb->keylen, - pk->protkey, &pk->len, &pk->type); + rc = pkey_key2protkey(key, keylen, pk->protkey, &pk->len, + &pk->type); } - return ret; + return rc; } static inline int __paes_convert_key(struct s390_paes_ctx *ctx) { - int ret; - struct pkey_protkey pkey; + struct paes_protkey pk; + int rc; - pkey.len = sizeof(pkey.protkey); - ret = __paes_keyblob2pkey(&ctx->kb, &pkey); - if (ret) - return ret; + pk.len = sizeof(pk.protkey); + rc = __paes_keyblob2pkey(ctx->kb.key, ctx->kb.keylen, &pk); + if (rc) + return rc; spin_lock_bh(&ctx->pk_lock); - memcpy(&ctx->pk, &pkey, sizeof(pkey)); + memcpy(&ctx->pk, &pk, sizeof(pk)); spin_unlock_bh(&ctx->pk_lock); return 0; @@ -176,8 +231,8 @@ static void ecb_paes_exit(struct crypto_skcipher *tfm) static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx) { - int rc; unsigned long fc; + int rc; rc = __paes_convert_key(ctx); if (rc) @@ -197,8 +252,8 @@ static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx) static int ecb_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { - int rc; struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); + int rc; _free_kb_keybuf(&ctx->kb); rc = _key_to_kb(&ctx->kb, in_key, key_len); @@ -212,19 +267,19 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - unsigned int nbytes, n, k; - int ret; struct { - u8 key[MAXPROTKEYSIZE]; + u8 key[PAES_256_PROTKEY_SIZE]; } param; + struct skcipher_walk walk; + unsigned int nbytes, n, k; + int rc; - ret = skcipher_walk_virt(&walk, req, false); - if (ret) - return ret; + rc = skcipher_walk_virt(&walk, req, false); + if (rc) + return rc; spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); while ((nbytes = walk.nbytes) != 0) { @@ -233,16 +288,16 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier) k = cpacf_km(ctx->fc | modifier, ¶m, walk.dst.virt.addr, walk.src.virt.addr, n); if (k) - ret = skcipher_walk_done(&walk, nbytes - k); + rc = skcipher_walk_done(&walk, nbytes - k); if (k < n) { if (__paes_convert_key(ctx)) return skcipher_walk_done(&walk, -EIO); spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); } } - return ret; + return rc; } static int ecb_paes_encrypt(struct skcipher_request *req) @@ -291,8 +346,8 @@ static void cbc_paes_exit(struct crypto_skcipher *tfm) static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx) { - int rc; unsigned long fc; + int rc; rc = __paes_convert_key(ctx); if (rc) @@ -312,8 +367,8 @@ static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx) static int cbc_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { - int rc; struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); + int rc; _free_kb_keybuf(&ctx->kb); rc = _key_to_kb(&ctx->kb, in_key, key_len); @@ -327,21 +382,21 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - unsigned int nbytes, n, k; - int ret; struct { u8 iv[AES_BLOCK_SIZE]; - u8 key[MAXPROTKEYSIZE]; + u8 key[PAES_256_PROTKEY_SIZE]; } param; + struct skcipher_walk walk; + unsigned int nbytes, n, k; + int rc; - ret = skcipher_walk_virt(&walk, req, false); - if (ret) - return ret; + rc = skcipher_walk_virt(&walk, req, false); + if (rc) + return rc; memcpy(param.iv, walk.iv, AES_BLOCK_SIZE); spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); while ((nbytes = walk.nbytes) != 0) { @@ -351,17 +406,17 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier) walk.dst.virt.addr, walk.src.virt.addr, n); if (k) { memcpy(walk.iv, param.iv, AES_BLOCK_SIZE); - ret = skcipher_walk_done(&walk, nbytes - k); + rc = skcipher_walk_done(&walk, nbytes - k); } if (k < n) { if (__paes_convert_key(ctx)) return skcipher_walk_done(&walk, -EIO); spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); } } - return ret; + return rc; } static int cbc_paes_encrypt(struct skcipher_request *req) @@ -396,8 +451,7 @@ static int xts_paes_init(struct crypto_skcipher *tfm) { struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); - ctx->kb[0].key = NULL; - ctx->kb[1].key = NULL; + ctx->kb.key = NULL; spin_lock_init(&ctx->pk_lock); return 0; @@ -407,24 +461,51 @@ static void xts_paes_exit(struct crypto_skcipher *tfm) { struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); - _free_kb_keybuf(&ctx->kb[0]); - _free_kb_keybuf(&ctx->kb[1]); + _free_kb_keybuf(&ctx->kb); } static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx) { - struct pkey_protkey pkey0, pkey1; + struct paes_protkey pk0, pk1; + size_t split_keylen; + int rc; - pkey0.len = sizeof(pkey0.protkey); - pkey1.len = sizeof(pkey1.protkey); + pk0.len = sizeof(pk0.protkey); + pk1.len = sizeof(pk1.protkey); - if (__paes_keyblob2pkey(&ctx->kb[0], &pkey0) || - __paes_keyblob2pkey(&ctx->kb[1], &pkey1)) + rc = __paes_keyblob2pkey(ctx->kb.key, ctx->kb.keylen, &pk0); + if (rc) + return rc; + + switch (pk0.type) { + case PKEY_KEYTYPE_AES_128: + case PKEY_KEYTYPE_AES_256: + /* second keytoken required */ + if (ctx->kb.keylen % 2) + return -EINVAL; + split_keylen = ctx->kb.keylen / 2; + + rc = __paes_keyblob2pkey(ctx->kb.key + split_keylen, + split_keylen, &pk1); + if (rc) + return rc; + + if (pk0.type != pk1.type) + return -EINVAL; + break; + case PKEY_KEYTYPE_AES_XTS_128: + case PKEY_KEYTYPE_AES_XTS_256: + /* single key */ + pk1.type = 0; + break; + default: + /* unsupported protected keytype */ return -EINVAL; + } spin_lock_bh(&ctx->pk_lock); - memcpy(&ctx->pk[0], &pkey0, sizeof(pkey0)); - memcpy(&ctx->pk[1], &pkey1, sizeof(pkey1)); + ctx->pk[0] = pk0; + ctx->pk[1] = pk1; spin_unlock_bh(&ctx->pk_lock); return 0; @@ -433,17 +514,30 @@ static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx) static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx) { unsigned long fc; + int rc; - if (__xts_paes_convert_key(ctx)) - return -EINVAL; - - if (ctx->pk[0].type != ctx->pk[1].type) - return -EINVAL; + rc = __xts_paes_convert_key(ctx); + if (rc) + return rc; /* Pick the correct function code based on the protected key type */ - fc = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PXTS_128 : - (ctx->pk[0].type == PKEY_KEYTYPE_AES_256) ? - CPACF_KM_PXTS_256 : 0; + switch (ctx->pk[0].type) { + case PKEY_KEYTYPE_AES_128: + fc = CPACF_KM_PXTS_128; + break; + case PKEY_KEYTYPE_AES_256: + fc = CPACF_KM_PXTS_256; + break; + case PKEY_KEYTYPE_AES_XTS_128: + fc = CPACF_KM_PXTS_128_FULL; + break; + case PKEY_KEYTYPE_AES_XTS_256: + fc = CPACF_KM_PXTS_256_FULL; + break; + default: + fc = 0; + break; + } /* Check if the function code is available */ ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; @@ -452,24 +546,19 @@ static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx) } static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, - unsigned int xts_key_len) + unsigned int in_keylen) { - int rc; struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); u8 ckey[2 * AES_MAX_KEY_SIZE]; - unsigned int ckey_len, key_len; + unsigned int ckey_len; + int rc; - if (xts_key_len % 2) + if ((in_keylen == 32 || in_keylen == 64) && + xts_verify_key(tfm, in_key, in_keylen)) return -EINVAL; - key_len = xts_key_len / 2; - - _free_kb_keybuf(&ctx->kb[0]); - _free_kb_keybuf(&ctx->kb[1]); - rc = _key_to_kb(&ctx->kb[0], in_key, key_len); - if (rc) - return rc; - rc = _key_to_kb(&ctx->kb[1], in_key + key_len, key_len); + _free_kb_keybuf(&ctx->kb); + rc = _xts_key_to_kb(&ctx->kb, in_key, in_keylen); if (rc) return rc; @@ -478,6 +567,13 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, return rc; /* + * It is not possible on a single protected key (e.g. full AES-XTS) to + * check, if k1 and k2 are the same. + */ + if (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128 || + ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_256) + return 0; + /* * xts_verify_key verifies the key length is not odd and makes * sure that the two keys are not the same. This can be done * on the two protected keys as well @@ -489,28 +585,82 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, return xts_verify_key(tfm, ckey, 2*ckey_len); } -static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier) +static int paes_xts_crypt_full(struct skcipher_request *req, + unsigned long modifier) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); + unsigned int keylen, offset, nbytes, n, k; + struct { + u8 key[64]; + u8 tweak[16]; + u8 nap[16]; + u8 wkvp[32]; + } fxts_param = { + .nap = {0}, + }; struct skcipher_walk walk; + int rc; + + rc = skcipher_walk_virt(&walk, req, false); + if (rc) + return rc; + + keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 64; + offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 0; + + spin_lock_bh(&ctx->pk_lock); + memcpy(fxts_param.key + offset, ctx->pk[0].protkey, keylen); + memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen, + sizeof(fxts_param.wkvp)); + spin_unlock_bh(&ctx->pk_lock); + memcpy(fxts_param.tweak, walk.iv, sizeof(fxts_param.tweak)); + fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */ + + while ((nbytes = walk.nbytes) != 0) { + /* only use complete blocks */ + n = nbytes & ~(AES_BLOCK_SIZE - 1); + k = cpacf_km(ctx->fc | modifier, fxts_param.key + offset, + walk.dst.virt.addr, walk.src.virt.addr, n); + if (k) + rc = skcipher_walk_done(&walk, nbytes - k); + if (k < n) { + if (__xts_paes_convert_key(ctx)) + return skcipher_walk_done(&walk, -EIO); + spin_lock_bh(&ctx->pk_lock); + memcpy(fxts_param.key + offset, ctx->pk[0].protkey, + keylen); + memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen, + sizeof(fxts_param.wkvp)); + spin_unlock_bh(&ctx->pk_lock); + } + } + + return rc; +} + +static int paes_xts_crypt(struct skcipher_request *req, unsigned long modifier) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); unsigned int keylen, offset, nbytes, n, k; - int ret; struct { - u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */ + u8 key[PAES_256_PROTKEY_SIZE]; u8 tweak[16]; u8 block[16]; u8 bit[16]; u8 xts[16]; } pcc_param; struct { - u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */ + u8 key[PAES_256_PROTKEY_SIZE]; u8 init[16]; } xts_param; + struct skcipher_walk walk; + int rc; - ret = skcipher_walk_virt(&walk, req, false); - if (ret) - return ret; + rc = skcipher_walk_virt(&walk, req, false); + if (rc) + return rc; keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 48 : 64; offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 16 : 0; @@ -530,7 +680,7 @@ static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier) k = cpacf_km(ctx->fc | modifier, xts_param.key + offset, walk.dst.virt.addr, walk.src.virt.addr, n); if (k) - ret = skcipher_walk_done(&walk, nbytes - k); + rc = skcipher_walk_done(&walk, nbytes - k); if (k < n) { if (__xts_paes_convert_key(ctx)) return skcipher_walk_done(&walk, -EIO); @@ -541,7 +691,24 @@ static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier) } } - return ret; + return rc; +} + +static inline int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm); + + switch (ctx->fc) { + case CPACF_KM_PXTS_128: + case CPACF_KM_PXTS_256: + return paes_xts_crypt(req, modifier); + case CPACF_KM_PXTS_128_FULL: + case CPACF_KM_PXTS_256_FULL: + return paes_xts_crypt_full(req, modifier); + default: + return -EINVAL; + } } static int xts_paes_encrypt(struct skcipher_request *req) @@ -591,8 +758,8 @@ static void ctr_paes_exit(struct crypto_skcipher *tfm) static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx) { - int rc; unsigned long fc; + int rc; rc = __paes_convert_key(ctx); if (rc) @@ -613,8 +780,8 @@ static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx) static int ctr_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { - int rc; struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); + int rc; _free_kb_keybuf(&ctx->kb); rc = _key_to_kb(&ctx->kb, in_key, key_len); @@ -644,19 +811,19 @@ static int ctr_paes_crypt(struct skcipher_request *req) struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm); u8 buf[AES_BLOCK_SIZE], *ctrptr; - struct skcipher_walk walk; - unsigned int nbytes, n, k; - int ret, locked; struct { - u8 key[MAXPROTKEYSIZE]; + u8 key[PAES_256_PROTKEY_SIZE]; } param; + struct skcipher_walk walk; + unsigned int nbytes, n, k; + int rc, locked; - ret = skcipher_walk_virt(&walk, req, false); - if (ret) - return ret; + rc = skcipher_walk_virt(&walk, req, false); + if (rc) + return rc; spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); locked = mutex_trylock(&ctrblk_lock); @@ -673,7 +840,7 @@ static int ctr_paes_crypt(struct skcipher_request *req) memcpy(walk.iv, ctrptr + k - AES_BLOCK_SIZE, AES_BLOCK_SIZE); crypto_inc(walk.iv, AES_BLOCK_SIZE); - ret = skcipher_walk_done(&walk, nbytes - k); + rc = skcipher_walk_done(&walk, nbytes - k); } if (k < n) { if (__paes_convert_key(ctx)) { @@ -682,7 +849,7 @@ static int ctr_paes_crypt(struct skcipher_request *req) return skcipher_walk_done(&walk, -EIO); } spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); } } @@ -702,15 +869,15 @@ static int ctr_paes_crypt(struct skcipher_request *req) if (__paes_convert_key(ctx)) return skcipher_walk_done(&walk, -EIO); spin_lock_bh(&ctx->pk_lock); - memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); + memcpy(param.key, ctx->pk.protkey, PAES_256_PROTKEY_SIZE); spin_unlock_bh(&ctx->pk_lock); } memcpy(walk.dst.virt.addr, buf, nbytes); crypto_inc(walk.iv, AES_BLOCK_SIZE); - ret = skcipher_walk_done(&walk, nbytes); + rc = skcipher_walk_done(&walk, nbytes); } - return ret; + return rc; } static struct skcipher_alg ctr_paes_alg = { @@ -750,7 +917,7 @@ static void paes_s390_fini(void) static int __init paes_s390_init(void) { - int ret; + int rc; /* Query available functions for KM, KMC and KMCTR */ cpacf_query(CPACF_KM, &km_functions); @@ -760,23 +927,23 @@ static int __init paes_s390_init(void) if (cpacf_test_func(&km_functions, CPACF_KM_PAES_128) || cpacf_test_func(&km_functions, CPACF_KM_PAES_192) || cpacf_test_func(&km_functions, CPACF_KM_PAES_256)) { - ret = crypto_register_skcipher(&ecb_paes_alg); - if (ret) + rc = crypto_register_skcipher(&ecb_paes_alg); + if (rc) goto out_err; } if (cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) { - ret = crypto_register_skcipher(&cbc_paes_alg); - if (ret) + rc = crypto_register_skcipher(&cbc_paes_alg); + if (rc) goto out_err; } if (cpacf_test_func(&km_functions, CPACF_KM_PXTS_128) || cpacf_test_func(&km_functions, CPACF_KM_PXTS_256)) { - ret = crypto_register_skcipher(&xts_paes_alg); - if (ret) + rc = crypto_register_skcipher(&xts_paes_alg); + if (rc) goto out_err; } @@ -785,24 +952,27 @@ static int __init paes_s390_init(void) cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_256)) { ctrblk = (u8 *) __get_free_page(GFP_KERNEL); if (!ctrblk) { - ret = -ENOMEM; + rc = -ENOMEM; goto out_err; } - ret = crypto_register_skcipher(&ctr_paes_alg); - if (ret) + rc = crypto_register_skcipher(&ctr_paes_alg); + if (rc) goto out_err; } return 0; out_err: paes_s390_fini(); - return ret; + return rc; } module_init(paes_s390_init); module_exit(paes_s390_fini); -MODULE_ALIAS_CRYPTO("paes"); +MODULE_ALIAS_CRYPTO("ecb(paes)"); +MODULE_ALIAS_CRYPTO("cbc(paes)"); +MODULE_ALIAS_CRYPTO("ctr(paes)"); +MODULE_ALIAS_CRYPTO("xts(paes)"); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm with protected keys"); MODULE_LICENSE("GPL"); diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index a077087bc6cc..2becd77df741 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -679,7 +679,7 @@ static ssize_t prng_chunksize_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size); + return sysfs_emit(buf, "%u\n", prng_chunk_size); } static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL); @@ -698,7 +698,7 @@ static ssize_t prng_counter_show(struct device *dev, counter = prng_data->prngws.byte_counter; mutex_unlock(&prng_data->mutex); - return scnprintf(buf, PAGE_SIZE, "%llu\n", counter); + return sysfs_emit(buf, "%llu\n", counter); } static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL); @@ -707,7 +707,7 @@ static ssize_t prng_errorflag_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag); + return sysfs_emit(buf, "%d\n", prng_errorflag); } static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL); @@ -717,9 +717,9 @@ static ssize_t prng_mode_show(struct device *dev, char *buf) { if (prng_mode == PRNG_MODE_TDES) - return scnprintf(buf, PAGE_SIZE, "TDES\n"); + return sysfs_emit(buf, "TDES\n"); else - return scnprintf(buf, PAGE_SIZE, "SHA512\n"); + return sysfs_emit(buf, "SHA512\n"); } static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL); @@ -742,7 +742,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit); + return sysfs_emit(buf, "%u\n", prng_reseed_limit); } static ssize_t prng_reseed_limit_store(struct device *dev, struct device_attribute *attr, @@ -773,7 +773,7 @@ static ssize_t prng_strength_show(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "256\n"); + return sysfs_emit(buf, "256\n"); } static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL); diff --git a/arch/s390/crypto/sha.h b/arch/s390/crypto/sha.h index 65ea12fc87a1..2bb22db54c31 100644 --- a/arch/s390/crypto/sha.h +++ b/arch/s390/crypto/sha.h @@ -25,6 +25,7 @@ struct s390_sha_ctx { u32 state[CPACF_MAX_PARMBLOCK_SIZE / sizeof(u32)]; u8 buf[SHA_MAX_BLOCK_SIZE]; int func; /* KIMD function to use */ + int first_message_part; }; struct shash_desc; diff --git a/arch/s390/crypto/sha3_256_s390.c b/arch/s390/crypto/sha3_256_s390.c index e1350e033a32..a84ef692f572 100644 --- a/arch/s390/crypto/sha3_256_s390.c +++ b/arch/s390/crypto/sha3_256_s390.c @@ -21,9 +21,11 @@ static int sha3_256_init(struct shash_desc *desc) { struct s390_sha_ctx *sctx = shash_desc_ctx(desc); - memset(sctx->state, 0, sizeof(sctx->state)); + if (!test_facility(86)) /* msa 12 */ + memset(sctx->state, 0, sizeof(sctx->state)); sctx->count = 0; sctx->func = CPACF_KIMD_SHA3_256; + sctx->first_message_part = 1; return 0; } @@ -36,6 +38,7 @@ static int sha3_256_export(struct shash_desc *desc, void *out) octx->rsiz = sctx->count; memcpy(octx->st, sctx->state, sizeof(octx->st)); memcpy(octx->buf, sctx->buf, sizeof(octx->buf)); + octx->partial = sctx->first_message_part; return 0; } @@ -48,6 +51,7 @@ static int sha3_256_import(struct shash_desc *desc, const void *in) sctx->count = ictx->rsiz; memcpy(sctx->state, ictx->st, sizeof(ictx->st)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); + sctx->first_message_part = ictx->partial; sctx->func = CPACF_KIMD_SHA3_256; return 0; @@ -61,6 +65,7 @@ static int sha3_224_import(struct shash_desc *desc, const void *in) sctx->count = ictx->rsiz; memcpy(sctx->state, ictx->st, sizeof(ictx->st)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); + sctx->first_message_part = ictx->partial; sctx->func = CPACF_KIMD_SHA3_224; return 0; @@ -88,9 +93,11 @@ static int sha3_224_init(struct shash_desc *desc) { struct s390_sha_ctx *sctx = shash_desc_ctx(desc); - memset(sctx->state, 0, sizeof(sctx->state)); + if (!test_facility(86)) /* msa 12 */ + memset(sctx->state, 0, sizeof(sctx->state)); sctx->count = 0; sctx->func = CPACF_KIMD_SHA3_224; + sctx->first_message_part = 1; return 0; } diff --git a/arch/s390/crypto/sha3_512_s390.c b/arch/s390/crypto/sha3_512_s390.c index 06c142ed9bb1..07528fc98ff7 100644 --- a/arch/s390/crypto/sha3_512_s390.c +++ b/arch/s390/crypto/sha3_512_s390.c @@ -20,9 +20,11 @@ static int sha3_512_init(struct shash_desc *desc) { struct s390_sha_ctx *sctx = shash_desc_ctx(desc); - memset(sctx->state, 0, sizeof(sctx->state)); + if (!test_facility(86)) /* msa 12 */ + memset(sctx->state, 0, sizeof(sctx->state)); sctx->count = 0; sctx->func = CPACF_KIMD_SHA3_512; + sctx->first_message_part = 1; return 0; } @@ -37,6 +39,7 @@ static int sha3_512_export(struct shash_desc *desc, void *out) memcpy(octx->st, sctx->state, sizeof(octx->st)); memcpy(octx->buf, sctx->buf, sizeof(octx->buf)); + octx->partial = sctx->first_message_part; return 0; } @@ -52,6 +55,7 @@ static int sha3_512_import(struct shash_desc *desc, const void *in) memcpy(sctx->state, ictx->st, sizeof(ictx->st)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); + sctx->first_message_part = ictx->partial; sctx->func = CPACF_KIMD_SHA3_512; return 0; @@ -68,6 +72,7 @@ static int sha3_384_import(struct shash_desc *desc, const void *in) memcpy(sctx->state, ictx->st, sizeof(ictx->st)); memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf)); + sctx->first_message_part = ictx->partial; sctx->func = CPACF_KIMD_SHA3_384; return 0; @@ -97,9 +102,11 @@ static int sha3_384_init(struct shash_desc *desc) { struct s390_sha_ctx *sctx = shash_desc_ctx(desc); - memset(sctx->state, 0, sizeof(sctx->state)); + if (!test_facility(86)) /* msa 12 */ + memset(sctx->state, 0, sizeof(sctx->state)); sctx->count = 0; sctx->func = CPACF_KIMD_SHA3_384; + sctx->first_message_part = 1; return 0; } diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c index 686fe7aa192f..961d7d522af1 100644 --- a/arch/s390/crypto/sha_common.c +++ b/arch/s390/crypto/sha_common.c @@ -18,6 +18,7 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) struct s390_sha_ctx *ctx = shash_desc_ctx(desc); unsigned int bsize = crypto_shash_blocksize(desc->tfm); unsigned int index, n; + int fc; /* how much is already in the buffer? */ index = ctx->count % bsize; @@ -26,10 +27,16 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) if ((index + len) < bsize) goto store; + fc = ctx->func; + if (ctx->first_message_part) + fc |= test_facility(86) ? CPACF_KIMD_NIP : 0; + /* process one stored block */ if (index) { memcpy(ctx->buf + index, data, bsize - index); - cpacf_kimd(ctx->func, ctx->state, ctx->buf, bsize); + cpacf_kimd(fc, ctx->state, ctx->buf, bsize); + ctx->first_message_part = 0; + fc &= ~CPACF_KIMD_NIP; data += bsize - index; len -= bsize - index; index = 0; @@ -38,7 +45,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) /* process as many blocks as possible */ if (len >= bsize) { n = (len / bsize) * bsize; - cpacf_kimd(ctx->func, ctx->state, data, n); + cpacf_kimd(fc, ctx->state, data, n); + ctx->first_message_part = 0; data += n; len -= n; } @@ -75,7 +83,7 @@ int s390_sha_final(struct shash_desc *desc, u8 *out) unsigned int bsize = crypto_shash_blocksize(desc->tfm); u64 bits; unsigned int n; - int mbl_offset; + int mbl_offset, fc; n = ctx->count % bsize; bits = ctx->count * 8; @@ -109,7 +117,11 @@ int s390_sha_final(struct shash_desc *desc, u8 *out) return -EINVAL; } - cpacf_klmd(ctx->func, ctx->state, ctx->buf, n); + fc = ctx->func; + fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0; + if (ctx->first_message_part) + fc |= CPACF_KLMD_NIP; + cpacf_klmd(fc, ctx->state, ctx->buf, n); /* copy digest to out */ memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm)); diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h index 65f4036fd541..83ebf54cca6b 100644 --- a/arch/s390/hypfs/hypfs.h +++ b/arch/s390/hypfs/hypfs.h @@ -78,7 +78,6 @@ struct hypfs_dbfs_file { struct dentry *dentry; }; -extern void hypfs_dbfs_exit(void); extern void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df); extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df); diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index 0e855c5e91c5..5d9effb0867c 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c @@ -76,7 +76,6 @@ static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static const struct file_operations dbfs_ops = { .read = dbfs_read, - .llseek = no_llseek, .unlocked_ioctl = dbfs_ioctl, }; diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 26a009f9c49e..c8af67d20994 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -29,8 +29,6 @@ static enum diag204_format diag204_info_type; /* used diag 204 data format */ static void *diag204_buf; /* 4K aligned buffer for diag204 data */ static int diag204_buf_pages; /* number of pages for diag204 data */ -static struct dentry *dbfs_d204_file; - enum diag204_format diag204_get_info_type(void) { return diag204_info_type; @@ -214,16 +212,13 @@ __init int hypfs_diag_init(void) hypfs_dbfs_create_file(&dbfs_file_d204); rc = hypfs_diag_fs_init(); - if (rc) { + if (rc) pr_err("The hardware system does not provide all functions required by hypfs\n"); - debugfs_remove(dbfs_d204_file); - } return rc; } void hypfs_diag_exit(void) { - debugfs_remove(dbfs_d204_file); hypfs_diag_fs_exit(); diag204_free_buffer(); hypfs_dbfs_remove_file(&dbfs_file_d204); diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 858beaf4a8cb..d428635abf08 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -443,7 +443,6 @@ static const struct file_operations hypfs_file_ops = { .release = hypfs_release, .read_iter = hypfs_read_iter, .write_iter = hypfs_write_iter, - .llseek = no_llseek, }; static struct file_system_type hypfs_type = { diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 4b904110d27c..297bf7157968 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -7,3 +7,4 @@ generated-y += unistd_nr.h generic-y += asm-offsets.h generic-y += kvm_types.h generic-y += mcs_spinlock.h +generic-y += mmzone.h diff --git a/arch/s390/include/asm/alternative.h b/arch/s390/include/asm/alternative.h index de980c938a3e..73e781b56bfe 100644 --- a/arch/s390/include/asm/alternative.h +++ b/arch/s390/include/asm/alternative.h @@ -39,11 +39,7 @@ #define ALT_TYPE_SHIFT 20 #define ALT_CTX_SHIFT 28 -#define ALT_FACILITY_EARLY(facility) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ - ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \ - (facility) << ALT_DATA_SHIFT) - -#define ALT_FACILITY(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \ +#define ALT_FACILITY(facility) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \ (facility) << ALT_DATA_SHIFT) diff --git a/arch/s390/include/asm/arch_hweight.h b/arch/s390/include/asm/arch_hweight.h index 50e23ce854e5..aca08b0acbc1 100644 --- a/arch/s390/include/asm/arch_hweight.h +++ b/arch/s390/include/asm/arch_hweight.h @@ -4,6 +4,7 @@ #define _ASM_S390_ARCH_HWEIGHT_H #include <linux/types.h> +#include <asm/march.h> static __always_inline unsigned long popcnt_z196(unsigned long w) { @@ -29,9 +30,9 @@ static __always_inline unsigned long popcnt_z15(unsigned long w) static __always_inline unsigned long __arch_hweight64(__u64 w) { - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + if (__is_defined(MARCH_HAS_Z15_FEATURES)) return popcnt_z15(w); - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + if (__is_defined(MARCH_HAS_Z196_FEATURES)) { w = popcnt_z196(w); w += w >> 32; w += w >> 16; @@ -43,9 +44,9 @@ static __always_inline unsigned long __arch_hweight64(__u64 w) static __always_inline unsigned int __arch_hweight32(unsigned int w) { - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + if (__is_defined(MARCH_HAS_Z15_FEATURES)) return popcnt_z15(w); - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + if (__is_defined(MARCH_HAS_Z196_FEATURES)) { w = popcnt_z196(w); w += w >> 16; w += w >> 8; @@ -56,9 +57,9 @@ static __always_inline unsigned int __arch_hweight32(unsigned int w) static __always_inline unsigned int __arch_hweight16(unsigned int w) { - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + if (__is_defined(MARCH_HAS_Z15_FEATURES)) return popcnt_z15((unsigned short)w); - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + if (__is_defined(MARCH_HAS_Z196_FEATURES)) { w = popcnt_z196(w); w += w >> 8; return w & 0xff; @@ -68,7 +69,7 @@ static __always_inline unsigned int __arch_hweight16(unsigned int w) static __always_inline unsigned int __arch_hweight8(unsigned int w) { - if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) + if (__is_defined(MARCH_HAS_Z196_FEATURES)) return popcnt_z196((unsigned char)w); return __sw_hweight8(w); } diff --git a/arch/s390/include/asm/asm.h b/arch/s390/include/asm/asm.h new file mode 100644 index 000000000000..ec011b94af2a --- /dev/null +++ b/arch/s390/include/asm/asm.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_S390_ASM_H +#define _ASM_S390_ASM_H + +#include <linux/stringify.h> + +/* + * Helper macros to be used for flag output operand handling. + * Inline assemblies must use four of the five supplied macros: + * + * Use CC_IPM(sym) at the end of the inline assembly; this extracts the + * condition code and program mask with the ipm instruction and writes it to + * the variable with symbolic name [sym] if the compiler has no support for + * flag output operands. If the compiler has support for flag output operands + * this generates no code. + * + * Use CC_OUT(sym, var) at the output operand list of an inline assembly. This + * defines an output operand with symbolic name [sym] for the variable + * [var]. [var] must be an int variable and [sym] must be identical with [sym] + * used with CC_IPM(). + * + * Use either CC_CLOBBER or CC_CLOBBER_LIST() for the clobber list. Use + * CC_CLOBBER if the clobber list contains only "cc", otherwise use + * CC_CLOBBER_LIST() and add all clobbers as argument to the macro. + * + * Use CC_TRANSFORM() to convert the variable [var] which contains the + * extracted condition code. If the condition code is extracted with ipm, the + * [var] also contains the program mask. CC_TRANSFORM() moves the condition + * code to the two least significant bits and sets all other bits to zero. + */ +#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_GCC_ASM_FLAG_OUTPUT_BROKEN)) + +#define __HAVE_ASM_FLAG_OUTPUTS__ + +#define CC_IPM(sym) +#define CC_OUT(sym, var) "=@cc" (var) +#define CC_TRANSFORM(cc) ({ cc; }) +#define CC_CLOBBER +#define CC_CLOBBER_LIST(...) __VA_ARGS__ + +#else + +#define CC_IPM(sym) " ipm %[" __stringify(sym) "]\n" +#define CC_OUT(sym, var) [sym] "=d" (var) +#define CC_TRANSFORM(cc) ({ (cc) >> 28; }) +#define CC_CLOBBER "cc" +#define CC_CLOBBER_LIST(...) "cc", __VA_ARGS__ + +#endif + +#endif /* _ASM_S390_ASM_H */ diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 0c4cad7d5a5b..6723fca64018 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -72,14 +72,24 @@ ATOMIC_OPS(xor) #define arch_atomic_fetch_or arch_atomic_fetch_or #define arch_atomic_fetch_xor arch_atomic_fetch_xor -#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) +static __always_inline int arch_atomic_xchg(atomic_t *v, int new) +{ + return arch_xchg(&v->counter, new); +} +#define arch_atomic_xchg arch_atomic_xchg static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) { - return __atomic_cmpxchg(&v->counter, old, new); + return arch_cmpxchg(&v->counter, old, new); } #define arch_atomic_cmpxchg arch_atomic_cmpxchg +static __always_inline bool arch_atomic_try_cmpxchg(atomic_t *v, int *old, int new) +{ + return arch_try_cmpxchg(&v->counter, old, new); +} +#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchg + #define ATOMIC64_INIT(i) { (i) } static __always_inline s64 arch_atomic64_read(const atomic64_t *v) @@ -112,14 +122,24 @@ static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v) } #define arch_atomic64_add arch_atomic64_add -#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new)) +static __always_inline s64 arch_atomic64_xchg(atomic64_t *v, s64 new) +{ + return arch_xchg(&v->counter, new); +} +#define arch_atomic64_xchg arch_atomic64_xchg static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new) { - return __atomic64_cmpxchg((long *)&v->counter, old, new); + return arch_cmpxchg(&v->counter, old, new); } #define arch_atomic64_cmpxchg arch_atomic64_cmpxchg +static __always_inline bool arch_atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new) +{ + return arch_try_cmpxchg(&v->counter, old, new); +} +#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchg + #define ATOMIC64_OPS(op) \ static __always_inline void arch_atomic64_##op(s64 i, atomic64_t *v) \ { \ diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index 742c7919cbcd..1d6b2056fad8 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -9,6 +9,7 @@ #define __ARCH_S390_ATOMIC_OPS__ #include <linux/limits.h> +#include <asm/march.h> static __always_inline int __atomic_read(const atomic_t *v) { @@ -56,7 +57,7 @@ static __always_inline void __atomic64_set(atomic64_t *v, s64 i) } } -#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifdef MARCH_HAS_Z196_FEATURES #define __ATOMIC_OP(op_name, op_type, op_string, op_barrier) \ static __always_inline op_type op_name(op_type val, op_type *ptr) \ @@ -107,7 +108,7 @@ __ATOMIC_CONST_OPS(__atomic64_add_const, long, "agsi") #undef __ATOMIC_CONST_OPS #undef __ATOMIC_CONST_OP -#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#else /* MARCH_HAS_Z196_FEATURES */ #define __ATOMIC_OP(op_name, op_string) \ static __always_inline int op_name(int val, int *ptr) \ @@ -166,81 +167,6 @@ __ATOMIC64_OPS(__atomic64_xor, "xgr") #define __atomic64_add_const(val, ptr) __atomic64_add(val, ptr) #define __atomic64_add_const_barrier(val, ptr) __atomic64_add(val, ptr) -#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ - -static __always_inline int __atomic_cmpxchg(int *ptr, int old, int new) -{ - asm volatile( - " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) - : [new] "d" (new) - : "cc", "memory"); - return old; -} - -static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) -{ - asm volatile( - " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+QS" (*ptr) - : [new] "d" (new) - : "cc", "memory"); - return old; -} - -/* GCC versions before 14.2.0 may die with an ICE in some configurations. */ -#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200)) - -static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) -{ - int cc; - - asm volatile( - " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr), "=@cc" (cc) - : [new] "d" (new) - : "memory"); - return cc == 0; -} - -static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) -{ - int cc; - - asm volatile( - " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+QS" (*ptr), "=@cc" (cc) - : [new] "d" (new) - : "memory"); - return cc == 0; -} - -#else /* __GCC_ASM_FLAG_OUTPUTS__ */ - -static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) -{ - int old_expected = old; - - asm volatile( - " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) - : [new] "d" (new) - : "cc", "memory"); - return old == old_expected; -} - -static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) -{ - long old_expected = old; - - asm volatile( - " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+QS" (*ptr) - : [new] "d" (new) - : "cc", "memory"); - return old == old_expected; -} - -#endif /* __GCC_ASM_FLAG_OUTPUTS__ */ +#endif /* MARCH_HAS_Z196_FEATURES */ #endif /* __ARCH_S390_ATOMIC_OPS__ */ diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h index 82de2a7c4160..d82130d7f2b6 100644 --- a/arch/s390/include/asm/barrier.h +++ b/arch/s390/include/asm/barrier.h @@ -8,13 +8,15 @@ #ifndef __ASM_BARRIER_H #define __ASM_BARRIER_H +#include <asm/march.h> + /* * Force strict CPU ordering. * And yes, this is required on UP too when we're talking * to devices. */ -#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifdef MARCH_HAS_Z196_FEATURES /* Fast-BCR without checkpoint synchronization */ #define __ASM_BCR_SERIALIZE "bcr 14,0\n" #else diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index aae0315374de..a9e2006033b7 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h @@ -11,185 +11,231 @@ #include <linux/mmdebug.h> #include <linux/types.h> #include <linux/bug.h> +#include <asm/asm.h> -void __xchg_called_with_bad_pointer(void); +void __cmpxchg_called_with_bad_pointer(void); + +static __always_inline u32 __cs_asm(u64 ptr, u32 old, u32 new) +{ + asm volatile( + " cs %[old],%[new],%[ptr]\n" + : [old] "+d" (old), [ptr] "+Q" (*(u32 *)ptr) + : [new] "d" (new) + : "memory", "cc"); + return old; +} + +static __always_inline u64 __csg_asm(u64 ptr, u64 old, u64 new) +{ + asm volatile( + " csg %[old],%[new],%[ptr]\n" + : [old] "+d" (old), [ptr] "+QS" (*(u64 *)ptr) + : [new] "d" (new) + : "memory", "cc"); + return old; +} -static __always_inline unsigned long -__arch_xchg(unsigned long x, unsigned long address, int size) +static inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new) { - unsigned long old; - int shift; + union { + u8 b[4]; + u32 w; + } old32, new32; + u32 prev; + int i; + + i = ptr & 3; + ptr &= ~0x3; + prev = READ_ONCE(*(u32 *)ptr); + do { + old32.w = prev; + if (old32.b[i] != old) + return old32.b[i]; + new32.w = old32.w; + new32.b[i] = new; + prev = __cs_asm(ptr, old32.w, new32.w); + } while (prev != old32.w); + return old; +} + +static inline u16 __arch_cmpxchg2(u64 ptr, u16 old, u16 new) +{ + union { + u16 b[2]; + u32 w; + } old32, new32; + u32 prev; + int i; + + i = (ptr & 3) >> 1; + ptr &= ~0x3; + prev = READ_ONCE(*(u32 *)ptr); + do { + old32.w = prev; + if (old32.b[i] != old) + return old32.b[i]; + new32.w = old32.w; + new32.b[i] = new; + prev = __cs_asm(ptr, old32.w, new32.w); + } while (prev != old32.w); + return old; +} +static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size) +{ switch (size) { - case 1: - shift = (3 ^ (address & 3)) << 3; - address ^= address & 3; - asm volatile( - " l %0,%1\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%1\n" - " jl 0b\n" - : "=&d" (old), "+Q" (*(int *) address) - : "d" ((x & 0xff) << shift), "d" (~(0xff << shift)) - : "memory", "cc", "0"); - return old >> shift; - case 2: - shift = (2 ^ (address & 2)) << 3; - address ^= address & 2; - asm volatile( - " l %0,%1\n" - "0: lr 0,%0\n" - " nr 0,%3\n" - " or 0,%2\n" - " cs %0,0,%1\n" - " jl 0b\n" - : "=&d" (old), "+Q" (*(int *) address) - : "d" ((x & 0xffff) << shift), "d" (~(0xffff << shift)) - : "memory", "cc", "0"); - return old >> shift; - case 4: - asm volatile( - " l %0,%1\n" - "0: cs %0,%2,%1\n" - " jl 0b\n" - : "=&d" (old), "+Q" (*(int *) address) - : "d" (x) - : "memory", "cc"); - return old; - case 8: - asm volatile( - " lg %0,%1\n" - "0: csg %0,%2,%1\n" - " jl 0b\n" - : "=&d" (old), "+QS" (*(long *) address) - : "d" (x) - : "memory", "cc"); - return old; + case 1: return __arch_cmpxchg1(ptr, old & 0xff, new & 0xff); + case 2: return __arch_cmpxchg2(ptr, old & 0xffff, new & 0xffff); + case 4: return __cs_asm(ptr, old & 0xffffffff, new & 0xffffffff); + case 8: return __csg_asm(ptr, old, new); + default: __cmpxchg_called_with_bad_pointer(); } - __xchg_called_with_bad_pointer(); - return x; + return old; } -#define arch_xchg(ptr, x) \ +#define arch_cmpxchg(ptr, o, n) \ ({ \ - __typeof__(*(ptr)) __ret; \ + (__typeof__(*(ptr)))__arch_cmpxchg((unsigned long)(ptr), \ + (unsigned long)(o), \ + (unsigned long)(n), \ + sizeof(*(ptr))); \ +}) + +#define arch_cmpxchg64 arch_cmpxchg +#define arch_cmpxchg_local arch_cmpxchg +#define arch_cmpxchg64_local arch_cmpxchg + +#ifdef __HAVE_ASM_FLAG_OUTPUTS__ + +#define arch_try_cmpxchg(ptr, oldp, new) \ +({ \ + __typeof__(ptr) __oldp = (__typeof__(ptr))(oldp); \ + __typeof__(*(ptr)) __old = *__oldp; \ + __typeof__(*(ptr)) __new = (new); \ + __typeof__(*(ptr)) __prev; \ + int __cc; \ \ - __ret = (__typeof__(*(ptr))) \ - __arch_xchg((unsigned long)(x), (unsigned long)(ptr), \ - sizeof(*(ptr))); \ - __ret; \ + switch (sizeof(*(ptr))) { \ + case 1: \ + case 2: { \ + __prev = arch_cmpxchg((ptr), (__old), (__new)); \ + __cc = (__prev != __old); \ + if (unlikely(__cc)) \ + *__oldp = __prev; \ + break; \ + } \ + case 4: { \ + asm volatile( \ + " cs %[__old],%[__new],%[__ptr]\n" \ + : [__old] "+d" (*__oldp), \ + [__ptr] "+Q" (*(ptr)), \ + "=@cc" (__cc) \ + : [__new] "d" (__new) \ + : "memory"); \ + break; \ + } \ + case 8: { \ + asm volatile( \ + " csg %[__old],%[__new],%[__ptr]\n" \ + : [__old] "+d" (*__oldp), \ + [__ptr] "+QS" (*(ptr)), \ + "=@cc" (__cc) \ + : [__new] "d" (__new) \ + : "memory"); \ + break; \ + } \ + default: \ + __cmpxchg_called_with_bad_pointer(); \ + } \ + likely(__cc == 0); \ }) -void __cmpxchg_called_with_bad_pointer(void); +#else /* __HAVE_ASM_FLAG_OUTPUTS__ */ -static __always_inline unsigned long __cmpxchg(unsigned long address, - unsigned long old, - unsigned long new, int size) +#define arch_try_cmpxchg(ptr, oldp, new) \ +({ \ + __typeof__((ptr)) __oldp = (__typeof__(ptr))(oldp); \ + __typeof__(*(ptr)) __old = *__oldp; \ + __typeof__(*(ptr)) __new = (new); \ + __typeof__(*(ptr)) __prev; \ + \ + __prev = arch_cmpxchg((ptr), (__old), (__new)); \ + if (unlikely(__prev != __old)) \ + *__oldp = __prev; \ + likely(__prev == __old); \ +}) + +#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */ + +#define arch_try_cmpxchg64 arch_try_cmpxchg +#define arch_try_cmpxchg_local arch_try_cmpxchg +#define arch_try_cmpxchg64_local arch_try_cmpxchg + +void __xchg_called_with_bad_pointer(void); + +static inline u8 __arch_xchg1(u64 ptr, u8 x) +{ + int shift = (3 ^ (ptr & 3)) << 3; + u32 mask, old, new; + + ptr &= ~0x3; + mask = ~(0xff << shift); + old = READ_ONCE(*(u32 *)ptr); + do { + new = old & mask; + new |= x << shift; + } while (!arch_try_cmpxchg((u32 *)ptr, &old, new)); + return old >> shift; +} + +static inline u16 __arch_xchg2(u64 ptr, u16 x) +{ + int shift = (2 ^ (ptr & 2)) << 3; + u32 mask, old, new; + + ptr &= ~0x3; + mask = ~(0xffff << shift); + old = READ_ONCE(*(u32 *)ptr); + do { + new = old & mask; + new |= x << shift; + } while (!arch_try_cmpxchg((u32 *)ptr, &old, new)); + return old >> shift; +} + +static __always_inline u64 __arch_xchg(u64 ptr, u64 x, int size) { switch (size) { - case 1: { - unsigned int prev, shift, mask; - - shift = (3 ^ (address & 3)) << 3; - address ^= address & 3; - old = (old & 0xff) << shift; - new = (new & 0xff) << shift; - mask = ~(0xff << shift); - asm volatile( - " l %[prev],%[address]\n" - " nr %[prev],%[mask]\n" - " xilf %[mask],0xffffffff\n" - " or %[new],%[prev]\n" - " or %[prev],%[tmp]\n" - "0: lr %[tmp],%[prev]\n" - " cs %[prev],%[new],%[address]\n" - " jnl 1f\n" - " xr %[tmp],%[prev]\n" - " xr %[new],%[tmp]\n" - " nr %[tmp],%[mask]\n" - " jz 0b\n" - "1:" - : [prev] "=&d" (prev), - [address] "+Q" (*(int *)address), - [tmp] "+&d" (old), - [new] "+&d" (new), - [mask] "+&d" (mask) - :: "memory", "cc"); - return prev >> shift; - } - case 2: { - unsigned int prev, shift, mask; - - shift = (2 ^ (address & 2)) << 3; - address ^= address & 2; - old = (old & 0xffff) << shift; - new = (new & 0xffff) << shift; - mask = ~(0xffff << shift); - asm volatile( - " l %[prev],%[address]\n" - " nr %[prev],%[mask]\n" - " xilf %[mask],0xffffffff\n" - " or %[new],%[prev]\n" - " or %[prev],%[tmp]\n" - "0: lr %[tmp],%[prev]\n" - " cs %[prev],%[new],%[address]\n" - " jnl 1f\n" - " xr %[tmp],%[prev]\n" - " xr %[new],%[tmp]\n" - " nr %[tmp],%[mask]\n" - " jz 0b\n" - "1:" - : [prev] "=&d" (prev), - [address] "+Q" (*(int *)address), - [tmp] "+&d" (old), - [new] "+&d" (new), - [mask] "+&d" (mask) - :: "memory", "cc"); - return prev >> shift; - } + case 1: + return __arch_xchg1(ptr, x & 0xff); + case 2: + return __arch_xchg2(ptr, x & 0xffff); case 4: { - unsigned int prev = old; - - asm volatile( - " cs %[prev],%[new],%[address]\n" - : [prev] "+&d" (prev), - [address] "+Q" (*(int *)address) - : [new] "d" (new) - : "memory", "cc"); - return prev; + u32 old = READ_ONCE(*(u32 *)ptr); + + do { + } while (!arch_try_cmpxchg((u32 *)ptr, &old, x & 0xffffffff)); + return old; } case 8: { - unsigned long prev = old; - - asm volatile( - " csg %[prev],%[new],%[address]\n" - : [prev] "+&d" (prev), - [address] "+QS" (*(long *)address) - : [new] "d" (new) - : "memory", "cc"); - return prev; + u64 old = READ_ONCE(*(u64 *)ptr); + + do { + } while (!arch_try_cmpxchg((u64 *)ptr, &old, x)); + return old; } } - __cmpxchg_called_with_bad_pointer(); - return old; + __xchg_called_with_bad_pointer(); + return x; } -#define arch_cmpxchg(ptr, o, n) \ +#define arch_xchg(ptr, x) \ ({ \ - __typeof__(*(ptr)) __ret; \ - \ - __ret = (__typeof__(*(ptr))) \ - __cmpxchg((unsigned long)(ptr), (unsigned long)(o), \ - (unsigned long)(n), sizeof(*(ptr))); \ - __ret; \ + (__typeof__(*(ptr)))__arch_xchg((unsigned long)(ptr), \ + (unsigned long)(x), \ + sizeof(*(ptr))); \ }) -#define arch_cmpxchg64 arch_cmpxchg -#define arch_cmpxchg_local arch_cmpxchg -#define arch_cmpxchg64_local arch_cmpxchg - #define system_has_cmpxchg128() 1 static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 new) @@ -203,5 +249,25 @@ static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 n } #define arch_cmpxchg128 arch_cmpxchg128 +#define arch_cmpxchg128_local arch_cmpxchg128 + +#ifdef __HAVE_ASM_FLAG_OUTPUTS__ + +static __always_inline bool arch_try_cmpxchg128(volatile u128 *ptr, u128 *oldp, u128 new) +{ + int cc; + + asm volatile( + " cdsg %[old],%[new],%[ptr]\n" + : [old] "+d" (*oldp), [ptr] "+QS" (*ptr), "=@cc" (cc) + : [new] "d" (new) + : "memory"); + return likely(cc == 0); +} + +#define arch_try_cmpxchg128 arch_try_cmpxchg128 +#define arch_try_cmpxchg128_local arch_try_cmpxchg128 + +#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */ #endif /* __ASM_CMPXCHG_H */ diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h index dae8843b164f..59ab1192e2d5 100644 --- a/arch/s390/include/asm/cpacf.h +++ b/arch/s390/include/asm/cpacf.h @@ -54,6 +54,10 @@ #define CPACF_KM_XTS_256 0x34 #define CPACF_KM_PXTS_128 0x3a #define CPACF_KM_PXTS_256 0x3c +#define CPACF_KM_XTS_128_FULL 0x52 +#define CPACF_KM_XTS_256_FULL 0x54 +#define CPACF_KM_PXTS_128_FULL 0x5a +#define CPACF_KM_PXTS_256_FULL 0x5c /* * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING) @@ -121,23 +125,31 @@ #define CPACF_KMAC_DEA 0x01 #define CPACF_KMAC_TDEA_128 0x02 #define CPACF_KMAC_TDEA_192 0x03 +#define CPACF_KMAC_HMAC_SHA_224 0x70 +#define CPACF_KMAC_HMAC_SHA_256 0x71 +#define CPACF_KMAC_HMAC_SHA_384 0x72 +#define CPACF_KMAC_HMAC_SHA_512 0x73 /* * Function codes for the PCKMO (PERFORM CRYPTOGRAPHIC KEY MANAGEMENT) * instruction */ -#define CPACF_PCKMO_QUERY 0x00 -#define CPACF_PCKMO_ENC_DES_KEY 0x01 -#define CPACF_PCKMO_ENC_TDES_128_KEY 0x02 -#define CPACF_PCKMO_ENC_TDES_192_KEY 0x03 -#define CPACF_PCKMO_ENC_AES_128_KEY 0x12 -#define CPACF_PCKMO_ENC_AES_192_KEY 0x13 -#define CPACF_PCKMO_ENC_AES_256_KEY 0x14 -#define CPACF_PCKMO_ENC_ECC_P256_KEY 0x20 -#define CPACF_PCKMO_ENC_ECC_P384_KEY 0x21 -#define CPACF_PCKMO_ENC_ECC_P521_KEY 0x22 -#define CPACF_PCKMO_ENC_ECC_ED25519_KEY 0x28 -#define CPACF_PCKMO_ENC_ECC_ED448_KEY 0x29 +#define CPACF_PCKMO_QUERY 0x00 +#define CPACF_PCKMO_ENC_DES_KEY 0x01 +#define CPACF_PCKMO_ENC_TDES_128_KEY 0x02 +#define CPACF_PCKMO_ENC_TDES_192_KEY 0x03 +#define CPACF_PCKMO_ENC_AES_128_KEY 0x12 +#define CPACF_PCKMO_ENC_AES_192_KEY 0x13 +#define CPACF_PCKMO_ENC_AES_256_KEY 0x14 +#define CPACF_PCKMO_ENC_AES_XTS_128_DOUBLE_KEY 0x15 +#define CPACF_PCKMO_ENC_AES_XTS_256_DOUBLE_KEY 0x16 +#define CPACF_PCKMO_ENC_ECC_P256_KEY 0x20 +#define CPACF_PCKMO_ENC_ECC_P384_KEY 0x21 +#define CPACF_PCKMO_ENC_ECC_P521_KEY 0x22 +#define CPACF_PCKMO_ENC_ECC_ED25519_KEY 0x28 +#define CPACF_PCKMO_ENC_ECC_ED448_KEY 0x29 +#define CPACF_PCKMO_ENC_HMAC_512_KEY 0x76 +#define CPACF_PCKMO_ENC_HMAC_1024_KEY 0x7a /* * Function codes for the PRNO (PERFORM RANDOM NUMBER OPERATION) @@ -165,7 +177,40 @@ #define CPACF_KMA_LAAD 0x200 /* Last-AAD */ #define CPACF_KMA_HS 0x400 /* Hash-subkey Supplied */ +/* + * Flags for the KIMD/KLMD (COMPUTE INTERMEDIATE/LAST MESSAGE DIGEST) + * instructions + */ +#define CPACF_KIMD_NIP 0x8000 +#define CPACF_KLMD_DUFOP 0x4000 +#define CPACF_KLMD_NIP 0x8000 + +/* + * Function codes for KDSA (COMPUTE DIGITAL SIGNATURE AUTHENTICATION) + * instruction + */ +#define CPACF_KDSA_QUERY 0x00 +#define CPACF_KDSA_ECDSA_VERIFY_P256 0x01 +#define CPACF_KDSA_ECDSA_VERIFY_P384 0x02 +#define CPACF_KDSA_ECDSA_VERIFY_P521 0x03 +#define CPACF_KDSA_ECDSA_SIGN_P256 0x09 +#define CPACF_KDSA_ECDSA_SIGN_P384 0x0a +#define CPACF_KDSA_ECDSA_SIGN_P521 0x0b +#define CPACF_KDSA_ENC_ECDSA_SIGN_P256 0x11 +#define CPACF_KDSA_ENC_ECDSA_SIGN_P384 0x12 +#define CPACF_KDSA_ENC_ECDSA_SIGN_P521 0x13 +#define CPACF_KDSA_EDDSA_VERIFY_ED25519 0x20 +#define CPACF_KDSA_EDDSA_VERIFY_ED448 0x24 +#define CPACF_KDSA_EDDSA_SIGN_ED25519 0x28 +#define CPACF_KDSA_EDDSA_SIGN_ED448 0x2c +#define CPACF_KDSA_ENC_EDDSA_SIGN_ED25519 0x30 +#define CPACF_KDSA_ENC_EDDSA_SIGN_ED448 0x34 + +#define CPACF_FC_QUERY 0x00 +#define CPACF_FC_QUERY_AUTH_INFO 0x7F + typedef struct { unsigned char bytes[16]; } cpacf_mask_t; +typedef struct { unsigned char bytes[256]; } cpacf_qai_t; /* * Prototype for a not existing function to produce a link @@ -175,80 +220,85 @@ typedef struct { unsigned char bytes[16]; } cpacf_mask_t; void __cpacf_bad_opcode(void); static __always_inline void __cpacf_query_rre(u32 opc, u8 r1, u8 r2, - cpacf_mask_t *mask) + u8 *pb, u8 fc) { asm volatile( - " la %%r1,%[mask]\n" - " xgr %%r0,%%r0\n" + " la %%r1,%[pb]\n" + " lghi %%r0,%[fc]\n" " .insn rre,%[opc] << 16,%[r1],%[r2]\n" - : [mask] "=R" (*mask) - : [opc] "i" (opc), + : [pb] "=R" (*pb) + : [opc] "i" (opc), [fc] "i" (fc), [r1] "i" (r1), [r2] "i" (r2) - : "cc", "r0", "r1"); + : "cc", "memory", "r0", "r1"); } -static __always_inline void __cpacf_query_rrf(u32 opc, - u8 r1, u8 r2, u8 r3, u8 m4, - cpacf_mask_t *mask) +static __always_inline void __cpacf_query_rrf(u32 opc, u8 r1, u8 r2, u8 r3, + u8 m4, u8 *pb, u8 fc) { asm volatile( - " la %%r1,%[mask]\n" - " xgr %%r0,%%r0\n" + " la %%r1,%[pb]\n" + " lghi %%r0,%[fc]\n" " .insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]\n" - : [mask] "=R" (*mask) - : [opc] "i" (opc), [r1] "i" (r1), [r2] "i" (r2), - [r3] "i" (r3), [m4] "i" (m4) - : "cc", "r0", "r1"); + : [pb] "=R" (*pb) + : [opc] "i" (opc), [fc] "i" (fc), [r1] "i" (r1), + [r2] "i" (r2), [r3] "i" (r3), [m4] "i" (m4) + : "cc", "memory", "r0", "r1"); } -static __always_inline void __cpacf_query(unsigned int opcode, - cpacf_mask_t *mask) +static __always_inline void __cpacf_query_insn(unsigned int opcode, void *pb, + u8 fc) { switch (opcode) { case CPACF_KDSA: - __cpacf_query_rre(CPACF_KDSA, 0, 2, mask); + __cpacf_query_rre(CPACF_KDSA, 0, 2, pb, fc); break; case CPACF_KIMD: - __cpacf_query_rre(CPACF_KIMD, 0, 2, mask); + __cpacf_query_rre(CPACF_KIMD, 0, 2, pb, fc); break; case CPACF_KLMD: - __cpacf_query_rre(CPACF_KLMD, 0, 2, mask); + __cpacf_query_rre(CPACF_KLMD, 0, 2, pb, fc); break; case CPACF_KM: - __cpacf_query_rre(CPACF_KM, 2, 4, mask); + __cpacf_query_rre(CPACF_KM, 2, 4, pb, fc); break; case CPACF_KMA: - __cpacf_query_rrf(CPACF_KMA, 2, 4, 6, 0, mask); + __cpacf_query_rrf(CPACF_KMA, 2, 4, 6, 0, pb, fc); break; case CPACF_KMAC: - __cpacf_query_rre(CPACF_KMAC, 0, 2, mask); + __cpacf_query_rre(CPACF_KMAC, 0, 2, pb, fc); break; case CPACF_KMC: - __cpacf_query_rre(CPACF_KMC, 2, 4, mask); + __cpacf_query_rre(CPACF_KMC, 2, 4, pb, fc); break; case CPACF_KMCTR: - __cpacf_query_rrf(CPACF_KMCTR, 2, 4, 6, 0, mask); + __cpacf_query_rrf(CPACF_KMCTR, 2, 4, 6, 0, pb, fc); break; case CPACF_KMF: - __cpacf_query_rre(CPACF_KMF, 2, 4, mask); + __cpacf_query_rre(CPACF_KMF, 2, 4, pb, fc); break; case CPACF_KMO: - __cpacf_query_rre(CPACF_KMO, 2, 4, mask); + __cpacf_query_rre(CPACF_KMO, 2, 4, pb, fc); break; case CPACF_PCC: - __cpacf_query_rre(CPACF_PCC, 0, 0, mask); + __cpacf_query_rre(CPACF_PCC, 0, 0, pb, fc); break; case CPACF_PCKMO: - __cpacf_query_rre(CPACF_PCKMO, 0, 0, mask); + __cpacf_query_rre(CPACF_PCKMO, 0, 0, pb, fc); break; case CPACF_PRNO: - __cpacf_query_rre(CPACF_PRNO, 2, 4, mask); + __cpacf_query_rre(CPACF_PRNO, 2, 4, pb, fc); break; default: __cpacf_bad_opcode(); } } +static __always_inline void __cpacf_query(unsigned int opcode, + cpacf_mask_t *mask) +{ + __cpacf_query_insn(opcode, mask, CPACF_FC_QUERY); +} + static __always_inline int __cpacf_check_opcode(unsigned int opcode) { switch (opcode) { @@ -269,6 +319,8 @@ static __always_inline int __cpacf_check_opcode(unsigned int opcode) return test_facility(57); /* check for MSA5 */ case CPACF_KMA: return test_facility(146); /* check for MSA8 */ + case CPACF_KDSA: + return test_facility(155); /* check for MSA9 */ default: __cpacf_bad_opcode(); return 0; @@ -276,14 +328,15 @@ static __always_inline int __cpacf_check_opcode(unsigned int opcode) } /** - * cpacf_query() - check if a specific CPACF function is available + * cpacf_query() - Query the function code mask for this CPACF opcode * @opcode: the opcode of the crypto instruction - * @func: the function code to test for + * @mask: ptr to struct cpacf_mask_t * * Executes the query function for the given crypto instruction @opcode * and checks if @func is available * - * Returns 1 if @func is available for @opcode, 0 otherwise + * On success 1 is returned and the mask is filled with the function + * code mask for this CPACF opcode, otherwise 0 is returned. */ static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask) { @@ -300,7 +353,8 @@ static inline int cpacf_test_func(cpacf_mask_t *mask, unsigned int func) return (mask->bytes[func >> 3] & (0x80 >> (func & 7))) != 0; } -static __always_inline int cpacf_query_func(unsigned int opcode, unsigned int func) +static __always_inline int cpacf_query_func(unsigned int opcode, + unsigned int func) { cpacf_mask_t mask; @@ -309,6 +363,32 @@ static __always_inline int cpacf_query_func(unsigned int opcode, unsigned int fu return 0; } +static __always_inline void __cpacf_qai(unsigned int opcode, cpacf_qai_t *qai) +{ + __cpacf_query_insn(opcode, qai, CPACF_FC_QUERY_AUTH_INFO); +} + +/** + * cpacf_qai() - Get the query authentication information for a CPACF opcode + * @opcode: the opcode of the crypto instruction + * @mask: ptr to struct cpacf_qai_t + * + * Executes the query authentication information function for the given crypto + * instruction @opcode and checks if @func is available + * + * On success 1 is returned and the mask is filled with the query authentication + * information for this CPACF opcode, otherwise 0 is returned. + */ +static __always_inline int cpacf_qai(unsigned int opcode, cpacf_qai_t *qai) +{ + if (cpacf_query_func(opcode, CPACF_FC_QUERY_AUTH_INFO)) { + __cpacf_qai(opcode, qai); + return 1; + } + memset(qai, 0, sizeof(*qai)); + return 0; +} + /** * cpacf_km() - executes the KM (CIPHER MESSAGE) instruction * @func: the function code passed to KM; see CPACF_KM_xxx defines @@ -391,7 +471,7 @@ static inline void cpacf_kimd(unsigned long func, void *param, asm volatile( " lgr 0,%[fc]\n" " lgr 1,%[pba]\n" - "0: .insn rre,%[opc] << 16,0,%[src]\n" + "0: .insn rrf,%[opc] << 16,0,%[src],8,0\n" " brc 1,0b\n" /* handle partial completion */ : [src] "+&d" (s.pair) : [fc] "d" (func), [pba] "d" ((unsigned long)(param)), @@ -416,7 +496,7 @@ static inline void cpacf_klmd(unsigned long func, void *param, asm volatile( " lgr 0,%[fc]\n" " lgr 1,%[pba]\n" - "0: .insn rre,%[opc] << 16,0,%[src]\n" + "0: .insn rrf,%[opc] << 16,0,%[src],8,0\n" " brc 1,0b\n" /* handle partial completion */ : [src] "+&d" (s.pair) : [fc] "d" (func), [pba] "d" ((unsigned long)param), @@ -425,29 +505,30 @@ static inline void cpacf_klmd(unsigned long func, void *param, } /** - * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) - * instruction - * @func: the function code passed to KM; see CPACF_KMAC_xxx defines + * _cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) + * instruction and updates flags in gr0 + * @gr0: pointer to gr0 (fc and flags) passed to KMAC; see CPACF_KMAC_xxx defines * @param: address of parameter block; see POP for details on each func * @src: address of source memory area * @src_len: length of src operand in bytes * * Returns 0 for the query func, number of processed bytes for digest funcs */ -static inline int cpacf_kmac(unsigned long func, void *param, - const u8 *src, long src_len) +static inline int _cpacf_kmac(unsigned long *gr0, void *param, + const u8 *src, long src_len) { union register_pair s; s.even = (unsigned long)src; s.odd = (unsigned long)src_len; asm volatile( - " lgr 0,%[fc]\n" + " lgr 0,%[r0]\n" " lgr 1,%[pba]\n" "0: .insn rre,%[opc] << 16,0,%[src]\n" " brc 1,0b\n" /* handle partial completion */ - : [src] "+&d" (s.pair) - : [fc] "d" (func), [pba] "d" ((unsigned long)param), + " lgr %[r0],0\n" + : [r0] "+d" (*gr0), [src] "+&d" (s.pair) + : [pba] "d" ((unsigned long)param), [opc] "i" (CPACF_KMAC) : "cc", "memory", "0", "1"); @@ -455,6 +536,22 @@ static inline int cpacf_kmac(unsigned long func, void *param, } /** + * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) + * instruction + * @func: function code passed to KMAC; see CPACF_KMAC_xxx defines + * @param: address of parameter block; see POP for details on each func + * @src: address of source memory area + * @src_len: length of src operand in bytes + * + * Returns 0 for the query func, number of processed bytes for digest funcs + */ +static inline int cpacf_kmac(unsigned long func, void *param, + const u8 *src, long src_len) +{ + return _cpacf_kmac(&func, param, src, src_len); +} + +/** * cpacf_kmctr() - executes the KMCTR (CIPHER MESSAGE WITH COUNTER) instruction * @func: the function code passed to KMCTR; see CPACF_KMCTR_xxx defines * @param: address of parameter block; see POP for details on each func diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index 9e4bbc3e53f8..e1a279e0d6a6 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h @@ -13,6 +13,7 @@ #include <linux/kmsan-checks.h> #include <asm/asm-extable.h> #include <asm/facility.h> +#include <asm/asm.h> asm(".include \"asm/cpu_mf-insn.h\"\n"); @@ -185,11 +186,12 @@ static inline int lcctl(u64 ctl) int cc; asm volatile ( - " lcctl %1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) : "Q" (ctl) : "cc"); - return cc; + " lcctl %[ctl]\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [ctl] "Q" (ctl) + : CC_CLOBBER); + return CC_TRANSFORM(cc); } /* Extract CPU counter */ @@ -199,12 +201,13 @@ static inline int __ecctr(u64 ctr, u64 *content) int cc; asm volatile ( - " ecctr %0,%2\n" - " ipm %1\n" - " srl %1,28\n" - : "=d" (_content), "=d" (cc) : "d" (ctr) : "cc"); + " ecctr %[_content],%[ctr]\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [_content] "=d" (_content) + : [ctr] "d" (ctr) + : CC_CLOBBER); *content = _content; - return cc; + return CC_TRANSFORM(cc); } /* Extract CPU counter */ @@ -234,18 +237,17 @@ static __always_inline int stcctm(enum stcctm_ctr_set set, u64 range, u64 *dest) int cc; asm volatile ( - " STCCTM %2,%3,%1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) - : "Q" (*dest), "d" (range), "i" (set) - : "cc", "memory"); + " STCCTM %[range],%[set],%[dest]\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [dest] "Q" (*dest), [range] "d" (range), [set] "i" (set) + : CC_CLOBBER_LIST("memory")); /* * If cc == 2, less than RANGE counters are stored, but it's not easy * to tell how many. Always unpoison the whole range for simplicity. */ kmsan_unpoison_memory(dest, range * sizeof(u64)); - return cc; + return CC_TRANSFORM(cc); } /* Query sampling information */ @@ -265,19 +267,20 @@ static inline int qsi(struct hws_qsi_info_block *info) /* Load sampling controls */ static inline int lsctl(struct hws_lsctl_request_block *req) { - int cc; + int cc, exception; - cc = 1; + exception = 1; asm volatile( - "0: lsctl 0(%1)\n" - "1: ipm %0\n" - " srl %0,28\n" + "0: lsctl %[req]\n" + "1: lhi %[exc],0\n" "2:\n" + CC_IPM(cc) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : "+d" (cc), "+a" (req) - : "m" (*req) - : "cc", "memory"); - - return cc ? -EINVAL : 0; + : CC_OUT(cc, cc), [exc] "+d" (exception) + : [req] "Q" (*req) + : CC_CLOBBER); + if (exception || CC_TRANSFORM(cc)) + return -EINVAL; + return 0; } #endif /* _ASM_S390_CPU_MF_H */ diff --git a/arch/s390/include/asm/ctlreg.h b/arch/s390/include/asm/ctlreg.h index 72a9556d04f3..e6527f51ad0b 100644 --- a/arch/s390/include/asm/ctlreg.h +++ b/arch/s390/include/asm/ctlreg.h @@ -202,8 +202,9 @@ union ctlreg0 { unsigned long : 3; unsigned long ccc : 1; /* Cryptography counter control */ unsigned long pec : 1; /* PAI extension control */ - unsigned long : 17; - unsigned long : 3; + unsigned long : 15; + unsigned long wti : 1; /* Warning-track */ + unsigned long : 4; unsigned long lap : 1; /* Low-address-protection control */ unsigned long : 4; unsigned long edat : 1; /* Enhanced-DAT-enablement control */ diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index c0d43512f4fc..e1316e181230 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h @@ -38,6 +38,7 @@ enum diag_stat_enum { DIAG_STAT_X308, DIAG_STAT_X318, DIAG_STAT_X320, + DIAG_STAT_X49C, DIAG_STAT_X500, NR_DIAG_STAT }; @@ -363,4 +364,12 @@ void _diag0c_amode31(unsigned long rx); void _diag308_reset_amode31(void); int _diag8c_amode31(struct diag8c *addr, struct ccw_dev_id *devno, size_t len); +/* diag 49c subcodes */ +enum diag49c_sc { + DIAG49C_SUBC_ACK = 0, + DIAG49C_SUBC_REG = 1 +}; + +int diag49c(unsigned long subcode); + #endif /* _ASM_S390_DIAG_H */ diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index b7d234838a36..5f5b1aa6c233 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -14,7 +14,7 @@ #include <linux/string.h> #include <linux/types.h> #include <linux/preempt.h> - +#include <asm/alternative.h> #include <asm/lowcore.h> #define MAX_FACILITY_BIT (sizeof(stfle_fac_list) * 8) @@ -39,33 +39,56 @@ static inline void __clear_facility(unsigned long nr, void *facilities) ptr[nr >> 3] &= ~(0x80 >> (nr & 7)); } -static inline int __test_facility(unsigned long nr, void *facilities) +static __always_inline bool __test_facility(unsigned long nr, void *facilities) { unsigned char *ptr; if (nr >= MAX_FACILITY_BIT) - return 0; + return false; ptr = (unsigned char *) facilities + (nr >> 3); return (*ptr & (0x80 >> (nr & 7))) != 0; } /* + * __test_facility_constant() generates a single instruction branch. If the + * tested facility is available (likely) the branch is patched into a nop. + * + * Do not use this function unless you know what you are doing. All users are + * supposed to use test_facility() which will do the right thing. + */ +static __always_inline bool __test_facility_constant(unsigned long nr) +{ + asm goto( + ALTERNATIVE("brcl 15,%l[l_no]", "brcl 0,0", ALT_FACILITY(%[nr])) + : + : [nr] "i" (nr) + : + : l_no); + return true; +l_no: + return false; +} + +/* * The test_facility function uses the bit ordering where the MSB is bit 0. * That makes it easier to query facility bits with the bit number as * documented in the Principles of Operation. */ -static inline int test_facility(unsigned long nr) +static __always_inline bool test_facility(unsigned long nr) { unsigned long facilities_als[] = { FACILITIES_ALS }; - if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) { - if (__test_facility(nr, &facilities_als)) - return 1; + if (!__is_defined(__DECOMPRESSOR) && __builtin_constant_p(nr)) { + if (nr < sizeof(facilities_als) * 8) { + if (__test_facility(nr, &facilities_als)) + return true; + } + return __test_facility_constant(nr); } return __test_facility(nr, &stfle_fac_list); } -static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) +static inline unsigned long __stfle_asm(u64 *fac_list, int size) { unsigned long reg0 = size - 1; @@ -73,7 +96,7 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) " lgr 0,%[reg0]\n" " .insn s,0xb2b00000,%[list]\n" /* stfle */ " lgr %[reg0],0\n" - : [reg0] "+&d" (reg0), [list] "+Q" (*stfle_fac_list) + : [reg0] "+&d" (reg0), [list] "+Q" (*fac_list) : : "memory", "cc", "0"); return reg0; @@ -81,10 +104,10 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) /** * stfle - Store facility list extended - * @stfle_fac_list: array where facility list can be stored + * @fac_list: array where facility list can be stored * @size: size of passed in array in double words */ -static inline void __stfle(u64 *stfle_fac_list, int size) +static inline void __stfle(u64 *fac_list, int size) { unsigned long nr; u32 stfl_fac_list; @@ -93,20 +116,20 @@ static inline void __stfle(u64 *stfle_fac_list, int size) " stfl 0(0)\n" : "=m" (get_lowcore()->stfl_fac_list)); stfl_fac_list = get_lowcore()->stfl_fac_list; - memcpy(stfle_fac_list, &stfl_fac_list, 4); + memcpy(fac_list, &stfl_fac_list, 4); nr = 4; /* bytes stored by stfl */ if (stfl_fac_list & 0x01000000) { /* More facility bits available with stfle */ - nr = __stfle_asm(stfle_fac_list, size); + nr = __stfle_asm(fac_list, size); nr = min_t(unsigned long, (nr + 1) * 8, size * 8); } - memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); + memset((char *)fac_list + nr, 0, size * 8 - nr); } -static inline void stfle(u64 *stfle_fac_list, int size) +static inline void stfle(u64 *fac_list, int size) { preempt_disable(); - __stfle(stfle_fac_list, size); + __stfle(fac_list, size); preempt_enable(); } diff --git a/arch/s390/include/asm/fpu-insn-asm.h b/arch/s390/include/asm/fpu-insn-asm.h index 02ccfe46050a..d296322be4bc 100644 --- a/arch/s390/include/asm/fpu-insn-asm.h +++ b/arch/s390/include/asm/fpu-insn-asm.h @@ -407,6 +407,28 @@ MRXBOPC 0, 0x0E, v1 .endm +/* VECTOR STORE BYTE REVERSED ELEMENTS */ + .macro VSTBR vr1, disp, index="%r0", base, m + VX_NUM v1, \vr1 + GR_NUM x2, \index + GR_NUM b2, \base + .word 0xE600 | ((v1&15) << 4) | (x2&15) + .word (b2 << 12) | (\disp) + MRXBOPC \m, 0x0E, v1 +.endm +.macro VSTBRH vr1, disp, index="%r0", base + VSTBR \vr1, \disp, \index, \base, 1 +.endm +.macro VSTBRF vr1, disp, index="%r0", base + VSTBR \vr1, \disp, \index, \base, 2 +.endm +.macro VSTBRG vr1, disp, index="%r0", base + VSTBR \vr1, \disp, \index, \base, 3 +.endm +.macro VSTBRQ vr1, disp, index="%r0", base + VSTBR \vr1, \disp, \index, \base, 4 +.endm + /* VECTOR STORE MULTIPLE */ .macro VSTM vfrom, vto, disp, base, hint=3 VX_NUM v1, \vfrom diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index fbadca645af7..fc97d75dc752 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -6,8 +6,23 @@ #define MCOUNT_INSN_SIZE 6 #ifndef __ASSEMBLY__ +#include <asm/stacktrace.h> -unsigned long return_address(unsigned int n); +static __always_inline unsigned long return_address(unsigned int n) +{ + struct stack_frame *sf; + + if (!n) + return (unsigned long)__builtin_return_address(0); + + sf = (struct stack_frame *)current_frame_address(); + do { + sf = (struct stack_frame *)sf->back_chain; + if (!sf) + return 0; + } while (--n); + return sf->gprs[8]; +} #define ftrace_return_address(n) return_address(n) void ftrace_caller(void); @@ -36,13 +51,11 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) return addr; } -struct ftrace_regs { - struct pt_regs regs; -}; +#include <linux/ftrace_regs.h> static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs) { - struct pt_regs *regs = &fregs->regs; + struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs; if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS)) return regs; @@ -66,32 +79,13 @@ static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -static __always_inline unsigned long -ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs) -{ - return fregs->regs.psw.addr; -} - static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip) { - fregs->regs.psw.addr = ip; + arch_ftrace_regs(fregs)->regs.psw.addr = ip; } -#define ftrace_regs_get_argument(fregs, n) \ - regs_get_kernel_argument(&(fregs)->regs, n) -#define ftrace_regs_get_stack_pointer(fregs) \ - kernel_stack_pointer(&(fregs)->regs) -#define ftrace_regs_return_value(fregs) \ - regs_return_value(&(fregs)->regs) -#define ftrace_regs_set_return_value(fregs, ret) \ - regs_set_return_value(&(fregs)->regs, ret) -#define ftrace_override_function_with_return(fregs) \ - override_function_with_return(&(fregs)->regs) -#define ftrace_regs_query_register_offset(name) \ - regs_query_register_offset(name) - #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS /* * When an ftrace registered caller is tracing a function that is @@ -102,7 +96,7 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, */ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) { - struct pt_regs *regs = &fregs->regs; + struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs; regs->orig_gpr2 = addr; } #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h index 9725586f4259..64761c78f774 100644 --- a/arch/s390/include/asm/gmap.h +++ b/arch/s390/include/asm/gmap.h @@ -107,9 +107,6 @@ void gmap_remove(struct gmap *gmap); struct gmap *gmap_get(struct gmap *gmap); void gmap_put(struct gmap *gmap); -void gmap_enable(struct gmap *gmap); -void gmap_disable(struct gmap *gmap); -struct gmap *gmap_get_enabled(void); int gmap_map_segment(struct gmap *gmap, unsigned long from, unsigned long to, unsigned long len); int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); diff --git a/arch/s390/include/asm/hiperdispatch.h b/arch/s390/include/asm/hiperdispatch.h new file mode 100644 index 000000000000..27e23aa27a24 --- /dev/null +++ b/arch/s390/include/asm/hiperdispatch.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright IBM Corp. 2024 + */ + +#ifndef _ASM_HIPERDISPATCH_H +#define _ASM_HIPERDISPATCH_H + +void hd_reset_state(void); +void hd_add_core(int cpu); +void hd_disable_hiperdispatch(void); +int hd_enable_hiperdispatch(void); + +#endif /* _ASM_HIPERDISPATCH_H */ diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index 0fbc992d7a5e..fc9933a743d6 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h @@ -16,8 +16,10 @@ #include <asm/pci_io.h> #define xlate_dev_mem_ptr xlate_dev_mem_ptr +#define kc_xlate_dev_mem_ptr xlate_dev_mem_ptr void *xlate_dev_mem_ptr(phys_addr_t phys); #define unxlate_dev_mem_ptr unxlate_dev_mem_ptr +#define kc_unxlate_dev_mem_ptr unxlate_dev_mem_ptr void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr); #define IO_SPACE_LIMIT 0 diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 54b42817f70a..d9e705f4a697 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h @@ -47,6 +47,7 @@ enum interruption_class { IRQEXT_CMS, IRQEXT_CMC, IRQEXT_FTP, + IRQEXT_WTI, IRQIO_CIO, IRQIO_DAS, IRQIO_C15, @@ -99,6 +100,7 @@ int unregister_external_irq(u16 code, ext_int_handler_t handler); enum irq_subclass { IRQ_SUBCLASS_MEASUREMENT_ALERT = 5, IRQ_SUBCLASS_SERVICE_SIGNAL = 9, + IRQ_SUBCLASS_WARNING_TRACK = 33, }; #define CR0_IRQ_SUBCLASS_MASK \ diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h index 1bd08eb56d5f..9084b750350d 100644 --- a/arch/s390/include/asm/kexec.h +++ b/arch/s390/include/asm/kexec.h @@ -94,6 +94,9 @@ void arch_kexec_protect_crashkres(void); void arch_kexec_unprotect_crashkres(void); #define arch_kexec_unprotect_crashkres arch_kexec_unprotect_crashkres + +bool is_kdump_kernel(void); +#define is_kdump_kernel is_kdump_kernel #endif #ifdef CONFIG_KEXEC_FILE diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 8e77afbed58e..51201b4ac93a 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -527,6 +527,9 @@ struct kvm_vcpu_stat { #define PGM_REGION_FIRST_TRANS 0x39 #define PGM_REGION_SECOND_TRANS 0x3a #define PGM_REGION_THIRD_TRANS 0x3b +#define PGM_SECURE_STORAGE_ACCESS 0x3d +#define PGM_NON_SECURE_STORAGE_ACCESS 0x3e +#define PGM_SECURE_STORAGE_VIOLATION 0x3f #define PGM_MONITOR 0x40 #define PGM_PER 0x80 #define PGM_CRYPTO_OPERATION 0x119 @@ -747,8 +750,6 @@ struct kvm_vcpu_arch { struct hrtimer ckc_timer; struct kvm_s390_pgm_info pgm; struct gmap *gmap; - /* backup location for the currently enabled gmap when scheduled out */ - struct gmap *enabled_gmap; struct kvm_guestdbg_info_arch guestdbg; unsigned long pfault_token; unsigned long pfault_select; diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 183ac29afaf8..42a092fa1029 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -98,8 +98,8 @@ struct lowcore { psw_t io_new_psw; /* 0x01f0 */ /* Save areas. */ - __u64 save_area_sync[8]; /* 0x0200 */ - __u64 save_area_async[8]; /* 0x0240 */ + __u64 save_area[8]; /* 0x0200 */ + __u8 pad_0x0240[0x0280-0x0240]; /* 0x0240 */ __u64 save_area_restart[1]; /* 0x0280 */ __u64 pcpu; /* 0x0288 */ @@ -165,8 +165,7 @@ struct lowcore { __u64 percpu_offset; /* 0x03b8 */ __u8 pad_0x03c0[0x03c8-0x03c0]; /* 0x03c0 */ __u64 machine_flags; /* 0x03c8 */ - __u64 gmap; /* 0x03d0 */ - __u8 pad_0x03d8[0x0400-0x03d8]; /* 0x03d8 */ + __u8 pad_0x03d0[0x0400-0x03d0]; /* 0x03d0 */ __u32 return_lpswe; /* 0x0400 */ __u32 return_mcck_lpswe; /* 0x0404 */ diff --git a/arch/s390/include/asm/march.h b/arch/s390/include/asm/march.h new file mode 100644 index 000000000000..fd9eef3be44c --- /dev/null +++ b/arch/s390/include/asm/march.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_S390_MARCH_H +#define __ASM_S390_MARCH_H + +#include <linux/kconfig.h> + +#define MARCH_HAS_Z10_FEATURES 1 + +#ifndef __DECOMPRESSOR + +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#define MARCH_HAS_Z196_FEATURES 1 +#endif + +#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES +#define MARCH_HAS_ZEC12_FEATURES 1 +#endif + +#ifdef CONFIG_HAVE_MARCH_Z13_FEATURES +#define MARCH_HAS_Z13_FEATURES 1 +#endif + +#ifdef CONFIG_HAVE_MARCH_Z14_FEATURES +#define MARCH_HAS_Z14_FEATURES 1 +#endif + +#ifdef CONFIG_HAVE_MARCH_Z15_FEATURES +#define MARCH_HAS_Z15_FEATURES 1 +#endif + +#ifdef CONFIG_HAVE_MARCH_Z16_FEATURES +#define MARCH_HAS_Z16_FEATURES 1 +#endif + +#endif /* __DECOMPRESSOR */ + +#endif /* __ASM_S390_MARCH_H */ diff --git a/arch/s390/include/asm/mmzone.h b/arch/s390/include/asm/mmzone.h deleted file mode 100644 index 73e3e7c6976c..000000000000 --- a/arch/s390/include/asm/mmzone.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * NUMA support for s390 - * - * Copyright IBM Corp. 2015 - */ - -#ifndef _ASM_S390_MMZONE_H -#define _ASM_S390_MMZONE_H - -#ifdef CONFIG_NUMA - -extern struct pglist_data *node_data[]; -#define NODE_DATA(nid) (node_data[nid]) - -#endif /* CONFIG_NUMA */ -#endif /* _ASM_S390_MMZONE_H */ diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h index 9f1eea15872c..916ab59e458a 100644 --- a/arch/s390/include/asm/module.h +++ b/arch/s390/include/asm/module.h @@ -38,4 +38,18 @@ struct mod_arch_specific { #endif /* CONFIG_FUNCTION_TRACER */ }; +static inline const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) +{ + const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + const Elf_Shdr *s, *se; + + for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) { + if (strcmp(name, secstrs + s->sh_name) == 0) + return s; + } + return NULL; +} + #endif /* _ASM_S390_MODULE_H */ diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 16e4caa931f1..d703e736bddc 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -10,15 +10,10 @@ #include <linux/const.h> #include <asm/types.h> +#include <asm/asm.h> -#define _PAGE_SHIFT CONFIG_PAGE_SHIFT -#define _PAGE_SIZE (_AC(1, UL) << _PAGE_SHIFT) -#define _PAGE_MASK (~(_PAGE_SIZE - 1)) +#include <vdso/page.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT _PAGE_SHIFT -#define PAGE_SIZE _PAGE_SIZE -#define PAGE_MASK _PAGE_MASK #define PAGE_DEFAULT_ACC _AC(0, UL) /* storage-protection override */ #define PAGE_SPO_ACC 9 @@ -148,11 +143,12 @@ static inline int page_reset_referenced(unsigned long addr) int cc; asm volatile( - " rrbe 0,%1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) : "a" (addr) : "cc"); - return cc; + " rrbe 0,%[addr]\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [addr] "a" (addr) + : CC_CLOBBER); + return CC_TRANSFORM(cc); } /* Bits int the storage key */ @@ -176,8 +172,6 @@ static inline int devmem_is_allowed(unsigned long pfn) int arch_make_folio_accessible(struct folio *folio); #define HAVE_ARCH_MAKE_FOLIO_ACCESSIBLE -int arch_make_page_accessible(struct page *page); -#define HAVE_ARCH_MAKE_PAGE_ACCESSIBLE struct vm_layout { unsigned long kaslr_offset; diff --git a/arch/s390/include/asm/pai.h b/arch/s390/include/asm/pai.h index 25f2077ba3c9..ebeabd0aaa51 100644 --- a/arch/s390/include/asm/pai.h +++ b/arch/s390/include/asm/pai.h @@ -11,6 +11,7 @@ #include <linux/jump_label.h> #include <asm/lowcore.h> #include <asm/ptrace.h> +#include <asm/asm.h> struct qpaci_info_block { u64 header; @@ -33,12 +34,11 @@ static inline int qpaci(struct qpaci_info_block *info) " lgr 0,%[size]\n" " .insn s,0xb28f0000,%[info]\n" " lgr %[size],0\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=d" (cc), [info] "=Q" (*info), [size] "+&d" (size) + CC_IPM(cc) + : CC_OUT(cc, cc), [info] "=Q" (*info), [size] "+&d" (size) : - : "0", "cc", "memory"); - return cc ? (size + 1) * sizeof(u64) : 0; + : CC_CLOBBER_LIST("0", "memory")); + return CC_TRANSFORM(cc) ? (size + 1) * sizeof(u64) : 0; } #define PAI_CRYPTO_BASE 0x1000 /* First event number */ diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 30820a649e6e..5013a690837e 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -107,9 +107,10 @@ struct zpci_bus { struct list_head resources; struct list_head bus_next; struct resource bus_resource; - int pchid; + int topo; /* TID if topo_is_tid, PCHID otherwise */ int domain_nr; - bool multifunction; + u8 multifunction : 1; + u8 topo_is_tid : 1; enum pci_bus_speed max_bus_speed; }; @@ -130,9 +131,12 @@ struct zpci_dev { u16 vfn; /* virtual function number */ u16 pchid; /* physical channel ID */ u16 maxstbl; /* Maximum store block size */ + u16 rid; /* RID as supplied by firmware */ + u16 tid; /* Topology for which RID is valid */ u8 pfgid; /* function group ID */ u8 pft; /* pci function type */ u8 port; + u8 fidparm; u8 dtsm; /* Supported DT mask */ u8 rid_available : 1; u8 has_hp_slot : 1; @@ -140,7 +144,8 @@ struct zpci_dev { u8 is_physfn : 1; u8 util_str_avail : 1; u8 irqs_registered : 1; - u8 reserved : 2; + u8 tid_avail : 1; + u8 reserved : 1; unsigned int devfn; /* DEVFN part of the RID*/ u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */ @@ -191,7 +196,14 @@ static inline bool zdev_enabled(struct zpci_dev *zdev) return (zdev->fh & (1UL << 31)) ? true : false; } -extern const struct attribute_group *zpci_attr_groups[]; +extern const struct attribute_group zpci_attr_group; +extern const struct attribute_group pfip_attr_group; +extern const struct attribute_group zpci_ident_attr_group; + +#define ARCH_PCI_DEV_GROUPS &zpci_attr_group, \ + &pfip_attr_group, \ + &zpci_ident_attr_group, + extern unsigned int s390_pci_force_floating __initdata; extern unsigned int s390_pci_no_rid; @@ -203,12 +215,14 @@ extern struct airq_iv *zpci_aif_sbv; ----------------------------------------------------------------------------- */ /* Base stuff */ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state); +int zpci_add_device(struct zpci_dev *zdev); int zpci_enable_device(struct zpci_dev *); int zpci_disable_device(struct zpci_dev *); int zpci_scan_configured_device(struct zpci_dev *zdev, u32 fh); int zpci_deconfigure_device(struct zpci_dev *zdev); void zpci_device_reserved(struct zpci_dev *zdev); bool zpci_is_device_configured(struct zpci_dev *zdev); +int zpci_scan_devices(void); int zpci_hot_reset_device(struct zpci_dev *zdev); int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64, u8 *); @@ -218,7 +232,7 @@ void zpci_update_fh(struct zpci_dev *zdev, u32 fh); /* CLP */ int clp_setup_writeback_mio(void); -int clp_scan_pci_devices(void); +int clp_scan_pci_devices(struct list_head *scan_list); int clp_query_pci_fn(struct zpci_dev *zdev); int clp_enable_fh(struct zpci_dev *zdev, u32 *fh, u8 nr_dma_as); int clp_disable_fh(struct zpci_dev *zdev, u32 *fh); diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h index f0c677ddd270..3fff2f7095c8 100644 --- a/arch/s390/include/asm/pci_clp.h +++ b/arch/s390/include/asm/pci_clp.h @@ -110,7 +110,8 @@ struct clp_req_query_pci { struct clp_rsp_query_pci { struct clp_rsp_hdr hdr; u16 vfn; /* virtual fn number */ - u16 : 3; + u16 : 2; + u16 tid_avail : 1; u16 rid_avail : 1; u16 is_physfn : 1; u16 reserved1 : 1; @@ -122,16 +123,18 @@ struct clp_rsp_query_pci { u16 pchid; __le32 bar[PCI_STD_NUM_BARS]; u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */ - u16 : 12; - u16 port : 4; + u8 fidparm; + u8 reserved3 : 4; + u8 port : 4; u8 fmb_len; u8 pft; /* pci function type */ u64 sdma; /* start dma as */ u64 edma; /* end dma as */ #define ZPCI_RID_MASK_DEVFN 0x00ff u16 rid; /* BUS/DEVFN PCI address */ - u16 reserved0; - u32 reserved[10]; + u32 reserved0; + u16 tid; + u32 reserved[9]; u32 uid; /* user defined id */ u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ u32 reserved2[16]; diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index 2686bee800e3..43a5ea4ee20f 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h @@ -143,7 +143,7 @@ static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max) static inline int zpci_memcpy_fromio(void *dst, const volatile void __iomem *src, - unsigned long n) + size_t n) { int size, rc = 0; @@ -162,7 +162,7 @@ static inline int zpci_memcpy_fromio(void *dst, } static inline int zpci_memcpy_toio(volatile void __iomem *dst, - const void *src, unsigned long n) + const void *src, size_t n) { int size, rc = 0; @@ -187,7 +187,7 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst, } static inline int zpci_memset_io(volatile void __iomem *dst, - unsigned char val, size_t count) + int val, size_t count) { u8 *src = kmalloc(count, GFP_KERNEL); int rc; diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index 89a28740b6ab..84f6b8357b45 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h @@ -4,6 +4,7 @@ #include <linux/preempt.h> #include <asm/cmpxchg.h> +#include <asm/march.h> /* * s390 uses its own implementation for per cpu data, the offset of @@ -50,7 +51,7 @@ #define this_cpu_or_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) #define this_cpu_or_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) -#ifndef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifndef MARCH_HAS_Z196_FEATURES #define this_cpu_add_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) #define this_cpu_add_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) @@ -61,7 +62,7 @@ #define this_cpu_or_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) #define this_cpu_or_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) -#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#else /* MARCH_HAS_Z196_FEATURES */ #define arch_this_cpu_add(pcp, val, op1, op2, szcast) \ { \ @@ -129,7 +130,7 @@ #define this_cpu_or_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lao") #define this_cpu_or_8(pcp, val) arch_this_cpu_to_op(pcp, val, "laog") -#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#endif /* MARCH_HAS_Z196_FEATURES */ #define arch_this_cpu_cmpxchg(pcp, oval, nval) \ ({ \ diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index 9917e2717b2b..e53894cedf08 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -37,9 +37,9 @@ extern ssize_t cpumf_events_sysfs_show(struct device *dev, /* Perf callbacks */ struct pt_regs; -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); -extern unsigned long perf_misc_flags(struct pt_regs *regs); -#define perf_misc_flags(regs) perf_misc_flags(regs) +extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_arch_misc_flags(struct pt_regs *regs); +#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs) #define perf_arch_bpf_user_pt_regs(regs) ®s->user_regs /* Perf pt_regs extension for sample-data-entry indicators */ @@ -48,31 +48,8 @@ struct perf_sf_sde_regs { unsigned long reserved:63; /* reserved */ }; -/* Perf PMU definitions for the counter facility */ -#define PERF_CPUM_CF_MAX_CTR 0xffffUL /* Max ctr for ECCTR */ - -/* Perf PMU definitions for the sampling facility */ -#define PERF_CPUM_SF_MAX_CTR 2 -#define PERF_EVENT_CPUM_SF 0xB0000UL /* Event: Basic-sampling */ -#define PERF_EVENT_CPUM_SF_DIAG 0xBD000UL /* Event: Combined-sampling */ -#define PERF_EVENT_CPUM_CF_DIAG 0xBC000UL /* Event: Counter sets */ -#define PERF_CPUM_SF_BASIC_MODE 0x0001 /* Basic-sampling flag */ -#define PERF_CPUM_SF_DIAG_MODE 0x0002 /* Diagnostic-sampling flag */ -#define PERF_CPUM_SF_MODE_MASK (PERF_CPUM_SF_BASIC_MODE| \ - PERF_CPUM_SF_DIAG_MODE) -#define PERF_CPUM_SF_FREQ_MODE 0x0008 /* Sampling with frequency */ - -#define REG_NONE 0 -#define REG_OVERFLOW 1 -#define OVERFLOW_REG(hwc) ((hwc)->extra_reg.config) -#define SFB_ALLOC_REG(hwc) ((hwc)->extra_reg.alloc) -#define TEAR_REG(hwc) ((hwc)->last_tag) -#define SAMPL_RATE(hwc) ((hwc)->event_base) -#define SAMPL_FLAGS(hwc) ((hwc)->config_base) -#define SAMPL_DIAG_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE) -#define SAMPLE_FREQ_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FREQ_MODE) - #define perf_arch_fetch_caller_regs(regs, __ip) do { \ + (regs)->psw.mask = 0; \ (regs)->psw.addr = (__ip); \ (regs)->gprs[15] = (unsigned long)__builtin_frame_address(0) - \ offsetof(struct stack_frame, back_chain); \ diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 3fa280d0672a..8b67036edb69 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -338,7 +338,7 @@ static inline int is_module_addr(void *addr) #define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT) #define _REGION3_INDEX (0x7ffUL << _REGION3_SHIFT) #define _SEGMENT_INDEX (0x7ffUL << _SEGMENT_SHIFT) -#define _PAGE_INDEX (0xffUL << _PAGE_SHIFT) +#define _PAGE_INDEX (0xffUL << PAGE_SHIFT) #define _REGION1_SIZE (1UL << _REGION1_SHIFT) #define _REGION2_SIZE (1UL << _REGION2_SHIFT) @@ -955,6 +955,7 @@ static inline int pte_unused(pte_t pte) * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID * must not be set. */ +#define pte_pgprot pte_pgprot static inline pgprot_t pte_pgprot(pte_t pte) { unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK; diff --git a/arch/s390/include/asm/physmem_info.h b/arch/s390/include/asm/physmem_info.h index f45cfc8bc233..51b68a43e195 100644 --- a/arch/s390/include/asm/physmem_info.h +++ b/arch/s390/include/asm/physmem_info.h @@ -9,6 +9,7 @@ enum physmem_info_source { MEM_DETECT_NONE = 0, MEM_DETECT_SCLP_STOR_INFO, MEM_DETECT_DIAG260, + MEM_DETECT_DIAG500_STOR_LIMIT, MEM_DETECT_SCLP_READ_INFO, MEM_DETECT_BIN_SEARCH }; @@ -107,6 +108,8 @@ static inline const char *get_physmem_info_source(void) return "sclp storage info"; case MEM_DETECT_DIAG260: return "diag260"; + case MEM_DETECT_DIAG500_STOR_LIMIT: + return "diag500 storage limit"; case MEM_DETECT_SCLP_READ_INFO: return "sclp read info"; case MEM_DETECT_BIN_SEARCH: diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h index 47d80a7451a6..5dca1a46a9f6 100644 --- a/arch/s390/include/asm/pkey.h +++ b/arch/s390/include/asm/pkey.h @@ -22,7 +22,7 @@ * @param protkey pointer to buffer receiving the protected key * @return 0 on success, negative errno value on failure */ -int pkey_keyblob2pkey(const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); +int pkey_key2protkey(const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype); #endif /* _KAPI_PKEY_H */ diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h index 3ae5f31c665d..0cde7e240373 100644 --- a/arch/s390/include/asm/preempt.h +++ b/arch/s390/include/asm/preempt.h @@ -5,8 +5,10 @@ #include <asm/current.h> #include <linux/thread_info.h> #include <asm/atomic_ops.h> +#include <asm/cmpxchg.h> +#include <asm/march.h> -#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifdef MARCH_HAS_Z196_FEATURES /* We use the MSB mostly because its available */ #define PREEMPT_NEED_RESCHED 0x80000000 @@ -21,12 +23,10 @@ static __always_inline void preempt_count_set(int pc) { int old, new; + old = READ_ONCE(get_lowcore()->preempt_count); do { - old = READ_ONCE(get_lowcore()->preempt_count); - new = (old & PREEMPT_NEED_RESCHED) | - (pc & ~PREEMPT_NEED_RESCHED); - } while (__atomic_cmpxchg(&get_lowcore()->preempt_count, - old, new) != old); + new = (old & PREEMPT_NEED_RESCHED) | (pc & ~PREEMPT_NEED_RESCHED); + } while (!arch_try_cmpxchg(&get_lowcore()->preempt_count, &old, new)); } static __always_inline void set_preempt_need_resched(void) @@ -75,7 +75,7 @@ static __always_inline bool should_resched(int preempt_offset) preempt_offset); } -#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#else /* MARCH_HAS_Z196_FEATURES */ #define PREEMPT_ENABLED (0) @@ -123,7 +123,7 @@ static __always_inline bool should_resched(int preempt_offset) tif_need_resched()); } -#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#endif /* MARCH_HAS_Z196_FEATURES */ #define init_task_preempt_count(p) do { } while (0) /* Deferred to CPU bringup time */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 5ecd442535b9..8761fd01a9f0 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -39,11 +39,13 @@ #include <asm/runtime_instr.h> #include <asm/irqflags.h> #include <asm/alternative.h> +#include <asm/fault.h> struct pcpu { unsigned long ec_mask; /* bit mask for ec_xxx functions */ unsigned long ec_clk; /* sigp timestamp for ec_xxx */ unsigned long flags; /* per CPU flags */ + unsigned long capacity; /* cpu capacity for scheduler */ signed char state; /* physical cpu state */ signed char polarization; /* physical polarization */ u16 address; /* physical cpu address */ @@ -186,10 +188,8 @@ struct thread_struct { unsigned long hardirq_timer; /* task cputime in hardirq context */ unsigned long softirq_timer; /* task cputime in softirq context */ const sys_call_ptr_t *sys_call_table; /* system call table address */ - unsigned long gmap_addr; /* address of last gmap fault. */ - unsigned int gmap_write_flag; /* gmap fault write indication */ + union teid gmap_teid; /* address and flags of last gmap fault */ unsigned int gmap_int_code; /* int code of last gmap fault */ - unsigned int gmap_pfault; /* signal of a pending guest pfault */ int ufpu_flags; /* user fpu flags */ int kfpu_flags; /* kernel fpu flags */ diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 2ad9324f6338..788bc4467445 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -14,11 +14,13 @@ #define PIF_SYSCALL 0 /* inside a system call */ #define PIF_EXECVE_PGSTE_RESTART 1 /* restart execve for PGSTE binaries */ #define PIF_SYSCALL_RET_SET 2 /* return value was set via ptrace */ +#define PIF_GUEST_FAULT 3 /* indicates program check in sie64a */ #define PIF_FTRACE_FULL_REGS 4 /* all register contents valid (ftrace) */ #define _PIF_SYSCALL BIT(PIF_SYSCALL) #define _PIF_EXECVE_PGSTE_RESTART BIT(PIF_EXECVE_PGSTE_RESTART) #define _PIF_SYSCALL_RET_SET BIT(PIF_SYSCALL_RET_SET) +#define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT) #define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS) #define PSW32_MASK_PER _AC(0x40000000, UL) diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index da3dad18fe50..eb00fa1771da 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -72,6 +72,7 @@ struct sclp_info { unsigned char has_core_type : 1; unsigned char has_sprp : 1; unsigned char has_hvs : 1; + unsigned char has_wti : 1; unsigned char has_esca : 1; unsigned char has_sief2 : 1; unsigned char has_64bscao : 1; diff --git a/arch/s390/include/asm/set_memory.h b/arch/s390/include/asm/set_memory.h index 06fbabe2f66c..cb4cc0f59012 100644 --- a/arch/s390/include/asm/set_memory.h +++ b/arch/s390/include/asm/set_memory.h @@ -62,5 +62,6 @@ __SET_MEMORY_FUNC(set_memory_4k, SET_MEMORY_4K) int set_direct_map_invalid_noflush(struct page *page); int set_direct_map_default_noflush(struct page *page); +bool kernel_page_present(struct page *page); #endif diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 8505737712ee..70b920b32827 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -34,6 +34,7 @@ #define MACHINE_FLAG_SCC BIT(17) #define MACHINE_FLAG_PCI_MIO BIT(18) #define MACHINE_FLAG_RDP BIT(19) +#define MACHINE_FLAG_SEQ_INSN BIT(20) #define LPP_MAGIC BIT(31) #define LPP_PID_MASK _AC(0xffffffff, UL) @@ -95,6 +96,7 @@ extern unsigned long mio_wb_bit_mask; #define MACHINE_HAS_SCC (get_lowcore()->machine_flags & MACHINE_FLAG_SCC) #define MACHINE_HAS_PCI_MIO (get_lowcore()->machine_flags & MACHINE_FLAG_PCI_MIO) #define MACHINE_HAS_RDP (get_lowcore()->machine_flags & MACHINE_FLAG_RDP) +#define MACHINE_HAS_SEQ_INSN (get_lowcore()->machine_flags & MACHINE_FLAG_SEQ_INSN) /* * Console mode. Override with conmode= @@ -115,6 +117,8 @@ extern unsigned int console_irq; #define SET_CONSOLE_VT220 do { console_mode = 4; } while (0) #define SET_CONSOLE_HVC do { console_mode = 5; } while (0) +void register_early_console(void); + #ifdef CONFIG_VMCP void vmcp_cma_reserve(void); #else diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index edee63da08e7..472943b77066 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h @@ -38,6 +38,8 @@ #ifndef __ASSEMBLY__ +#include <asm/asm.h> + static inline int ____pcpu_sigp(u16 addr, u8 order, unsigned long parm, u32 *status) { @@ -46,13 +48,12 @@ static inline int ____pcpu_sigp(u16 addr, u8 order, unsigned long parm, asm volatile( " sigp %[r1],%[addr],0(%[order])\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc), [r1] "+&d" (r1.pair) + CC_IPM(cc) + : CC_OUT(cc, cc), [r1] "+d" (r1.pair) : [addr] "d" (addr), [order] "a" (order) - : "cc"); + : CC_CLOBBER); *status = r1.even; - return cc; + return CC_TRANSFORM(cc); } static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm, diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index cd835f4fb11a..7feca96c48c6 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -12,6 +12,7 @@ #include <asm/processor.h> #define raw_smp_processor_id() (get_lowcore()->cpu_nr) +#define arch_scale_cpu_capacity smp_cpu_get_capacity extern struct mutex smp_cpu_state_mutex; extern unsigned int smp_cpu_mt_shift; @@ -34,6 +35,9 @@ extern void smp_save_dump_secondary_cpus(void); extern void smp_yield_cpu(int cpu); extern void smp_cpu_set_polarization(int cpu, int val); extern int smp_cpu_get_polarization(int cpu); +extern void smp_cpu_set_capacity(int cpu, unsigned long val); +extern void smp_set_core_capacity(int cpu, unsigned long val); +extern unsigned long smp_cpu_get_capacity(int cpu); extern int smp_cpu_get_cpu_address(int cpu); extern void smp_fill_possible_mask(void); extern void smp_detect_cpus(void); diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h index c549893602ea..668dfc5de538 100644 --- a/arch/s390/include/asm/sparsemem.h +++ b/arch/s390/include/asm/sparsemem.h @@ -2,7 +2,23 @@ #ifndef _ASM_S390_SPARSEMEM_H #define _ASM_S390_SPARSEMEM_H -#define SECTION_SIZE_BITS 28 +#define SECTION_SIZE_BITS 27 #define MAX_PHYSMEM_BITS CONFIG_MAX_PHYSMEM_BITS +#ifdef CONFIG_NUMA + +static inline int memory_add_physaddr_to_nid(u64 addr) +{ + return 0; +} +#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid + +static inline int phys_to_target_node(u64 start) +{ + return 0; +} +#define phys_to_target_node phys_to_target_node + +#endif /* CONFIG_NUMA */ + #endif /* _ASM_S390_SPARSEMEM_H */ diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index 77d5e804af93..ac868a9bb0d1 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h @@ -57,8 +57,10 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lp) static inline int arch_spin_trylock_once(arch_spinlock_t *lp) { + int old = 0; + barrier(); - return likely(__atomic_cmpxchg_bool(&lp->lock, 0, SPINLOCK_LOCKVAL)); + return likely(arch_try_cmpxchg(&lp->lock, &old, SPINLOCK_LOCKVAL)); } static inline void arch_spin_lock(arch_spinlock_t *lp) @@ -118,7 +120,9 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) static inline void arch_write_lock(arch_rwlock_t *rw) { - if (!__atomic_cmpxchg_bool(&rw->cnts, 0, 0x30000)) + int old = 0; + + if (!arch_try_cmpxchg(&rw->cnts, &old, 0x30000)) arch_write_lock_wait(rw); } @@ -133,8 +137,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) int old; old = READ_ONCE(rw->cnts); - return (!(old & 0xffff0000) && - __atomic_cmpxchg_bool(&rw->cnts, old, old + 1)); + return (!(old & 0xffff0000) && arch_try_cmpxchg(&rw->cnts, &old, old + 1)); } static inline int arch_write_trylock(arch_rwlock_t *rw) @@ -142,7 +145,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) int old; old = READ_ONCE(rw->cnts); - return !old && __atomic_cmpxchg_bool(&rw->cnts, 0, 0x30000); + return !old && arch_try_cmpxchg(&rw->cnts, &old, 0x30000); } #endif /* __ASM_SPINLOCK_H */ diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 640901f2fbc3..8fe56456feab 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -13,6 +13,7 @@ #include <linux/preempt.h> #include <linux/time64.h> #include <asm/lowcore.h> +#include <asm/asm.h> /* The value of the TOD clock for 1.1.1970. */ #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL @@ -44,11 +45,12 @@ static inline int set_tod_clock(__u64 time) int cc; asm volatile( - " sck %1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) : "Q" (time) : "cc"); - return cc; + " sck %[time]\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [time] "Q" (time) + : CC_CLOBBER); + return CC_TRANSFORM(cc); } static inline int store_tod_clock_ext_cc(union tod_clock *clk) @@ -56,11 +58,12 @@ static inline int store_tod_clock_ext_cc(union tod_clock *clk) int cc; asm volatile( - " stcke %1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc), "=Q" (*clk) : : "cc"); - return cc; + " stcke %[clk]\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [clk] "=Q" (*clk) + : + : CC_CLOBBER); + return CC_TRANSFORM(cc); } static __always_inline void store_tod_clock_ext(union tod_clock *tod) @@ -149,12 +152,11 @@ struct ptff_qui { " lgr 0,%[reg0]\n" \ " lgr 1,%[reg1]\n" \ " ptff\n" \ - " ipm %[rc]\n" \ - " srl %[rc],28\n" \ - : [rc] "=&d" (rc), "+m" (*(struct addrtype *)reg1) \ + CC_IPM(rc) \ + : CC_OUT(rc, rc), "+m" (*(struct addrtype *)reg1) \ : [reg0] "d" (reg0), [reg1] "d" (reg1) \ - : "cc", "0", "1"); \ - rc; \ + : CC_CLOBBER_LIST("0", "1")); \ + CC_TRANSFORM(rc); \ }) static inline unsigned long local_tick_disable(void) diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 3a0ac0c7a9a3..cef06bffad80 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -67,6 +67,9 @@ static inline void topology_expect_change(void) { } #define POLARIZATION_VM (2) #define POLARIZATION_VH (3) +#define CPU_CAPACITY_HIGH SCHED_CAPACITY_SCALE +#define CPU_CAPACITY_LOW (SCHED_CAPACITY_SCALE >> 3) + #define SD_BOOK_INIT SD_CPU_INIT #ifdef CONFIG_NUMA diff --git a/arch/s390/include/asm/trace/hiperdispatch.h b/arch/s390/include/asm/trace/hiperdispatch.h new file mode 100644 index 000000000000..46462ee645b0 --- /dev/null +++ b/arch/s390/include/asm/trace/hiperdispatch.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Tracepoint header for hiperdispatch + * + * Copyright IBM Corp. 2024 + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM s390 + +#if !defined(_TRACE_S390_HIPERDISPATCH_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_S390_HIPERDISPATCH_H + +#include <linux/tracepoint.h> + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH asm/trace +#define TRACE_INCLUDE_FILE hiperdispatch + +TRACE_EVENT(s390_hd_work_fn, + TP_PROTO(int steal_time_percentage, + int entitled_core_count, + int highcap_core_count), + TP_ARGS(steal_time_percentage, + entitled_core_count, + highcap_core_count), + TP_STRUCT__entry(__field(int, steal_time_percentage) + __field(int, entitled_core_count) + __field(int, highcap_core_count)), + TP_fast_assign(__entry->steal_time_percentage = steal_time_percentage; + __entry->entitled_core_count = entitled_core_count; + __entry->highcap_core_count = highcap_core_count;), + TP_printk("steal: %d entitled_core_count: %d highcap_core_count: %d", + __entry->steal_time_percentage, + __entry->entitled_core_count, + __entry->highcap_core_count) +); + +TRACE_EVENT(s390_hd_rebuild_domains, + TP_PROTO(int current_highcap_core_count, + int new_highcap_core_count), + TP_ARGS(current_highcap_core_count, + new_highcap_core_count), + TP_STRUCT__entry(__field(int, current_highcap_core_count) + __field(int, new_highcap_core_count)), + TP_fast_assign(__entry->current_highcap_core_count = current_highcap_core_count; + __entry->new_highcap_core_count = new_highcap_core_count), + TP_printk("change highcap_core_count: %u -> %u", + __entry->current_highcap_core_count, + __entry->new_highcap_core_count) +); + +#endif /* _TRACE_S390_HIPERDISPATCH_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h index 153d93468b77..dc332609f2c3 100644 --- a/arch/s390/include/asm/uv.h +++ b/arch/s390/include/asm/uv.h @@ -2,7 +2,7 @@ /* * Ultravisor Interfaces * - * Copyright IBM Corp. 2019, 2022 + * Copyright IBM Corp. 2019, 2024 * * Author(s): * Vasily Gorbik <gor@linux.ibm.com> @@ -17,6 +17,7 @@ #include <linux/sched.h> #include <asm/page.h> #include <asm/gmap.h> +#include <asm/asm.h> #define UVC_CC_OK 0 #define UVC_CC_ERROR 1 @@ -28,9 +29,11 @@ #define UVC_RC_INV_STATE 0x0003 #define UVC_RC_INV_LEN 0x0005 #define UVC_RC_NO_RESUME 0x0007 +#define UVC_RC_MORE_DATA 0x0100 #define UVC_RC_NEED_DESTROY 0x8000 #define UVC_CMD_QUI 0x0001 +#define UVC_CMD_QUERY_KEYS 0x0002 #define UVC_CMD_INIT_UV 0x000f #define UVC_CMD_CREATE_SEC_CONF 0x0100 #define UVC_CMD_DESTROY_SEC_CONF 0x0101 @@ -61,6 +64,7 @@ #define UVC_CMD_ADD_SECRET 0x1031 #define UVC_CMD_LIST_SECRETS 0x1033 #define UVC_CMD_LOCK_SECRETS 0x1034 +#define UVC_CMD_RETR_SECRET 0x1035 /* Bits in installed uv calls */ enum uv_cmds_inst { @@ -94,6 +98,8 @@ enum uv_cmds_inst { BIT_UVC_CMD_ADD_SECRET = 29, BIT_UVC_CMD_LIST_SECRETS = 30, BIT_UVC_CMD_LOCK_SECRETS = 31, + BIT_UVC_CMD_RETR_SECRET = 33, + BIT_UVC_CMD_QUERY_KEYS = 34, }; enum uv_feat_ind { @@ -140,11 +146,27 @@ struct uv_cb_qui { u64 reservedf0; /* 0x00f0 */ u64 supp_add_secret_req_ver; /* 0x00f8 */ u64 supp_add_secret_pcf; /* 0x0100 */ - u64 supp_secret_types; /* 0x0180 */ - u16 max_secrets; /* 0x0110 */ - u8 reserved112[0x120 - 0x112]; /* 0x0112 */ + u64 supp_secret_types; /* 0x0108 */ + u16 max_assoc_secrets; /* 0x0110 */ + u16 max_retr_secrets; /* 0x0112 */ + u8 reserved114[0x120 - 0x114]; /* 0x0114 */ } __packed __aligned(8); +struct uv_key_hash { + u64 dword[4]; +} __packed __aligned(8); + +#define UVC_QUERY_KEYS_IDX_HK 0 +#define UVC_QUERY_KEYS_IDX_BACK_HK 1 + +/* Query Ultravisor Keys */ +struct uv_cb_query_keys { + struct uv_cb_header header; /* 0x0000 */ + u64 reserved08[3]; /* 0x0008 */ + struct uv_key_hash key_hashes[15]; /* 0x0020 */ +} __packed __aligned(8); +static_assert(sizeof(struct uv_cb_query_keys) == 0x200); + /* Initialize Ultravisor */ struct uv_cb_init { struct uv_cb_header header; @@ -317,7 +339,6 @@ struct uv_cb_dump_complete { * A common UV call struct for pv guests that contains a single address * Examples: * Add Secret - * List Secrets */ struct uv_cb_guest_addr { struct uv_cb_header header; @@ -326,18 +347,102 @@ struct uv_cb_guest_addr { u64 reserved28[4]; } __packed __aligned(8); +#define UVC_RC_RETR_SECR_BUF_SMALL 0x0109 +#define UVC_RC_RETR_SECR_STORE_EMPTY 0x010f +#define UVC_RC_RETR_SECR_INV_IDX 0x0110 +#define UVC_RC_RETR_SECR_INV_SECRET 0x0111 + +struct uv_cb_retr_secr { + struct uv_cb_header header; + u64 reserved08[2]; + u16 secret_idx; + u16 reserved1a; + u32 buf_size; + u64 buf_addr; + u64 reserved28[4]; +} __packed __aligned(8); + +struct uv_cb_list_secrets { + struct uv_cb_header header; + u64 reserved08[2]; + u8 reserved18[6]; + u16 start_idx; + u64 list_addr; + u64 reserved28[4]; +} __packed __aligned(8); + +enum uv_secret_types { + UV_SECRET_INVAL = 0x0, + UV_SECRET_NULL = 0x1, + UV_SECRET_ASSOCIATION = 0x2, + UV_SECRET_PLAIN = 0x3, + UV_SECRET_AES_128 = 0x4, + UV_SECRET_AES_192 = 0x5, + UV_SECRET_AES_256 = 0x6, + UV_SECRET_AES_XTS_128 = 0x7, + UV_SECRET_AES_XTS_256 = 0x8, + UV_SECRET_HMAC_SHA_256 = 0x9, + UV_SECRET_HMAC_SHA_512 = 0xa, + /* 0x0b - 0x10 reserved */ + UV_SECRET_ECDSA_P256 = 0x11, + UV_SECRET_ECDSA_P384 = 0x12, + UV_SECRET_ECDSA_P521 = 0x13, + UV_SECRET_ECDSA_ED25519 = 0x14, + UV_SECRET_ECDSA_ED448 = 0x15, +}; + +/** + * uv_secret_list_item_hdr - UV secret metadata. + * @index: Index of the secret in the secret list. + * @type: Type of the secret. See `enum uv_secret_types`. + * @length: Length of the stored secret. + */ +struct uv_secret_list_item_hdr { + u16 index; + u16 type; + u32 length; +} __packed __aligned(8); + +#define UV_SECRET_ID_LEN 32 +/** + * uv_secret_list_item - UV secret entry. + * @hdr: The metadata of this secret. + * @id: The ID of this secret, not the secret itself. + */ +struct uv_secret_list_item { + struct uv_secret_list_item_hdr hdr; + u64 reserverd08; + u8 id[UV_SECRET_ID_LEN]; +} __packed __aligned(8); + +/** + * uv_secret_list - UV secret-metadata list. + * @num_secr_stored: Number of secrets stored in this list. + * @total_num_secrets: Number of secrets stored in the UV for this guest. + * @next_secret_idx: positive number if there are more secrets available or zero. + * @secrets: Up to 85 UV-secret metadata entries. + */ +struct uv_secret_list { + u16 num_secr_stored; + u16 total_num_secrets; + u16 next_secret_idx; + u16 reserved_06; + u64 reserved_08; + struct uv_secret_list_item secrets[85]; +} __packed __aligned(8); +static_assert(sizeof(struct uv_secret_list) == PAGE_SIZE); + static inline int __uv_call(unsigned long r1, unsigned long r2) { int cc; asm volatile( - " .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=d" (cc) + " .insn rrf,0xb9a40000,%[r1],%[r2],0,0\n" + CC_IPM(cc) + : CC_OUT(cc, cc) : [r1] "a" (r1), [r2] "a" (r2) - : "memory", "cc"); - return cc; + : CC_CLOBBER_LIST("memory")); + return CC_TRANSFORM(cc); } static inline int uv_call(unsigned long r1, unsigned long r2) @@ -382,6 +487,48 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc) return cc ? -EINVAL : 0; } +/** + * uv_list_secrets() - Do a List Secrets UVC. + * + * @buf: Buffer to write list into; size of one page. + * @start_idx: The smallest index that should be included in the list. + * For the fist invocation use 0. + * @rc: Pointer to store the return code or NULL. + * @rrc: Pointer to store the return reason code or NULL. + * + * This function calls the List Secrets UVC. The result is written into `buf`, + * that needs to be at least one page of writable memory. + * `buf` consists of: + * * %struct uv_secret_list_hdr + * * %struct uv_secret_list_item (multiple) + * + * For `start_idx` use _0_ for the first call. If there are more secrets available + * but could not fit into the page then `rc` is `UVC_RC_MORE_DATA`. + * In this case use `uv_secret_list_hdr.next_secret_idx` for `start_idx`. + * + * Context: might sleep. + * + * Return: The UVC condition code. + */ +static inline int uv_list_secrets(struct uv_secret_list *buf, u16 start_idx, + u16 *rc, u16 *rrc) +{ + struct uv_cb_list_secrets uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_LIST_SECRETS, + .start_idx = start_idx, + .list_addr = (u64)buf, + }; + int cc = uv_call_sched(0, (u64)&uvcb); + + if (rc) + *rc = uvcb.header.rc; + if (rrc) + *rrc = uvcb.header.rrc; + + return cc; +} + struct uv_info { unsigned long inst_calls_list[4]; unsigned long uv_base_stor_len; @@ -402,7 +549,8 @@ struct uv_info { unsigned long supp_add_secret_req_ver; unsigned long supp_add_secret_pcf; unsigned long supp_secret_types; - unsigned short max_secrets; + unsigned short max_assoc_secrets; + unsigned short max_retr_secrets; }; extern struct uv_info uv_info; @@ -468,6 +616,10 @@ static inline int uv_remove_shared(unsigned long addr) return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); } +int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN], + struct uv_secret_list_item_hdr *secret); +int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size); + extern int prot_virt_host; static inline int is_prot_virt_host(void) diff --git a/arch/s390/include/asm/vdso-symbols.h b/arch/s390/include/asm/vdso-symbols.h new file mode 100644 index 000000000000..0df17574d788 --- /dev/null +++ b/arch/s390/include/asm/vdso-symbols.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __S390_VDSO_SYMBOLS_H__ +#define __S390_VDSO_SYMBOLS_H__ + +#include <generated/vdso64-offsets.h> +#ifdef CONFIG_COMPAT +#include <generated/vdso32-offsets.h> +#endif + +#define VDSO64_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso64_offset_##name)) +#ifdef CONFIG_COMPAT +#define VDSO32_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso32_offset_##name)) +#else +#define VDSO32_SYMBOL(tsk, name) (-1UL) +#endif + +#endif /* __S390_VDSO_SYMBOLS_H__ */ diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h index 53165aa7813a..92c73e4d97a9 100644 --- a/arch/s390/include/asm/vdso.h +++ b/arch/s390/include/asm/vdso.h @@ -6,27 +6,12 @@ #ifndef __ASSEMBLY__ -#include <generated/vdso64-offsets.h> -#ifdef CONFIG_COMPAT -#include <generated/vdso32-offsets.h> -#endif - -#define VDSO64_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso64_offset_##name)) -#ifdef CONFIG_COMPAT -#define VDSO32_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso32_offset_##name)) -#else -#define VDSO32_SYMBOL(tsk, name) (-1UL) -#endif - extern struct vdso_data *vdso_data; int vdso_getcpu_init(void); #endif /* __ASSEMBLY__ */ -/* Default link address for the vDSO */ -#define VDSO_LBASE 0 - #define __VVAR_PAGES 2 #define VDSO_VERSION_STRING LINUX_2.6.29 diff --git a/arch/s390/include/asm/vdso/data.h b/arch/s390/include/asm/vdso/data.h deleted file mode 100644 index 0e2b40ef69b0..000000000000 --- a/arch/s390/include/asm/vdso/data.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __S390_ASM_VDSO_DATA_H -#define __S390_ASM_VDSO_DATA_H - -#include <linux/types.h> - -struct arch_vdso_data { - __s64 tod_steering_delta; - __u64 tod_steering_end; -}; - -#endif /* __S390_ASM_VDSO_DATA_H */ diff --git a/arch/s390/include/asm/vdso/getrandom.h b/arch/s390/include/asm/vdso/getrandom.h new file mode 100644 index 000000000000..36355af7160b --- /dev/null +++ b/arch/s390/include/asm/vdso/getrandom.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_VDSO_GETRANDOM_H +#define __ASM_VDSO_GETRANDOM_H + +#ifndef __ASSEMBLY__ + +#include <vdso/datapage.h> +#include <asm/vdso/vsyscall.h> +#include <asm/syscall.h> +#include <asm/unistd.h> +#include <asm/page.h> + +/** + * getrandom_syscall - Invoke the getrandom() syscall. + * @buffer: Destination buffer to fill with random bytes. + * @len: Size of @buffer in bytes. + * @flags: Zero or more GRND_* flags. + * Returns: The number of random bytes written to @buffer, or a negative value indicating an error. + */ +static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsigned int flags) +{ + return syscall3(__NR_getrandom, (long)buffer, (long)len, (long)flags); +} + +static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) +{ + /* + * The RNG data is in the real VVAR data page, but if a task belongs to a time namespace + * then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_ + * PAGE_OFFSET points to the real VVAR page. + */ + if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS) + return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE; + return &_vdso_rng_data; +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_VDSO_GETRANDOM_H */ diff --git a/arch/s390/include/asm/vdso/time_data.h b/arch/s390/include/asm/vdso/time_data.h new file mode 100644 index 000000000000..8a08752422e6 --- /dev/null +++ b/arch/s390/include/asm/vdso/time_data.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __S390_ASM_VDSO_TIME_DATA_H +#define __S390_ASM_VDSO_TIME_DATA_H + +#include <linux/types.h> + +struct arch_vdso_time_data { + __s64 tod_steering_delta; + __u64 tod_steering_end; +}; + +#endif /* __S390_ASM_VDSO_TIME_DATA_H */ diff --git a/arch/s390/include/asm/vdso/vsyscall.h b/arch/s390/include/asm/vdso/vsyscall.h index 6c67c08cefdd..3eb576ecd3bd 100644 --- a/arch/s390/include/asm/vdso/vsyscall.h +++ b/arch/s390/include/asm/vdso/vsyscall.h @@ -2,15 +2,19 @@ #ifndef __ASM_VDSO_VSYSCALL_H #define __ASM_VDSO_VSYSCALL_H +#define __VDSO_RND_DATA_OFFSET 768 + #ifndef __ASSEMBLY__ #include <linux/hrtimer.h> -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> #include <asm/vdso.h> -/* - * Update the vDSO data page to keep in sync with kernel timekeeping. - */ + +enum vvar_pages { + VVAR_DATA_PAGE_OFFSET, + VVAR_TIMENS_PAGE_OFFSET, + VVAR_NR_PAGES +}; static __always_inline struct vdso_data *__s390_get_k_vdso_data(void) { @@ -18,6 +22,12 @@ static __always_inline struct vdso_data *__s390_get_k_vdso_data(void) } #define __arch_get_k_vdso_data __s390_get_k_vdso_data +static __always_inline struct vdso_rng_data *__s390_get_k_vdso_rnd_data(void) +{ + return (void *)vdso_data + __VDSO_RND_DATA_OFFSET; +} +#define __arch_get_k_vdso_rng_data __s390_get_k_vdso_rnd_data + /* The asm-generic header needs to be included after the definitions above */ #include <asm-generic/vdso/vsyscall.h> diff --git a/arch/s390/include/uapi/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h index b11d98800458..7c364b33c84d 100644 --- a/arch/s390/include/uapi/asm/dasd.h +++ b/arch/s390/include/uapi/asm/dasd.h @@ -294,7 +294,7 @@ struct dasd_snid_ioctl_data { /******************************************************************************** * SECTION: Definition of IOCTLs * - * Here ist how the ioctl-nr should be used: + * Here is how the ioctl-nr should be used: * 0 - 31 DASD driver itself * 32 - 239 still open * 240 - 255 reserved for EMC diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h index 5ad76471e73f..ca42e941675d 100644 --- a/arch/s390/include/uapi/asm/pkey.h +++ b/arch/s390/include/uapi/asm/pkey.h @@ -41,23 +41,29 @@ #define PKEY_KEYTYPE_ECC_P521 7 #define PKEY_KEYTYPE_ECC_ED25519 8 #define PKEY_KEYTYPE_ECC_ED448 9 +#define PKEY_KEYTYPE_AES_XTS_128 10 +#define PKEY_KEYTYPE_AES_XTS_256 11 +#define PKEY_KEYTYPE_HMAC_512 12 +#define PKEY_KEYTYPE_HMAC_1024 13 /* the newer ioctls use a pkey_key_type enum for type information */ enum pkey_key_type { - PKEY_TYPE_CCA_DATA = (__u32) 1, - PKEY_TYPE_CCA_CIPHER = (__u32) 2, - PKEY_TYPE_EP11 = (__u32) 3, - PKEY_TYPE_CCA_ECC = (__u32) 0x1f, - PKEY_TYPE_EP11_AES = (__u32) 6, - PKEY_TYPE_EP11_ECC = (__u32) 7, + PKEY_TYPE_CCA_DATA = (__u32)1, + PKEY_TYPE_CCA_CIPHER = (__u32)2, + PKEY_TYPE_EP11 = (__u32)3, + PKEY_TYPE_CCA_ECC = (__u32)0x1f, + PKEY_TYPE_EP11_AES = (__u32)6, + PKEY_TYPE_EP11_ECC = (__u32)7, + PKEY_TYPE_PROTKEY = (__u32)8, + PKEY_TYPE_UVSECRET = (__u32)9, }; /* the newer ioctls use a pkey_key_size enum for key size information */ enum pkey_key_size { - PKEY_SIZE_AES_128 = (__u32) 128, - PKEY_SIZE_AES_192 = (__u32) 192, - PKEY_SIZE_AES_256 = (__u32) 256, - PKEY_SIZE_UNKNOWN = (__u32) 0xFFFFFFFF, + PKEY_SIZE_AES_128 = (__u32)128, + PKEY_SIZE_AES_192 = (__u32)192, + PKEY_SIZE_AES_256 = (__u32)256, + PKEY_SIZE_UNKNOWN = (__u32)0xFFFFFFFF, }; /* some of the newer ioctls use these flags */ @@ -120,6 +126,7 @@ struct pkey_genseck { __u32 keytype; /* in: key type to generate */ struct pkey_seckey seckey; /* out: the secure key blob */ }; + #define PKEY_GENSECK _IOWR(PKEY_IOCTL_MAGIC, 0x01, struct pkey_genseck) /* @@ -132,6 +139,7 @@ struct pkey_clr2seck { struct pkey_clrkey clrkey; /* in: the clear key value */ struct pkey_seckey seckey; /* out: the secure key blob */ }; + #define PKEY_CLR2SECK _IOWR(PKEY_IOCTL_MAGIC, 0x02, struct pkey_clr2seck) /* @@ -143,6 +151,7 @@ struct pkey_sec2protk { struct pkey_seckey seckey; /* in: the secure key blob */ struct pkey_protkey protkey; /* out: the protected key */ }; + #define PKEY_SEC2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x03, struct pkey_sec2protk) /* @@ -153,6 +162,7 @@ struct pkey_clr2protk { struct pkey_clrkey clrkey; /* in: the clear key value */ struct pkey_protkey protkey; /* out: the protected key */ }; + #define PKEY_CLR2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x04, struct pkey_clr2protk) /* @@ -164,6 +174,7 @@ struct pkey_findcard { __u16 cardnr; /* out: card number */ __u16 domain; /* out: domain number */ }; + #define PKEY_FINDCARD _IOWR(PKEY_IOCTL_MAGIC, 0x05, struct pkey_findcard) /* @@ -173,6 +184,7 @@ struct pkey_skey2pkey { struct pkey_seckey seckey; /* in: the secure key blob */ struct pkey_protkey protkey; /* out: the protected key */ }; + #define PKEY_SKEY2PKEY _IOWR(PKEY_IOCTL_MAGIC, 0x06, struct pkey_skey2pkey) /* @@ -190,6 +202,7 @@ struct pkey_verifykey { __u16 keysize; /* out: key size in bits */ __u32 attributes; /* out: attribute bits */ }; + #define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey) #define PKEY_VERIFY_ATTR_AES 0x00000001 /* key is an AES key */ #define PKEY_VERIFY_ATTR_OLD_MKVP 0x00000100 /* key has old MKVP value */ @@ -221,6 +234,7 @@ struct pkey_kblob2pkey { __u32 keylen; /* in: the key blob length */ struct pkey_protkey protkey; /* out: the protected key */ }; + #define PKEY_KBLOB2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x0A, struct pkey_kblob2pkey) /* @@ -253,6 +267,7 @@ struct pkey_genseck2 { __u32 keylen; /* in: available key blob buffer size */ /* out: actual key blob size */ }; + #define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2) /* @@ -287,6 +302,7 @@ struct pkey_clr2seck2 { __u32 keylen; /* in: available key blob buffer size */ /* out: actual key blob size */ }; + #define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2) /* @@ -324,6 +340,7 @@ struct pkey_verifykey2 { enum pkey_key_size size; /* out: the key size */ __u32 flags; /* out: additional key info flags */ }; + #define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2) /* @@ -346,6 +363,7 @@ struct pkey_kblob2pkey2 { __u32 apqn_entries; /* in: # of apqn target list entries */ struct pkey_protkey protkey; /* out: the protected key */ }; + #define PKEY_KBLOB2PROTK2 _IOWR(PKEY_IOCTL_MAGIC, 0x1A, struct pkey_kblob2pkey2) /* @@ -382,6 +400,7 @@ struct pkey_apqns4key { __u32 apqn_entries; /* in: max # of apqn entries in the list */ /* out: # apqns stored into the list */ }; + #define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key) /* @@ -421,6 +440,7 @@ struct pkey_apqns4keytype { __u32 apqn_entries; /* in: max # of apqn entries in the list */ /* out: # apqns stored into the list */ }; + #define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, struct pkey_apqns4keytype) /* @@ -447,6 +467,7 @@ struct pkey_kblob2pkey3 { __u32 pkeylen; /* in/out: size of pkey buffer/actual len of pkey */ __u8 __user *pkey; /* in: pkey blob buffer space ptr */ }; + #define PKEY_KBLOB2PROTK3 _IOWR(PKEY_IOCTL_MAGIC, 0x1D, struct pkey_kblob2pkey3) #endif /* _UAPI_PKEY_H */ diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h index b9c2f14a6af3..4947f26ad9fb 100644 --- a/arch/s390/include/uapi/asm/uvdevice.h +++ b/arch/s390/include/uapi/asm/uvdevice.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* - * Copyright IBM Corp. 2022 + * Copyright IBM Corp. 2022, 2024 * Author(s): Steffen Eiden <seiden@linux.ibm.com> */ #ifndef __S390_ASM_UVDEVICE_H @@ -52,7 +52,7 @@ struct uvio_uvdev_info { __u64 supp_uvio_cmds; /* * If bit `n` is set, the Ultravisor(UV) supports the UV-call - * corresponding to the IOCTL with nr `n` in the calling contextx (host + * corresponding to the IOCTL with nr `n` in the calling context (host * or guest). The value is only valid if the corresponding bit in * @supp_uvio_cmds is set as well. */ @@ -71,6 +71,7 @@ struct uvio_uvdev_info { #define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 #define UVIO_ADD_SECRET_MAX_LEN 0x100000 #define UVIO_LIST_SECRETS_LEN 0x1000 +#define UVIO_RETR_SECRET_MAX_LEN 0x2000 #define UVIO_DEVICE_NAME "uv" #define UVIO_TYPE_UVC 'u' @@ -81,22 +82,25 @@ enum UVIO_IOCTL_NR { UVIO_IOCTL_ADD_SECRET_NR, UVIO_IOCTL_LIST_SECRETS_NR, UVIO_IOCTL_LOCK_SECRETS_NR, + UVIO_IOCTL_RETR_SECRET_NR, /* must be the last entry */ UVIO_IOCTL_NUM_IOCTLS }; -#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb) -#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR) -#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR) -#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR) -#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR) -#define UVIO_IOCTL_LOCK_SECRETS UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR) +#define UVIO_IOCTL(nr) _IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb) +#define UVIO_IOCTL_UVDEV_INFO UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR) +#define UVIO_IOCTL_ATT UVIO_IOCTL(UVIO_IOCTL_ATT_NR) +#define UVIO_IOCTL_ADD_SECRET UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR) +#define UVIO_IOCTL_LIST_SECRETS UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR) +#define UVIO_IOCTL_LOCK_SECRETS UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR) +#define UVIO_IOCTL_RETR_SECRET UVIO_IOCTL(UVIO_IOCTL_RETR_SECRET_NR) -#define UVIO_SUPP_CALL(nr) (1ULL << (nr)) -#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR) -#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR) -#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR) -#define UVIO_SUPP_LIST_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR) -#define UVIO_SUPP_LOCK_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR) +#define UVIO_SUPP_CALL(nr) (1ULL << (nr)) +#define UVIO_SUPP_UDEV_INFO UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR) +#define UVIO_SUPP_ATT UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR) +#define UVIO_SUPP_ADD_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR) +#define UVIO_SUPP_LIST_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR) +#define UVIO_SUPP_LOCK_SECRETS UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR) +#define UVIO_SUPP_RETR_SECRET UVIO_SUPP_CALL(UVIO_IOCTL_RETR_SECRET_NR) #endif /* __S390_ASM_UVDEVICE_H */ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index e47a4be54ff8..48caae8c7e10 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -36,22 +36,23 @@ CFLAGS_stacktrace.o += -fno-optimize-sibling-calls CFLAGS_dumpstack.o += -fno-optimize-sibling-calls CFLAGS_unwind_bc.o += -fno-optimize-sibling-calls -obj-y := head64.o traps.o time.o process.o earlypgm.o early.o setup.o idle.o vtime.o +obj-y := head64.o traps.o time.o process.o early.o setup.o idle.o vtime.o obj-y += processor.o syscall.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o cpufeature.o obj-y += sysinfo.o lgr.o os_info.o ctlreg.o obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o obj-y += entry.o reipl.o kdebugfs.o alternative.o obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o -obj-y += smp.o text_amode31.o stacktrace.o abs_lowcore.o facility.o uv.o +obj-y += smp.o text_amode31.o stacktrace.o abs_lowcore.o facility.o uv.o wti.o extra-y += vmlinux.lds obj-$(CONFIG_SYSFS) += nospec-sysfs.o CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE) +obj-$(CONFIG_SYSFS) += cpacf.o obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_SCHED_TOPOLOGY) += topology.o +obj-$(CONFIG_SCHED_TOPOLOGY) += topology.o hiperdispatch.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_AUDIT) += audit.o compat-obj-$(CONFIG_AUDIT) += compat_audit.o diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index ffa0dd2dbaac..862a9140528e 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -13,7 +13,6 @@ #include <linux/purgatory.h> #include <linux/pgtable.h> #include <linux/ftrace.h> -#include <asm/gmap.h> #include <asm/stacktrace.h> int main(void) @@ -112,8 +111,7 @@ int main(void) OFFSET(__LC_MCK_NEW_PSW, lowcore, mcck_new_psw); OFFSET(__LC_IO_NEW_PSW, lowcore, io_new_psw); /* software defined lowcore locations 0x200 - 0xdff*/ - OFFSET(__LC_SAVE_AREA_SYNC, lowcore, save_area_sync); - OFFSET(__LC_SAVE_AREA_ASYNC, lowcore, save_area_async); + OFFSET(__LC_SAVE_AREA, lowcore, save_area); OFFSET(__LC_SAVE_AREA_RESTART, lowcore, save_area_restart); OFFSET(__LC_PCPU, lowcore, pcpu); OFFSET(__LC_RETURN_PSW, lowcore, return_psw); @@ -139,7 +137,6 @@ int main(void) OFFSET(__LC_USER_ASCE, lowcore, user_asce); OFFSET(__LC_LPP, lowcore, lpp); OFFSET(__LC_CURRENT_PID, lowcore, current_pid); - OFFSET(__LC_GMAP, lowcore, gmap); OFFSET(__LC_LAST_BREAK, lowcore, last_break); /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ OFFSET(__LC_DUMP_REIPL, lowcore, ipib); @@ -162,7 +159,6 @@ int main(void) OFFSET(__LC_PGM_TDB, lowcore, pgm_tdb); BLANK(); /* gmap/sie offsets */ - OFFSET(__GMAP_ASCE, gmap, asce); OFFSET(__SIE_PROG0C, kvm_s390_sie_block, prog0c); OFFSET(__SIE_PROG20, kvm_s390_sie_block, prog20); /* kexec_sha_region */ @@ -185,8 +181,8 @@ int main(void) OFFSET(__FGRAPH_RET_FP, fgraph_ret_regs, fp); DEFINE(__FGRAPH_RET_SIZE, sizeof(struct fgraph_ret_regs)); #endif - OFFSET(__FTRACE_REGS_PT_REGS, ftrace_regs, regs); - DEFINE(__FTRACE_REGS_SIZE, sizeof(struct ftrace_regs)); + OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs); + DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs)); OFFSET(__PCPU_FLAGS, pcpu, flags); return 0; diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 1942e2a9f8db..5a86b9d1da71 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -24,11 +24,11 @@ #include <linux/tty.h> #include <linux/personality.h> #include <linux/binfmts.h> +#include <asm/vdso-symbols.h> #include <asm/access-regs.h> #include <asm/ucontext.h> #include <linux/uaccess.h> #include <asm/lowcore.h> -#include <asm/vdso.h> #include <asm/fpu.h> #include "compat_linux.h" #include "compat_ptrace.h" diff --git a/arch/s390/kernel/cpacf.c b/arch/s390/kernel/cpacf.c new file mode 100644 index 000000000000..c8575dbc890d --- /dev/null +++ b/arch/s390/kernel/cpacf.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corp. 2024 + */ + +#define KMSG_COMPONENT "cpacf" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include <linux/cpu.h> +#include <linux/device.h> +#include <linux/sysfs.h> +#include <asm/cpacf.h> + +#define CPACF_QUERY(name, instruction) \ +static ssize_t name##_query_raw_read(struct file *fp, \ + struct kobject *kobj, \ + struct bin_attribute *attr, \ + char *buf, loff_t offs, \ + size_t count) \ +{ \ + cpacf_mask_t mask; \ + \ + if (!cpacf_query(CPACF_##instruction, &mask)) \ + return -EOPNOTSUPP; \ + return memory_read_from_buffer(buf, count, &offs, &mask, sizeof(mask)); \ +} \ +static BIN_ATTR_RO(name##_query_raw, sizeof(cpacf_mask_t)) + +CPACF_QUERY(km, KM); +CPACF_QUERY(kmc, KMC); +CPACF_QUERY(kimd, KIMD); +CPACF_QUERY(klmd, KLMD); +CPACF_QUERY(kmac, KMAC); +CPACF_QUERY(pckmo, PCKMO); +CPACF_QUERY(kmf, KMF); +CPACF_QUERY(kmctr, KMCTR); +CPACF_QUERY(kmo, KMO); +CPACF_QUERY(pcc, PCC); +CPACF_QUERY(prno, PRNO); +CPACF_QUERY(kma, KMA); +CPACF_QUERY(kdsa, KDSA); + +#define CPACF_QAI(name, instruction) \ +static ssize_t name##_query_auth_info_raw_read( \ + struct file *fp, struct kobject *kobj, \ + struct bin_attribute *attr, char *buf, loff_t offs, \ + size_t count) \ +{ \ + cpacf_qai_t qai; \ + \ + if (!cpacf_qai(CPACF_##instruction, &qai)) \ + return -EOPNOTSUPP; \ + return memory_read_from_buffer(buf, count, &offs, &qai, \ + sizeof(qai)); \ +} \ +static BIN_ATTR_RO(name##_query_auth_info_raw, sizeof(cpacf_qai_t)) + +CPACF_QAI(km, KM); +CPACF_QAI(kmc, KMC); +CPACF_QAI(kimd, KIMD); +CPACF_QAI(klmd, KLMD); +CPACF_QAI(kmac, KMAC); +CPACF_QAI(pckmo, PCKMO); +CPACF_QAI(kmf, KMF); +CPACF_QAI(kmctr, KMCTR); +CPACF_QAI(kmo, KMO); +CPACF_QAI(pcc, PCC); +CPACF_QAI(prno, PRNO); +CPACF_QAI(kma, KMA); +CPACF_QAI(kdsa, KDSA); + +static struct bin_attribute *cpacf_attrs[] = { + &bin_attr_km_query_raw, + &bin_attr_kmc_query_raw, + &bin_attr_kimd_query_raw, + &bin_attr_klmd_query_raw, + &bin_attr_kmac_query_raw, + &bin_attr_pckmo_query_raw, + &bin_attr_kmf_query_raw, + &bin_attr_kmctr_query_raw, + &bin_attr_kmo_query_raw, + &bin_attr_pcc_query_raw, + &bin_attr_prno_query_raw, + &bin_attr_kma_query_raw, + &bin_attr_kdsa_query_raw, + &bin_attr_km_query_auth_info_raw, + &bin_attr_kmc_query_auth_info_raw, + &bin_attr_kimd_query_auth_info_raw, + &bin_attr_klmd_query_auth_info_raw, + &bin_attr_kmac_query_auth_info_raw, + &bin_attr_pckmo_query_auth_info_raw, + &bin_attr_kmf_query_auth_info_raw, + &bin_attr_kmctr_query_auth_info_raw, + &bin_attr_kmo_query_auth_info_raw, + &bin_attr_pcc_query_auth_info_raw, + &bin_attr_prno_query_auth_info_raw, + &bin_attr_kma_query_auth_info_raw, + &bin_attr_kdsa_query_auth_info_raw, + NULL, +}; + +static const struct attribute_group cpacf_attr_grp = { + .name = "cpacf", + .bin_attrs = cpacf_attrs, +}; + +static int __init cpacf_init(void) +{ + struct device *cpu_root; + int rc = 0; + + cpu_root = bus_get_dev_root(&cpu_subsys); + if (cpu_root) { + rc = sysfs_create_group(&cpu_root->kobj, &cpacf_attr_grp); + put_device(cpu_root); + } + return rc; +} +device_initcall(cpacf_init); diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index b210a29d3ee9..2f4174b961de 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -20,6 +20,7 @@ #include <asm/diag.h> #include <asm/ebcdic.h> #include <asm/cpcmd.h> +#include <asm/asm.h> static DEFINE_SPINLOCK(cpcmd_lock); static char cpcmd_buf[241]; @@ -45,12 +46,11 @@ static int diag8_response(int cmdlen, char *response, int *rlen) ry.odd = *rlen; asm volatile( " diag %[rx],%[ry],0x8\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc), [ry] "+&d" (ry.pair) + CC_IPM(cc) + : CC_OUT(cc, cc), [ry] "+d" (ry.pair) : [rx] "d" (rx.pair) - : "cc"); - if (cc) + : CC_CLOBBER); + if (CC_TRANSFORM(cc)) *rlen += ry.odd; else *rlen = ry.odd; diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index edae13416196..cd0c93a8fb8b 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -237,6 +237,17 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from, prot); } +/* + * Return true only when in a kdump or stand-alone kdump environment. + * Note that /proc/vmcore might also be available in "standard zfcp/nvme dump" + * environments, where this function returns false; see dump_available(). + */ +bool is_kdump_kernel(void) +{ + return oldmem_data.start; +} +EXPORT_SYMBOL_GPL(is_kdump_kernel); + static const char *nt_name(Elf64_Word type) { const char *name = "LINUX"; diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index bce50ca75ea7..b3f2103694e4 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -38,13 +38,13 @@ typedef struct file_private_info { loff_t offset; /* offset of last read in file */ - int act_area; /* number of last formated area */ + int act_area; /* number of last formatted area */ int act_page; /* act page in given area */ - int act_entry; /* last formated entry (offset */ + int act_entry; /* last formatted entry (offset */ /* relative to beginning of last */ - /* formated page) */ + /* formatted page) */ size_t act_entry_offset; /* up to this offset we copied */ - /* in last read the last formated */ + /* in last read the last formatted */ /* entry to userland */ char temp_buf[2048]; /* buffer for output */ debug_info_t *debug_info_org; /* original debug information */ @@ -63,7 +63,7 @@ typedef struct { long args[]; } debug_sprintf_entry_t; -/* internal function prototyes */ +/* internal function prototypes */ static int debug_init(void); static ssize_t debug_output(struct file *file, char __user *user_buf, @@ -163,7 +163,6 @@ static const struct file_operations debug_file_ops = { .write = debug_input, .open = debug_open, .release = debug_close, - .llseek = no_llseek, }; static struct dentry *debug_debugfs_root_entry; @@ -381,7 +380,7 @@ static void debug_info_put(debug_info_t *db_info) /* * debug_format_entry: - * - format one debug entry and return size of formated data + * - format one debug entry and return size of formatted data */ static int debug_format_entry(file_private_info_t *p_info) { @@ -450,7 +449,7 @@ out: /* * debug_output: * - called for user read() - * - copies formated debug entries to the user buffer + * - copies formatted debug entries to the user buffer */ static ssize_t debug_output(struct file *file, /* file descriptor */ char __user *user_buf, /* user buffer */ @@ -524,7 +523,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf, /* * debug_open: * - called for user open() - * - copies formated output to private_data area of the file + * - copies formatted output to private_data area of the file * handle */ static int debug_open(struct inode *inode, struct file *file) @@ -1514,7 +1513,7 @@ int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view, EXPORT_SYMBOL(debug_dflt_header_fn); /* - * prints debug data sprintf-formated: + * prints debug data sprintf-formatted: * debug_sprinf_event/exception calls must be used together with this view */ diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c index ac7b8c8e3133..cdd6e31344fa 100644 --- a/arch/s390/kernel/diag.c +++ b/arch/s390/kernel/diag.c @@ -16,6 +16,7 @@ #include <asm/diag.h> #include <asm/trace/diag.h> #include <asm/sections.h> +#include <asm/asm.h> #include "entry.h" struct diag_stat { @@ -52,6 +53,7 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = { [DIAG_STAT_X308] = { .code = 0x308, .name = "List-Directed IPL" }, [DIAG_STAT_X318] = { .code = 0x318, .name = "CP Name and Version Codes" }, [DIAG_STAT_X320] = { .code = 0x320, .name = "Certificate Store" }, + [DIAG_STAT_X49C] = { .code = 0x49c, .name = "Warning-Track Interruption" }, [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" }, }; @@ -303,3 +305,18 @@ int diag26c(void *req, void *resp, enum diag26c_sc subcode) return diag_amode31_ops.diag26c(virt_to_phys(req), virt_to_phys(resp), subcode); } EXPORT_SYMBOL(diag26c); + +int diag49c(unsigned long subcode) +{ + int cc; + + diag_stat_inc(DIAG_STAT_X49C); + asm volatile( + " diag %[subcode],0,0x49c\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [subcode] "d" (subcode) + : CC_CLOBBER); + return CC_TRANSFORM(cc); +} +EXPORT_SYMBOL(diag49c); diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 89dc826a8d2e..94eb8168ea44 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -122,6 +122,7 @@ enum { U8_32, /* 8 bit unsigned value starting at 32 */ U12_16, /* 12 bit unsigned value starting at 16 */ U16_16, /* 16 bit unsigned value starting at 16 */ + U16_20, /* 16 bit unsigned value starting at 20 */ U16_32, /* 16 bit unsigned value starting at 32 */ U32_16, /* 32 bit unsigned value starting at 16 */ VX_12, /* Vector index register starting at position 12 */ @@ -184,6 +185,7 @@ static const struct s390_operand operands[] = { [U8_32] = { 8, 32, 0 }, [U12_16] = { 12, 16, 0 }, [U16_16] = { 16, 16, 0 }, + [U16_20] = { 16, 20, 0 }, [U16_32] = { 16, 32, 0 }, [U32_16] = { 32, 16, 0 }, [VX_12] = { 4, 12, OPERAND_INDEX | OPERAND_VR }, @@ -257,7 +259,6 @@ static const unsigned char formats[][6] = { [INSTR_RSL_R0RD] = { D_20, L4_8, B_16, 0, 0, 0 }, [INSTR_RSY_AARD] = { A_8, A_12, D20_20, B_16, 0, 0 }, [INSTR_RSY_CCRD] = { C_8, C_12, D20_20, B_16, 0, 0 }, - [INSTR_RSY_RDRU] = { R_8, D20_20, B_16, U4_12, 0, 0 }, [INSTR_RSY_RRRD] = { R_8, R_12, D20_20, B_16, 0, 0 }, [INSTR_RSY_RURD] = { R_8, U4_12, D20_20, B_16, 0, 0 }, [INSTR_RSY_RURD2] = { R_8, D20_20, B_16, U4_12, 0, 0 }, @@ -300,14 +301,17 @@ static const unsigned char formats[][6] = { [INSTR_VRI_V0UU2] = { V_8, U16_16, U4_32, 0, 0, 0 }, [INSTR_VRI_V0UUU] = { V_8, U8_16, U8_24, U4_32, 0, 0 }, [INSTR_VRI_VR0UU] = { V_8, R_12, U8_28, U4_24, 0, 0 }, + [INSTR_VRI_VV0UU] = { V_8, V_12, U8_28, U4_24, 0, 0 }, [INSTR_VRI_VVUU] = { V_8, V_12, U16_16, U4_32, 0, 0 }, [INSTR_VRI_VVUUU] = { V_8, V_12, U12_16, U4_32, U4_28, 0 }, [INSTR_VRI_VVUUU2] = { V_8, V_12, U8_28, U8_16, U4_24, 0 }, [INSTR_VRI_VVV0U] = { V_8, V_12, V_16, U8_24, 0, 0 }, [INSTR_VRI_VVV0UU] = { V_8, V_12, V_16, U8_24, U4_32, 0 }, [INSTR_VRI_VVV0UU2] = { V_8, V_12, V_16, U8_28, U4_24, 0 }, - [INSTR_VRR_0V] = { V_12, 0, 0, 0, 0, 0 }, + [INSTR_VRI_VVV0UV] = { V_8, V_12, V_16, V_32, U8_24, 0 }, + [INSTR_VRR_0V0U] = { V_12, U16_20, 0, 0, 0, 0 }, [INSTR_VRR_0VV0U] = { V_12, V_16, U4_24, 0, 0, 0 }, + [INSTR_VRR_0VVU] = { V_12, V_16, U16_20, 0, 0, 0 }, [INSTR_VRR_RV0UU] = { R_8, V_12, U4_24, U4_28, 0, 0 }, [INSTR_VRR_VRR] = { V_8, R_12, R_16, 0, 0, 0 }, [INSTR_VRR_VV] = { V_8, V_12, 0, 0, 0, 0 }, @@ -455,21 +459,21 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) if (separator) ptr += sprintf(ptr, "%c", separator); if (operand->flags & OPERAND_GPR) - ptr += sprintf(ptr, "%%r%i", value); + ptr += sprintf(ptr, "%%r%u", value); else if (operand->flags & OPERAND_FPR) - ptr += sprintf(ptr, "%%f%i", value); + ptr += sprintf(ptr, "%%f%u", value); else if (operand->flags & OPERAND_AR) - ptr += sprintf(ptr, "%%a%i", value); + ptr += sprintf(ptr, "%%a%u", value); else if (operand->flags & OPERAND_CR) - ptr += sprintf(ptr, "%%c%i", value); + ptr += sprintf(ptr, "%%c%u", value); else if (operand->flags & OPERAND_VR) - ptr += sprintf(ptr, "%%v%i", value); + ptr += sprintf(ptr, "%%v%u", value); else if (operand->flags & OPERAND_PCREL) { void *pcrel = (void *)((int)value + addr); ptr += sprintf(ptr, "%px", pcrel); } else if (operand->flags & OPERAND_SIGNED) - ptr += sprintf(ptr, "%i", value); + ptr += sprintf(ptr, "%i", (int)value); else ptr += sprintf(ptr, "%u", value); if (operand->flags & OPERAND_DISP) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 14d324865e33..62f8f5a750a3 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -7,6 +7,7 @@ #define KMSG_COMPONENT "setup" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/sched/debug.h> #include <linux/compiler.h> #include <linux/init.h> #include <linux/errno.h> @@ -175,20 +176,45 @@ static __init void setup_topology(void) topology_max_mnest = max_mnest; } -void __do_early_pgm_check(struct pt_regs *regs) +void __init __do_early_pgm_check(struct pt_regs *regs) { - if (!fixup_exception(regs)) - disabled_wait(); + struct lowcore *lc = get_lowcore(); + unsigned long ip; + + regs->int_code = lc->pgm_int_code; + regs->int_parm_long = lc->trans_exc_code; + ip = __rewind_psw(regs->psw, regs->int_code >> 16); + + /* Monitor Event? Might be a warning */ + if ((regs->int_code & PGM_INT_CODE_MASK) == 0x40) { + if (report_bug(ip, regs) == BUG_TRAP_TYPE_WARN) + return; + } + if (fixup_exception(regs)) + return; + /* + * Unhandled exception - system cannot continue but try to get some + * helpful messages to the console. Use early_printk() to print + * some basic information in case it is too early for printk(). + */ + register_early_console(); + early_printk("PANIC: early exception %04x PSW: %016lx %016lx\n", + regs->int_code & 0xffff, regs->psw.mask, regs->psw.addr); + show_regs(regs); + disabled_wait(); } static noinline __init void setup_lowcore_early(void) { + struct lowcore *lc = get_lowcore(); psw_t psw; psw.addr = (unsigned long)early_pgm_check_handler; psw.mask = PSW_KERNEL_BITS; - get_lowcore()->program_new_psw = psw; - get_lowcore()->preempt_count = INIT_PREEMPT_COUNT; + lc->program_new_psw = psw; + lc->preempt_count = INIT_PREEMPT_COUNT; + lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW); + lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); } static __init void detect_diag9c(void) @@ -242,6 +268,8 @@ static __init void detect_machine_facilities(void) } if (test_facility(194)) get_lowcore()->machine_flags |= MACHINE_FLAG_RDP; + if (test_facility(85)) + get_lowcore()->machine_flags |= MACHINE_FLAG_SEQ_INSN; } static inline void save_vector_registers(void) diff --git a/arch/s390/kernel/early_printk.c b/arch/s390/kernel/early_printk.c index d9d53f44008a..cefe020a3be3 100644 --- a/arch/s390/kernel/early_printk.c +++ b/arch/s390/kernel/early_printk.c @@ -6,6 +6,7 @@ #include <linux/console.h> #include <linux/kernel.h> #include <linux/init.h> +#include <asm/setup.h> #include <asm/sclp.h> static void sclp_early_write(struct console *con, const char *s, unsigned int len) @@ -20,6 +21,16 @@ static struct console sclp_early_console = { .index = -1, }; +void __init register_early_console(void) +{ + if (early_console) + return; + if (!sclp.has_linemode && !sclp.has_vt220) + return; + early_console = &sclp_early_console; + register_console(early_console); +} + static int __init setup_early_printk(char *buf) { if (early_console) @@ -27,10 +38,7 @@ static int __init setup_early_printk(char *buf) /* Accept only "earlyprintk" and "earlyprintk=sclp" */ if (buf && !str_has_prefix(buf, "sclp")) return 0; - if (!sclp.has_linemode && !sclp.has_vt220) - return 0; - early_console = &sclp_early_console; - register_console(early_console); + register_early_console(); return 0; } early_param("earlyprintk", setup_early_printk); diff --git a/arch/s390/kernel/earlypgm.S b/arch/s390/kernel/earlypgm.S deleted file mode 100644 index c634871f0d90..000000000000 --- a/arch/s390/kernel/earlypgm.S +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright IBM Corp. 2006, 2007 - * Author(s): Michael Holzheu <holzheu@de.ibm.com> - */ - -#include <linux/linkage.h> -#include <asm/asm-offsets.h> - -SYM_CODE_START(early_pgm_check_handler) - stmg %r8,%r15,__LC_SAVE_AREA_SYNC - aghi %r15,-(STACK_FRAME_OVERHEAD+__PT_SIZE) - la %r11,STACK_FRAME_OVERHEAD(%r15) - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) - stmg %r0,%r7,__PT_R0(%r11) - mvc __PT_PSW(16,%r11),__LC_PGM_OLD_PSW - mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC - lgr %r2,%r11 - brasl %r14,__do_early_pgm_check - mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) - lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) - lpswe __LC_RETURN_PSW -SYM_CODE_END(early_pgm_check_handler) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 749410cfdbc0..1ff13239d4e5 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -42,7 +42,7 @@ _LPP_OFFSET = __LC_LPP .macro LPSWEY address, lpswe ALTERNATIVE_2 "b \lpswe;nopr", \ - ".insn siy,0xeb0000000071,\address,0", ALT_FACILITY_EARLY(193), \ + ".insn siy,0xeb0000000071,\address,0", ALT_FACILITY(193), \ __stringify(.insn siy,0xeb0000000071,LOWCORE_ALT_ADDRESS+\address,0), \ ALT_LOWCORE .endm @@ -222,17 +222,6 @@ SYM_FUNC_START(__sie64a) lctlg %c1,%c1,__LC_KERNEL_ASCE(%r14) # load primary asce lg %r14,__LC_CURRENT(%r14) mvi __TI_sie(%r14),0 -# some program checks are suppressing. C code (e.g. do_protection_exception) -# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There -# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable. -# Other instructions between __sie64a and .Lsie_done should not cause program -# interrupts. So lets use 3 nops as a landing pad for all possible rewinds. -.Lrewind_pad6: - nopr 7 -.Lrewind_pad4: - nopr 7 -.Lrewind_pad2: - nopr 7 SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL) lg %r14,__SF_SIE_SAVEAREA(%r15) # load guest register save area stmg %r0,%r13,0(%r14) # save guest gprs 0-13 @@ -244,15 +233,6 @@ SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL) lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers lg %r2,__SF_SIE_REASON(%r15) # return exit reason code BR_EX %r14 -.Lsie_fault: - lghi %r14,-EFAULT - stg %r14,__SF_SIE_REASON(%r15) # set exit reason code - j sie_exit - - EX_TABLE(.Lrewind_pad6,.Lsie_fault) - EX_TABLE(.Lrewind_pad4,.Lsie_fault) - EX_TABLE(.Lrewind_pad2,.Lsie_fault) - EX_TABLE(sie_exit,.Lsie_fault) SYM_FUNC_END(__sie64a) EXPORT_SYMBOL(__sie64a) EXPORT_SYMBOL(sie_exit) @@ -264,7 +244,7 @@ EXPORT_SYMBOL(sie_exit) */ SYM_CODE_START(system_call) - STMG_LC %r8,%r15,__LC_SAVE_AREA_SYNC + STMG_LC %r8,%r15,__LC_SAVE_AREA GET_LC %r13 stpt __LC_SYS_ENTER_TIMER(%r13) BPOFF @@ -287,7 +267,7 @@ SYM_CODE_START(system_call) xgr %r10,%r10 xgr %r11,%r11 la %r2,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs - mvc __PT_R8(64,%r2),__LC_SAVE_AREA_SYNC(%r13) + mvc __PT_R8(64,%r2),__LC_SAVE_AREA(%r13) MBEAR %r2,%r13 lgr %r3,%r14 brasl %r14,__do_syscall @@ -323,42 +303,41 @@ SYM_CODE_END(ret_from_fork) */ SYM_CODE_START(pgm_check_handler) - STMG_LC %r8,%r15,__LC_SAVE_AREA_SYNC + STMG_LC %r8,%r15,__LC_SAVE_AREA GET_LC %r13 stpt __LC_SYS_ENTER_TIMER(%r13) BPOFF - lgr %r10,%r15 lmg %r8,%r9,__LC_PGM_OLD_PSW(%r13) + xgr %r10,%r10 tmhh %r8,0x0001 # coming from user space? jno .Lpgm_skip_asce lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) j 3f # -> fault in user space .Lpgm_skip_asce: +#if IS_ENABLED(CONFIG_KVM) + lg %r11,__LC_CURRENT(%r13) + tm __TI_sie(%r11),0xff + jz 1f + BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST + SIEEXIT __SF_SIE_CONTROL(%r15),%r13 + lghi %r10,_PIF_GUEST_FAULT +#endif 1: tmhh %r8,0x4000 # PER bit set in old PSW ? jnz 2f # -> enabled, can't be a double fault tm __LC_PGM_ILC+3(%r13),0x80 # check for per exception jnz .Lpgm_svcper # -> single stepped svc -2: CHECK_STACK __LC_SAVE_AREA_SYNC,%r13 +2: CHECK_STACK __LC_SAVE_AREA,%r13 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) # CHECK_VMAP_STACK branches to stack_overflow or 4f - CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,%r13,4f + CHECK_VMAP_STACK __LC_SAVE_AREA,%r13,4f 3: lg %r15,__LC_KERNEL_STACK(%r13) 4: la %r11,STACK_FRAME_OVERHEAD(%r15) - xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) + stg %r10,__PT_FLAGS(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) stmg %r0,%r7,__PT_R0(%r11) - mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC(%r13) + mvc __PT_R8(64,%r11),__LC_SAVE_AREA(%r13) mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK(%r13) - stctg %c1,%c1,__PT_CR1(%r11) -#if IS_ENABLED(CONFIG_KVM) - ltg %r12,__LC_GMAP(%r13) - jz 5f - clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11) - jne 5f - BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST - SIEEXIT __SF_SIE_CONTROL(%r10),%r13 -#endif -5: stmg %r8,%r9,__PT_PSW(%r11) + stmg %r8,%r9,__PT_PSW(%r11) # clear user controlled registers to prevent speculative use xgr %r0,%r0 xgr %r1,%r1 @@ -367,6 +346,7 @@ SYM_CODE_START(pgm_check_handler) xgr %r5,%r5 xgr %r6,%r6 xgr %r7,%r7 + xgr %r12,%r12 lgr %r2,%r11 brasl %r14,__do_pgm_check tmhh %r8,0x0001 # returning to user space? @@ -398,7 +378,7 @@ SYM_CODE_END(pgm_check_handler) */ .macro INT_HANDLER name,lc_old_psw,handler SYM_CODE_START(\name) - STMG_LC %r8,%r15,__LC_SAVE_AREA_ASYNC + STMG_LC %r8,%r15,__LC_SAVE_AREA GET_LC %r13 stckf __LC_INT_CLOCK(%r13) stpt __LC_SYS_ENTER_TIMER(%r13) @@ -414,7 +394,7 @@ SYM_CODE_START(\name) BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST SIEEXIT __SF_SIE_CONTROL(%r15),%r13 #endif -0: CHECK_STACK __LC_SAVE_AREA_ASYNC,%r13 +0: CHECK_STACK __LC_SAVE_AREA,%r13 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) j 2f 1: lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) @@ -432,7 +412,7 @@ SYM_CODE_START(\name) xgr %r7,%r7 xgr %r10,%r10 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) - mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC(%r13) + mvc __PT_R8(64,%r11),__LC_SAVE_AREA(%r13) MBEAR %r11,%r13 stmg %r8,%r9,__PT_PSW(%r11) lgr %r2,%r11 # pass pointer to pt_regs @@ -599,6 +579,24 @@ SYM_CODE_START(restart_int_handler) 3: j 3b SYM_CODE_END(restart_int_handler) + __INIT +SYM_CODE_START(early_pgm_check_handler) + STMG_LC %r8,%r15,__LC_SAVE_AREA + GET_LC %r13 + aghi %r15,-(STACK_FRAME_OVERHEAD+__PT_SIZE) + la %r11,STACK_FRAME_OVERHEAD(%r15) + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + stmg %r0,%r7,__PT_R0(%r11) + mvc __PT_PSW(16,%r11),__LC_PGM_OLD_PSW(%r13) + mvc __PT_R8(64,%r11),__LC_SAVE_AREA(%r13) + lgr %r2,%r11 + brasl %r14,__do_early_pgm_check + mvc __LC_RETURN_PSW(16,%r13),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) + lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) + LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE +SYM_CODE_END(early_pgm_check_handler) + __FINIT + .section .kprobes.text, "ax" #if defined(CONFIG_CHECK_STACK) || defined(CONFIG_VMAP_STACK) diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 0bd6adc40a34..51439a71e392 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -50,10 +50,6 @@ struct ftrace_insn { s32 disp; } __packed; -#ifdef CONFIG_MODULES -static char *ftrace_plt; -#endif /* CONFIG_MODULES */ - static const char *ftrace_shared_hotpatch_trampoline(const char **end) { const char *tstart, *tend; @@ -73,19 +69,20 @@ static const char *ftrace_shared_hotpatch_trampoline(const char **end) bool ftrace_need_init_nop(void) { - return true; + return !MACHINE_HAS_SEQ_INSN; } int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) { static struct ftrace_hotpatch_trampoline *next_vmlinux_trampoline = __ftrace_hotpatch_trampolines_start; - static const char orig[6] = { 0xc0, 0x04, 0x00, 0x00, 0x00, 0x00 }; + static const struct ftrace_insn orig = { .opc = 0xc004, .disp = 0 }; static struct ftrace_hotpatch_trampoline *trampoline; struct ftrace_hotpatch_trampoline **next_trampoline; struct ftrace_hotpatch_trampoline *trampolines_end; struct ftrace_hotpatch_trampoline tmp; struct ftrace_insn *insn; + struct ftrace_insn old; const char *shared; s32 disp; @@ -99,7 +96,6 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) if (mod) { next_trampoline = &mod->arch.next_trampoline; trampolines_end = mod->arch.trampolines_end; - shared = ftrace_plt; } #endif @@ -107,8 +103,10 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) return -ENOMEM; trampoline = (*next_trampoline)++; + if (copy_from_kernel_nofault(&old, (void *)rec->ip, sizeof(old))) + return -EFAULT; /* Check for the compiler-generated fentry nop (brcl 0, .). */ - if (WARN_ON_ONCE(memcmp((const void *)rec->ip, &orig, sizeof(orig)))) + if (WARN_ON_ONCE(memcmp(&orig, &old, sizeof(old)))) return -EINVAL; /* Generate the trampoline. */ @@ -144,8 +142,35 @@ static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrac return trampoline; } -int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, - unsigned long addr) +static inline struct ftrace_insn +ftrace_generate_branch_insn(unsigned long ip, unsigned long target) +{ + /* brasl r0,target or brcl 0,0 */ + return (struct ftrace_insn){ .opc = target ? 0xc005 : 0xc004, + .disp = target ? (target - ip) / 2 : 0 }; +} + +static int ftrace_patch_branch_insn(unsigned long ip, unsigned long old_target, + unsigned long target) +{ + struct ftrace_insn orig = ftrace_generate_branch_insn(ip, old_target); + struct ftrace_insn new = ftrace_generate_branch_insn(ip, target); + struct ftrace_insn old; + + if (!IS_ALIGNED(ip, 8)) + return -EINVAL; + if (copy_from_kernel_nofault(&old, (void *)ip, sizeof(old))) + return -EFAULT; + /* Verify that the to be replaced code matches what we expect. */ + if (memcmp(&orig, &old, sizeof(old))) + return -EINVAL; + s390_kernel_write((void *)ip, &new, sizeof(new)); + return 0; +} + +static int ftrace_modify_trampoline_call(struct dyn_ftrace *rec, + unsigned long old_addr, + unsigned long addr) { struct ftrace_hotpatch_trampoline *trampoline; u64 old; @@ -161,6 +186,15 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, return 0; } +int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, + unsigned long addr) +{ + if (MACHINE_HAS_SEQ_INSN) + return ftrace_patch_branch_insn(rec->ip, old_addr, addr); + else + return ftrace_modify_trampoline_call(rec, old_addr, addr); +} + static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable) { u16 old; @@ -179,11 +213,14 @@ static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable) int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { - /* Expect brcl 0xf,... */ - return ftrace_patch_branch_mask((void *)rec->ip, 0xc0f4, false); + /* Expect brcl 0xf,... for the !MACHINE_HAS_SEQ_INSN case */ + if (MACHINE_HAS_SEQ_INSN) + return ftrace_patch_branch_insn(rec->ip, addr, 0); + else + return ftrace_patch_branch_mask((void *)rec->ip, 0xc0f4, false); } -int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +static int ftrace_make_trampoline_call(struct dyn_ftrace *rec, unsigned long addr) { struct ftrace_hotpatch_trampoline *trampoline; @@ -195,6 +232,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) return ftrace_patch_branch_mask((void *)rec->ip, 0xc004, true); } +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + if (MACHINE_HAS_SEQ_INSN) + return ftrace_patch_branch_insn(rec->ip, 0, addr); + else + return ftrace_make_trampoline_call(rec, addr); +} + int ftrace_update_ftrace_func(ftrace_func_t func) { ftrace_func = func; @@ -215,25 +260,6 @@ void ftrace_arch_code_modify_post_process(void) text_poke_sync_lock(); } -#ifdef CONFIG_MODULES - -static int __init ftrace_plt_init(void) -{ - const char *start, *end; - - ftrace_plt = execmem_alloc(EXECMEM_FTRACE, PAGE_SIZE); - if (!ftrace_plt) - panic("cannot allocate ftrace plt\n"); - - start = ftrace_shared_hotpatch_trampoline(&end); - memcpy(ftrace_plt, start, end - start); - set_memory_rox((unsigned long)ftrace_plt, 1); - return 0; -} -device_initcall(ftrace_plt_init); - -#endif /* CONFIG_MODULES */ - #ifdef CONFIG_FUNCTION_GRAPH_TRACER /* * Hook the return address and push it in the stack of return addresses @@ -264,26 +290,14 @@ NOKPROBE_SYMBOL(prepare_ftrace_return); */ int ftrace_enable_ftrace_graph_caller(void) { - int rc; - /* Expect brc 0xf,... */ - rc = ftrace_patch_branch_mask(ftrace_graph_caller, 0xa7f4, false); - if (rc) - return rc; - text_poke_sync_lock(); - return 0; + return ftrace_patch_branch_mask(ftrace_graph_caller, 0xa7f4, false); } int ftrace_disable_ftrace_graph_caller(void) { - int rc; - /* Expect brc 0x0,... */ - rc = ftrace_patch_branch_mask(ftrace_graph_caller, 0xa704, true); - if (rc) - return rc; - text_poke_sync_lock(); - return 0; + return ftrace_patch_branch_mask(ftrace_graph_caller, 0xa704, true); } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ @@ -304,7 +318,7 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, if (bit < 0) return; - kmsan_unpoison_memory(fregs, sizeof(*fregs)); + kmsan_unpoison_memory(fregs, ftrace_regs_size()); regs = ftrace_get_regs(fregs); p = get_kprobe((kprobe_opcode_t *)ip); if (!regs || unlikely(!p) || kprobe_disabled(p)) diff --git a/arch/s390/kernel/ftrace.h b/arch/s390/kernel/ftrace.h index 7f75a9616406..23337065f402 100644 --- a/arch/s390/kernel/ftrace.h +++ b/arch/s390/kernel/ftrace.h @@ -18,7 +18,5 @@ extern const char ftrace_shared_hotpatch_trampoline_br[]; extern const char ftrace_shared_hotpatch_trampoline_br_end[]; extern const char ftrace_shared_hotpatch_trampoline_exrl[]; extern const char ftrace_shared_hotpatch_trampoline_exrl_end[]; -extern const char ftrace_plt_template[]; -extern const char ftrace_plt_template_end[]; #endif /* _FTRACE_H */ diff --git a/arch/s390/kernel/hiperdispatch.c b/arch/s390/kernel/hiperdispatch.c new file mode 100644 index 000000000000..2a99a216ab62 --- /dev/null +++ b/arch/s390/kernel/hiperdispatch.c @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corp. 2024 + */ + +#define KMSG_COMPONENT "hd" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +/* + * Hiperdispatch: + * Dynamically calculates the optimum number of high capacity COREs + * by considering the state the system is in. When hiperdispatch decides + * that a capacity update is necessary, it schedules a topology update. + * During topology updates the CPU capacities are always re-adjusted. + * + * There is two places where CPU capacities are being accessed within + * hiperdispatch. + * -> hiperdispatch's reoccuring work function reads CPU capacities to + * determine high capacity CPU count. + * -> during a topology update hiperdispatch's adjustment function + * updates CPU capacities. + * These two can run on different CPUs in parallel which can cause + * hiperdispatch to make wrong decisions. This can potentially cause + * some overhead by leading to extra rebuild_sched_domains() calls + * for correction. Access to capacities within hiperdispatch has to be + * serialized to prevent the overhead. + * + * Hiperdispatch decision making revolves around steal time. + * HD_STEAL_THRESHOLD value is taken as reference. Whenever steal time + * crosses the threshold value hiperdispatch falls back to giving high + * capacities to entitled CPUs. When steal time drops below the + * threshold boundary, hiperdispatch utilizes all CPUs by giving all + * of them high capacity. + * + * The theory behind HD_STEAL_THRESHOLD is related to the SMP thread + * performance. Comparing the throughput of; + * - single CORE, with N threads, running N tasks + * - N separate COREs running N tasks, + * using individual COREs for individual tasks yield better + * performance. This performance difference is roughly ~30% (can change + * between machine generations) + * + * Hiperdispatch tries to hint scheduler to use individual COREs for + * each task, as long as steal time on those COREs are less than 30%, + * therefore delaying the throughput loss caused by using SMP threads. + */ + +#include <linux/cpumask.h> +#include <linux/debugfs.h> +#include <linux/device.h> +#include <linux/kernel_stat.h> +#include <linux/kstrtox.h> +#include <linux/ktime.h> +#include <linux/sysctl.h> +#include <linux/types.h> +#include <linux/workqueue.h> +#include <asm/hiperdispatch.h> +#include <asm/setup.h> +#include <asm/smp.h> +#include <asm/topology.h> + +#define CREATE_TRACE_POINTS +#include <asm/trace/hiperdispatch.h> + +#define HD_DELAY_FACTOR (4) +#define HD_DELAY_INTERVAL (HZ / 4) +#define HD_STEAL_THRESHOLD 30 +#define HD_STEAL_AVG_WEIGHT 16 + +static cpumask_t hd_vl_coremask; /* Mask containing all vertical low COREs */ +static cpumask_t hd_vmvl_cpumask; /* Mask containing vertical medium and low CPUs */ +static int hd_high_capacity_cores; /* Current CORE count with high capacity */ +static int hd_entitled_cores; /* Total vertical high and medium CORE count */ +static int hd_online_cores; /* Current online CORE count */ + +static unsigned long hd_previous_steal; /* Previous iteration's CPU steal timer total */ +static unsigned long hd_high_time; /* Total time spent while all cpus have high capacity */ +static unsigned long hd_low_time; /* Total time spent while vl cpus have low capacity */ +static atomic64_t hd_adjustments; /* Total occurrence count of hiperdispatch adjustments */ + +static unsigned int hd_steal_threshold = HD_STEAL_THRESHOLD; +static unsigned int hd_delay_factor = HD_DELAY_FACTOR; +static int hd_enabled; + +static void hd_capacity_work_fn(struct work_struct *work); +static DECLARE_DELAYED_WORK(hd_capacity_work, hd_capacity_work_fn); + +static int hd_set_hiperdispatch_mode(int enable) +{ + if (!MACHINE_HAS_TOPOLOGY) + enable = 0; + if (hd_enabled == enable) + return 0; + hd_enabled = enable; + return 1; +} + +void hd_reset_state(void) +{ + cpumask_clear(&hd_vl_coremask); + cpumask_clear(&hd_vmvl_cpumask); + hd_entitled_cores = 0; + hd_online_cores = 0; +} + +void hd_add_core(int cpu) +{ + const struct cpumask *siblings; + int polarization; + + hd_online_cores++; + polarization = smp_cpu_get_polarization(cpu); + siblings = topology_sibling_cpumask(cpu); + switch (polarization) { + case POLARIZATION_VH: + hd_entitled_cores++; + break; + case POLARIZATION_VM: + hd_entitled_cores++; + cpumask_or(&hd_vmvl_cpumask, &hd_vmvl_cpumask, siblings); + break; + case POLARIZATION_VL: + cpumask_set_cpu(cpu, &hd_vl_coremask); + cpumask_or(&hd_vmvl_cpumask, &hd_vmvl_cpumask, siblings); + break; + } +} + +/* Serialize update and read operations of debug counters. */ +static DEFINE_MUTEX(hd_counter_mutex); + +static void hd_update_times(void) +{ + static ktime_t prev; + ktime_t now; + + /* + * Check if hiperdispatch is active, if not set the prev to 0. + * This way it is possible to differentiate the first update iteration after + * enabling hiperdispatch. + */ + if (hd_entitled_cores == 0 || hd_enabled == 0) { + prev = ktime_set(0, 0); + return; + } + now = ktime_get(); + if (ktime_after(prev, 0)) { + if (hd_high_capacity_cores == hd_online_cores) + hd_high_time += ktime_ms_delta(now, prev); + else + hd_low_time += ktime_ms_delta(now, prev); + } + prev = now; +} + +static void hd_update_capacities(void) +{ + int cpu, upscaling_cores; + unsigned long capacity; + + upscaling_cores = hd_high_capacity_cores - hd_entitled_cores; + capacity = upscaling_cores > 0 ? CPU_CAPACITY_HIGH : CPU_CAPACITY_LOW; + hd_high_capacity_cores = hd_entitled_cores; + for_each_cpu(cpu, &hd_vl_coremask) { + smp_set_core_capacity(cpu, capacity); + if (capacity != CPU_CAPACITY_HIGH) + continue; + hd_high_capacity_cores++; + upscaling_cores--; + if (upscaling_cores == 0) + capacity = CPU_CAPACITY_LOW; + } +} + +void hd_disable_hiperdispatch(void) +{ + cancel_delayed_work_sync(&hd_capacity_work); + hd_high_capacity_cores = hd_online_cores; + hd_previous_steal = 0; +} + +int hd_enable_hiperdispatch(void) +{ + mutex_lock(&hd_counter_mutex); + hd_update_times(); + mutex_unlock(&hd_counter_mutex); + if (hd_enabled == 0) + return 0; + if (hd_entitled_cores == 0) + return 0; + if (hd_online_cores <= hd_entitled_cores) + return 0; + mod_delayed_work(system_wq, &hd_capacity_work, HD_DELAY_INTERVAL * hd_delay_factor); + hd_update_capacities(); + return 1; +} + +static unsigned long hd_steal_avg(unsigned long new) +{ + static unsigned long steal; + + steal = (steal * (HD_STEAL_AVG_WEIGHT - 1) + new) / HD_STEAL_AVG_WEIGHT; + return steal; +} + +static unsigned long hd_calculate_steal_percentage(void) +{ + unsigned long time_delta, steal_delta, steal, percentage; + static ktime_t prev; + int cpus, cpu; + ktime_t now; + + cpus = 0; + steal = 0; + percentage = 0; + for_each_cpu(cpu, &hd_vmvl_cpumask) { + steal += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + cpus++; + } + /* + * If there is no vertical medium and low CPUs steal time + * is 0 as vertical high CPUs shouldn't experience steal time. + */ + if (cpus == 0) + return percentage; + now = ktime_get(); + time_delta = ktime_to_ns(ktime_sub(now, prev)); + if (steal > hd_previous_steal && hd_previous_steal != 0) { + steal_delta = (steal - hd_previous_steal) * 100 / time_delta; + percentage = steal_delta / cpus; + } + hd_previous_steal = steal; + prev = now; + return percentage; +} + +static void hd_capacity_work_fn(struct work_struct *work) +{ + unsigned long steal_percentage, new_cores; + + mutex_lock(&smp_cpu_state_mutex); + /* + * If online cores are less or equal to entitled cores hiperdispatch + * does not need to make any adjustments, call a topology update to + * disable hiperdispatch. + * Normally this check is handled on topology update, but during cpu + * unhotplug, topology and cpu mask updates are done in reverse + * order, causing hd_enable_hiperdispatch() to get stale data. + */ + if (hd_online_cores <= hd_entitled_cores) { + topology_schedule_update(); + mutex_unlock(&smp_cpu_state_mutex); + return; + } + steal_percentage = hd_steal_avg(hd_calculate_steal_percentage()); + if (steal_percentage < hd_steal_threshold) + new_cores = hd_online_cores; + else + new_cores = hd_entitled_cores; + if (hd_high_capacity_cores != new_cores) { + trace_s390_hd_rebuild_domains(hd_high_capacity_cores, new_cores); + hd_high_capacity_cores = new_cores; + atomic64_inc(&hd_adjustments); + topology_schedule_update(); + } + trace_s390_hd_work_fn(steal_percentage, hd_entitled_cores, hd_high_capacity_cores); + mutex_unlock(&smp_cpu_state_mutex); + schedule_delayed_work(&hd_capacity_work, HD_DELAY_INTERVAL); +} + +static int hiperdispatch_ctl_handler(const struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + int hiperdispatch; + int rc; + struct ctl_table ctl_entry = { + .procname = ctl->procname, + .data = &hiperdispatch, + .maxlen = sizeof(int), + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }; + + hiperdispatch = hd_enabled; + rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos); + if (rc < 0 || !write) + return rc; + mutex_lock(&smp_cpu_state_mutex); + if (hd_set_hiperdispatch_mode(hiperdispatch)) + topology_schedule_update(); + mutex_unlock(&smp_cpu_state_mutex); + return 0; +} + +static struct ctl_table hiperdispatch_ctl_table[] = { + { + .procname = "hiperdispatch", + .mode = 0644, + .proc_handler = hiperdispatch_ctl_handler, + }, +}; + +static ssize_t hd_steal_threshold_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%u\n", hd_steal_threshold); +} + +static ssize_t hd_steal_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + unsigned int val; + int rc; + + rc = kstrtouint(buf, 0, &val); + if (rc) + return rc; + if (val > 100) + return -ERANGE; + hd_steal_threshold = val; + return count; +} + +static DEVICE_ATTR_RW(hd_steal_threshold); + +static ssize_t hd_delay_factor_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%u\n", hd_delay_factor); +} + +static ssize_t hd_delay_factor_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + unsigned int val; + int rc; + + rc = kstrtouint(buf, 0, &val); + if (rc) + return rc; + if (!val) + return -ERANGE; + hd_delay_factor = val; + return count; +} + +static DEVICE_ATTR_RW(hd_delay_factor); + +static struct attribute *hd_attrs[] = { + &dev_attr_hd_steal_threshold.attr, + &dev_attr_hd_delay_factor.attr, + NULL, +}; + +static const struct attribute_group hd_attr_group = { + .name = "hiperdispatch", + .attrs = hd_attrs, +}; + +static int hd_greedy_time_get(void *unused, u64 *val) +{ + mutex_lock(&hd_counter_mutex); + hd_update_times(); + *val = hd_high_time; + mutex_unlock(&hd_counter_mutex); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(hd_greedy_time_fops, hd_greedy_time_get, NULL, "%llu\n"); + +static int hd_conservative_time_get(void *unused, u64 *val) +{ + mutex_lock(&hd_counter_mutex); + hd_update_times(); + *val = hd_low_time; + mutex_unlock(&hd_counter_mutex); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(hd_conservative_time_fops, hd_conservative_time_get, NULL, "%llu\n"); + +static int hd_adjustment_count_get(void *unused, u64 *val) +{ + *val = atomic64_read(&hd_adjustments); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(hd_adjustments_fops, hd_adjustment_count_get, NULL, "%llu\n"); + +static void __init hd_create_debugfs_counters(void) +{ + struct dentry *dir; + + dir = debugfs_create_dir("hiperdispatch", arch_debugfs_dir); + debugfs_create_file("conservative_time_ms", 0400, dir, NULL, &hd_conservative_time_fops); + debugfs_create_file("greedy_time_ms", 0400, dir, NULL, &hd_greedy_time_fops); + debugfs_create_file("adjustment_count", 0400, dir, NULL, &hd_adjustments_fops); +} + +static void __init hd_create_attributes(void) +{ + struct device *dev; + + dev = bus_get_dev_root(&cpu_subsys); + if (!dev) + return; + if (sysfs_create_group(&dev->kobj, &hd_attr_group)) + pr_warn("Unable to create hiperdispatch attribute group\n"); + put_device(dev); +} + +static int __init hd_init(void) +{ + if (IS_ENABLED(CONFIG_HIPERDISPATCH_ON)) { + hd_set_hiperdispatch_mode(1); + topology_schedule_update(); + } + if (!register_sysctl("s390", hiperdispatch_ctl_table)) + pr_warn("Failed to register s390.hiperdispatch sysctl attribute\n"); + hd_create_debugfs_counters(); + hd_create_attributes(); + return 0; +} +late_initcall(hd_init); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index f17bb7bf9392..edbb52ce3f1e 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -209,7 +209,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \ struct kobj_attribute *attr, \ char *page) \ { \ - return scnprintf(page, PAGE_SIZE, _format, ##args); \ + return sysfs_emit(page, _format, ##args); \ } #define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \ @@ -372,7 +372,7 @@ EXPORT_SYMBOL_GPL(ipl_info); static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", ipl_type_str(ipl_info.type)); + return sysfs_emit(page, "%s\n", ipl_type_str(ipl_info.type)); } static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); @@ -380,7 +380,7 @@ static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); static ssize_t ipl_secure_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%i\n", !!ipl_secure_flag); + return sysfs_emit(page, "%i\n", !!ipl_secure_flag); } static struct kobj_attribute sys_ipl_secure_attr = @@ -389,7 +389,7 @@ static struct kobj_attribute sys_ipl_secure_attr = static ssize_t ipl_has_secure_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%i\n", !!sclp.has_sipl); + return sysfs_emit(page, "%i\n", !!sclp.has_sipl); } static struct kobj_attribute sys_ipl_has_secure_attr = @@ -402,7 +402,7 @@ static ssize_t ipl_vm_parm_show(struct kobject *kobj, if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW)) ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block); - return sprintf(page, "%s\n", parm); + return sysfs_emit(page, "%s\n", parm); } static struct kobj_attribute sys_ipl_vm_parm_attr = @@ -413,18 +413,18 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj, { switch (ipl_info.type) { case IPL_TYPE_CCW: - return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid, - ipl_block.ccw.devno); + return sysfs_emit(page, "0.%x.%04x\n", ipl_block.ccw.ssid, + ipl_block.ccw.devno); case IPL_TYPE_ECKD: case IPL_TYPE_ECKD_DUMP: - return sprintf(page, "0.%x.%04x\n", ipl_block.eckd.ssid, - ipl_block.eckd.devno); + return sysfs_emit(page, "0.%x.%04x\n", ipl_block.eckd.ssid, + ipl_block.eckd.devno); case IPL_TYPE_FCP: case IPL_TYPE_FCP_DUMP: - return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno); + return sysfs_emit(page, "0.0.%04x\n", ipl_block.fcp.devno); case IPL_TYPE_NVME: case IPL_TYPE_NVME_DUMP: - return sprintf(page, "%08ux\n", ipl_block.nvme.fid); + return sysfs_emit(page, "%08ux\n", ipl_block.nvme.fid); default: return 0; } @@ -503,12 +503,12 @@ static ssize_t eckd_##_name##_br_chr_show(struct kobject *kobj, \ if (!ipb->br_chr.cyl && \ !ipb->br_chr.head && \ !ipb->br_chr.record) \ - return sprintf(buf, "auto\n"); \ + return sysfs_emit(buf, "auto\n"); \ \ - return sprintf(buf, "0x%x,0x%x,0x%x\n", \ - ipb->br_chr.cyl, \ - ipb->br_chr.head, \ - ipb->br_chr.record); \ + return sysfs_emit(buf, "0x%x,0x%x,0x%x\n", \ + ipb->br_chr.cyl, \ + ipb->br_chr.head, \ + ipb->br_chr.record); \ } #define IPL_ATTR_BR_CHR_STORE_FN(_name, _ipb) \ @@ -573,11 +573,11 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, char loadparm[LOADPARM_LEN + 1] = {}; if (!sclp_ipl_info.is_valid) - return sprintf(page, "#unknown#\n"); + return sysfs_emit(page, "#unknown#\n"); memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); EBCASC(loadparm, LOADPARM_LEN); strim(loadparm); - return sprintf(page, "%s\n", loadparm); + return sysfs_emit(page, "%s\n", loadparm); } static struct kobj_attribute sys_ipl_ccw_loadparm_attr = @@ -731,7 +731,7 @@ static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb, char vmparm[DIAG308_VMPARM_SIZE + 1] = {}; ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb); - return sprintf(page, "%s\n", vmparm); + return sysfs_emit(page, "%s\n", vmparm); } static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb, @@ -839,7 +839,7 @@ static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb, char buf[LOADPARM_LEN + 1]; reipl_get_ascii_loadparm(buf, ipb); - return sprintf(page, "%s\n", buf); + return sysfs_emit(page, "%s\n", buf); } static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb, @@ -895,7 +895,7 @@ DEFINE_GENERIC_LOADPARM(eckd); static ssize_t reipl_fcp_clear_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%u\n", reipl_fcp_clear); + return sysfs_emit(page, "%u\n", reipl_fcp_clear); } static ssize_t reipl_fcp_clear_store(struct kobject *kobj, @@ -963,7 +963,7 @@ static struct attribute_group reipl_nvme_attr_group = { static ssize_t reipl_nvme_clear_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%u\n", reipl_nvme_clear); + return sysfs_emit(page, "%u\n", reipl_nvme_clear); } static ssize_t reipl_nvme_clear_store(struct kobject *kobj, @@ -984,7 +984,7 @@ DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw); static ssize_t reipl_ccw_clear_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%u\n", reipl_ccw_clear); + return sysfs_emit(page, "%u\n", reipl_ccw_clear); } static ssize_t reipl_ccw_clear_store(struct kobject *kobj, @@ -1056,7 +1056,7 @@ static struct attribute_group reipl_eckd_attr_group = { static ssize_t reipl_eckd_clear_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%u\n", reipl_eckd_clear); + return sysfs_emit(page, "%u\n", reipl_eckd_clear); } static ssize_t reipl_eckd_clear_store(struct kobject *kobj, @@ -1086,7 +1086,7 @@ static ssize_t reipl_nss_name_show(struct kobject *kobj, char nss_name[NSS_NAME_SIZE + 1] = {}; reipl_get_ascii_nss_name(nss_name, reipl_block_nss); - return sprintf(page, "%s\n", nss_name); + return sysfs_emit(page, "%s\n", nss_name); } static ssize_t reipl_nss_name_store(struct kobject *kobj, @@ -1171,7 +1171,7 @@ static int reipl_set_type(enum ipl_type type) static ssize_t reipl_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", ipl_type_str(reipl_type)); + return sysfs_emit(page, "%s\n", ipl_type_str(reipl_type)); } static ssize_t reipl_type_store(struct kobject *kobj, @@ -1692,7 +1692,7 @@ static int dump_set_type(enum dump_type type) static ssize_t dump_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", dump_type_str(dump_type)); + return sysfs_emit(page, "%s\n", dump_type_str(dump_type)); } static ssize_t dump_type_store(struct kobject *kobj, @@ -1717,6 +1717,24 @@ static ssize_t dump_type_store(struct kobject *kobj, static struct kobj_attribute dump_type_attr = __ATTR(dump_type, 0644, dump_type_show, dump_type_store); +static ssize_t dump_area_size_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) +{ + return sysfs_emit(page, "%lu\n", sclp.hsa_size); +} + +static struct kobj_attribute dump_area_size_attr = __ATTR_RO(dump_area_size); + +static struct attribute *dump_attrs[] = { + &dump_type_attr.attr, + &dump_area_size_attr.attr, + NULL, +}; + +static struct attribute_group dump_attr_group = { + .attrs = dump_attrs, +}; + static struct kset *dump_kset; static void diag308_dump(void *dump_block) @@ -1853,7 +1871,7 @@ static int __init dump_init(void) dump_kset = kset_create_and_add("dump", NULL, firmware_kobj); if (!dump_kset) return -ENOMEM; - rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr); + rc = sysfs_create_group(&dump_kset->kobj, &dump_attr_group); if (rc) { kset_unregister(dump_kset); return rc; @@ -2034,7 +2052,7 @@ static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR, static ssize_t on_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", on_reboot_trigger.action->name); + return sysfs_emit(page, "%s\n", on_reboot_trigger.action->name); } static ssize_t on_reboot_store(struct kobject *kobj, @@ -2060,7 +2078,7 @@ static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action}; static ssize_t on_panic_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", on_panic_trigger.action->name); + return sysfs_emit(page, "%s\n", on_panic_trigger.action->name); } static ssize_t on_panic_store(struct kobject *kobj, @@ -2086,7 +2104,7 @@ static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR, static ssize_t on_restart_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", on_restart_trigger.action->name); + return sysfs_emit(page, "%s\n", on_restart_trigger.action->name); } static ssize_t on_restart_store(struct kobject *kobj, @@ -2122,7 +2140,7 @@ static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action}; static ssize_t on_halt_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", on_halt_trigger.action->name); + return sysfs_emit(page, "%s\n", on_halt_trigger.action->name); } static ssize_t on_halt_store(struct kobject *kobj, @@ -2148,7 +2166,7 @@ static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action}; static ssize_t on_poff_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { - return sprintf(page, "%s\n", on_poff_trigger.action->name); + return sysfs_emit(page, "%s\n", on_poff_trigger.action->name); } static ssize_t on_poff_store(struct kobject *kobj, diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 1af5a08d72ab..ef7be599e1f7 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -30,6 +30,7 @@ #include <asm/stacktrace.h> #include <asm/softirq_stack.h> #include <asm/vtime.h> +#include <asm/asm.h> #include "entry.h" DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); @@ -76,6 +77,7 @@ static const struct irq_class irqclass_sub_desc[] = { {.irq = IRQEXT_CMS, .name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, {.irq = IRQEXT_CMC, .name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, {.irq = IRQEXT_FTP, .name = "FTP", .desc = "[EXT] HMC FTP Service"}, + {.irq = IRQEXT_WTI, .name = "WTI", .desc = "[EXT] Warning Track"}, {.irq = IRQIO_CIO, .name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, {.irq = IRQIO_DAS, .name = "DAS", .desc = "[I/O] DASD"}, {.irq = IRQIO_C15, .name = "C15", .desc = "[I/O] 3215"}, @@ -128,9 +130,13 @@ static int irq_pending(struct pt_regs *regs) { int cc; - asm volatile("tpi 0\n" - "ipm %0" : "=d" (cc) : : "cc"); - return cc >> 28; + asm volatile( + " tpi 0\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : + : CC_CLOBBER); + return CC_TRANSFORM(cc); } void noinstr do_io_irq(struct pt_regs *regs) @@ -252,7 +258,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); goto out; } - if (index < nr_irqs) { + if (index < irq_get_nr_irqs()) { show_msi_interrupt(p, index); goto out; } diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 05c83505e979..6295faf0987d 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -21,6 +21,7 @@ #include <linux/hardirq.h> #include <linux/ftrace.h> #include <linux/execmem.h> +#include <asm/text-patching.h> #include <asm/set_memory.h> #include <asm/sections.h> #include <asm/dis.h> @@ -152,7 +153,12 @@ void arch_arm_kprobe(struct kprobe *p) { struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; - stop_machine_cpuslocked(swap_instruction, &args, NULL); + if (MACHINE_HAS_SEQ_INSN) { + swap_instruction(&args); + text_poke_sync(); + } else { + stop_machine_cpuslocked(swap_instruction, &args, NULL); + } } NOKPROBE_SYMBOL(arch_arm_kprobe); @@ -160,7 +166,12 @@ void arch_disarm_kprobe(struct kprobe *p) { struct swap_insn_args args = {.p = p, .arm_kprobe = 0}; - stop_machine_cpuslocked(swap_instruction, &args, NULL); + if (MACHINE_HAS_SEQ_INSN) { + swap_instruction(&args); + text_poke_sync(); + } else { + stop_machine_cpuslocked(swap_instruction, &args, NULL); + } } NOKPROBE_SYMBOL(arch_disarm_kprobe); diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index ae4d4fd9afcd..7e267ef63a7f 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -9,6 +9,7 @@ #include <asm/ftrace.h> #include <asm/nospec-insn.h> #include <asm/ptrace.h> +#include <asm/march.h> #define STACK_FRAME_SIZE_PTREGS (STACK_FRAME_OVERHEAD + __PT_SIZE) #define STACK_PTREGS (STACK_FRAME_OVERHEAD) @@ -88,7 +89,7 @@ SYM_CODE_START(ftrace_caller) SYM_CODE_END(ftrace_caller) SYM_CODE_START(ftrace_common) -#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifdef MARCH_HAS_Z196_FEATURES aghik %r2,%r0,-MCOUNT_INSN_SIZE lgrl %r4,function_trace_op lgrl %r1,ftrace_func @@ -115,7 +116,7 @@ SYM_INNER_LABEL(ftrace_graph_caller, SYM_L_GLOBAL) .Lftrace_graph_caller_end: #endif lg %r0,(STACK_FREGS_PTREGS_PSW+8)(%r15) -#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +#ifdef MARCH_HAS_Z196_FEATURES ltg %r1,STACK_FREGS_PTREGS_ORIG_GPR2(%r15) locgrz %r1,%r0 #else diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c index a95188818637..5970dd3ee7c5 100644 --- a/arch/s390/kernel/nospec-sysfs.c +++ b/arch/s390/kernel/nospec-sysfs.c @@ -7,17 +7,17 @@ ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Mitigation: __user pointer sanitization\n"); + return sysfs_emit(buf, "Mitigation: __user pointer sanitization\n"); } ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) { if (test_facility(156)) - return sprintf(buf, "Mitigation: etokens\n"); + return sysfs_emit(buf, "Mitigation: etokens\n"); if (nospec_uses_trampoline()) - return sprintf(buf, "Mitigation: execute trampolines\n"); + return sysfs_emit(buf, "Mitigation: execute trampolines\n"); if (nobp_enabled()) - return sprintf(buf, "Mitigation: limited branch prediction\n"); - return sprintf(buf, "Vulnerable\n"); + return sysfs_emit(buf, "Mitigation: limited branch prediction\n"); + return sysfs_emit(buf, "Vulnerable\n"); } diff --git a/arch/s390/kernel/numa.c b/arch/s390/kernel/numa.c index 23ab9f02f278..ddc1448ea2e1 100644 --- a/arch/s390/kernel/numa.c +++ b/arch/s390/kernel/numa.c @@ -14,9 +14,6 @@ #include <linux/node.h> #include <asm/numa.h> -struct pglist_data *node_data[MAX_NUMNODES]; -EXPORT_SYMBOL(node_data); - void __init numa_setup(void) { int nid; diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c index b695f980bbde..29080d6d5d8d 100644 --- a/arch/s390/kernel/os_info.c +++ b/arch/s390/kernel/os_info.c @@ -180,7 +180,7 @@ fail: } /* - * Return pointer to os infor entry and its size + * Return pointer to os info entry and its size */ void *os_info_old_entry(int nr, unsigned long *size) { diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 6968be98af11..b0bc68da6a11 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -22,6 +22,10 @@ #include <asm/hwctrset.h> #include <asm/debug.h> +/* Perf PMU definitions for the counter facility */ +#define PERF_CPUM_CF_MAX_CTR 0xffffUL /* Max ctr for ECCTR */ +#define PERF_EVENT_CPUM_CF_DIAG 0xBC000UL /* Event: Counter sets */ + enum cpumf_ctr_set { CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */ CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */ @@ -831,7 +835,7 @@ static int __hw_perf_event_init(struct perf_event *event, unsigned int type) return validate_ctr_version(hwc->config, set); } -/* Events CPU_CYLCES and INSTRUCTIONS can be submitted with two different +/* Events CPU_CYCLES and INSTRUCTIONS can be submitted with two different * attribute::type values: * - PERF_TYPE_HARDWARE: * - pmu->type: @@ -875,8 +879,8 @@ static int hw_perf_event_reset(struct perf_event *event) u64 prev, new; int err; + prev = local64_read(&event->hw.prev_count); do { - prev = local64_read(&event->hw.prev_count); err = ecctr(event->hw.config, &new); if (err) { if (err != 3) @@ -888,7 +892,7 @@ static int hw_perf_event_reset(struct perf_event *event) */ new = 0; } - } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev); + } while (!local64_try_cmpxchg(&event->hw.prev_count, &prev, new)); return err; } @@ -898,12 +902,12 @@ static void hw_perf_event_update(struct perf_event *event) u64 prev, new, delta; int err; + prev = local64_read(&event->hw.prev_count); do { - prev = local64_read(&event->hw.prev_count); err = ecctr(event->hw.config, &new); if (err) return; - } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev); + } while (!local64_try_cmpxchg(&event->hw.prev_count, &prev, new)); delta = (prev <= new) ? new - prev : (-1ULL - prev) + new + 1; /* overflow */ @@ -1050,7 +1054,7 @@ static void cpumf_pmu_del(struct perf_event *event, int flags) * * When a new perf event has been added but not yet started, this can * clear enable control and resets all counters in a set. Therefore, - * cpumf_pmu_start() always has to reenable a counter set. + * cpumf_pmu_start() always has to re-enable a counter set. */ for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) if (!atomic_read(&cpuhw->ctr_set[i])) @@ -1694,7 +1698,6 @@ static const struct file_operations cfset_fops = { .release = cfset_release, .unlocked_ioctl = cfset_ioctl, .compat_ioctl = cfset_ioctl, - .llseek = no_llseek }; static struct miscdevice cfset_dev = { @@ -1860,7 +1863,7 @@ static const struct attribute_group *cfdiag_attr_groups[] = { /* Performance monitoring unit for event CF_DIAG. Since this event * is also started and stopped via the perf_event_open() system call, use * the same event enable/disable call back functions. They do not - * have a pointer to the perf_event strcture as first parameter. + * have a pointer to the perf_event structure as first parameter. * * The functions XXX_add, XXX_del, XXX_start and XXX_stop are also common. * Reuse them and distinguish the event (always first parameter) via diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index 736c1d9632dd..0cde42f8af6e 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -24,6 +24,22 @@ #include <asm/timex.h> #include <linux/io.h> +/* Perf PMU definitions for the sampling facility */ +#define PERF_CPUM_SF_MAX_CTR 2 +#define PERF_EVENT_CPUM_SF 0xB0000UL /* Event: Basic-sampling */ +#define PERF_EVENT_CPUM_SF_DIAG 0xBD000UL /* Event: Combined-sampling */ +#define PERF_CPUM_SF_BASIC_MODE 0x0001 /* Basic-sampling flag */ +#define PERF_CPUM_SF_DIAG_MODE 0x0002 /* Diagnostic-sampling flag */ +#define PERF_CPUM_SF_FREQ_MODE 0x0008 /* Sampling with frequency */ + +#define OVERFLOW_REG(hwc) ((hwc)->extra_reg.config) +#define SFB_ALLOC_REG(hwc) ((hwc)->extra_reg.alloc) +#define TEAR_REG(hwc) ((hwc)->last_tag) +#define SAMPL_RATE(hwc) ((hwc)->event_base) +#define SAMPL_FLAGS(hwc) ((hwc)->config_base) +#define SAMPL_DIAG_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE) +#define SAMPL_FREQ_MODE(hwc) (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FREQ_MODE) + /* Minimum number of sample-data-block-tables: * At least one table is required for the sampling buffer structure. * A single table contains up to 511 pointers to sample-data-blocks. @@ -113,17 +129,6 @@ static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi, return USEC_PER_SEC * qsi->cpu_speed / rate; } -/* Return TOD timestamp contained in an trailer entry */ -static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te) -{ - /* TOD in STCKE format */ - if (te->header.t) - return *((unsigned long long *)&te->timestamp[1]); - - /* TOD in STCK format */ - return *((unsigned long long *)&te->timestamp[0]); -} - /* Return pointer to trailer entry of an sample data block */ static inline struct hws_trailer_entry *trailer_entry_ptr(unsigned long v) { @@ -154,12 +159,12 @@ static inline unsigned long *get_next_sdbt(unsigned long *s) /* * sf_disable() - Switch off sampling facility */ -static int sf_disable(void) +static void sf_disable(void) { struct hws_lsctl_request_block sreq; memset(&sreq, 0, sizeof(sreq)); - return lsctl(&sreq); + lsctl(&sreq); } /* @@ -208,8 +213,6 @@ static void free_sampling_buffer(struct sf_buffer *sfb) } } - debug_sprintf_event(sfdbg, 5, "%s: freed sdbt %#lx\n", __func__, - (unsigned long)sfb->sdbt); memset(sfb, 0, sizeof(*sfb)); } @@ -265,10 +268,8 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, * the sampling buffer origin. */ if (sfb->sdbt != get_next_sdbt(tail)) { - debug_sprintf_event(sfdbg, 3, "%s: " - "sampling buffer is not linked: origin %#lx" - " tail %#lx\n", __func__, - (unsigned long)sfb->sdbt, + debug_sprintf_event(sfdbg, 3, "%s buffer not linked origin %#lx tail %#lx\n", + __func__, (unsigned long)sfb->sdbt, (unsigned long)tail); return -EINVAL; } @@ -318,9 +319,6 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, *tail = virt_to_phys(sfb->sdbt) + 1; sfb->tail = tail; - debug_sprintf_event(sfdbg, 4, "%s: new buffer" - " settings: sdbt %lu sdb %lu\n", __func__, - sfb->num_sdbt, sfb->num_sdb); return rc; } @@ -357,15 +355,8 @@ static int alloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb) /* Allocate requested number of sample-data-blocks */ rc = realloc_sampling_buffer(sfb, num_sdb, GFP_KERNEL); - if (rc) { + if (rc) free_sampling_buffer(sfb); - debug_sprintf_event(sfdbg, 4, "%s: " - "realloc_sampling_buffer failed with rc %i\n", - __func__, rc); - } else - debug_sprintf_event(sfdbg, 4, - "%s: tear %#lx dear %#lx\n", __func__, - (unsigned long)sfb->sdbt, (unsigned long)*sfb->sdbt); return rc; } @@ -377,8 +368,8 @@ static void sfb_set_limits(unsigned long min, unsigned long max) CPUM_SF_MAX_SDB = max; memset(&si, 0, sizeof(si)); - if (!qsi(&si)) - CPUM_SF_SDB_DIAG_FACTOR = DIV_ROUND_UP(si.dsdes, si.bsdes); + qsi(&si); + CPUM_SF_SDB_DIAG_FACTOR = DIV_ROUND_UP(si.dsdes, si.bsdes); } static unsigned long sfb_max_limit(struct hw_perf_event *hwc) @@ -397,12 +388,6 @@ static unsigned long sfb_pending_allocs(struct sf_buffer *sfb, return 0; } -static int sfb_has_pending_allocs(struct sf_buffer *sfb, - struct hw_perf_event *hwc) -{ - return sfb_pending_allocs(sfb, hwc) > 0; -} - static void sfb_account_allocs(unsigned long num, struct hw_perf_event *hwc) { /* Limit the number of SDBs to not exceed the maximum */ @@ -419,14 +404,13 @@ static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc) static void deallocate_buffers(struct cpu_hw_sf *cpuhw) { - if (cpuhw->sfb.sdbt) + if (sf_buffer_available(cpuhw)) free_sampling_buffer(&cpuhw->sfb); } static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) { unsigned long n_sdb, freq; - size_t sample_size; /* Calculate sampling buffers using 4K pages * @@ -457,7 +441,6 @@ static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) * ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up * to 511 SDBs). */ - sample_size = sizeof(struct hws_basic_entry); freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc)); n_sdb = CPUM_SF_MIN_SDB + DIV_ROUND_UP(freq, 10000); @@ -473,12 +456,6 @@ static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc) if (sf_buffer_available(cpuhw)) return 0; - debug_sprintf_event(sfdbg, 3, - "%s: rate %lu f %lu sdb %lu/%lu" - " sample_size %lu cpuhw %p\n", __func__, - SAMPL_RATE(hwc), freq, n_sdb, sfb_max_limit(hwc), - sample_size, cpuhw); - return alloc_sampling_buffer(&cpuhw->sfb, sfb_pending_allocs(&cpuhw->sfb, hwc)); } @@ -535,8 +512,6 @@ static void sfb_account_overflows(struct cpu_hw_sf *cpuhw, if (num) sfb_account_allocs(num, hwc); - debug_sprintf_event(sfdbg, 5, "%s: overflow %llu ratio %lu num %lu\n", - __func__, OVERFLOW_REG(hwc), ratio, num); OVERFLOW_REG(hwc) = 0; } @@ -554,13 +529,11 @@ static void sfb_account_overflows(struct cpu_hw_sf *cpuhw, static void extend_sampling_buffer(struct sf_buffer *sfb, struct hw_perf_event *hwc) { - unsigned long num, num_old; - int rc; + unsigned long num; num = sfb_pending_allocs(sfb, hwc); if (!num) return; - num_old = sfb->num_sdb; /* Disable the sampling facility to reset any states and also * clear pending measurement alerts. @@ -572,51 +545,32 @@ static void extend_sampling_buffer(struct sf_buffer *sfb, * called by perf. Because this is a reallocation, it is fine if the * new SDB-request cannot be satisfied immediately. */ - rc = realloc_sampling_buffer(sfb, num, GFP_ATOMIC); - if (rc) - debug_sprintf_event(sfdbg, 5, "%s: realloc failed with rc %i\n", - __func__, rc); - - if (sfb_has_pending_allocs(sfb, hwc)) - debug_sprintf_event(sfdbg, 5, "%s: " - "req %lu alloc %lu remaining %lu\n", - __func__, num, sfb->num_sdb - num_old, - sfb_pending_allocs(sfb, hwc)); + realloc_sampling_buffer(sfb, num, GFP_ATOMIC); } /* Number of perf events counting hardware events */ -static atomic_t num_events; +static refcount_t num_events; /* Used to avoid races in calling reserve/release_cpumf_hardware */ static DEFINE_MUTEX(pmc_reserve_mutex); #define PMC_INIT 0 #define PMC_RELEASE 1 -#define PMC_FAILURE 2 static void setup_pmc_cpu(void *flags) { - struct cpu_hw_sf *cpusf = this_cpu_ptr(&cpu_hw_sf); - int err = 0; + struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf); + sf_disable(); switch (*((int *)flags)) { case PMC_INIT: - memset(cpusf, 0, sizeof(*cpusf)); - err = qsi(&cpusf->qsi); - if (err) - break; - cpusf->flags |= PMU_F_RESERVED; - err = sf_disable(); + memset(cpuhw, 0, sizeof(*cpuhw)); + qsi(&cpuhw->qsi); + cpuhw->flags |= PMU_F_RESERVED; break; case PMC_RELEASE: - cpusf->flags &= ~PMU_F_RESERVED; - err = sf_disable(); - if (!err) - deallocate_buffers(cpusf); + cpuhw->flags &= ~PMU_F_RESERVED; + deallocate_buffers(cpuhw); break; } - if (err) { - *((int *)flags) |= PMC_FAILURE; - pr_err("Switching off the sampling facility failed with rc %i\n", err); - } } static void release_pmc_hardware(void) @@ -627,27 +581,19 @@ static void release_pmc_hardware(void) on_each_cpu(setup_pmc_cpu, &flags, 1); } -static int reserve_pmc_hardware(void) +static void reserve_pmc_hardware(void) { int flags = PMC_INIT; on_each_cpu(setup_pmc_cpu, &flags, 1); - if (flags & PMC_FAILURE) { - release_pmc_hardware(); - return -ENODEV; - } irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); - - return 0; } static void hw_perf_event_destroy(struct perf_event *event) { /* Release PMC if this is the last perf event */ - if (!atomic_add_unless(&num_events, -1, 1)) { - mutex_lock(&pmc_reserve_mutex); - if (atomic_dec_return(&num_events) == 0) - release_pmc_hardware(); + if (refcount_dec_and_mutex_lock(&num_events, &pmc_reserve_mutex)) { + release_pmc_hardware(); mutex_unlock(&pmc_reserve_mutex); } } @@ -751,9 +697,6 @@ static unsigned long getrate(bool freq, unsigned long sample, */ if (sample_rate_to_freq(si, rate) > sysctl_perf_event_sample_rate) { - debug_sprintf_event(sfdbg, 1, "%s: " - "Sampling rate exceeds maximum " - "perf sample rate\n", __func__); rate = 0; } } @@ -798,9 +741,6 @@ static int __hw_perf_event_init_rate(struct perf_event *event, attr->sample_period = rate; SAMPL_RATE(hwc) = rate; hw_init_period(hwc, SAMPL_RATE(hwc)); - debug_sprintf_event(sfdbg, 4, "%s: cpu %d period %#llx freq %d,%#lx\n", - __func__, event->cpu, event->attr.sample_period, - event->attr.freq, SAMPLE_FREQ_MODE(hwc)); return 0; } @@ -810,23 +750,16 @@ static int __hw_perf_event_init(struct perf_event *event) struct hws_qsi_info_block si; struct perf_event_attr *attr = &event->attr; struct hw_perf_event *hwc = &event->hw; - int cpu, err; + int cpu, err = 0; /* Reserve CPU-measurement sampling facility */ - err = 0; - if (!atomic_inc_not_zero(&num_events)) { - mutex_lock(&pmc_reserve_mutex); - if (atomic_read(&num_events) == 0 && reserve_pmc_hardware()) - err = -EBUSY; - else - atomic_inc(&num_events); - mutex_unlock(&pmc_reserve_mutex); + mutex_lock(&pmc_reserve_mutex); + if (!refcount_inc_not_zero(&num_events)) { + reserve_pmc_hardware(); + refcount_set(&num_events, 1); } event->destroy = hw_perf_event_destroy; - if (err) - goto out; - /* Access per-CPU sampling information (query sampling info) */ /* * The event->cpu value can be -1 to count on every CPU, for example, @@ -838,9 +771,9 @@ static int __hw_perf_event_init(struct perf_event *event) */ memset(&si, 0, sizeof(si)); cpuhw = NULL; - if (event->cpu == -1) + if (event->cpu == -1) { qsi(&si); - else { + } else { /* Event is pinned to a particular CPU, retrieve the per-CPU * sampling structure for accessing the CPU-specific QSI. */ @@ -881,13 +814,9 @@ static int __hw_perf_event_init(struct perf_event *event) if (err) goto out; - /* Initialize sample data overflow accounting */ - hwc->extra_reg.reg = REG_OVERFLOW; - OVERFLOW_REG(hwc) = 0; - /* Use AUX buffer. No need to allocate it by ourself */ if (attr->config == PERF_EVENT_CPUM_SF_DIAG) - return 0; + goto out; /* Allocate the per-CPU sampling buffer using the CPU information * from the event. If the event is not pinned to a particular @@ -917,6 +846,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (is_default_overflow_handler(event)) event->overflow_handler = cpumsf_output_event_pid; out: + mutex_unlock(&pmc_reserve_mutex); return err; } @@ -979,10 +909,14 @@ static void cpumsf_pmu_enable(struct pmu *pmu) struct hw_perf_event *hwc; int err; - if (cpuhw->flags & PMU_F_ENABLED) - return; - - if (cpuhw->flags & PMU_F_ERR_MASK) + /* + * Event must be + * - added/started on this CPU (PMU_F_IN_USE set) + * - and CPU must be available (PMU_F_RESERVED set) + * - and not already enabled (PMU_F_ENABLED not set) + * - and not in error condition (PMU_F_ERR_MASK not set) + */ + if (cpuhw->flags != (PMU_F_IN_USE | PMU_F_RESERVED)) return; /* Check whether to extent the sampling buffer. @@ -996,39 +930,27 @@ static void cpumsf_pmu_enable(struct pmu *pmu) * facility, but it can be fully re-enabled using sampling controls that * have been saved in cpumsf_pmu_disable(). */ - if (cpuhw->event) { - hwc = &cpuhw->event->hw; - if (!(SAMPL_DIAG_MODE(hwc))) { - /* - * Account number of overflow-designated - * buffer extents - */ - sfb_account_overflows(cpuhw, hwc); - extend_sampling_buffer(&cpuhw->sfb, hwc); - } - /* Rate may be adjusted with ioctl() */ - cpuhw->lsctl.interval = SAMPL_RATE(&cpuhw->event->hw); + hwc = &cpuhw->event->hw; + if (!(SAMPL_DIAG_MODE(hwc))) { + /* + * Account number of overflow-designated buffer extents + */ + sfb_account_overflows(cpuhw, hwc); + extend_sampling_buffer(&cpuhw->sfb, hwc); } + /* Rate may be adjusted with ioctl() */ + cpuhw->lsctl.interval = SAMPL_RATE(hwc); /* (Re)enable the PMU and sampling facility */ - cpuhw->flags |= PMU_F_ENABLED; - barrier(); - err = lsctl(&cpuhw->lsctl); if (err) { - cpuhw->flags &= ~PMU_F_ENABLED; pr_err("Loading sampling controls failed: op 1 err %i\n", err); return; } /* Load current program parameter */ lpp(&get_lowcore()->lpp); - - debug_sprintf_event(sfdbg, 6, "%s: es %i cs %i ed %i cd %i " - "interval %#lx tear %#lx dear %#lx\n", __func__, - cpuhw->lsctl.es, cpuhw->lsctl.cs, cpuhw->lsctl.ed, - cpuhw->lsctl.cd, cpuhw->lsctl.interval, - cpuhw->lsctl.tear, cpuhw->lsctl.dear); + cpuhw->flags |= PMU_F_ENABLED; } static void cpumsf_pmu_disable(struct pmu *pmu) @@ -1055,21 +977,18 @@ static void cpumsf_pmu_disable(struct pmu *pmu) return; } - /* Save state of TEAR and DEAR register contents */ - err = qsi(&si); - if (!err) { - /* TEAR/DEAR values are valid only if the sampling facility is - * enabled. Note that cpumsf_pmu_disable() might be called even - * for a disabled sampling facility because cpumsf_pmu_enable() - * controls the enable/disable state. - */ - if (si.es) { - cpuhw->lsctl.tear = si.tear; - cpuhw->lsctl.dear = si.dear; - } - } else - debug_sprintf_event(sfdbg, 3, "%s: qsi() failed with err %i\n", - __func__, err); + /* + * Save state of TEAR and DEAR register contents. + * TEAR/DEAR values are valid only if the sampling facility is + * enabled. Note that cpumsf_pmu_disable() might be called even + * for a disabled sampling facility because cpumsf_pmu_enable() + * controls the enable/disable state. + */ + qsi(&si); + if (si.es) { + cpuhw->lsctl.tear = si.tear; + cpuhw->lsctl.dear = si.dear; + } cpuhw->flags &= ~PMU_F_ENABLED; } @@ -1235,11 +1154,6 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, /* Count discarded samples */ *overflow += 1; } else { - debug_sprintf_event(sfdbg, 4, - "%s: Found unknown" - " sampling data entry: te->f %i" - " basic.def %#4x (%p)\n", __func__, - te->header.f, sample->def, sample); /* Sample slot is not yet written or other record. * * This condition can occur if the buffer was reused @@ -1274,8 +1188,8 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt, static void hw_perf_event_update(struct perf_event *event, int flush_all) { unsigned long long event_overflow, sampl_overflow, num_sdb; - union hws_trailer_header old, prev, new; struct hw_perf_event *hwc = &event->hw; + union hws_trailer_header prev, new; struct hws_trailer_entry *te; unsigned long *sdbt, sdb; int done; @@ -1284,7 +1198,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) * AUX buffer is used when in diagnostic sampling mode. * No perf events/samples are created. */ - if (SAMPL_DIAG_MODE(&event->hw)) + if (SAMPL_DIAG_MODE(hwc)) return; sdbt = (unsigned long *)TEAR_REG(hwc); @@ -1309,13 +1223,6 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) */ sampl_overflow += te->header.overflow; - /* Timestamps are valid for full sample-data-blocks only */ - debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx/%#lx " - "overflow %llu timestamp %#llx\n", - __func__, sdb, (unsigned long)sdbt, - te->header.overflow, - (te->header.f) ? trailer_timestamp(te) : 0ULL); - /* Collect all samples from a single sample-data-block and * flag if an (perf) event overflow happened. If so, the PMU * is stopped and remaining samples will be discarded. @@ -1326,13 +1233,11 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) /* Reset trailer (using compare-double-and-swap) */ prev.val = READ_ONCE_ALIGNED_128(te->header.val); do { - old.val = prev.val; new.val = prev.val; new.f = 0; new.a = 1; new.overflow = 0; - prev.val = cmpxchg128(&te->header.val, old.val, new.val); - } while (prev.val != old.val); + } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val)); /* Advance to next sample-data-block */ sdbt++; @@ -1340,7 +1245,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) sdbt = get_next_sdbt(sdbt); /* Update event hardware registers */ - TEAR_REG(hwc) = (unsigned long) sdbt; + TEAR_REG(hwc) = (unsigned long)sdbt; /* Stop processing sample-data if all samples of the current * sample-data-block were flushed even if it was not full. @@ -1362,19 +1267,8 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) * are dropped. * Slightly increase the interval to avoid hitting this limit. */ - if (event_overflow) { + if (event_overflow) SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10); - debug_sprintf_event(sfdbg, 1, "%s: rate adjustment %ld\n", - __func__, - DIV_ROUND_UP(SAMPL_RATE(hwc), 10)); - } - - if (sampl_overflow || event_overflow) - debug_sprintf_event(sfdbg, 4, "%s: " - "overflows: sample %llu event %llu" - " total %llu num_sdb %llu\n", - __func__, sampl_overflow, event_overflow, - OVERFLOW_REG(hwc), num_sdb); } static inline unsigned long aux_sdb_index(struct aux_buffer *aux, @@ -1442,9 +1336,6 @@ static void aux_output_end(struct perf_output_handle *handle) /* Remove alert indicators in the buffer */ te = aux_sdb_trailer(aux, aux->alert_mark); te->header.a = 0; - - debug_sprintf_event(sfdbg, 6, "%s: SDBs %ld range %ld head %ld\n", - __func__, i, range_scan, aux->head); } /* @@ -1463,7 +1354,7 @@ static int aux_output_begin(struct perf_output_handle *handle, unsigned long range, i, range_scan, idx, head, base, offset; struct hws_trailer_entry *te; - if (WARN_ON_ONCE(handle->head & ~PAGE_MASK)) + if (handle->head & ~PAGE_MASK) return -EINVAL; aux->head = handle->head >> PAGE_SHIFT; @@ -1475,10 +1366,6 @@ static int aux_output_begin(struct perf_output_handle *handle, * SDBs between aux->head and aux->empty_mark are already ready * for new data. range_scan is num of SDBs not within them. */ - debug_sprintf_event(sfdbg, 6, - "%s: range %ld head %ld alert %ld empty %ld\n", - __func__, range, aux->head, aux->alert_mark, - aux->empty_mark); if (range > aux_sdb_num_empty(aux)) { range_scan = range - aux_sdb_num_empty(aux); idx = aux->empty_mark + 1; @@ -1504,12 +1391,6 @@ static int aux_output_begin(struct perf_output_handle *handle, cpuhw->lsctl.tear = virt_to_phys((void *)base) + offset * sizeof(unsigned long); cpuhw->lsctl.dear = virt_to_phys((void *)aux->sdb_index[head]); - debug_sprintf_event(sfdbg, 6, "%s: head %ld alert %ld empty %ld " - "index %ld tear %#lx dear %#lx\n", __func__, - aux->head, aux->alert_mark, aux->empty_mark, - head / CPUM_SF_SDB_PER_TABLE, - cpuhw->lsctl.tear, cpuhw->lsctl.dear); - return 0; } @@ -1522,16 +1403,15 @@ static int aux_output_begin(struct perf_output_handle *handle, static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, unsigned long long *overflow) { - union hws_trailer_header old, prev, new; + union hws_trailer_header prev, new; struct hws_trailer_entry *te; te = aux_sdb_trailer(aux, alert_index); prev.val = READ_ONCE_ALIGNED_128(te->header.val); do { - old.val = prev.val; new.val = prev.val; - *overflow = old.overflow; - if (old.f) { + *overflow = prev.overflow; + if (prev.f) { /* * SDB is already set by hardware. * Abort and try to set somewhere @@ -1541,8 +1421,7 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, } new.a = 1; new.overflow = 0; - prev.val = cmpxchg128(&te->header.val, old.val, new.val); - } while (prev.val != old.val); + } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val)); return true; } @@ -1571,14 +1450,11 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index, static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, unsigned long long *overflow) { - unsigned long i, range_scan, idx, idx_old; - union hws_trailer_header old, prev, new; + union hws_trailer_header prev, new; + unsigned long i, range_scan, idx; unsigned long long orig_overflow; struct hws_trailer_entry *te; - debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld " - "empty %ld\n", __func__, range, aux->head, - aux->alert_mark, aux->empty_mark); if (range <= aux_sdb_num_empty(aux)) /* * No need to scan. All SDBs in range are marked as empty. @@ -1601,31 +1477,26 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range, * indicator fall into this range, set it. */ range_scan = range - aux_sdb_num_empty(aux); - idx_old = idx = aux->empty_mark + 1; + idx = aux->empty_mark + 1; for (i = 0; i < range_scan; i++, idx++) { te = aux_sdb_trailer(aux, idx); prev.val = READ_ONCE_ALIGNED_128(te->header.val); do { - old.val = prev.val; new.val = prev.val; - orig_overflow = old.overflow; + orig_overflow = prev.overflow; new.f = 0; new.overflow = 0; if (idx == aux->alert_mark) new.a = 1; else new.a = 0; - prev.val = cmpxchg128(&te->header.val, old.val, new.val); - } while (prev.val != old.val); + } while (!try_cmpxchg128(&te->header.val, &prev.val, new.val)); *overflow += orig_overflow; } /* Update empty_mark to new position */ aux->empty_mark = aux->head + range - 1; - debug_sprintf_event(sfdbg, 6, "%s: range_scan %ld idx %ld..%ld " - "empty %ld\n", __func__, range_scan, idx_old, - idx - 1, aux->empty_mark); return true; } @@ -1642,12 +1513,12 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) unsigned long num_sdb; aux = perf_get_aux(handle); - if (WARN_ON_ONCE(!aux)) + if (!aux) return; /* Inform user space new data arrived */ size = aux_sdb_num_alert(aux) << PAGE_SHIFT; - debug_sprintf_event(sfdbg, 6, "%s: #alert %ld\n", __func__, + debug_sprintf_event(sfdbg, 6, "%s #alert %ld\n", __func__, size >> PAGE_SHIFT); perf_aux_output_end(handle, size); @@ -1661,7 +1532,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) num_sdb); break; } - if (WARN_ON_ONCE(!aux)) + if (!aux) return; /* Update head and alert_mark to new position */ @@ -1681,23 +1552,11 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw) perf_aux_output_end(&cpuhw->handle, size); pr_err("Sample data caused the AUX buffer with %lu " "pages to overflow\n", aux->sfb.num_sdb); - debug_sprintf_event(sfdbg, 1, "%s: head %ld range %ld " - "overflow %lld\n", __func__, - aux->head, range, overflow); } else { size = aux_sdb_num_alert(aux) << PAGE_SHIFT; perf_aux_output_end(&cpuhw->handle, size); - debug_sprintf_event(sfdbg, 6, "%s: head %ld alert %ld " - "already full, try another\n", - __func__, - aux->head, aux->alert_mark); } } - - if (done) - debug_sprintf_event(sfdbg, 6, "%s: head %ld alert %ld " - "empty %ld\n", __func__, aux->head, - aux->alert_mark, aux->empty_mark); } /* @@ -1719,8 +1578,6 @@ static void aux_buffer_free(void *data) kfree(aux->sdbt_index); kfree(aux->sdb_index); kfree(aux); - - debug_sprintf_event(sfdbg, 4, "%s: SDBTs %lu\n", __func__, num_sdbt); } static void aux_sdb_init(unsigned long sdb) @@ -1828,9 +1685,6 @@ static void *aux_buffer_setup(struct perf_event *event, void **pages, */ aux->empty_mark = sfb->num_sdb - 1; - debug_sprintf_event(sfdbg, 4, "%s: SDBTs %lu SDBs %lu\n", __func__, - sfb->num_sdbt, sfb->num_sdb); - return aux; no_sdbt: @@ -1863,8 +1717,7 @@ static int cpumsf_pmu_check_period(struct perf_event *event, u64 value) memset(&si, 0, sizeof(si)); if (event->cpu == -1) { - if (qsi(&si)) - return -ENODEV; + qsi(&si); } else { /* Event is pinned to a particular CPU, retrieve the per-CPU * sampling structure for accessing the CPU-specific QSI. @@ -1874,7 +1727,7 @@ static int cpumsf_pmu_check_period(struct perf_event *event, u64 value) si = cpuhw->qsi; } - do_freq = !!SAMPLE_FREQ_MODE(&event->hw); + do_freq = !!SAMPL_FREQ_MODE(&event->hw); rate = getrate(do_freq, value, &si); if (!rate) return -EINVAL; @@ -1882,10 +1735,6 @@ static int cpumsf_pmu_check_period(struct perf_event *event, u64 value) event->attr.sample_period = rate; SAMPL_RATE(&event->hw) = rate; hw_init_period(&event->hw, SAMPL_RATE(&event->hw)); - debug_sprintf_event(sfdbg, 4, "%s:" - " cpu %d value %#llx period %#llx freq %d\n", - __func__, event->cpu, value, - event->attr.sample_period, do_freq); return 0; } @@ -1896,12 +1745,8 @@ static void cpumsf_pmu_start(struct perf_event *event, int flags) { struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf); - if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) + if (!(event->hw.state & PERF_HES_STOPPED)) return; - - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); - perf_pmu_disable(event->pmu); event->hw.state = 0; cpuhw->lsctl.cs = 1; @@ -1926,7 +1771,9 @@ static void cpumsf_pmu_stop(struct perf_event *event, int flags) event->hw.state |= PERF_HES_STOPPED; if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) { - hw_perf_event_update(event, 1); + /* CPU hotplug off removes SDBs. No samples to extract. */ + if (cpuhw->flags & PMU_F_RESERVED) + hw_perf_event_update(event, 1); event->hw.state |= PERF_HES_UPTODATE; } perf_pmu_enable(event->pmu); @@ -1936,15 +1783,14 @@ static int cpumsf_pmu_add(struct perf_event *event, int flags) { struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf); struct aux_buffer *aux; - int err; + int err = 0; if (cpuhw->flags & PMU_F_IN_USE) return -EAGAIN; - if (!SAMPL_DIAG_MODE(&event->hw) && !cpuhw->sfb.sdbt) + if (!SAMPL_DIAG_MODE(&event->hw) && !sf_buffer_available(cpuhw)) return -EINVAL; - err = 0; perf_pmu_disable(event->pmu); event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; @@ -2104,18 +1950,17 @@ static void cpumf_measurement_alert(struct ext_code ext_code, /* Program alert request */ if (alert & CPU_MF_INT_SF_PRA) { - if (cpuhw->flags & PMU_F_IN_USE) + if (cpuhw->flags & PMU_F_IN_USE) { if (SAMPL_DIAG_MODE(&cpuhw->event->hw)) hw_collect_aux(cpuhw); else hw_perf_event_update(cpuhw->event, 0); - else - WARN_ON_ONCE(!(cpuhw->flags & PMU_F_IN_USE)); + } } /* Report measurement alerts only for non-PRA codes */ if (alert != CPU_MF_INT_SF_PRA) - debug_sprintf_event(sfdbg, 6, "%s: alert %#x\n", __func__, + debug_sprintf_event(sfdbg, 6, "%s alert %#x\n", __func__, alert); /* Sampling authorization change request */ @@ -2131,7 +1976,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code, /* Invalid sampling buffer entry */ if (alert & (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE)) { - pr_err("A sampling buffer entry is incorrect (alert=0x%x)\n", + pr_err("A sampling buffer entry is incorrect (alert=%#x)\n", alert); cpuhw->flags |= PMU_F_ERR_IBE; sf_disable(); @@ -2143,7 +1988,7 @@ static int cpusf_pmu_setup(unsigned int cpu, int flags) /* Ignore the notification if no events are scheduled on the PMU. * This might be racy... */ - if (!atomic_read(&num_events)) + if (!refcount_read(&num_events)) return 0; local_irq_disable(); @@ -2205,10 +2050,12 @@ static const struct kernel_param_ops param_ops_sfb_size = { .get = param_get_sfb_size, }; -#define RS_INIT_FAILURE_QSI 0x0001 -#define RS_INIT_FAILURE_BSDES 0x0002 -#define RS_INIT_FAILURE_ALRT 0x0003 -#define RS_INIT_FAILURE_PERF 0x0004 +enum { + RS_INIT_FAILURE_BSDES = 2, /* Bad basic sampling size */ + RS_INIT_FAILURE_ALRT = 3, /* IRQ registration failure */ + RS_INIT_FAILURE_PERF = 4 /* PMU registration failure */ +}; + static void __init pr_cpumsf_err(unsigned int reason) { pr_err("Sampling facility support for perf is not available: " @@ -2224,11 +2071,7 @@ static int __init init_cpum_sampling_pmu(void) return -ENODEV; memset(&si, 0, sizeof(si)); - if (qsi(&si)) { - pr_cpumsf_err(RS_INIT_FAILURE_QSI); - return -ENODEV; - } - + qsi(&si); if (!si.as && !si.ad) return -ENODEV; diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index 5fff629b1a89..2b9611c4718e 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c @@ -57,7 +57,7 @@ static unsigned long instruction_pointer_guest(struct pt_regs *regs) return sie_block(regs)->gpsw.addr; } -unsigned long perf_instruction_pointer(struct pt_regs *regs) +unsigned long perf_arch_instruction_pointer(struct pt_regs *regs) { return is_in_guest(regs) ? instruction_pointer_guest(regs) : instruction_pointer(regs); @@ -84,7 +84,7 @@ static unsigned long perf_misc_flags_sf(struct pt_regs *regs) return flags; } -unsigned long perf_misc_flags(struct pt_regs *regs) +unsigned long perf_arch_misc_flags(struct pt_regs *regs) { /* Check if the cpum_sf PMU has created the pt_regs structure. * In this case, perf misc flags can be easily extracted. Otherwise, @@ -228,5 +228,5 @@ ssize_t cpumf_events_sysfs_show(struct device *dev, struct perf_pmu_events_attr *pmu_attr; pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); - return sprintf(page, "event=0x%04llx\n", pmu_attr->id); + return sysfs_emit(page, "event=0x%04llx\n", pmu_attr->id); } diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index 2f5a20e300f6..fa7325454266 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -738,6 +738,22 @@ static const char * const paicrypt_ctrnames[] = { [154] = "PCKMO_ENCRYPT_ECC_ED448_KEY", [155] = "IBM_RESERVED_155", [156] = "IBM_RESERVED_156", + [157] = "KM_FULL_XTS_AES_128", + [158] = "KM_FULL_XTS_AES_256", + [159] = "KM_FULL_XTS_ENCRYPTED_AES_128", + [160] = "KM_FULL_XTS_ENCRYPTED_AES_256", + [161] = "KMAC_HMAC_SHA_224", + [162] = "KMAC_HMAC_SHA_256", + [163] = "KMAC_HMAC_SHA_384", + [164] = "KMAC_HMAC_SHA_512", + [165] = "KMAC_HMAC_ENCRYPTED_SHA_224", + [166] = "KMAC_HMAC_ENCRYPTED_SHA_256", + [167] = "KMAC_HMAC_ENCRYPTED_SHA_384", + [168] = "KMAC_HMAC_ENCRYPTED_SHA_512", + [169] = "PCKMO_ENCRYPT_HMAC_512_KEY", + [170] = "PCKMO_ENCRYPT_HMAC_1024_KEY", + [171] = "PCKMO_ENCRYPT_AES_XTS_128", + [172] = "PCKMO_ENCRYPT_AES_XTS_256", }; static void __init attr_event_free(struct attribute **attrs, int num) diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index 6295531b39a2..7f462bef1fc0 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -635,6 +635,15 @@ static const char * const paiext_ctrnames[] = { [25] = "NNPA_1MFRAME", [26] = "NNPA_2GFRAME", [27] = "NNPA_ACCESSEXCEPT", + [28] = "NNPA_TRANSFORM", + [29] = "NNPA_GELU", + [30] = "NNPA_MOMENTS", + [31] = "NNPA_LAYERNORM", + [32] = "NNPA_MATMUL_OP_BCAST1", + [33] = "NNPA_SQRT", + [34] = "NNPA_INVSQRT", + [35] = "NNPA_NORM", + [36] = "NNPA_REDUCE", }; static void __init attr_event_free(struct attribute **attrs, int num) diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6c2cb345402f..e48013cd832c 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -30,9 +30,9 @@ #include <linux/compat.h> #include <asm/ucontext.h> #include <linux/uaccess.h> +#include <asm/vdso-symbols.h> #include <asm/access-regs.h> #include <asm/lowcore.h> -#include <asm/vdso.h> #include "entry.h" /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fbba37ec53cf..822d8e6f8717 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -574,7 +574,7 @@ int smp_store_status(int cpu) /* * Collect CPU state of the previous, crashed system. - * There are four cases: + * There are three cases: * 1) standard zfcp/nvme dump * condition: OLDMEM_BASE == NULL && is_ipl_type_dump() == true * The state for all CPUs except the boot CPU needs to be collected @@ -587,16 +587,16 @@ int smp_store_status(int cpu) * with sigp stop-and-store-status. The firmware or the boot-loader * stored the registers of the boot CPU in the absolute lowcore in the * memory of the old system. - * 3) kdump and the old kernel did not store the CPU state, - * or stand-alone kdump for DASD - * condition: OLDMEM_BASE != NULL && !is_kdump_kernel() + * 3) kdump or stand-alone kdump for DASD + * condition: OLDMEM_BASE != NULL && is_ipl_type_dump() == false * The state for all CPUs except the boot CPU needs to be collected * with sigp stop-and-store-status. The kexec code or the boot-loader * stored the registers of the boot CPU in the memory of the old system. - * 4) kdump and the old kernel stored the CPU state - * condition: OLDMEM_BASE != NULL && is_kdump_kernel() - * This case does not exist for s390 anymore, setup_arch explicitly - * deactivates the elfcorehdr= kernel parameter + * + * Note that the legacy kdump mode where the old kernel stored the CPU states + * does no longer exist: setup_arch() explicitly deactivates the elfcorehdr= + * kernel parameter. The is_kdump_kernel() implementation on s390 is independent + * of the elfcorehdr= parameter. */ static bool dump_available(void) { @@ -671,6 +671,25 @@ int smp_cpu_get_polarization(int cpu) return per_cpu(pcpu_devices, cpu).polarization; } +void smp_cpu_set_capacity(int cpu, unsigned long val) +{ + per_cpu(pcpu_devices, cpu).capacity = val; +} + +unsigned long smp_cpu_get_capacity(int cpu) +{ + return per_cpu(pcpu_devices, cpu).capacity; +} + +void smp_set_core_capacity(int cpu, unsigned long val) +{ + int i; + + cpu = smp_get_base_cpu(cpu); + for (i = cpu; (i <= cpu + smp_cpu_mtid) && (i < nr_cpu_ids); i++) + smp_cpu_set_capacity(i, val); +} + int smp_cpu_get_cpu_address(int cpu) { return per_cpu(pcpu_devices, cpu).address; @@ -719,6 +738,7 @@ static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail, else pcpu->state = CPU_STATE_STANDBY; smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + smp_cpu_set_capacity(cpu, CPU_CAPACITY_HIGH); set_cpu_present(cpu, true); if (!early && arch_register_cpu(cpu)) set_cpu_present(cpu, false); @@ -961,6 +981,7 @@ void __init smp_prepare_boot_cpu(void) ipl_pcpu->state = CPU_STATE_CONFIGURED; lc->pcpu = (unsigned long)ipl_pcpu; smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); + smp_cpu_set_capacity(0, CPU_CAPACITY_HIGH); } void __init smp_setup_processor_id(void) @@ -990,7 +1011,7 @@ static ssize_t cpu_configure_show(struct device *dev, ssize_t count; mutex_lock(&smp_cpu_state_mutex); - count = sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).state); + count = sysfs_emit(buf, "%d\n", per_cpu(pcpu_devices, dev->id).state); mutex_unlock(&smp_cpu_state_mutex); return count; } @@ -1062,7 +1083,7 @@ static DEVICE_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); static ssize_t show_cpu_address(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).address); + return sysfs_emit(buf, "%d\n", per_cpu(pcpu_devices, dev->id).address); } static DEVICE_ATTR(address, 0444, show_cpu_address, NULL); diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index 640363b2a105..9f59837d159e 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c @@ -162,22 +162,3 @@ void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, { arch_stack_walk_user_common(consume_entry, cookie, NULL, regs, false); } - -unsigned long return_address(unsigned int n) -{ - struct unwind_state state; - unsigned long addr; - - /* Increment to skip current stack entry */ - n++; - - unwind_for_each_frame(&state, NULL, NULL, 0) { - addr = unwind_get_return_address(&state); - if (!addr) - break; - if (!n--) - return addr; - } - return 0; -} -EXPORT_SYMBOL_GPL(return_address); diff --git a/arch/s390/kernel/sthyi.c b/arch/s390/kernel/sthyi.c index 1cf2ad04f8e9..d40f0b983e74 100644 --- a/arch/s390/kernel/sthyi.c +++ b/arch/s390/kernel/sthyi.c @@ -17,6 +17,7 @@ #include <asm/ebcdic.h> #include <asm/facility.h> #include <asm/sthyi.h> +#include <asm/asm.h> #include "entry.h" #define DED_WEIGHT 0xffff @@ -425,13 +426,12 @@ static int sthyi(u64 vaddr, u64 *rc) asm volatile( ".insn rre,0xB2560000,%[r1],%[r2]\n" - "ipm %[cc]\n" - "srl %[cc],28\n" - : [cc] "=&d" (cc), [r2] "+&d" (r2.pair) + CC_IPM(cc) + : CC_OUT(cc, cc), [r2] "+&d" (r2.pair) : [r1] "d" (r1.pair) - : "memory", "cc"); + : CC_CLOBBER_LIST("memory")); *rc = r2.odd; - return cc; + return CC_TRANSFORM(cc); } static int fill_dst(void *dst, u64 *rc) diff --git a/arch/s390/kernel/syscalls/Makefile b/arch/s390/kernel/syscalls/Makefile index 1bb78b9468e8..c5d958a09ff4 100644 --- a/arch/s390/kernel/syscalls/Makefile +++ b/arch/s390/kernel/syscalls/Makefile @@ -12,7 +12,7 @@ kapi-hdrs-y := $(kapi)/unistd_nr.h uapi-hdrs-y := $(uapi)/unistd_32.h uapi-hdrs-y += $(uapi)/unistd_64.h -targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y)) +targets += $(addprefix ../../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y)) PHONY += kapi uapi @@ -23,23 +23,26 @@ uapi: $(uapi-hdrs-y) # Create output directory if not already present $(shell mkdir -p $(uapi) $(kapi)) -filechk_syshdr = $(CONFIG_SHELL) '$(systbl)' -H -a $(syshdr_abi_$(basetarget)) -f "$2" < $< +quiet_cmd_syshdr = SYSHDR $@ + cmd_syshdr = $(CONFIG_SHELL) '$(systbl)' -H -a $(syshdr_abi_$(basetarget)) -f "$@" < $< > $@ -filechk_sysnr = $(CONFIG_SHELL) '$(systbl)' -N -a $(sysnr_abi_$(basetarget)) < $< +quiet_cmd_sysnr = SYSNR $@ + cmd_sysnr = $(CONFIG_SHELL) '$(systbl)' -N -a $(sysnr_abi_$(basetarget)) < $< > $@ -filechk_syscalls = $(CONFIG_SHELL) '$(systbl)' -S < $< +quiet_cmd_syscalls = SYSTBL $@ + cmd_syscalls = $(CONFIG_SHELL) '$(systbl)' -S < $< > $@ syshdr_abi_unistd_32 := common,32 -$(uapi)/unistd_32.h: $(syscall) FORCE - $(call filechk,syshdr,$@) +$(uapi)/unistd_32.h: $(syscall) $(systbl) FORCE + $(call if_changed,syshdr) syshdr_abi_unistd_64 := common,64 -$(uapi)/unistd_64.h: $(syscall) FORCE - $(call filechk,syshdr,$@) +$(uapi)/unistd_64.h: $(syscall) $(systbl) FORCE + $(call if_changed,syshdr) -$(kapi)/syscall_table.h: $(syscall) FORCE - $(call filechk,syscalls) +$(kapi)/syscall_table.h: $(syscall) $(systbl) FORCE + $(call if_changed,syscalls) sysnr_abi_unistd_nr := common,32,64 -$(kapi)/unistd_nr.h: $(syscall) FORCE - $(call filechk,sysnr) +$(kapi)/unistd_nr.h: $(syscall) $(systbl) FORCE + $(call if_changed,sysnr) diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 01071182763e..e9115b4d8b63 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -465,3 +465,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal sys_mseal +463 common setxattrat sys_setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat sys_removexattrat diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 2be30a96696a..88055f58fbda 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -498,7 +498,6 @@ static const struct file_operations stsi_##fc##_##s1##_##s2##_fs_ops = { \ .open = stsi_open_##fc##_##s1##_##s2, \ .release = stsi_release, \ .read = stsi_read, \ - .llseek = no_llseek, \ }; static int stsi_release(struct inode *inode, struct file *file) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index b713effe0579..30fd10a72c5d 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -36,7 +36,6 @@ #include <linux/profile.h> #include <linux/timex.h> #include <linux/notifier.h> -#include <linux/timekeeper_internal.h> #include <linux/clockchips.h> #include <linux/gfp.h> #include <linux/kprobes.h> @@ -729,8 +728,8 @@ static ssize_t ctn_id_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid()) - ret = sprintf(buf, "%016lx\n", - *(unsigned long *) stp_info.ctnid); + ret = sysfs_emit(buf, "%016lx\n", + *(unsigned long *)stp_info.ctnid); mutex_unlock(&stp_mutex); return ret; } @@ -745,7 +744,7 @@ static ssize_t ctn_type_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid()) - ret = sprintf(buf, "%i\n", stp_info.ctn); + ret = sysfs_emit(buf, "%i\n", stp_info.ctn); mutex_unlock(&stp_mutex); return ret; } @@ -760,7 +759,7 @@ static ssize_t dst_offset_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid() && (stp_info.vbits & 0x2000)) - ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); + ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.dsto); mutex_unlock(&stp_mutex); return ret; } @@ -775,7 +774,7 @@ static ssize_t leap_seconds_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid() && (stp_info.vbits & 0x8000)) - ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); + ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.leaps); mutex_unlock(&stp_mutex); return ret; } @@ -801,11 +800,11 @@ static ssize_t leap_seconds_scheduled_show(struct device *dev, return ret; if (!stzi.lsoib.p) - return sprintf(buf, "0,0\n"); + return sysfs_emit(buf, "0,0\n"); - return sprintf(buf, "%lu,%d\n", - tod_to_ns(stzi.lsoib.nlsout - TOD_UNIX_EPOCH) / NSEC_PER_SEC, - stzi.lsoib.nlso - stzi.lsoib.also); + return sysfs_emit(buf, "%lu,%d\n", + tod_to_ns(stzi.lsoib.nlsout - TOD_UNIX_EPOCH) / NSEC_PER_SEC, + stzi.lsoib.nlso - stzi.lsoib.also); } static DEVICE_ATTR_RO(leap_seconds_scheduled); @@ -818,7 +817,7 @@ static ssize_t stratum_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid()) - ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); + ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.stratum); mutex_unlock(&stp_mutex); return ret; } @@ -833,7 +832,7 @@ static ssize_t time_offset_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid() && (stp_info.vbits & 0x0800)) - ret = sprintf(buf, "%i\n", (int) stp_info.tto); + ret = sysfs_emit(buf, "%i\n", (int)stp_info.tto); mutex_unlock(&stp_mutex); return ret; } @@ -848,7 +847,7 @@ static ssize_t time_zone_offset_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid() && (stp_info.vbits & 0x4000)) - ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); + ret = sysfs_emit(buf, "%i\n", (int)(s16)stp_info.tzo); mutex_unlock(&stp_mutex); return ret; } @@ -863,7 +862,7 @@ static ssize_t timing_mode_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid()) - ret = sprintf(buf, "%i\n", stp_info.tmd); + ret = sysfs_emit(buf, "%i\n", stp_info.tmd); mutex_unlock(&stp_mutex); return ret; } @@ -878,7 +877,7 @@ static ssize_t timing_state_show(struct device *dev, mutex_lock(&stp_mutex); if (stpinfo_valid()) - ret = sprintf(buf, "%i\n", stp_info.tst); + ret = sysfs_emit(buf, "%i\n", stp_info.tst); mutex_unlock(&stp_mutex); return ret; } @@ -889,7 +888,7 @@ static ssize_t online_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%i\n", stp_online); + return sysfs_emit(buf, "%i\n", stp_online); } static ssize_t online_store(struct device *dev, diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 22029ecae1c5..4f9c301a705b 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -24,7 +24,9 @@ #include <linux/mm.h> #include <linux/nodemask.h> #include <linux/node.h> +#include <asm/hiperdispatch.h> #include <asm/sysinfo.h> +#include <asm/asm.h> #define PTF_HORIZONTAL (0UL) #define PTF_VERTICAL (1UL) @@ -47,6 +49,7 @@ static int topology_mode = TOPOLOGY_MODE_UNINITIALIZED; static void set_topology_timer(void); static void topology_work_fn(struct work_struct *work); static struct sysinfo_15_1_x *tl_info; +static int cpu_management; static DECLARE_WORK(topology_work, topology_work_fn); @@ -144,6 +147,7 @@ static void add_cpus_to_mask(struct topology_core *tl_core, cpumask_set_cpu(cpu, &book->mask); cpumask_set_cpu(cpu, &socket->mask); smp_cpu_set_polarization(cpu, tl_core->pp); + smp_cpu_set_capacity(cpu, CPU_CAPACITY_HIGH); } } } @@ -221,15 +225,15 @@ static void topology_update_polarization_simple(void) static int ptf(unsigned long fc) { - int rc; + int cc; asm volatile( - " .insn rre,0xb9a20000,%1,%1\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (rc) - : "d" (fc) : "cc"); - return rc; + " .insn rre,0xb9a20000,%[fc],%[fc]\n" + CC_IPM(cc) + : CC_OUT(cc, cc) + : [fc] "d" (fc) + : CC_CLOBBER); + return CC_TRANSFORM(cc); } int topology_set_cpu_management(int fc) @@ -270,6 +274,7 @@ void update_cpu_masks(void) topo->drawer_id = id; } } + hd_reset_state(); for_each_online_cpu(cpu) { topo = &cpu_topology[cpu]; pkg_first = cpumask_first(&topo->core_mask); @@ -278,8 +283,10 @@ void update_cpu_masks(void) for_each_cpu(sibling, &topo->core_mask) { topo_sibling = &cpu_topology[sibling]; smt_first = cpumask_first(&topo_sibling->thread_mask); - if (sibling == smt_first) + if (sibling == smt_first) { topo_package->booted_cores++; + hd_add_core(sibling); + } } } else { topo->booted_cores = topo_package->booted_cores; @@ -303,8 +310,10 @@ static void __arch_update_dedicated_flag(void *arg) static int __arch_update_cpu_topology(void) { struct sysinfo_15_1_x *info = tl_info; - int rc = 0; + int rc, hd_status; + hd_status = 0; + rc = 0; mutex_lock(&smp_cpu_state_mutex); if (MACHINE_HAS_TOPOLOGY) { rc = 1; @@ -314,7 +323,11 @@ static int __arch_update_cpu_topology(void) update_cpu_masks(); if (!MACHINE_HAS_TOPOLOGY) topology_update_polarization_simple(); + if (cpu_management == 1) + hd_status = hd_enable_hiperdispatch(); mutex_unlock(&smp_cpu_state_mutex); + if (hd_status == 0) + hd_disable_hiperdispatch(); return rc; } @@ -374,7 +387,24 @@ void topology_expect_change(void) set_topology_timer(); } -static int cpu_management; +static int set_polarization(int polarization) +{ + int rc = 0; + + cpus_read_lock(); + mutex_lock(&smp_cpu_state_mutex); + if (cpu_management == polarization) + goto out; + rc = topology_set_cpu_management(polarization); + if (rc) + goto out; + cpu_management = polarization; + topology_expect_change(); +out: + mutex_unlock(&smp_cpu_state_mutex); + cpus_read_unlock(); + return rc; +} static ssize_t dispatching_show(struct device *dev, struct device_attribute *attr, @@ -383,7 +413,7 @@ static ssize_t dispatching_show(struct device *dev, ssize_t count; mutex_lock(&smp_cpu_state_mutex); - count = sprintf(buf, "%d\n", cpu_management); + count = sysfs_emit(buf, "%d\n", cpu_management); mutex_unlock(&smp_cpu_state_mutex); return count; } @@ -400,19 +430,7 @@ static ssize_t dispatching_store(struct device *dev, return -EINVAL; if (val != 0 && val != 1) return -EINVAL; - rc = 0; - cpus_read_lock(); - mutex_lock(&smp_cpu_state_mutex); - if (cpu_management == val) - goto out; - rc = topology_set_cpu_management(val); - if (rc) - goto out; - cpu_management = val; - topology_expect_change(); -out: - mutex_unlock(&smp_cpu_state_mutex); - cpus_read_unlock(); + rc = set_polarization(val); return rc ? rc : count; } static DEVICE_ATTR_RW(dispatching); @@ -426,19 +444,19 @@ static ssize_t cpu_polarization_show(struct device *dev, mutex_lock(&smp_cpu_state_mutex); switch (smp_cpu_get_polarization(cpu)) { case POLARIZATION_HRZ: - count = sprintf(buf, "horizontal\n"); + count = sysfs_emit(buf, "horizontal\n"); break; case POLARIZATION_VL: - count = sprintf(buf, "vertical:low\n"); + count = sysfs_emit(buf, "vertical:low\n"); break; case POLARIZATION_VM: - count = sprintf(buf, "vertical:medium\n"); + count = sysfs_emit(buf, "vertical:medium\n"); break; case POLARIZATION_VH: - count = sprintf(buf, "vertical:high\n"); + count = sysfs_emit(buf, "vertical:high\n"); break; default: - count = sprintf(buf, "unknown\n"); + count = sysfs_emit(buf, "unknown\n"); break; } mutex_unlock(&smp_cpu_state_mutex); @@ -462,7 +480,7 @@ static ssize_t cpu_dedicated_show(struct device *dev, ssize_t count; mutex_lock(&smp_cpu_state_mutex); - count = sprintf(buf, "%d\n", topology_cpu_dedicated(cpu)); + count = sysfs_emit(buf, "%d\n", topology_cpu_dedicated(cpu)); mutex_unlock(&smp_cpu_state_mutex); return count; } @@ -624,12 +642,37 @@ static int topology_ctl_handler(const struct ctl_table *ctl, int write, return rc; } +static int polarization_ctl_handler(const struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + int polarization; + int rc; + struct ctl_table ctl_entry = { + .procname = ctl->procname, + .data = &polarization, + .maxlen = sizeof(int), + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }; + + polarization = cpu_management; + rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos); + if (rc < 0 || !write) + return rc; + return set_polarization(polarization); +} + static struct ctl_table topology_ctl_table[] = { { .procname = "topology", .mode = 0644, .proc_handler = topology_ctl_handler, }, + { + .procname = "polarization", + .mode = 0644, + .proc_handler = polarization_ctl_handler, + }, }; static int __init topology_init(void) @@ -642,6 +685,8 @@ static int __init topology_init(void) set_topology_timer(); else topology_update_polarization_simple(); + if (IS_ENABLED(CONFIG_SCHED_TOPOLOGY_VERTICAL)) + set_polarization(1); register_sysctl("s390", topology_ctl_table); dev_root = bus_get_dev_root(&cpu_subsys); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 160b2acba8db..24fee11b030d 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -31,6 +31,7 @@ #include <asm/asm-extable.h> #include <asm/vtime.h> #include <asm/fpu.h> +#include <asm/fault.h> #include "entry.h" static inline void __user *get_trap_ip(struct pt_regs *regs) @@ -317,9 +318,24 @@ void noinstr __do_pgm_check(struct pt_regs *regs) struct lowcore *lc = get_lowcore(); irqentry_state_t state; unsigned int trapnr; + union teid teid; + teid.val = lc->trans_exc_code; regs->int_code = lc->pgm_int_code; - regs->int_parm_long = lc->trans_exc_code; + regs->int_parm_long = teid.val; + + /* + * In case of a guest fault, short-circuit the fault handler and return. + * This way the sie64a() function will return 0; fault address and + * other relevant bits are saved in current->thread.gmap_teid, and + * the fault number in current->thread.gmap_int_code. KVM will be + * able to use this information to handle the fault. + */ + if (test_pt_regs_flag(regs, PIF_GUEST_FAULT)) { + current->thread.gmap_teid.val = regs->int_parm_long; + current->thread.gmap_int_code = regs->int_code & 0xffff; + return; + } state = irqentry_enter(regs); @@ -408,8 +424,8 @@ static void (*pgm_check_table[128])(struct pt_regs *regs) = { [0x3b] = do_dat_exception, [0x3c] = default_trap_handler, [0x3d] = do_secure_storage_access, - [0x3e] = do_non_secure_storage_access, - [0x3f] = do_secure_storage_violation, + [0x3e] = default_trap_handler, + [0x3f] = default_trap_handler, [0x40] = monitor_event_exception, [0x41 ... 0x7f] = default_trap_handler, }; @@ -420,5 +436,3 @@ static void (*pgm_check_table[128])(struct pt_regs *regs) = { __stringify(default_trap_handler)) COND_TRAP(do_secure_storage_access); -COND_TRAP(do_non_secure_storage_access); -COND_TRAP(do_secure_storage_violation); diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c index 36db065c7cf7..6f9654a191ad 100644 --- a/arch/s390/kernel/uv.c +++ b/arch/s390/kernel/uv.c @@ -2,7 +2,7 @@ /* * Common Ultravisor functions and initialization * - * Copyright IBM Corp. 2019, 2020 + * Copyright IBM Corp. 2019, 2024 */ #define KMSG_COMPONENT "prot_virt" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt @@ -14,6 +14,7 @@ #include <linux/memblock.h> #include <linux/pagemap.h> #include <linux/swap.h> +#include <linux/pagewalk.h> #include <asm/facility.h> #include <asm/sections.h> #include <asm/uv.h> @@ -462,9 +463,9 @@ EXPORT_SYMBOL_GPL(gmap_convert_to_secure); int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr) { struct vm_area_struct *vma; + struct folio_walk fw; unsigned long uaddr; struct folio *folio; - struct page *page; int rc; rc = -EFAULT; @@ -483,11 +484,15 @@ int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr) goto out; rc = 0; - /* we take an extra reference here */ - page = follow_page(vma, uaddr, FOLL_WRITE | FOLL_GET); - if (IS_ERR_OR_NULL(page)) + folio = folio_walk_start(&fw, vma, uaddr, 0); + if (!folio) goto out; - folio = page_folio(page); + /* + * See gmap_make_secure(): large folios cannot be secure. Small + * folio implies FW_LEVEL_PTE. + */ + if (folio_test_large(folio) || !pte_write(fw.pte)) + goto out_walk_end; rc = uv_destroy_folio(folio); /* * Fault handlers can race; it is possible that two CPUs will fault @@ -500,7 +505,8 @@ int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr) */ if (rc) rc = uv_convert_from_secure_folio(folio); - folio_put(folio); +out_walk_end: + folio_walk_end(&fw, vma); out: mmap_read_unlock(gmap->mm); return rc; @@ -548,11 +554,6 @@ int arch_make_folio_accessible(struct folio *folio) } EXPORT_SYMBOL_GPL(arch_make_folio_accessible); -int arch_make_page_accessible(struct page *page) -{ - return arch_make_folio_accessible(page_folio(page)); -} -EXPORT_SYMBOL_GPL(arch_make_page_accessible); static ssize_t uv_query_facilities(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -695,12 +696,32 @@ static struct kobj_attribute uv_query_supp_secret_types_attr = static ssize_t uv_query_max_secrets(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sysfs_emit(buf, "%d\n", uv_info.max_secrets); + return sysfs_emit(buf, "%d\n", + uv_info.max_assoc_secrets + uv_info.max_retr_secrets); } static struct kobj_attribute uv_query_max_secrets_attr = __ATTR(max_secrets, 0444, uv_query_max_secrets, NULL); +static ssize_t uv_query_max_retr_secrets(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%d\n", uv_info.max_retr_secrets); +} + +static struct kobj_attribute uv_query_max_retr_secrets_attr = + __ATTR(max_retr_secrets, 0444, uv_query_max_retr_secrets, NULL); + +static ssize_t uv_query_max_assoc_secrets(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%d\n", uv_info.max_assoc_secrets); +} + +static struct kobj_attribute uv_query_max_assoc_secrets_attr = + __ATTR(max_assoc_secrets, 0444, uv_query_max_assoc_secrets, NULL); + static struct attribute *uv_query_attrs[] = { &uv_query_facilities_attr.attr, &uv_query_feature_indications_attr.attr, @@ -718,13 +739,81 @@ static struct attribute *uv_query_attrs[] = { &uv_query_supp_add_secret_pcf_attr.attr, &uv_query_supp_secret_types_attr.attr, &uv_query_max_secrets_attr.attr, + &uv_query_max_assoc_secrets_attr.attr, + &uv_query_max_retr_secrets_attr.attr, NULL, }; +static inline struct uv_cb_query_keys uv_query_keys(void) +{ + struct uv_cb_query_keys uvcb = { + .header.cmd = UVC_CMD_QUERY_KEYS, + .header.len = sizeof(uvcb) + }; + + uv_call(0, (uint64_t)&uvcb); + return uvcb; +} + +static inline ssize_t emit_hash(struct uv_key_hash *hash, char *buf, int at) +{ + return sysfs_emit_at(buf, at, "%016llx%016llx%016llx%016llx\n", + hash->dword[0], hash->dword[1], hash->dword[2], hash->dword[3]); +} + +static ssize_t uv_keys_host_key(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct uv_cb_query_keys uvcb = uv_query_keys(); + + return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_HK], buf, 0); +} + +static struct kobj_attribute uv_keys_host_key_attr = + __ATTR(host_key, 0444, uv_keys_host_key, NULL); + +static ssize_t uv_keys_backup_host_key(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct uv_cb_query_keys uvcb = uv_query_keys(); + + return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_BACK_HK], buf, 0); +} + +static struct kobj_attribute uv_keys_backup_host_key_attr = + __ATTR(backup_host_key, 0444, uv_keys_backup_host_key, NULL); + +static ssize_t uv_keys_all(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct uv_cb_query_keys uvcb = uv_query_keys(); + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(uvcb.key_hashes); i++) + len += emit_hash(uvcb.key_hashes + i, buf, len); + + return len; +} + +static struct kobj_attribute uv_keys_all_attr = + __ATTR(all, 0444, uv_keys_all, NULL); + static struct attribute_group uv_query_attr_group = { .attrs = uv_query_attrs, }; +static struct attribute *uv_keys_attrs[] = { + &uv_keys_host_key_attr.attr, + &uv_keys_backup_host_key_attr.attr, + &uv_keys_all_attr.attr, + NULL, +}; + +static struct attribute_group uv_keys_attr_group = { + .attrs = uv_keys_attrs, +}; + static ssize_t uv_is_prot_virt_guest(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -750,9 +839,27 @@ static const struct attribute *uv_prot_virt_attrs[] = { }; static struct kset *uv_query_kset; +static struct kset *uv_keys_kset; static struct kobject *uv_kobj; -static int __init uv_info_init(void) +static int __init uv_sysfs_dir_init(const struct attribute_group *grp, + struct kset **uv_dir_kset, const char *name) +{ + struct kset *kset; + int rc; + + kset = kset_create_and_add(name, NULL, uv_kobj); + if (!kset) + return -ENOMEM; + *uv_dir_kset = kset; + + rc = sysfs_create_group(&kset->kobj, grp); + if (rc) + kset_unregister(kset); + return rc; +} + +static int __init uv_sysfs_init(void) { int rc = -ENOMEM; @@ -767,17 +874,16 @@ static int __init uv_info_init(void) if (rc) goto out_kobj; - uv_query_kset = kset_create_and_add("query", NULL, uv_kobj); - if (!uv_query_kset) { - rc = -ENOMEM; + rc = uv_sysfs_dir_init(&uv_query_attr_group, &uv_query_kset, "query"); + if (rc) goto out_ind_files; - } - rc = sysfs_create_group(&uv_query_kset->kobj, &uv_query_attr_group); - if (!rc) - return 0; + /* Get installed key hashes if available, ignore any errors */ + if (test_bit_inv(BIT_UVC_CMD_QUERY_KEYS, uv_info.inst_calls_list)) + uv_sysfs_dir_init(&uv_keys_attr_group, &uv_keys_kset, "keys"); + + return 0; - kset_unregister(uv_query_kset); out_ind_files: sysfs_remove_files(uv_kobj, uv_prot_virt_attrs); out_kobj: @@ -785,4 +891,131 @@ out_kobj: kobject_put(uv_kobj); return rc; } -device_initcall(uv_info_init); +device_initcall(uv_sysfs_init); + +/* + * Find the secret with the secret_id in the provided list. + * + * Context: might sleep. + */ +static int find_secret_in_page(const u8 secret_id[UV_SECRET_ID_LEN], + const struct uv_secret_list *list, + struct uv_secret_list_item_hdr *secret) +{ + u16 i; + + for (i = 0; i < list->total_num_secrets; i++) { + if (memcmp(secret_id, list->secrets[i].id, UV_SECRET_ID_LEN) == 0) { + *secret = list->secrets[i].hdr; + return 0; + } + } + return -ENOENT; +} + +/* + * Do the actual search for `uv_get_secret_metadata`. + * + * Context: might sleep. + */ +static int find_secret(const u8 secret_id[UV_SECRET_ID_LEN], + struct uv_secret_list *list, + struct uv_secret_list_item_hdr *secret) +{ + u16 start_idx = 0; + u16 list_rc; + int ret; + + do { + uv_list_secrets(list, start_idx, &list_rc, NULL); + if (list_rc != UVC_RC_EXECUTED && list_rc != UVC_RC_MORE_DATA) { + if (list_rc == UVC_RC_INV_CMD) + return -ENODEV; + else + return -EIO; + } + ret = find_secret_in_page(secret_id, list, secret); + if (ret == 0) + return ret; + start_idx = list->next_secret_idx; + } while (list_rc == UVC_RC_MORE_DATA && start_idx < list->next_secret_idx); + + return -ENOENT; +} + +/** + * uv_get_secret_metadata() - get secret metadata for a given secret id. + * @secret_id: search pattern. + * @secret: output data, containing the secret's metadata. + * + * Search for a secret with the given secret_id in the Ultravisor secret store. + * + * Context: might sleep. + * + * Return: + * * %0: - Found entry; secret->idx and secret->type are valid. + * * %ENOENT - No entry found. + * * %ENODEV: - Not supported: UV not available or command not available. + * * %EIO: - Other unexpected UV error. + */ +int uv_get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN], + struct uv_secret_list_item_hdr *secret) +{ + struct uv_secret_list *buf; + int rc; + + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + rc = find_secret(secret_id, buf, secret); + kfree(buf); + return rc; +} +EXPORT_SYMBOL_GPL(uv_get_secret_metadata); + +/** + * uv_retrieve_secret() - get the secret value for the secret index. + * @secret_idx: Secret index for which the secret should be retrieved. + * @buf: Buffer to store retrieved secret. + * @buf_size: Size of the buffer. The correct buffer size is reported as part of + * the result from `uv_get_secret_metadata`. + * + * Calls the Retrieve Secret UVC and translates the UV return code into an errno. + * + * Context: might sleep. + * + * Return: + * * %0 - Entry found; buffer contains a valid secret. + * * %ENOENT: - No entry found or secret at the index is non-retrievable. + * * %ENODEV: - Not supported: UV not available or command not available. + * * %EINVAL: - Buffer too small for content. + * * %EIO: - Other unexpected UV error. + */ +int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size) +{ + struct uv_cb_retr_secr uvcb = { + .header.len = sizeof(uvcb), + .header.cmd = UVC_CMD_RETR_SECRET, + .secret_idx = secret_idx, + .buf_addr = (u64)buf, + .buf_size = buf_size, + }; + + uv_call_sched(0, (u64)&uvcb); + + switch (uvcb.header.rc) { + case UVC_RC_EXECUTED: + return 0; + case UVC_RC_INV_CMD: + return -ENODEV; + case UVC_RC_RETR_SECR_STORE_EMPTY: + case UVC_RC_RETR_SECR_INV_SECRET: + case UVC_RC_RETR_SECR_INV_IDX: + return -ENOENT; + case UVC_RC_RETR_SECR_BUF_SMALL: + return -EINVAL; + default: + return -EIO; + } +} +EXPORT_SYMBOL_GPL(uv_retrieve_secret); diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 2f967ac2b8e3..598b512cde01 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -12,12 +12,15 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/smp.h> #include <linux/time_namespace.h> #include <linux/random.h> #include <vdso/datapage.h> +#include <asm/vdso/vsyscall.h> +#include <asm/alternative.h> #include <asm/vdso.h> extern char vdso64_start[], vdso64_end[]; @@ -29,12 +32,6 @@ static union vdso_data_store vdso_data_store __page_aligned_data; struct vdso_data *vdso_data = vdso_data_store.data; -enum vvar_pages { - VVAR_DATA_PAGE_OFFSET, - VVAR_TIMENS_PAGE_OFFSET, - VVAR_NR_PAGES, -}; - #ifdef CONFIG_TIME_NS struct vdso_data *arch_get_vdso_data(void *vvar_page) { @@ -250,8 +247,25 @@ static struct page ** __init vdso_setup_pages(void *start, void *end) return pagelist; } +static void vdso_apply_alternatives(void) +{ + const struct elf64_shdr *alt, *shdr; + struct alt_instr *start, *end; + const struct elf64_hdr *hdr; + + hdr = (struct elf64_hdr *)vdso64_start; + shdr = (void *)hdr + hdr->e_shoff; + alt = find_section(hdr, shdr, ".altinstructions"); + if (!alt) + return; + start = (void *)hdr + alt->sh_offset; + end = (void *)hdr + alt->sh_offset + alt->sh_size; + apply_alternatives(start, end); +} + static int __init vdso_init(void) { + vdso_apply_alternatives(); vdso64_mapping.pages = vdso_setup_pages(vdso64_start, vdso64_end); if (IS_ENABLED(CONFIG_COMPAT)) vdso32_mapping.pages = vdso_setup_pages(vdso32_start, vdso32_end); diff --git a/arch/s390/kernel/vdso32/vdso32.lds.S b/arch/s390/kernel/vdso32/vdso32.lds.S index 65b9513a5a0e..c916c4f73f76 100644 --- a/arch/s390/kernel/vdso32/vdso32.lds.S +++ b/arch/s390/kernel/vdso32/vdso32.lds.S @@ -16,7 +16,7 @@ SECTIONS #ifdef CONFIG_TIME_NS PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); #endif - . = VDSO_LBASE + SIZEOF_HEADERS; + . = SIZEOF_HEADERS; .hash : { *(.hash) } :text .gnu.hash : { *(.gnu.hash) } diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index ba19c0ca7c87..37bb4b761229 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile @@ -3,12 +3,17 @@ # Include the generic Makefile to check the built vdso. include $(srctree)/lib/vdso/Makefile -obj-vdso64 = vdso_user_wrapper.o note.o -obj-cvdso64 = vdso64_generic.o getcpu.o +obj-vdso64 = vdso_user_wrapper.o note.o vgetrandom-chacha.o +obj-cvdso64 = vdso64_generic.o getcpu.o vgetrandom.o VDSO_CFLAGS_REMOVE := -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) $(CC_FLAGS_CHECK_STACK) CFLAGS_REMOVE_getcpu.o = $(VDSO_CFLAGS_REMOVE) +CFLAGS_REMOVE_vgetrandom.o = $(VDSO_CFLAGS_REMOVE) CFLAGS_REMOVE_vdso64_generic.o = $(VDSO_CFLAGS_REMOVE) +ifneq ($(c-getrandom-y),) + CFLAGS_vgetrandom.o += -include $(c-getrandom-y) +endif + # Build rules targets := $(obj-vdso64) $(obj-cvdso64) vdso64.so vdso64.so.dbg diff --git a/arch/s390/kernel/vdso64/vdso.h b/arch/s390/kernel/vdso64/vdso.h index 34c7a2312f9d..9e5397e7b590 100644 --- a/arch/s390/kernel/vdso64/vdso.h +++ b/arch/s390/kernel/vdso64/vdso.h @@ -10,5 +10,6 @@ int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unuse int __s390_vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); int __s390_vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts); int __s390_vdso_clock_getres(clockid_t clock, struct __kernel_timespec *ts); +ssize_t __kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len); #endif /* __ARCH_S390_KERNEL_VDSO64_VDSO_H */ diff --git a/arch/s390/kernel/vdso64/vdso64.lds.S b/arch/s390/kernel/vdso64/vdso64.lds.S index 37e2a505e81d..ec42b7d9cb53 100644 --- a/arch/s390/kernel/vdso64/vdso64.lds.S +++ b/arch/s390/kernel/vdso64/vdso64.lds.S @@ -4,6 +4,7 @@ * library */ +#include <asm/vdso/vsyscall.h> #include <asm/page.h> #include <asm/vdso.h> @@ -13,10 +14,11 @@ OUTPUT_ARCH(s390:64-bit) SECTIONS { PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE); + PROVIDE(_vdso_rng_data = _vdso_data + __VDSO_RND_DATA_OFFSET); #ifdef CONFIG_TIME_NS PROVIDE(_timens_data = _vdso_data + PAGE_SIZE); #endif - . = VDSO_LBASE + SIZEOF_HEADERS; + . = SIZEOF_HEADERS; .hash : { *(.hash) } :text .gnu.hash : { *(.gnu.hash) } @@ -42,6 +44,10 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } + . = ALIGN(8); + .altinstructions : { *(.altinstructions) } + .altinstr_replacement : { *(.altinstr_replacement) } + .dynamic : { *(.dynamic) } :text :dynamic .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr @@ -140,6 +146,7 @@ VERSION __kernel_restart_syscall; __kernel_rt_sigreturn; __kernel_sigreturn; + __kernel_getrandom; local: *; }; } diff --git a/arch/s390/kernel/vdso64/vdso_user_wrapper.S b/arch/s390/kernel/vdso64/vdso_user_wrapper.S index e26e68675c08..aa06c85bcbd3 100644 --- a/arch/s390/kernel/vdso64/vdso_user_wrapper.S +++ b/arch/s390/kernel/vdso64/vdso_user_wrapper.S @@ -13,10 +13,7 @@ * for details. */ .macro vdso_func func - .globl __kernel_\func - .type __kernel_\func,@function - __ALIGN -__kernel_\func: +SYM_FUNC_START(__kernel_\func) CFI_STARTPROC aghi %r15,-STACK_FRAME_VDSO_OVERHEAD CFI_DEF_CFA_OFFSET (STACK_FRAME_USER_OVERHEAD + STACK_FRAME_VDSO_OVERHEAD) @@ -32,7 +29,7 @@ __kernel_\func: CFI_RESTORE 15 br %r14 CFI_ENDPROC - .size __kernel_\func,.-__kernel_\func +SYM_FUNC_END(__kernel_\func) .endm vdso_func gettimeofday @@ -41,16 +38,13 @@ vdso_func clock_gettime vdso_func getcpu .macro vdso_syscall func,syscall - .globl __kernel_\func - .type __kernel_\func,@function - __ALIGN -__kernel_\func: +SYM_FUNC_START(__kernel_\func) CFI_STARTPROC svc \syscall /* Make sure we notice when a syscall returns, which shouldn't happen */ .word 0 CFI_ENDPROC - .size __kernel_\func,.-__kernel_\func +SYM_FUNC_END(__kernel_\func) .endm vdso_syscall restart_syscall,__NR_restart_syscall diff --git a/arch/s390/kernel/vdso64/vgetrandom-chacha.S b/arch/s390/kernel/vdso64/vgetrandom-chacha.S new file mode 100644 index 000000000000..09c034c2f853 --- /dev/null +++ b/arch/s390/kernel/vdso64/vgetrandom-chacha.S @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/stringify.h> +#include <linux/linkage.h> +#include <asm/alternative.h> +#include <asm/dwarf.h> +#include <asm/fpu-insn.h> + +#define STATE0 %v0 +#define STATE1 %v1 +#define STATE2 %v2 +#define STATE3 %v3 +#define COPY0 %v4 +#define COPY1 %v5 +#define COPY2 %v6 +#define COPY3 %v7 +#define BEPERM %v19 +#define TMP0 %v20 +#define TMP1 %v21 +#define TMP2 %v22 +#define TMP3 %v23 + + .section .rodata + + .balign 32 +SYM_DATA_START_LOCAL(chacha20_constants) + .long 0x61707865,0x3320646e,0x79622d32,0x6b206574 # endian-neutral + .long 0x03020100,0x07060504,0x0b0a0908,0x0f0e0d0c # byte swap +SYM_DATA_END(chacha20_constants) + + .text +/* + * s390 ChaCha20 implementation meant for vDSO. Produces a given positive + * number of blocks of output with nonce 0, taking an input key and 8-bytes + * counter. Does not spill to the stack. + * + * void __arch_chacha20_blocks_nostack(uint8_t *dst_bytes, + * const uint8_t *key, + * uint32_t *counter, + * size_t nblocks) + */ +SYM_FUNC_START(__arch_chacha20_blocks_nostack) + CFI_STARTPROC + larl %r1,chacha20_constants + + /* COPY0 = "expand 32-byte k" */ + VL COPY0,0,,%r1 + + /* BEPERM = byte selectors for VPERM */ + ALTERNATIVE __stringify(VL BEPERM,16,,%r1), "brcl 0,0", ALT_FACILITY(148) + + /* COPY1,COPY2 = key */ + VLM COPY1,COPY2,0,%r3 + + /* COPY3 = counter || zero nonce */ + lg %r3,0(%r4) + VZERO COPY3 + VLVGG COPY3,%r3,0 + + lghi %r1,0 +.Lblock: + VLR STATE0,COPY0 + VLR STATE1,COPY1 + VLR STATE2,COPY2 + VLR STATE3,COPY3 + + lghi %r0,10 +.Ldoubleround: + /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 16) */ + VAF STATE0,STATE0,STATE1 + VX STATE3,STATE3,STATE0 + VERLLF STATE3,STATE3,16 + + /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 12) */ + VAF STATE2,STATE2,STATE3 + VX STATE1,STATE1,STATE2 + VERLLF STATE1,STATE1,12 + + /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 8) */ + VAF STATE0,STATE0,STATE1 + VX STATE3,STATE3,STATE0 + VERLLF STATE3,STATE3,8 + + /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 7) */ + VAF STATE2,STATE2,STATE3 + VX STATE1,STATE1,STATE2 + VERLLF STATE1,STATE1,7 + + /* STATE1[0,1,2,3] = STATE1[1,2,3,0] */ + VSLDB STATE1,STATE1,STATE1,4 + /* STATE2[0,1,2,3] = STATE2[2,3,0,1] */ + VSLDB STATE2,STATE2,STATE2,8 + /* STATE3[0,1,2,3] = STATE3[3,0,1,2] */ + VSLDB STATE3,STATE3,STATE3,12 + + /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 16) */ + VAF STATE0,STATE0,STATE1 + VX STATE3,STATE3,STATE0 + VERLLF STATE3,STATE3,16 + + /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 12) */ + VAF STATE2,STATE2,STATE3 + VX STATE1,STATE1,STATE2 + VERLLF STATE1,STATE1,12 + + /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 8) */ + VAF STATE0,STATE0,STATE1 + VX STATE3,STATE3,STATE0 + VERLLF STATE3,STATE3,8 + + /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 7) */ + VAF STATE2,STATE2,STATE3 + VX STATE1,STATE1,STATE2 + VERLLF STATE1,STATE1,7 + + /* STATE1[0,1,2,3] = STATE1[3,0,1,2] */ + VSLDB STATE1,STATE1,STATE1,12 + /* STATE2[0,1,2,3] = STATE2[2,3,0,1] */ + VSLDB STATE2,STATE2,STATE2,8 + /* STATE3[0,1,2,3] = STATE3[1,2,3,0] */ + VSLDB STATE3,STATE3,STATE3,4 + brctg %r0,.Ldoubleround + + /* OUTPUT0 = STATE0 + COPY0 */ + VAF STATE0,STATE0,COPY0 + /* OUTPUT1 = STATE1 + COPY1 */ + VAF STATE1,STATE1,COPY1 + /* OUTPUT2 = STATE2 + COPY2 */ + VAF STATE2,STATE2,COPY2 + /* OUTPUT3 = STATE3 + COPY3 */ + VAF STATE3,STATE3,COPY3 + + ALTERNATIVE \ + __stringify( \ + /* Convert STATE to little endian and store to OUTPUT */\ + VPERM TMP0,STATE0,STATE0,BEPERM; \ + VPERM TMP1,STATE1,STATE1,BEPERM; \ + VPERM TMP2,STATE2,STATE2,BEPERM; \ + VPERM TMP3,STATE3,STATE3,BEPERM; \ + VSTM TMP0,TMP3,0,%r2), \ + __stringify( \ + /* 32 bit wise little endian store to OUTPUT */ \ + VSTBRF STATE0,0,,%r2; \ + VSTBRF STATE1,16,,%r2; \ + VSTBRF STATE2,32,,%r2; \ + VSTBRF STATE3,48,,%r2; \ + brcl 0,0), \ + ALT_FACILITY(148) + + /* ++COPY3.COUNTER */ + /* alsih %r3,1 */ + .insn rilu,0xcc0a00000000,%r3,1 + alcr %r3,%r1 + VLVGG COPY3,%r3,0 + + /* OUTPUT += 64, --NBLOCKS */ + aghi %r2,64 + brctg %r5,.Lblock + + /* COUNTER = COPY3.COUNTER */ + stg %r3,0(%r4) + + /* Zero out potentially sensitive regs */ + VZERO STATE0 + VZERO STATE1 + VZERO STATE2 + VZERO STATE3 + VZERO COPY1 + VZERO COPY2 + + /* Early exit if TMP0-TMP3 have not been used */ + ALTERNATIVE "nopr", "br %r14", ALT_FACILITY(148) + + VZERO TMP0 + VZERO TMP1 + VZERO TMP2 + VZERO TMP3 + + br %r14 + CFI_ENDPROC +SYM_FUNC_END(__arch_chacha20_blocks_nostack) diff --git a/arch/s390/kernel/vdso64/vgetrandom.c b/arch/s390/kernel/vdso64/vgetrandom.c new file mode 100644 index 000000000000..b5268b507fb5 --- /dev/null +++ b/arch/s390/kernel/vdso64/vgetrandom.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <asm/facility.h> +#include <uapi/asm-generic/errno.h> +#include "vdso.h" + +ssize_t __kernel_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len) +{ + if (test_facility(129)) + return __cvdso_getrandom(buffer, len, flags, opaque_state, opaque_len); + if (unlikely(opaque_len == ~0UL && !buffer && !len && !flags)) + return -ENOSYS; + return getrandom_syscall(buffer, len, flags); +} diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index ae5d0a9d6911..377b9aaf8c92 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -191,8 +191,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); INIT_DATA_SECTION(0x100) - RUNTIME_CONST(shift, d_hash_shift) - RUNTIME_CONST(ptr, dentry_hashtable) + RUNTIME_CONST_VARIABLES PERCPU_SECTION(0x100) diff --git a/arch/s390/kernel/wti.c b/arch/s390/kernel/wti.c new file mode 100644 index 000000000000..949fdbf0e8b6 --- /dev/null +++ b/arch/s390/kernel/wti.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for warning track interruption + * + * Copyright IBM Corp. 2023 + */ + +#include <linux/cpu.h> +#include <linux/debugfs.h> +#include <linux/kallsyms.h> +#include <linux/smpboot.h> +#include <linux/irq.h> +#include <uapi/linux/sched/types.h> +#include <asm/debug.h> +#include <asm/diag.h> +#include <asm/sclp.h> + +#define WTI_DBF_LEN 64 + +struct wti_debug { + unsigned long missed; + unsigned long addr; + pid_t pid; +}; + +struct wti_state { + /* debug data for s390dbf */ + struct wti_debug dbg; + /* + * Represents the real-time thread responsible to + * acknowledge the warning-track interrupt and trigger + * preliminary and postliminary precautions. + */ + struct task_struct *thread; + /* + * If pending is true, the real-time thread must be scheduled. + * If not, a wake up of that thread will remain a noop. + */ + bool pending; +}; + +static DEFINE_PER_CPU(struct wti_state, wti_state); + +static debug_info_t *wti_dbg; + +/* + * During a warning-track grace period, interrupts are disabled + * to prevent delays of the warning-track acknowledgment. + * + * Once the CPU is physically dispatched again, interrupts are + * re-enabled. + */ + +static void wti_irq_disable(void) +{ + unsigned long flags; + struct ctlreg cr6; + + local_irq_save(flags); + local_ctl_store(6, &cr6); + /* disable all I/O interrupts */ + cr6.val &= ~0xff000000UL; + local_ctl_load(6, &cr6); + local_irq_restore(flags); +} + +static void wti_irq_enable(void) +{ + unsigned long flags; + struct ctlreg cr6; + + local_irq_save(flags); + local_ctl_store(6, &cr6); + /* enable all I/O interrupts */ + cr6.val |= 0xff000000UL; + local_ctl_load(6, &cr6); + local_irq_restore(flags); +} + +static void store_debug_data(struct wti_state *st) +{ + struct pt_regs *regs = get_irq_regs(); + + st->dbg.pid = current->pid; + st->dbg.addr = 0; + if (!user_mode(regs)) + st->dbg.addr = regs->psw.addr; +} + +static void wti_interrupt(struct ext_code ext_code, + unsigned int param32, unsigned long param64) +{ + struct wti_state *st = this_cpu_ptr(&wti_state); + + inc_irq_stat(IRQEXT_WTI); + wti_irq_disable(); + store_debug_data(st); + st->pending = true; + wake_up_process(st->thread); +} + +static int wti_pending(unsigned int cpu) +{ + struct wti_state *st = per_cpu_ptr(&wti_state, cpu); + + return st->pending; +} + +static void wti_dbf_grace_period(struct wti_state *st) +{ + struct wti_debug *wdi = &st->dbg; + char buf[WTI_DBF_LEN]; + + if (wdi->addr) + snprintf(buf, sizeof(buf), "%d %pS", wdi->pid, (void *)wdi->addr); + else + snprintf(buf, sizeof(buf), "%d <user>", wdi->pid); + debug_text_event(wti_dbg, 2, buf); + wdi->missed++; +} + +static int wti_show(struct seq_file *seq, void *v) +{ + struct wti_state *st; + int cpu; + + cpus_read_lock(); + seq_puts(seq, " "); + for_each_online_cpu(cpu) + seq_printf(seq, "CPU%-8d", cpu); + seq_putc(seq, '\n'); + for_each_online_cpu(cpu) { + st = per_cpu_ptr(&wti_state, cpu); + seq_printf(seq, " %10lu", st->dbg.missed); + } + seq_putc(seq, '\n'); + cpus_read_unlock(); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(wti); + +static void wti_thread_fn(unsigned int cpu) +{ + struct wti_state *st = per_cpu_ptr(&wti_state, cpu); + + st->pending = false; + /* + * Yield CPU voluntarily to the hypervisor. Control + * resumes when hypervisor decides to dispatch CPU + * to this LPAR again. + */ + if (diag49c(DIAG49C_SUBC_ACK)) + wti_dbf_grace_period(st); + wti_irq_enable(); +} + +static struct smp_hotplug_thread wti_threads = { + .store = &wti_state.thread, + .thread_should_run = wti_pending, + .thread_fn = wti_thread_fn, + .thread_comm = "cpuwti/%u", + .selfparking = false, +}; + +static int __init wti_init(void) +{ + struct sched_param wti_sched_param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct dentry *wti_dir; + struct wti_state *st; + int cpu, rc; + + rc = -EOPNOTSUPP; + if (!sclp.has_wti) + goto out; + rc = smpboot_register_percpu_thread(&wti_threads); + if (WARN_ON(rc)) + goto out; + for_each_online_cpu(cpu) { + st = per_cpu_ptr(&wti_state, cpu); + sched_setscheduler(st->thread, SCHED_FIFO, &wti_sched_param); + } + rc = register_external_irq(EXT_IRQ_WARNING_TRACK, wti_interrupt); + if (rc) { + pr_warn("Couldn't request external interrupt 0x1007\n"); + goto out_thread; + } + irq_subclass_register(IRQ_SUBCLASS_WARNING_TRACK); + rc = diag49c(DIAG49C_SUBC_REG); + if (rc) { + pr_warn("Failed to register warning track interrupt through DIAG 49C\n"); + rc = -EOPNOTSUPP; + goto out_subclass; + } + wti_dir = debugfs_create_dir("wti", arch_debugfs_dir); + debugfs_create_file("stat", 0400, wti_dir, NULL, &wti_fops); + wti_dbg = debug_register("wti", 1, 1, WTI_DBF_LEN); + if (!wti_dbg) { + rc = -ENOMEM; + goto out_debug_register; + } + rc = debug_register_view(wti_dbg, &debug_hex_ascii_view); + if (rc) + goto out_debug_register; + goto out; +out_debug_register: + debug_unregister(wti_dbg); +out_subclass: + irq_subclass_unregister(IRQ_SUBCLASS_WARNING_TRACK); + unregister_external_irq(EXT_IRQ_WARNING_TRACK, wti_interrupt); +out_thread: + smpboot_unregister_percpu_thread(&wti_threads); +out: + return rc; +} +late_initcall(wti_init); diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 2a32438e09ce..74f73141f9b9 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -77,7 +77,7 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu) vcpu->stat.instruction_diagnose_258++; if (vcpu->run->s.regs.gprs[rx] & 7) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); - rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm)); + rc = read_guest_real(vcpu, vcpu->run->s.regs.gprs[rx], &parm, sizeof(parm)); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258) diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index e65f597e3044..a688351f4ab5 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -828,6 +828,8 @@ static int access_guest_page(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa, const gfn_t gfn = gpa_to_gfn(gpa); int rc; + if (!gfn_to_memslot(kvm, gfn)) + return PGM_ADDRESSING; if (mode == GACC_STORE) rc = kvm_write_guest_page(kvm, gfn, data, offset, len); else @@ -985,6 +987,8 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, gra += fragment_len; data += fragment_len; } + if (rc > 0) + vcpu->arch.pgm.code = rc; return rc; } diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index b320d12aa049..3fde45a151f2 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -405,11 +405,12 @@ int read_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data, * @len: number of bytes to copy * * Copy @len bytes from @data (kernel space) to @gra (guest real address). - * It is up to the caller to ensure that the entire guest memory range is - * valid memory before calling this function. * Guest low address and key protection are not checked. * - * Returns zero on success or -EFAULT on error. + * Returns zero on success, -EFAULT when copying from @data failed, or + * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info + * is also stored to allow injecting into the guest (if applicable) using + * kvm_s390_inject_prog_cond(). * * If an error occurs data may have been copied partially to guest memory. */ @@ -428,11 +429,12 @@ int write_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data, * @len: number of bytes to copy * * Copy @len bytes from @gra (guest real address) to @data (kernel space). - * It is up to the caller to ensure that the entire guest memory range is - * valid memory before calling this function. * Guest key protection is not checked. * - * Returns zero on success or -EFAULT on error. + * Returns zero on success, -EFAULT when copying to @data failed, or + * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info + * is also stored to allow injecting into the guest (if applicable) using + * kvm_s390_inject_prog_cond(). * * If an error occurs data may have been copied partially to kernel space. */ diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index b16352083ff9..5bbaadf75dc6 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -367,7 +367,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) reg2, &srcaddr, GACC_FETCH, 0); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); - rc = kvm_arch_fault_in_page(vcpu, srcaddr, 0); + rc = gmap_fault(vcpu->arch.gmap, srcaddr, 0); if (rc != 0) return rc; @@ -376,7 +376,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) reg1, &dstaddr, GACC_STORE, 0); if (rc) return kvm_s390_inject_prog_cond(vcpu, rc); - rc = kvm_arch_fault_in_page(vcpu, dstaddr, 1); + rc = gmap_fault(vcpu->arch.gmap, dstaddr, FAULT_FLAG_WRITE); if (rc != 0) return rc; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0fd96860fc45..deeb32034ad5 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -43,6 +43,7 @@ #include <asm/sclp.h> #include <asm/cpacf.h> #include <asm/timex.h> +#include <asm/asm.h> #include <asm/fpu.h> #include <asm/ap.h> #include <asm/uv.h> @@ -340,28 +341,36 @@ static inline int plo_test_bit(unsigned char nr) " lgr 0,%[function]\n" /* Parameter registers are ignored for "test bit" */ " plo 0,0,0,0(0)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) + CC_IPM(cc) + : CC_OUT(cc, cc) : [function] "d" (function) - : "cc", "0"); - return cc == 0; + : CC_CLOBBER_LIST("0")); + return CC_TRANSFORM(cc) == 0; } -static __always_inline void __insn32_query(unsigned int opcode, u8 *query) +static __always_inline void __sortl_query(u8 (*query)[32]) { asm volatile( " lghi 0,0\n" - " lgr 1,%[query]\n" + " la 1,%[query]\n" /* Parameter registers are ignored */ - " .insn rrf,%[opc] << 16,2,4,6,0\n" + " .insn rre,0xb9380000,2,4\n" + : [query] "=R" (*query) : - : [query] "d" ((unsigned long)query), [opc] "i" (opcode) - : "cc", "memory", "0", "1"); + : "cc", "0", "1"); } -#define INSN_SORTL 0xb938 -#define INSN_DFLTCC 0xb939 +static __always_inline void __dfltcc_query(u8 (*query)[32]) +{ + asm volatile( + " lghi 0,0\n" + " la 1,%[query]\n" + /* Parameter registers are ignored */ + " .insn rrf,0xb9390000,2,4,6,0\n" + : [query] "=R" (*query) + : + : "cc", "0", "1"); +} static void __init kvm_s390_cpu_feat_init(void) { @@ -415,10 +424,10 @@ static void __init kvm_s390_cpu_feat_init(void) kvm_s390_available_subfunc.kdsa); if (test_facility(150)) /* SORTL */ - __insn32_query(INSN_SORTL, kvm_s390_available_subfunc.sortl); + __sortl_query(&kvm_s390_available_subfunc.sortl); if (test_facility(151)) /* DFLTCC */ - __insn32_query(INSN_DFLTCC, kvm_s390_available_subfunc.dfltcc); + __dfltcc_query(&kvm_s390_available_subfunc.dfltcc); if (MACHINE_HAS_ESOP) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); @@ -3710,7 +3719,6 @@ __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { - gmap_enable(vcpu->arch.enabled_gmap); kvm_s390_set_cpuflags(vcpu, CPUSTAT_RUNNING); if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu)) __start_cpu_timer_accounting(vcpu); @@ -3723,8 +3731,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu)) __stop_cpu_timer_accounting(vcpu); kvm_s390_clear_cpuflags(vcpu, CPUSTAT_RUNNING); - vcpu->arch.enabled_gmap = gmap_get_enabled(); - gmap_disable(vcpu->arch.enabled_gmap); } @@ -3742,8 +3748,6 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) } if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0) vcpu->arch.sie_block->ictl |= ICTL_OPEREXC; - /* make vcpu_load load the right gmap on the first trigger */ - vcpu->arch.enabled_gmap = vcpu->arch.gmap; } static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr) @@ -4570,22 +4574,6 @@ int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clo return 1; } -/** - * kvm_arch_fault_in_page - fault-in guest page if necessary - * @vcpu: The corresponding virtual cpu - * @gpa: Guest physical address - * @writable: Whether the page should be writable or not - * - * Make sure that a guest page has been faulted-in on the host. - * - * Return: Zero on success, negative error code otherwise. - */ -long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable) -{ - return gmap_fault(vcpu->arch.gmap, gpa, - writable ? FAULT_FLAG_WRITE : 0); -} - static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token, unsigned long token) { @@ -4653,12 +4641,11 @@ static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu) if (!vcpu->arch.gmap->pfault_enabled) return false; - hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr)); - hva += current->thread.gmap_addr & ~PAGE_MASK; + hva = gfn_to_hva(vcpu->kvm, current->thread.gmap_teid.addr); if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8)) return false; - return kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch); + return kvm_setup_async_pf(vcpu, current->thread.gmap_teid.addr * PAGE_SIZE, hva, &arch); } static int vcpu_pre_run(struct kvm_vcpu *vcpu) @@ -4696,6 +4683,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu) clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask); vcpu->arch.sie_block->icptcode = 0; + current->thread.gmap_int_code = 0; cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags); VCPU_EVENT(vcpu, 6, "entering sie flags %x", cpuflags); trace_kvm_s390_sie_enter(vcpu, cpuflags); @@ -4703,7 +4691,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu) return 0; } -static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu) +static int vcpu_post_run_addressing_exception(struct kvm_vcpu *vcpu) { struct kvm_s390_pgm_info pgm_info = { .code = PGM_ADDRESSING, @@ -4739,10 +4727,106 @@ static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu) return kvm_s390_inject_prog_irq(vcpu, &pgm_info); } +static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) +{ + unsigned int flags = 0; + unsigned long gaddr; + int rc = 0; + + gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; + if (kvm_s390_cur_gmap_fault_is_write()) + flags = FAULT_FLAG_WRITE; + + switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) { + case 0: + vcpu->stat.exit_null++; + break; + case PGM_NON_SECURE_STORAGE_ACCESS: + KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, + "Unexpected program interrupt 0x%x, TEID 0x%016lx", + current->thread.gmap_int_code, current->thread.gmap_teid.val); + /* + * This is normal operation; a page belonging to a protected + * guest has not been imported yet. Try to import the page into + * the protected guest. + */ + if (gmap_convert_to_secure(vcpu->arch.gmap, gaddr) == -EINVAL) + send_sig(SIGSEGV, current, 0); + break; + case PGM_SECURE_STORAGE_ACCESS: + case PGM_SECURE_STORAGE_VIOLATION: + KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, + "Unexpected program interrupt 0x%x, TEID 0x%016lx", + current->thread.gmap_int_code, current->thread.gmap_teid.val); + /* + * This can happen after a reboot with asynchronous teardown; + * the new guest (normal or protected) will run on top of the + * previous protected guest. The old pages need to be destroyed + * so the new guest can use them. + */ + if (gmap_destroy_page(vcpu->arch.gmap, gaddr)) { + /* + * Either KVM messed up the secure guest mapping or the + * same page is mapped into multiple secure guests. + * + * This exception is only triggered when a guest 2 is + * running and can therefore never occur in kernel + * context. + */ + pr_warn_ratelimited("Secure storage violation (%x) in task: %s, pid %d\n", + current->thread.gmap_int_code, current->comm, + current->pid); + send_sig(SIGSEGV, current, 0); + } + break; + case PGM_PROTECTION: + case PGM_SEGMENT_TRANSLATION: + case PGM_PAGE_TRANSLATION: + case PGM_ASCE_TYPE: + case PGM_REGION_FIRST_TRANS: + case PGM_REGION_SECOND_TRANS: + case PGM_REGION_THIRD_TRANS: + KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, + "Unexpected program interrupt 0x%x, TEID 0x%016lx", + current->thread.gmap_int_code, current->thread.gmap_teid.val); + if (vcpu->arch.gmap->pfault_enabled) { + rc = gmap_fault(vcpu->arch.gmap, gaddr, flags | FAULT_FLAG_RETRY_NOWAIT); + if (rc == -EFAULT) + return vcpu_post_run_addressing_exception(vcpu); + if (rc == -EAGAIN) { + trace_kvm_s390_major_guest_pfault(vcpu); + if (kvm_arch_setup_async_pf(vcpu)) + return 0; + vcpu->stat.pfault_sync++; + } else { + return rc; + } + } + rc = gmap_fault(vcpu->arch.gmap, gaddr, flags); + if (rc == -EFAULT) { + if (kvm_is_ucontrol(vcpu->kvm)) { + vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; + vcpu->run->s390_ucontrol.trans_exc_code = gaddr; + vcpu->run->s390_ucontrol.pgm_code = 0x10; + return -EREMOTE; + } + return vcpu_post_run_addressing_exception(vcpu); + } + break; + default: + KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", + current->thread.gmap_int_code, current->thread.gmap_teid.val); + send_sig(SIGSEGV, current, 0); + break; + } + return rc; +} + static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) { struct mcck_volatile_info *mcck_info; struct sie_page *sie_page; + int rc; VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", vcpu->arch.sie_block->icptcode); @@ -4764,7 +4848,7 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) } if (vcpu->arch.sie_block->icptcode > 0) { - int rc = kvm_handle_sie_intercept(vcpu); + rc = kvm_handle_sie_intercept(vcpu); if (rc != -EOPNOTSUPP) return rc; @@ -4773,24 +4857,9 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) vcpu->run->s390_sieic.ipa = vcpu->arch.sie_block->ipa; vcpu->run->s390_sieic.ipb = vcpu->arch.sie_block->ipb; return -EREMOTE; - } else if (exit_reason != -EFAULT) { - vcpu->stat.exit_null++; - return 0; - } else if (kvm_is_ucontrol(vcpu->kvm)) { - vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; - vcpu->run->s390_ucontrol.trans_exc_code = - current->thread.gmap_addr; - vcpu->run->s390_ucontrol.pgm_code = 0x10; - return -EREMOTE; - } else if (current->thread.gmap_pfault) { - trace_kvm_s390_major_guest_pfault(vcpu); - current->thread.gmap_pfault = 0; - if (kvm_arch_setup_async_pf(vcpu)) - return 0; - vcpu->stat.pfault_sync++; - return kvm_arch_fault_in_page(vcpu, current->thread.gmap_addr, 1); } - return vcpu_post_run_fault_in_sie(vcpu); + + return vcpu_post_run_handle_fault(vcpu); } #define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK) @@ -4826,7 +4895,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) } exit_reason = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs, - gmap_get_enabled()->asce); + vcpu->arch.gmap->asce); if (kvm_s390_pv_cpu_is_protected(vcpu)) { memcpy(vcpu->run->s.regs.gprs, sie_page->pv_grregs, diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index e680c6bf0c9d..597d7a71deeb 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -394,7 +394,6 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); /* implemented in kvm-s390.c */ int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod); -long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable); int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr); int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr); int kvm_s390_vcpu_start(struct kvm_vcpu *vcpu); @@ -529,6 +528,13 @@ static inline int kvm_s390_use_sca_entries(void) void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu, struct mcck_volatile_info *mcck_info); +static inline bool kvm_s390_cur_gmap_fault_is_write(void) +{ + if (current->thread.gmap_int_code == PGM_PROTECTION) + return true; + return test_facility(75) && (current->thread.gmap_teid.fsi == TEID_FSI_STORE); +} + /** * kvm_s390_vcpu_crypto_reset_all * diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c index ffa7739c7a28..a61518b549f0 100644 --- a/arch/s390/kvm/pci.c +++ b/arch/s390/kvm/pci.c @@ -103,7 +103,7 @@ static int zpci_reset_aipb(u8 nisc) /* * AEN registration can only happen once per system boot. If * an aipb already exists then AEN was already registered and - * we can re-use the aipb contents. This can only happen if + * we can reuse the aipb contents. This can only happen if * the KVM module was removed and re-inserted. However, we must * ensure that the same forwarding ISC is used as this is assigned * during KVM module load. diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 89cafea4c41f..d3cdde1b18e5 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -922,19 +922,19 @@ static int handle_fault(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { int rc; - if (current->thread.gmap_int_code == PGM_PROTECTION) + if ((current->thread.gmap_int_code & PGM_INT_CODE_MASK) == PGM_PROTECTION) /* we can directly forward all protection exceptions */ return inject_fault(vcpu, PGM_PROTECTION, - current->thread.gmap_addr, 1); + current->thread.gmap_teid.addr * PAGE_SIZE, 1); rc = kvm_s390_shadow_fault(vcpu, vsie_page->gmap, - current->thread.gmap_addr, NULL); + current->thread.gmap_teid.addr * PAGE_SIZE, NULL); if (rc > 0) { rc = inject_fault(vcpu, rc, - current->thread.gmap_addr, - current->thread.gmap_write_flag); + current->thread.gmap_teid.addr * PAGE_SIZE, + kvm_s390_cur_gmap_fault_is_write()); if (rc >= 0) - vsie_page->fault_addr = current->thread.gmap_addr; + vsie_page->fault_addr = current->thread.gmap_teid.addr * PAGE_SIZE; } return rc; } @@ -1148,9 +1148,10 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) * also kick the vSIE. */ vcpu->arch.sie_block->prog0c |= PROG_IN_SIE; + current->thread.gmap_int_code = 0; barrier(); if (!kvm_s390_vcpu_sie_inhibited(vcpu)) - rc = sie64a(scb_s, vcpu->run->s.regs.gprs, gmap_get_enabled()->asce); + rc = sie64a(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce); barrier(); vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; @@ -1172,7 +1173,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) if (rc > 0) rc = 0; /* we could still have an icpt */ - else if (rc == -EFAULT) + else if (current->thread.gmap_int_code) return handle_fault(vcpu, vsie_page); switch (scb_s->icptcode) { @@ -1295,10 +1296,8 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) if (!rc) rc = map_prefix(vcpu, vsie_page); if (!rc) { - gmap_enable(vsie_page->gmap); update_intervention_requests(vsie_page); rc = do_vsie_run(vcpu, vsie_page); - gmap_enable(vcpu->arch.gmap); } atomic_andnot(PROG_BLOCK_SIE, &scb_s->prog20); diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 9f86ad8fa8b4..09d735010ee1 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -127,8 +127,8 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) node_id = node->node_id; /* Enqueue the node for this CPU in the spinlock wait queue */ + old = READ_ONCE(lp->lock); while (1) { - old = READ_ONCE(lp->lock); if ((old & _Q_LOCK_CPU_MASK) == 0 && (old & _Q_LOCK_STEAL_MASK) != _Q_LOCK_STEAL_MASK) { /* @@ -139,7 +139,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) * waiter will get the lock. */ new = (old ? (old + _Q_LOCK_STEAL_ADD) : 0) | lockval; - if (__atomic_cmpxchg_bool(&lp->lock, old, new)) + if (arch_try_cmpxchg(&lp->lock, &old, new)) /* Got the lock */ goto out; /* lock passing in progress */ @@ -147,7 +147,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) } /* Make the node of this CPU the new tail. */ new = node_id | (old & _Q_LOCK_MASK); - if (__atomic_cmpxchg_bool(&lp->lock, old, new)) + if (arch_try_cmpxchg(&lp->lock, &old, new)) break; } /* Set the 'next' pointer of the tail node in the queue */ @@ -184,7 +184,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp) if (!owner) { tail_id = old & _Q_TAIL_MASK; new = ((tail_id != node_id) ? tail_id : 0) | lockval; - if (__atomic_cmpxchg_bool(&lp->lock, old, new)) + if (arch_try_cmpxchg(&lp->lock, &old, new)) /* Got the lock */ break; continue; @@ -258,7 +258,7 @@ int arch_spin_trylock_retry(arch_spinlock_t *lp) owner = READ_ONCE(lp->lock); /* Try to get the lock if it is free. */ if (!owner) { - if (__atomic_cmpxchg_bool(&lp->lock, 0, cpu)) + if (arch_try_cmpxchg(&lp->lock, &owner, cpu)) return 1; } } @@ -300,7 +300,7 @@ void arch_write_lock_wait(arch_rwlock_t *rw) while (1) { old = READ_ONCE(rw->cnts); if ((old & 0x1ffff) == 0 && - __atomic_cmpxchg_bool(&rw->cnts, old, old | 0x10000)) + arch_try_cmpxchg(&rw->cnts, &old, old | 0x10000)) /* Got the lock */ break; barrier(); diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index 7d8741818239..373fa1f01937 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/string.h> #include <linux/export.h> +#include <asm/asm.h> /* * Helper functions to find the end of a string @@ -238,12 +239,11 @@ static inline int clcle(const char *s1, unsigned long l1, asm volatile( "0: clcle %[r1],%[r3],0\n" " jo 0b\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=&d" (cc), [r1] "+&d" (r1.pair), [r3] "+&d" (r3.pair) + CC_IPM(cc) + : CC_OUT(cc, cc), [r1] "+d" (r1.pair), [r3] "+d" (r3.pair) : - : "cc", "memory"); - return cc; + : CC_CLOBBER_LIST("memory")); + return CC_TRANSFORM(cc); } /** diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c index 8b7f981e6f34..6e42100875e7 100644 --- a/arch/s390/lib/test_unwind.c +++ b/arch/s390/lib/test_unwind.c @@ -270,9 +270,9 @@ static void notrace __used test_unwind_ftrace_handler(unsigned long ip, struct ftrace_ops *fops, struct ftrace_regs *fregs) { - struct unwindme *u = (struct unwindme *)fregs->regs.gprs[2]; + struct unwindme *u = (struct unwindme *)arch_ftrace_regs(fregs)->regs.gprs[2]; - u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &fregs->regs : NULL, + u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &arch_ftrace_regs(fregs)->regs : NULL, (u->flags & UWM_SP) ? u->sp : 0); } diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 75d15bf41d97..d01724a715d0 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -95,11 +95,12 @@ static long cmm_alloc_pages(long nr, long *counter, (*counter)++; spin_unlock(&cmm_lock); nr--; + cond_resched(); } return nr; } -static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) +static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) { struct cmm_page_array *pa; unsigned long addr; @@ -123,6 +124,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) return nr; } +static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) +{ + long inc = 0; + + while (nr) { + inc = min(256L, nr); + nr -= inc; + inc = __cmm_free_pages(inc, counter, list); + if (inc) + break; + cond_resched(); + } + return nr + inc; +} + static int cmm_oom_notify(struct notifier_block *self, unsigned long dummy, void *parm) { diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index 0a67fcee4414..fa54f3bc0c8d 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -18,89 +18,12 @@ static unsigned long max_addr; struct addr_marker { int is_start; unsigned long start_address; + unsigned long size; const char *name; }; -enum address_markers_idx { - KVA_NR = 0, - LOWCORE_START_NR, - LOWCORE_END_NR, - AMODE31_START_NR, - AMODE31_END_NR, - KERNEL_START_NR, - KERNEL_END_NR, -#ifdef CONFIG_KFENCE - KFENCE_START_NR, - KFENCE_END_NR, -#endif - IDENTITY_START_NR, - IDENTITY_END_NR, - VMEMMAP_NR, - VMEMMAP_END_NR, - VMALLOC_NR, - VMALLOC_END_NR, -#ifdef CONFIG_KMSAN - KMSAN_VMALLOC_SHADOW_START_NR, - KMSAN_VMALLOC_SHADOW_END_NR, - KMSAN_VMALLOC_ORIGIN_START_NR, - KMSAN_VMALLOC_ORIGIN_END_NR, - KMSAN_MODULES_SHADOW_START_NR, - KMSAN_MODULES_SHADOW_END_NR, - KMSAN_MODULES_ORIGIN_START_NR, - KMSAN_MODULES_ORIGIN_END_NR, -#endif - MODULES_NR, - MODULES_END_NR, - ABS_LOWCORE_NR, - ABS_LOWCORE_END_NR, - MEMCPY_REAL_NR, - MEMCPY_REAL_END_NR, -#ifdef CONFIG_KASAN - KASAN_SHADOW_START_NR, - KASAN_SHADOW_END_NR, -#endif -}; - -static struct addr_marker address_markers[] = { - [KVA_NR] = {0, 0, "Kernel Virtual Address Space"}, - [LOWCORE_START_NR] = {1, 0, "Lowcore Start"}, - [LOWCORE_END_NR] = {0, 0, "Lowcore End"}, - [IDENTITY_START_NR] = {1, 0, "Identity Mapping Start"}, - [IDENTITY_END_NR] = {0, 0, "Identity Mapping End"}, - [AMODE31_START_NR] = {1, 0, "Amode31 Area Start"}, - [AMODE31_END_NR] = {0, 0, "Amode31 Area End"}, - [KERNEL_START_NR] = {1, (unsigned long)_stext, "Kernel Image Start"}, - [KERNEL_END_NR] = {0, (unsigned long)_end, "Kernel Image End"}, -#ifdef CONFIG_KFENCE - [KFENCE_START_NR] = {1, 0, "KFence Pool Start"}, - [KFENCE_END_NR] = {0, 0, "KFence Pool End"}, -#endif - [VMEMMAP_NR] = {1, 0, "vmemmap Area Start"}, - [VMEMMAP_END_NR] = {0, 0, "vmemmap Area End"}, - [VMALLOC_NR] = {1, 0, "vmalloc Area Start"}, - [VMALLOC_END_NR] = {0, 0, "vmalloc Area End"}, -#ifdef CONFIG_KMSAN - [KMSAN_VMALLOC_SHADOW_START_NR] = {1, 0, "Kmsan vmalloc Shadow Start"}, - [KMSAN_VMALLOC_SHADOW_END_NR] = {0, 0, "Kmsan vmalloc Shadow End"}, - [KMSAN_VMALLOC_ORIGIN_START_NR] = {1, 0, "Kmsan vmalloc Origins Start"}, - [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, 0, "Kmsan vmalloc Origins End"}, - [KMSAN_MODULES_SHADOW_START_NR] = {1, 0, "Kmsan Modules Shadow Start"}, - [KMSAN_MODULES_SHADOW_END_NR] = {0, 0, "Kmsan Modules Shadow End"}, - [KMSAN_MODULES_ORIGIN_START_NR] = {1, 0, "Kmsan Modules Origins Start"}, - [KMSAN_MODULES_ORIGIN_END_NR] = {0, 0, "Kmsan Modules Origins End"}, -#endif - [MODULES_NR] = {1, 0, "Modules Area Start"}, - [MODULES_END_NR] = {0, 0, "Modules Area End"}, - [ABS_LOWCORE_NR] = {1, 0, "Lowcore Area Start"}, - [ABS_LOWCORE_END_NR] = {0, 0, "Lowcore Area End"}, - [MEMCPY_REAL_NR] = {1, 0, "Real Memory Copy Area Start"}, - [MEMCPY_REAL_END_NR] = {0, 0, "Real Memory Copy Area End"}, -#ifdef CONFIG_KASAN - [KASAN_SHADOW_START_NR] = {1, KASAN_SHADOW_START, "Kasan Shadow Start"}, - [KASAN_SHADOW_END_NR] = {0, KASAN_SHADOW_END, "Kasan Shadow End"}, -#endif - {1, -1UL, NULL} -}; +static struct addr_marker *markers; +static unsigned int markers_cnt; struct pg_state { struct ptdump_state ptdump; @@ -173,7 +96,8 @@ static void note_page_update_state(struct pg_state *st, unsigned long addr, unsi while (addr >= st->marker[1].start_address) { st->marker++; - pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); + pt_dump_seq_printf(m, "---[ %s %s ]---\n", st->marker->name, + st->marker->is_start ? "Start" : "End"); } st->start_address = addr; st->current_prot = prot; @@ -202,7 +126,7 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, if (level == -1) addr = max_addr; if (st->level == -1) { - pt_dump_seq_printf(m, "---[ %s ]---\n", st->marker->name); + pt_dump_seq_puts(m, "---[ Kernel Virtual Address Space ]---\n"); note_page_update_state(st, addr, prot, level); } else if (prot != st->current_prot || level != st->level || addr >= st->marker[1].start_address) { @@ -276,7 +200,7 @@ static int ptdump_show(struct seq_file *m, void *v) .check_wx = false, .wx_pages = 0, .start_address = 0, - .marker = address_markers, + .marker = markers, }; get_online_mems(); @@ -299,10 +223,23 @@ static int ptdump_cmp(const void *a, const void *b) if (ama->start_address < amb->start_address) return -1; /* - * If the start addresses of two markers are identical consider the - * marker which defines the start of an area higher than the one which - * defines the end of an area. This keeps pairs of markers sorted. + * If the start addresses of two markers are identical sort markers in an + * order that considers areas contained within other areas correctly. */ + if (ama->is_start && amb->is_start) { + if (ama->size > amb->size) + return -1; + if (ama->size < amb->size) + return 1; + return 0; + } + if (!ama->is_start && !amb->is_start) { + if (ama->size > amb->size) + return 1; + if (ama->size < amb->size) + return -1; + return 0; + } if (ama->is_start) return 1; if (amb->is_start) @@ -310,12 +247,41 @@ static int ptdump_cmp(const void *a, const void *b) return 0; } +static int add_marker(unsigned long start, unsigned long end, const char *name) +{ + size_t oldsize, newsize; + + oldsize = markers_cnt * sizeof(*markers); + newsize = oldsize + 2 * sizeof(*markers); + if (!oldsize) + markers = kvmalloc(newsize, GFP_KERNEL); + else + markers = kvrealloc(markers, newsize, GFP_KERNEL); + if (!markers) + goto error; + markers[markers_cnt].is_start = 1; + markers[markers_cnt].start_address = start; + markers[markers_cnt].size = end - start; + markers[markers_cnt].name = name; + markers_cnt++; + markers[markers_cnt].is_start = 0; + markers[markers_cnt].start_address = end; + markers[markers_cnt].size = end - start; + markers[markers_cnt].name = name; + markers_cnt++; + return 0; +error: + markers_cnt = 0; + return -ENOMEM; +} + static int pt_dump_init(void) { #ifdef CONFIG_KFENCE unsigned long kfence_start = (unsigned long)__kfence_pool; #endif unsigned long lowcore = (unsigned long)get_lowcore(); + int rc; /* * Figure out the maximum virtual address being accessible with the @@ -324,41 +290,38 @@ static int pt_dump_init(void) */ max_addr = (get_lowcore()->kernel_asce.val & _REGION_ENTRY_TYPE_MASK) >> 2; max_addr = 1UL << (max_addr * 11 + 31); - address_markers[LOWCORE_START_NR].start_address = lowcore; - address_markers[LOWCORE_END_NR].start_address = lowcore + sizeof(struct lowcore); - address_markers[IDENTITY_START_NR].start_address = __identity_base; - address_markers[IDENTITY_END_NR].start_address = __identity_base + ident_map_size; - address_markers[AMODE31_START_NR].start_address = (unsigned long)__samode31; - address_markers[AMODE31_END_NR].start_address = (unsigned long)__eamode31; - address_markers[MODULES_NR].start_address = MODULES_VADDR; - address_markers[MODULES_END_NR].start_address = MODULES_END; - address_markers[ABS_LOWCORE_NR].start_address = __abs_lowcore; - address_markers[ABS_LOWCORE_END_NR].start_address = __abs_lowcore + ABS_LOWCORE_MAP_SIZE; - address_markers[MEMCPY_REAL_NR].start_address = __memcpy_real_area; - address_markers[MEMCPY_REAL_END_NR].start_address = __memcpy_real_area + MEMCPY_REAL_SIZE; - address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap; - address_markers[VMEMMAP_END_NR].start_address = (unsigned long)vmemmap + vmemmap_size; - address_markers[VMALLOC_NR].start_address = VMALLOC_START; - address_markers[VMALLOC_END_NR].start_address = VMALLOC_END; + /* start + end markers - must be added first */ + rc = add_marker(0, -1UL, NULL); + rc |= add_marker((unsigned long)_stext, (unsigned long)_end, "Kernel Image"); + rc |= add_marker(lowcore, lowcore + sizeof(struct lowcore), "Lowcore"); + rc |= add_marker(__identity_base, __identity_base + ident_map_size, "Identity Mapping"); + rc |= add_marker((unsigned long)__samode31, (unsigned long)__eamode31, "Amode31 Area"); + rc |= add_marker(MODULES_VADDR, MODULES_END, "Modules Area"); + rc |= add_marker(__abs_lowcore, __abs_lowcore + ABS_LOWCORE_MAP_SIZE, "Lowcore Area"); + rc |= add_marker(__memcpy_real_area, __memcpy_real_area + MEMCPY_REAL_SIZE, "Real Memory Copy Area"); + rc |= add_marker((unsigned long)vmemmap, (unsigned long)vmemmap + vmemmap_size, "vmemmap Area"); + rc |= add_marker(VMALLOC_START, VMALLOC_END, "vmalloc Area"); #ifdef CONFIG_KFENCE - address_markers[KFENCE_START_NR].start_address = kfence_start; - address_markers[KFENCE_END_NR].start_address = kfence_start + KFENCE_POOL_SIZE; + rc |= add_marker(kfence_start, kfence_start + KFENCE_POOL_SIZE, "KFence Pool"); #endif #ifdef CONFIG_KMSAN - address_markers[KMSAN_VMALLOC_SHADOW_START_NR].start_address = KMSAN_VMALLOC_SHADOW_START; - address_markers[KMSAN_VMALLOC_SHADOW_END_NR].start_address = KMSAN_VMALLOC_SHADOW_END; - address_markers[KMSAN_VMALLOC_ORIGIN_START_NR].start_address = KMSAN_VMALLOC_ORIGIN_START; - address_markers[KMSAN_VMALLOC_ORIGIN_END_NR].start_address = KMSAN_VMALLOC_ORIGIN_END; - address_markers[KMSAN_MODULES_SHADOW_START_NR].start_address = KMSAN_MODULES_SHADOW_START; - address_markers[KMSAN_MODULES_SHADOW_END_NR].start_address = KMSAN_MODULES_SHADOW_END; - address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START; - address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END; + rc |= add_marker(KMSAN_VMALLOC_SHADOW_START, KMSAN_VMALLOC_SHADOW_END, "Kmsan vmalloc Shadow"); + rc |= add_marker(KMSAN_VMALLOC_ORIGIN_START, KMSAN_VMALLOC_ORIGIN_END, "Kmsan vmalloc Origins"); + rc |= add_marker(KMSAN_MODULES_SHADOW_START, KMSAN_MODULES_SHADOW_END, "Kmsan Modules Shadow"); + rc |= add_marker(KMSAN_MODULES_ORIGIN_START, KMSAN_MODULES_ORIGIN_END, "Kmsan Modules Origins"); +#endif +#ifdef CONFIG_KASAN + rc |= add_marker(KASAN_SHADOW_START, KASAN_SHADOW_END, "Kasan Shadow"); #endif - sort(address_markers, ARRAY_SIZE(address_markers) - 1, - sizeof(address_markers[0]), ptdump_cmp, NULL); + if (rc) + goto error; + sort(&markers[1], markers_cnt - 1, sizeof(*markers), ptdump_cmp, NULL); #ifdef CONFIG_PTDUMP_DEBUGFS debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops); #endif /* CONFIG_PTDUMP_DEBUGFS */ return 0; +error: + kvfree(markers); + return -ENOMEM; } device_initcall(pt_dump_init); diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 282fefe107a2..4692136c0af1 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -28,6 +28,7 @@ #include <asm/extmem.h> #include <asm/cpcmd.h> #include <asm/setup.h> +#include <asm/asm.h> #define DCSS_PURGESEG 0x08 #define DCSS_LOADSHRX 0x20 @@ -134,20 +135,21 @@ dcss_diag(int *func, void *parameter, unsigned long *ret1, unsigned long *ret2) { unsigned long rx, ry; - int rc; + int cc; rx = virt_to_phys(parameter); ry = (unsigned long) *func; diag_stat_inc(DIAG_STAT_X064); asm volatile( - " diag %0,%1,0x64\n" - " ipm %2\n" - " srl %2,28\n" - : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); + " diag %[rx],%[ry],0x64\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [rx] "+d" (rx), [ry] "+d" (ry) + : + : CC_CLOBBER); *ret1 = rx; *ret2 = ry; - return rc; + return CC_TRANSFORM(cc); } static inline int diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 8e149ef5e89b..646326fa0fad 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -34,6 +34,7 @@ #include <linux/uaccess.h> #include <linux/hugetlb.h> #include <linux/kfence.h> +#include <linux/pagewalk.h> #include <asm/asm-extable.h> #include <asm/asm-offsets.h> #include <asm/ptrace.h> @@ -45,12 +46,6 @@ #include <asm/uv.h> #include "../kernel/entry.h" -enum fault_type { - KERNEL_FAULT, - USER_FAULT, - GMAP_FAULT, -}; - static DEFINE_STATIC_KEY_FALSE(have_store_indication); static int __init fault_init(void) @@ -64,28 +59,15 @@ early_initcall(fault_init); /* * Find out which address space caused the exception. */ -static enum fault_type get_fault_type(struct pt_regs *regs) +static bool is_kernel_fault(struct pt_regs *regs) { union teid teid = { .val = regs->int_parm_long }; - struct gmap *gmap; - if (likely(teid.as == PSW_BITS_AS_PRIMARY)) { - if (user_mode(regs)) - return USER_FAULT; - if (!IS_ENABLED(CONFIG_PGSTE)) - return KERNEL_FAULT; - gmap = (struct gmap *)get_lowcore()->gmap; - if (gmap && gmap->asce == regs->cr1) - return GMAP_FAULT; - return KERNEL_FAULT; - } + if (user_mode(regs)) + return false; if (teid.as == PSW_BITS_AS_SECONDARY) - return USER_FAULT; - /* Access register mode, not used in the kernel */ - if (teid.as == PSW_BITS_AS_ACCREG) - return USER_FAULT; - /* Home space -> access via kernel ASCE */ - return KERNEL_FAULT; + return false; + return true; } static unsigned long get_fault_address(struct pt_regs *regs) @@ -146,7 +128,7 @@ static void dump_pagetable(unsigned long asce, unsigned long address) goto out; table = __va(entry & _SEGMENT_ENTRY_ORIGIN); } - table += (address & _PAGE_INDEX) >> _PAGE_SHIFT; + table += (address & _PAGE_INDEX) >> PAGE_SHIFT; if (get_kernel_nofault(entry, table)) goto bad; pr_cont("P:%016lx ", entry); @@ -180,21 +162,12 @@ static void dump_fault_info(struct pt_regs *regs) break; } pr_cont("mode while using "); - switch (get_fault_type(regs)) { - case USER_FAULT: - asce = get_lowcore()->user_asce.val; - pr_cont("user "); - break; - case GMAP_FAULT: - asce = ((struct gmap *)get_lowcore()->gmap)->asce; - pr_cont("gmap "); - break; - case KERNEL_FAULT: + if (is_kernel_fault(regs)) { asce = get_lowcore()->kernel_asce.val; pr_cont("kernel "); - break; - default: - unreachable(); + } else { + asce = get_lowcore()->user_asce.val; + pr_cont("user "); } pr_cont("ASCE.\n"); dump_pagetable(asce, get_fault_address(regs)); @@ -229,7 +202,6 @@ static void do_sigsegv(struct pt_regs *regs, int si_code) static void handle_fault_error_nolock(struct pt_regs *regs, int si_code) { - enum fault_type fault_type; unsigned long address; bool is_write; @@ -240,17 +212,15 @@ static void handle_fault_error_nolock(struct pt_regs *regs, int si_code) } if (fixup_exception(regs)) return; - fault_type = get_fault_type(regs); - if (fault_type == KERNEL_FAULT) { + if (is_kernel_fault(regs)) { address = get_fault_address(regs); is_write = fault_is_write(regs); if (kfence_handle_page_fault(address, is_write, regs)) return; - } - if (fault_type == KERNEL_FAULT) pr_alert("Unable to handle kernel pointer dereference in virtual kernel address space\n"); - else + } else { pr_alert("Unable to handle kernel paging request in virtual user address space\n"); + } dump_fault_info(regs); die(regs, "Oops"); } @@ -284,9 +254,7 @@ static void do_exception(struct pt_regs *regs, int access) struct vm_area_struct *vma; unsigned long address; struct mm_struct *mm; - enum fault_type type; unsigned int flags; - struct gmap *gmap; vm_fault_t fault; bool is_write; @@ -300,16 +268,8 @@ static void do_exception(struct pt_regs *regs, int access) mm = current->mm; address = get_fault_address(regs); is_write = fault_is_write(regs); - type = get_fault_type(regs); - switch (type) { - case KERNEL_FAULT: + if (is_kernel_fault(regs) || faulthandler_disabled() || !mm) return handle_fault_error_nolock(regs, 0); - case USER_FAULT: - case GMAP_FAULT: - if (faulthandler_disabled() || !mm) - return handle_fault_error_nolock(regs, 0); - break; - } perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); flags = FAULT_FLAG_DEFAULT; if (user_mode(regs)) @@ -333,14 +293,11 @@ static void do_exception(struct pt_regs *regs, int access) vma_end_read(vma); if (!(fault & VM_FAULT_RETRY)) { count_vm_vma_lock_event(VMA_LOCK_SUCCESS); - if (unlikely(fault & VM_FAULT_ERROR)) - goto error; - return; + goto done; } count_vm_vma_lock_event(VMA_LOCK_RETRY); if (fault & VM_FAULT_MAJOR) flags |= FAULT_FLAG_TRIED; - /* Quick path to respond to signals */ if (fault_signal_pending(fault, regs)) { if (!user_mode(regs)) @@ -348,81 +305,29 @@ static void do_exception(struct pt_regs *regs, int access) return; } lock_mmap: - mmap_read_lock(mm); - gmap = NULL; - if (IS_ENABLED(CONFIG_PGSTE) && type == GMAP_FAULT) { - gmap = (struct gmap *)get_lowcore()->gmap; - current->thread.gmap_addr = address; - current->thread.gmap_write_flag = !!(flags & FAULT_FLAG_WRITE); - current->thread.gmap_int_code = regs->int_code & 0xffff; - address = __gmap_translate(gmap, address); - if (address == -EFAULT) - return handle_fault_error(regs, SEGV_MAPERR); - if (gmap->pfault_enabled) - flags |= FAULT_FLAG_RETRY_NOWAIT; - } retry: - vma = find_vma(mm, address); + vma = lock_mm_and_find_vma(mm, address, regs); if (!vma) - return handle_fault_error(regs, SEGV_MAPERR); - if (unlikely(vma->vm_start > address)) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - return handle_fault_error(regs, SEGV_MAPERR); - vma = expand_stack(mm, address); - if (!vma) - return handle_fault_error_nolock(regs, SEGV_MAPERR); - } + return handle_fault_error_nolock(regs, SEGV_MAPERR); if (unlikely(!(vma->vm_flags & access))) return handle_fault_error(regs, SEGV_ACCERR); fault = handle_mm_fault(vma, address, flags, regs); if (fault_signal_pending(fault, regs)) { - if (flags & FAULT_FLAG_RETRY_NOWAIT) - mmap_read_unlock(mm); if (!user_mode(regs)) handle_fault_error_nolock(regs, 0); return; } /* The fault is fully completed (including releasing mmap lock) */ - if (fault & VM_FAULT_COMPLETED) { - if (gmap) { - mmap_read_lock(mm); - goto gmap; - } + if (fault & VM_FAULT_COMPLETED) return; - } - if (unlikely(fault & VM_FAULT_ERROR)) { - mmap_read_unlock(mm); - goto error; - } if (fault & VM_FAULT_RETRY) { - if (IS_ENABLED(CONFIG_PGSTE) && gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) { - /* - * FAULT_FLAG_RETRY_NOWAIT has been set, - * mmap_lock has not been released - */ - current->thread.gmap_pfault = 1; - return handle_fault_error(regs, 0); - } - flags &= ~FAULT_FLAG_RETRY_NOWAIT; flags |= FAULT_FLAG_TRIED; - mmap_read_lock(mm); goto retry; } -gmap: - if (IS_ENABLED(CONFIG_PGSTE) && gmap) { - address = __gmap_link(gmap, current->thread.gmap_addr, - address); - if (address == -EFAULT) - return handle_fault_error(regs, SEGV_MAPERR); - if (address == -ENOMEM) { - fault = VM_FAULT_OOM; - mmap_read_unlock(mm); - goto error; - } - } mmap_read_unlock(mm); - return; -error: +done: + if (!(fault & VM_FAULT_ERROR)) + return; if (fault & VM_FAULT_OOM) { if (!user_mode(regs)) handle_fault_error_nolock(regs, 0); @@ -492,10 +397,9 @@ void do_secure_storage_access(struct pt_regs *regs) union teid teid = { .val = regs->int_parm_long }; unsigned long addr = get_fault_address(regs); struct vm_area_struct *vma; + struct folio_walk fw; struct mm_struct *mm; struct folio *folio; - struct page *page; - struct gmap *gmap; int rc; /* @@ -520,82 +424,35 @@ void do_secure_storage_access(struct pt_regs *regs) */ panic("Unexpected PGM 0x3d with TEID bit 61=0"); } - switch (get_fault_type(regs)) { - case GMAP_FAULT: - mm = current->mm; - gmap = (struct gmap *)get_lowcore()->gmap; - mmap_read_lock(mm); - addr = __gmap_translate(gmap, addr); - mmap_read_unlock(mm); - if (IS_ERR_VALUE(addr)) - return handle_fault_error_nolock(regs, SEGV_MAPERR); - fallthrough; - case USER_FAULT: + if (is_kernel_fault(regs)) { + folio = phys_to_folio(addr); + if (unlikely(!folio_try_get(folio))) + return; + rc = arch_make_folio_accessible(folio); + folio_put(folio); + if (rc) + BUG(); + } else { mm = current->mm; mmap_read_lock(mm); vma = find_vma(mm, addr); if (!vma) return handle_fault_error(regs, SEGV_MAPERR); - page = follow_page(vma, addr, FOLL_WRITE | FOLL_GET); - if (IS_ERR_OR_NULL(page)) { + folio = folio_walk_start(&fw, vma, addr, 0); + if (!folio) { mmap_read_unlock(mm); - break; + return; } - folio = page_folio(page); - if (arch_make_folio_accessible(folio)) - send_sig(SIGSEGV, current, 0); - folio_put(folio); - mmap_read_unlock(mm); - break; - case KERNEL_FAULT: - folio = phys_to_folio(addr); - if (unlikely(!folio_try_get(folio))) - break; + /* arch_make_folio_accessible() needs a raised refcount. */ + folio_get(folio); rc = arch_make_folio_accessible(folio); folio_put(folio); + folio_walk_end(&fw, vma); if (rc) - BUG(); - break; - default: - unreachable(); + send_sig(SIGSEGV, current, 0); + mmap_read_unlock(mm); } } NOKPROBE_SYMBOL(do_secure_storage_access); -void do_non_secure_storage_access(struct pt_regs *regs) -{ - struct gmap *gmap = (struct gmap *)get_lowcore()->gmap; - unsigned long gaddr = get_fault_address(regs); - - if (WARN_ON_ONCE(get_fault_type(regs) != GMAP_FAULT)) - return handle_fault_error_nolock(regs, SEGV_MAPERR); - if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL) - send_sig(SIGSEGV, current, 0); -} -NOKPROBE_SYMBOL(do_non_secure_storage_access); - -void do_secure_storage_violation(struct pt_regs *regs) -{ - struct gmap *gmap = (struct gmap *)get_lowcore()->gmap; - unsigned long gaddr = get_fault_address(regs); - - /* - * If the VM has been rebooted, its address space might still contain - * secure pages from the previous boot. - * Clear the page so it can be reused. - */ - if (!gmap_destroy_page(gmap, gaddr)) - return; - /* - * Either KVM messed up the secure guest mapping or the same - * page is mapped into multiple secure guests. - * - * This exception is only triggered when a guest 2 is running - * and can therefore never occur in kernel context. - */ - pr_warn_ratelimited("Secure storage violation in task: %s, pid %d\n", - current->comm, current->pid); - send_sig(SIGSEGV, current, 0); -} - #endif /* CONFIG_PGSTE */ diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index eb0b51a36be0..643e47bfaddc 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -281,37 +281,6 @@ void gmap_remove(struct gmap *gmap) } EXPORT_SYMBOL_GPL(gmap_remove); -/** - * gmap_enable - switch primary space to the guest address space - * @gmap: pointer to the guest address space structure - */ -void gmap_enable(struct gmap *gmap) -{ - get_lowcore()->gmap = (unsigned long)gmap; -} -EXPORT_SYMBOL_GPL(gmap_enable); - -/** - * gmap_disable - switch back to the standard primary address space - * @gmap: pointer to the guest address space structure - */ -void gmap_disable(struct gmap *gmap) -{ - get_lowcore()->gmap = 0UL; -} -EXPORT_SYMBOL_GPL(gmap_disable); - -/** - * gmap_get_enabled - get a pointer to the currently enabled gmap - * - * Returns a pointer to the currently enabled gmap. 0 if none is enabled. - */ -struct gmap *gmap_get_enabled(void) -{ - return (struct gmap *)get_lowcore()->gmap; -} -EXPORT_SYMBOL_GPL(gmap_get_enabled); - /* * gmap_alloc_table is assumed to be called with mmap_lock held */ @@ -637,44 +606,124 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) } /** - * gmap_fault - resolve a fault on a guest address + * fixup_user_fault_nowait - manually resolve a user page fault without waiting + * @mm: mm_struct of target mm + * @address: user address + * @fault_flags:flags to pass down to handle_mm_fault() + * @unlocked: did we unlock the mmap_lock while retrying + * + * This function behaves similarly to fixup_user_fault(), but it guarantees + * that the fault will be resolved without waiting. The function might drop + * and re-acquire the mm lock, in which case @unlocked will be set to true. + * + * The guarantee is that the fault is handled without waiting, but the + * function itself might sleep, due to the lock. + * + * Context: Needs to be called with mm->mmap_lock held in read mode, and will + * return with the lock held in read mode; @unlocked will indicate whether + * the lock has been dropped and re-acquired. This is the same behaviour as + * fixup_user_fault(). + * + * Return: 0 on success, -EAGAIN if the fault cannot be resolved without + * waiting, -EFAULT if the fault cannot be resolved, -ENOMEM if out of + * memory. + */ +static int fixup_user_fault_nowait(struct mm_struct *mm, unsigned long address, + unsigned int fault_flags, bool *unlocked) +{ + struct vm_area_struct *vma; + unsigned int test_flags; + vm_fault_t fault; + int rc; + + fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT; + test_flags = fault_flags & FAULT_FLAG_WRITE ? VM_WRITE : VM_READ; + + vma = find_vma(mm, address); + if (unlikely(!vma || address < vma->vm_start)) + return -EFAULT; + if (unlikely(!(vma->vm_flags & test_flags))) + return -EFAULT; + + fault = handle_mm_fault(vma, address, fault_flags, NULL); + /* the mm lock has been dropped, take it again */ + if (fault & VM_FAULT_COMPLETED) { + *unlocked = true; + mmap_read_lock(mm); + return 0; + } + /* the mm lock has not been dropped */ + if (fault & VM_FAULT_ERROR) { + rc = vm_fault_to_errno(fault, 0); + BUG_ON(!rc); + return rc; + } + /* the mm lock has not been dropped because of FAULT_FLAG_RETRY_NOWAIT */ + if (fault & VM_FAULT_RETRY) + return -EAGAIN; + /* nothing needed to be done and the mm lock has not been dropped */ + return 0; +} + +/** + * __gmap_fault - resolve a fault on a guest address * @gmap: pointer to guest mapping meta data structure * @gaddr: guest address * @fault_flags: flags to pass down to handle_mm_fault() * - * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT - * if the vm address is already mapped to a different guest segment. + * Context: Needs to be called with mm->mmap_lock held in read mode. Might + * drop and re-acquire the lock. Will always return with the lock held. */ -int gmap_fault(struct gmap *gmap, unsigned long gaddr, - unsigned int fault_flags) +static int __gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags) { unsigned long vmaddr; - int rc; bool unlocked; - - mmap_read_lock(gmap->mm); + int rc = 0; retry: unlocked = false; + vmaddr = __gmap_translate(gmap, gaddr); - if (IS_ERR_VALUE(vmaddr)) { - rc = vmaddr; - goto out_up; - } - if (fixup_user_fault(gmap->mm, vmaddr, fault_flags, - &unlocked)) { - rc = -EFAULT; - goto out_up; - } + if (IS_ERR_VALUE(vmaddr)) + return vmaddr; + + if (fault_flags & FAULT_FLAG_RETRY_NOWAIT) + rc = fixup_user_fault_nowait(gmap->mm, vmaddr, fault_flags, &unlocked); + else + rc = fixup_user_fault(gmap->mm, vmaddr, fault_flags, &unlocked); + if (rc) + return rc; /* * In the case that fixup_user_fault unlocked the mmap_lock during - * faultin redo __gmap_translate to not race with a map/unmap_segment. + * fault-in, redo __gmap_translate() to avoid racing with a + * map/unmap_segment. + * In particular, __gmap_translate(), fixup_user_fault{,_nowait}(), + * and __gmap_link() must all be called atomically in one go; if the + * lock had been dropped in between, a retry is needed. */ if (unlocked) goto retry; - rc = __gmap_link(gmap, gaddr, vmaddr); -out_up: + return __gmap_link(gmap, gaddr, vmaddr); +} + +/** + * gmap_fault - resolve a fault on a guest address + * @gmap: pointer to guest mapping meta data structure + * @gaddr: guest address + * @fault_flags: flags to pass down to handle_mm_fault() + * + * Returns 0 on success, -ENOMEM for out of memory conditions, -EFAULT if the + * vm address is already mapped to a different guest segment, and -EAGAIN if + * FAULT_FLAG_RETRY_NOWAIT was specified and the fault could not be processed + * immediately. + */ +int gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags) +{ + int rc; + + mmap_read_lock(gmap->mm); + rc = __gmap_fault(gmap, gaddr, fault_flags); mmap_read_unlock(gmap->mm); return rc; } @@ -851,7 +900,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap, if (*table & _REGION_ENTRY_INVALID) return NULL; table = __va(*table & _SEGMENT_ENTRY_ORIGIN); - table += (gaddr & _PAGE_INDEX) >> _PAGE_SHIFT; + table += (gaddr & _PAGE_INDEX) >> PAGE_SHIFT; } return table; } @@ -1317,7 +1366,7 @@ static void gmap_unshadow_page(struct gmap *sg, unsigned long raddr) table = gmap_table_walk(sg, raddr, 0); /* get page table pointer */ if (!table || *table & _PAGE_INVALID) return; - gmap_call_notifier(sg, raddr, raddr + _PAGE_SIZE - 1); + gmap_call_notifier(sg, raddr, raddr + PAGE_SIZE - 1); ptep_unshadow_pte(sg->mm, raddr, (pte_t *) table); } @@ -1335,7 +1384,7 @@ static void __gmap_unshadow_pgt(struct gmap *sg, unsigned long raddr, int i; BUG_ON(!gmap_is_shadow(sg)); - for (i = 0; i < _PAGE_ENTRIES; i++, raddr += _PAGE_SIZE) + for (i = 0; i < _PAGE_ENTRIES; i++, raddr += PAGE_SIZE) pgt[i] = _PAGE_INVALID; } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index e3d258f9e726..7a96623a9d2e 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -62,7 +62,7 @@ EXPORT_SYMBOL(zero_page_mask); static void __init setup_zero_pages(void) { - unsigned long total_pages = PHYS_PFN(memblock_phys_mem_size() - memblock_reserved_size()); + unsigned long total_pages = memblock_estimated_nr_free_pages(); unsigned int order; struct page *page; int i; @@ -97,7 +97,7 @@ void __init paging_init(void) vmem_map_init(); sparse_init(); - zone_dma_bits = 31; + zone_dma_limit = DMA_BIT_MASK(31); memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); max_zone_pfns[ZONE_DMA] = virt_to_pfn(MAX_DMA_ADDRESS); max_zone_pfns[ZONE_NORMAL] = max_low_pfn; diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 206756946589..96efa061ce01 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -82,7 +82,7 @@ static int get_align_mask(struct file *filp, unsigned long flags) unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; @@ -117,7 +117,7 @@ check_asce_limit: unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, vm_flags_t vm_flags) { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 5f805ad42d4c..4a0f422cfeb6 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -12,6 +12,7 @@ #include <asm/pgalloc.h> #include <asm/kfence.h> #include <asm/page.h> +#include <asm/asm.h> #include <asm/set_memory.h> static inline unsigned long sske_frame(unsigned long addr, unsigned char skey) @@ -406,6 +407,21 @@ int set_direct_map_default_noflush(struct page *page) return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF); } +bool kernel_page_present(struct page *page) +{ + unsigned long addr; + unsigned int cc; + + addr = (unsigned long)page_address(page); + asm volatile( + " lra %[addr],0(%[addr])\n" + CC_IPM(cc) + : CC_OUT(cc, cc), [addr] "+a" (addr) + : + : CC_CLOBBER); + return CC_TRANSFORM(cc) == 0; +} + #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE) static void ipte_range(pte_t *pte, unsigned long address, int nr) diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index f691e0fb66a2..58696a0c4e4a 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -278,7 +278,7 @@ static inline unsigned long base_##NAME##_addr_end(unsigned long addr, \ return (next - 1) < (end - 1) ? next : end; \ } -BASE_ADDR_END_FUNC(page, _PAGE_SIZE) +BASE_ADDR_END_FUNC(page, PAGE_SIZE) BASE_ADDR_END_FUNC(segment, _SEGMENT_SIZE) BASE_ADDR_END_FUNC(region3, _REGION3_SIZE) BASE_ADDR_END_FUNC(region2, _REGION2_SIZE) @@ -302,7 +302,7 @@ static int base_page_walk(unsigned long *origin, unsigned long addr, if (!alloc) return 0; pte = origin; - pte += (addr & _PAGE_INDEX) >> _PAGE_SHIFT; + pte += (addr & _PAGE_INDEX) >> PAGE_SHIFT; do { next = base_page_addr_end(addr, end); *pte = base_lra(addr); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 2c944bafb030..cea5dba80468 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -525,7 +525,7 @@ static inline void pudp_idte_global(struct mm_struct *mm, else /* * Invalid bit position is the same for pmd and pud, so we can - * re-use _pmd_csp() here + * reuse _pmd_csp() here */ __pmdp_csp((pmd_t *) pudp); } diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile index 0547a10406e7..2c21f0394c9a 100644 --- a/arch/s390/pci/Makefile +++ b/arch/s390/pci/Makefile @@ -3,7 +3,8 @@ # Makefile for the s390 PCI subsystem. # -obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o pci_sysfs.o \ +obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o \ pci_event.o pci_debug.o pci_insn.o pci_mmio.o \ pci_bus.o pci_kvm_hook.o obj-$(CONFIG_PCI_IOV) += pci_iov.o +obj-$(CONFIG_SYSFS) += pci_sysfs.o diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index cff4838fad21..b7efa96776ea 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -29,6 +29,7 @@ #include <linux/pci.h> #include <linux/printk.h> #include <linux/lockdep.h> +#include <linux/list_sort.h> #include <asm/isc.h> #include <asm/airq.h> @@ -587,7 +588,6 @@ int pcibios_device_add(struct pci_dev *pdev) if (pdev->is_physfn) pdev->no_vf_scan = 1; - pdev->dev.groups = zpci_attr_groups; zpci_map_resources(pdev); for (i = 0; i < PCI_STD_NUM_BARS; i++) { @@ -786,7 +786,6 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) struct zpci_dev *zdev; int rc; - zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", fid, fh, state); zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); if (!zdev) return ERR_PTR(-ENOMEM); @@ -806,6 +805,19 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) mutex_init(&zdev->fmb_lock); mutex_init(&zdev->kzdev_lock); + return zdev; + +error: + zpci_dbg(0, "crt fid:%x, rc:%d\n", fid, rc); + kfree(zdev); + return ERR_PTR(rc); +} + +int zpci_add_device(struct zpci_dev *zdev) +{ + int rc; + + zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state); rc = zpci_init_iommu(zdev); if (rc) goto error; @@ -817,15 +829,13 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) spin_lock(&zpci_list_lock); list_add_tail(&zdev->entry, &zpci_list); spin_unlock(&zpci_list_lock); - - return zdev; + return 0; error_destroy_iommu: zpci_destroy_iommu(zdev); error: - zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc); - kfree(zdev); - return ERR_PTR(rc); + zpci_dbg(0, "add fid:%x, rc:%d\n", zdev->fid, rc); + return rc; } bool zpci_is_device_configured(struct zpci_dev *zdev) @@ -1083,6 +1093,49 @@ bool zpci_is_enabled(void) return s390_pci_initialized; } +static int zpci_cmp_rid(void *priv, const struct list_head *a, + const struct list_head *b) +{ + struct zpci_dev *za = container_of(a, struct zpci_dev, entry); + struct zpci_dev *zb = container_of(b, struct zpci_dev, entry); + + /* + * PCI functions without RID available maintain original order + * between themselves but sort before those with RID. + */ + if (za->rid == zb->rid) + return za->rid_available > zb->rid_available; + /* + * PCI functions with RID sort by RID ascending. + */ + return za->rid > zb->rid; +} + +static void zpci_add_devices(struct list_head *scan_list) +{ + struct zpci_dev *zdev, *tmp; + + list_sort(NULL, scan_list, &zpci_cmp_rid); + list_for_each_entry_safe(zdev, tmp, scan_list, entry) { + list_del_init(&zdev->entry); + zpci_add_device(zdev); + } +} + +int zpci_scan_devices(void) +{ + LIST_HEAD(scan_list); + int rc; + + rc = clp_scan_pci_devices(&scan_list); + if (rc) + return rc; + + zpci_add_devices(&scan_list); + zpci_bus_scan_busses(); + return 0; +} + static int __init pci_base_init(void) { int rc; @@ -1112,10 +1165,9 @@ static int __init pci_base_init(void) if (rc) goto out_irq; - rc = clp_scan_pci_devices(); + rc = zpci_scan_devices(); if (rc) goto out_find; - zpci_bus_scan_busses(); s390_pci_initialized = 1; return 0; diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index daa5d7450c7d..1b74a000ff64 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -168,9 +168,16 @@ void zpci_bus_scan_busses(void) mutex_unlock(&zbus_list_lock); } +static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev) +{ + return !s390_pci_no_rid && zdev->rid_available && + zpci_is_device_configured(zdev) && + !zdev->vfn; +} + /* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus * @zbus: the zbus holding the zdevices - * @fr: PCI root function that will determine the bus's domain, and bus speeed + * @fr: PCI root function that will determine the bus's domain, and bus speed * @ops: the pci operations * * The PCI function @fr determines the domain (its UID), multifunction property @@ -188,7 +195,7 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, s return domain; zbus->domain_nr = domain; - zbus->multifunction = fr->rid_available; + zbus->multifunction = zpci_bus_is_multifunction_root(fr); zbus->max_bus_speed = fr->max_bus_speed; /* @@ -232,13 +239,15 @@ static void zpci_bus_put(struct zpci_bus *zbus) kref_put(&zbus->kref, zpci_bus_release); } -static struct zpci_bus *zpci_bus_get(int pchid) +static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) { struct zpci_bus *zbus; mutex_lock(&zbus_list_lock); list_for_each_entry(zbus, &zbus_list, bus_next) { - if (pchid == zbus->pchid) { + if (!zbus->multifunction) + continue; + if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { kref_get(&zbus->kref); goto out_unlock; } @@ -249,7 +258,7 @@ out_unlock: return zbus; } -static struct zpci_bus *zpci_bus_alloc(int pchid) +static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) { struct zpci_bus *zbus; @@ -257,7 +266,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) if (!zbus) return NULL; - zbus->pchid = pchid; + zbus->topo = topo; + zbus->topo_is_tid = topo_is_tid; INIT_LIST_HEAD(&zbus->bus_next); mutex_lock(&zbus_list_lock); list_add_tail(&zbus->bus_next, &zbus_list); @@ -292,19 +302,22 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev) { int rc = -EINVAL; + if (zbus->multifunction) { + if (!zdev->rid_available) { + WARN_ONCE(1, "rid_available not set for multifunction\n"); + return rc; + } + zdev->devfn = zdev->rid & ZPCI_RID_MASK_DEVFN; + } + if (zbus->function[zdev->devfn]) { pr_err("devfn %04x is already assigned\n", zdev->devfn); return rc; } - zdev->zbus = zbus; zbus->function[zdev->devfn] = zdev; zpci_nb_devices++; - if (zbus->multifunction && !zdev->rid_available) { - WARN_ONCE(1, "rid_available not set for multifunction\n"); - goto error; - } rc = zpci_init_slot(zdev); if (rc) goto error; @@ -321,8 +334,9 @@ error: int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) { + bool topo_is_tid = zdev->tid_avail; struct zpci_bus *zbus = NULL; - int rc = -EBADF; + int topo, rc = -EBADF; if (zpci_nb_devices == ZPCI_NR_DEVICES) { pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", @@ -330,14 +344,10 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) return -ENOSPC; } - if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) - return -EINVAL; - - if (!s390_pci_no_rid && zdev->rid_available) - zbus = zpci_bus_get(zdev->pchid); - + topo = topo_is_tid ? zdev->tid : zdev->pchid; + zbus = zpci_bus_get(topo, topo_is_tid); if (!zbus) { - zbus = zpci_bus_alloc(zdev->pchid); + zbus = zpci_bus_alloc(topo, topo_is_tid); if (!zbus) return -ENOMEM; } diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h index af9f0ac79a1b..e86a9419d233 100644 --- a/arch/s390/pci/pci_bus.h +++ b/arch/s390/pci/pci_bus.h @@ -6,6 +6,10 @@ * Pierre Morel <pmorel@linux.ibm.com> * */ +#ifndef __S390_PCI_BUS_H +#define __S390_PCI_BUS_H + +#include <linux/pci.h> int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops); void zpci_bus_device_unregister(struct zpci_dev *zdev); @@ -40,3 +44,4 @@ static inline struct zpci_dev *zdev_from_bus(struct pci_bus *bus, return (devfn >= ZPCI_FUNCTIONS_PER_BUS) ? NULL : zbus->function[devfn]; } +#endif /* __S390_PCI_BUS_H */ diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index ee90a91ed888..14bf7e8d06b7 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -20,6 +20,7 @@ #include <asm/asm-extable.h> #include <asm/pci_debug.h> #include <asm/pci_clp.h> +#include <asm/asm.h> #include <asm/clp.h> #include <uapi/asm/clp.h> @@ -52,18 +53,20 @@ static inline void zpci_err_clp(unsigned int rsp, int rc) static inline int clp_get_ilp(unsigned long *ilp) { unsigned long mask; - int cc = 3; + int cc, exception; + exception = 1; asm volatile ( " .insn rrf,0xb9a00000,%[mask],%[cmd],8,0\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [mask] "=d" (mask) : [cmd] "a" (1) - : "cc"); + : CC_OUT(cc, cc), [mask] "=d" (mask), [exc] "+d" (exception) + : [cmd] "a" (1) + : CC_CLOBBER); *ilp = mask; - return cc; + return exception ? 3 : CC_TRANSFORM(cc); } /* @@ -72,19 +75,20 @@ static inline int clp_get_ilp(unsigned long *ilp) static __always_inline int clp_req(void *data, unsigned int lps) { struct { u8 _[CLP_BLK_SIZE]; } *req = data; + int cc, exception; u64 ignored; - int cc = 3; + exception = 1; asm volatile ( " .insn rrf,0xb9a00000,%[ign],%[req],0,%[lps]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [ign] "=d" (ignored), "+m" (*req) + : CC_OUT(cc, cc), [ign] "=d" (ignored), "+m" (*req), [exc] "+d" (exception) : [req] "a" (req), [lps] "i" (lps) - : "cc"); - return cc; + : CC_CLOBBER); + return exception ? 3 : CC_TRANSFORM(cc); } static void *clp_alloc_block(gfp_t gfp_mask) @@ -162,12 +166,16 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, zdev->pft = response->pft; zdev->vfn = response->vfn; zdev->port = response->port; + zdev->fidparm = response->fidparm; zdev->uid = response->uid; zdev->fmb_length = sizeof(u32) * response->fmb_len; - zdev->rid_available = response->rid_avail; zdev->is_physfn = response->is_physfn; - if (!s390_pci_no_rid && zdev->rid_available) - zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; + zdev->rid_available = response->rid_avail; + if (zdev->rid_available) + zdev->rid = response->rid; + zdev->tid_avail = response->tid_avail; + if (zdev->tid_avail) + zdev->tid = response->tid; memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); if (response->util_str_avail) { @@ -407,6 +415,7 @@ static int clp_find_pci(struct clp_req_rsp_list_pci *rrb, u32 fid, static void __clp_add(struct clp_fh_list_entry *entry, void *data) { + struct list_head *scan_list = data; struct zpci_dev *zdev; if (!entry->vendor_id) @@ -417,10 +426,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data) zpci_zdev_put(zdev); return; } - zpci_create_device(entry->fid, entry->fh, entry->config_state); + zdev = zpci_create_device(entry->fid, entry->fh, entry->config_state); + list_add_tail(&zdev->entry, scan_list); } -int clp_scan_pci_devices(void) +int clp_scan_pci_devices(struct list_head *scan_list) { struct clp_req_rsp_list_pci *rrb; int rc; @@ -429,7 +439,7 @@ int clp_scan_pci_devices(void) if (!rrb) return -ENOMEM; - rc = clp_list_pci(rrb, NULL, __clp_add); + rc = clp_list_pci(rrb, scan_list, __clp_add); clp_free_block(rrb); return rc; @@ -657,7 +667,6 @@ static const struct file_operations clp_misc_fops = { .release = clp_misc_release, .unlocked_ioctl = clp_misc_ioctl, .compat_ioctl = clp_misc_ioctl, - .llseek = no_llseek, }; static struct miscdevice clp_misc_device = { diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index dbe95ec5917e..47f934f4e828 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c @@ -280,18 +280,19 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) goto no_pdev; switch (ccdf->pec) { - case 0x003a: /* Service Action or Error Recovery Successful */ + case 0x002a: /* Error event concerns FMB */ + case 0x002b: + case 0x002c: + break; + case 0x0040: /* Service Action or Error Recovery Failed */ + case 0x003b: + zpci_event_io_failure(pdev, pci_channel_io_perm_failure); + break; + default: /* PCI function left in the error state attempt to recover */ ers_res = zpci_event_attempt_error_recovery(pdev); if (ers_res != PCI_ERS_RESULT_RECOVERED) zpci_event_io_failure(pdev, pci_channel_io_perm_failure); break; - default: - /* - * Mark as frozen not permanently failed because the device - * could be subsequently recovered by the platform. - */ - zpci_event_io_failure(pdev, pci_channel_io_frozen); - break; } pci_dev_put(pdev); no_pdev: @@ -339,6 +340,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); if (IS_ERR(zdev)) break; + zpci_add_device(zdev); } else { /* the configuration request may be stale */ if (zdev->state != ZPCI_FN_STATE_STANDBY) @@ -348,10 +350,14 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) zpci_scan_configured_device(zdev, ccdf->fh); break; case 0x0302: /* Reserved -> Standby */ - if (!zdev) - zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); - else + if (!zdev) { + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); + if (IS_ERR(zdev)) + break; + zpci_add_device(zdev); + } else { zpci_update_fh(zdev, ccdf->fh); + } break; case 0x0303: /* Deconfiguration requested */ if (zdev) { @@ -380,7 +386,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) break; case 0x0306: /* 0x308 or 0x302 for multiple devices */ zpci_remove_reserved_devices(); - clp_scan_pci_devices(); + zpci_scan_devices(); break; case 0x0308: /* Standby -> Reserved */ if (!zdev) diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c index 56480be48244..f5a75ea7629a 100644 --- a/arch/s390/pci/pci_insn.c +++ b/arch/s390/pci/pci_insn.c @@ -15,6 +15,7 @@ #include <asm/pci_debug.h> #include <asm/pci_io.h> #include <asm/processor.h> +#include <asm/asm.h> #define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */ @@ -57,16 +58,16 @@ static inline void zpci_err_insn_addr(int lvl, u8 insn, u8 cc, u8 status, /* Modify PCI Function Controls */ static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status) { - u8 cc; + int cc; asm volatile ( " .insn rxy,0xe300000000d0,%[req],%[fib]\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib) - : : "cc"); + CC_IPM(cc) + : CC_OUT(cc, cc), [req] "+d" (req), [fib] "+Q" (*fib) + : + : CC_CLOBBER); *status = req >> 24 & 0xff; - return cc; + return CC_TRANSFORM(cc); } u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status) @@ -98,17 +99,16 @@ EXPORT_SYMBOL_GPL(zpci_mod_fc); static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status) { union register_pair addr_range = {.even = addr, .odd = range}; - u8 cc; + int cc; asm volatile ( " .insn rre,0xb9d30000,%[fn],%[addr_range]\n" - " ipm %[cc]\n" - " srl %[cc],28\n" - : [cc] "=d" (cc), [fn] "+d" (fn) + CC_IPM(cc) + : CC_OUT(cc, cc), [fn] "+d" (fn) : [addr_range] "d" (addr_range.pair) - : "cc"); + : CC_CLOBBER); *status = fn >> 24 & 0xff; - return cc; + return CC_TRANSFORM(cc); } int zpci_refresh_trans(u64 fn, u64 addr, u64 range) @@ -156,20 +156,23 @@ EXPORT_SYMBOL_GPL(zpci_set_irq_ctrl); static inline int ____pcilg(u64 *data, u64 req, u64 offset, u8 *status) { union register_pair req_off = {.even = req, .odd = offset}; - int cc = -ENXIO; + int cc, exception; u64 __data; + exception = 1; asm volatile ( " .insn rre,0xb9d20000,%[data],%[req_off]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [data] "=d" (__data), - [req_off] "+&d" (req_off.pair) :: "cc"); + : CC_OUT(cc, cc), [data] "=d" (__data), + [req_off] "+d" (req_off.pair), [exc] "+d" (exception) + : + : CC_CLOBBER); *status = req_off.even >> 24 & 0xff; *data = __data; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status) @@ -222,20 +225,23 @@ static inline int zpci_load_fh(u64 *data, const volatile void __iomem *addr, static inline int __pcilg_mio(u64 *data, u64 ioaddr, u64 len, u8 *status) { union register_pair ioaddr_len = {.even = ioaddr, .odd = len}; - int cc = -ENXIO; + int cc, exception; u64 __data; + exception = 1; asm volatile ( " .insn rre,0xb9d60000,%[data],%[ioaddr_len]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [data] "=d" (__data), - [ioaddr_len] "+&d" (ioaddr_len.pair) :: "cc"); + : CC_OUT(cc, cc), [data] "=d" (__data), + [ioaddr_len] "+d" (ioaddr_len.pair), [exc] "+d" (exception) + : + : CC_CLOBBER); *status = ioaddr_len.odd >> 24 & 0xff; *data = __data; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } int zpci_load(u64 *data, const volatile void __iomem *addr, unsigned long len) @@ -258,19 +264,20 @@ EXPORT_SYMBOL_GPL(zpci_load); static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status) { union register_pair req_off = {.even = req, .odd = offset}; - int cc = -ENXIO; + int cc, exception; + exception = 1; asm volatile ( " .insn rre,0xb9d00000,%[data],%[req_off]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [req_off] "+&d" (req_off.pair) + : CC_OUT(cc, cc), [req_off] "+d" (req_off.pair), [exc] "+d" (exception) : [data] "d" (data) - : "cc"); + : CC_CLOBBER); *status = req_off.even >> 24 & 0xff; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } int __zpci_store(u64 data, u64 req, u64 offset) @@ -311,19 +318,20 @@ static inline int zpci_store_fh(const volatile void __iomem *addr, u64 data, static inline int __pcistg_mio(u64 data, u64 ioaddr, u64 len, u8 *status) { union register_pair ioaddr_len = {.even = ioaddr, .odd = len}; - int cc = -ENXIO; + int cc, exception; + exception = 1; asm volatile ( " .insn rre,0xb9d40000,%[data],%[ioaddr_len]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [ioaddr_len] "+&d" (ioaddr_len.pair) + : CC_OUT(cc, cc), [ioaddr_len] "+d" (ioaddr_len.pair), [exc] "+d" (exception) : [data] "d" (data) - : "cc", "memory"); + : CC_CLOBBER_LIST("memory")); *status = ioaddr_len.odd >> 24 & 0xff; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } int zpci_store(const volatile void __iomem *addr, u64 data, unsigned long len) @@ -345,19 +353,20 @@ EXPORT_SYMBOL_GPL(zpci_store); /* PCI Store Block */ static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status) { - int cc = -ENXIO; + int cc, exception; + exception = 1; asm volatile ( " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [req] "+d" (req) + : CC_OUT(cc, cc), [req] "+d" (req), [exc] "+d" (exception) : [offset] "d" (offset), [data] "Q" (*data) - : "cc"); + : CC_CLOBBER); *status = req >> 24 & 0xff; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } int __zpci_store_block(const u64 *data, u64 req, u64 offset) @@ -398,19 +407,20 @@ static inline int zpci_write_block_fh(volatile void __iomem *dst, static inline int __pcistb_mio(const u64 *data, u64 ioaddr, u64 len, u8 *status) { - int cc = -ENXIO; + int cc, exception; + exception = 1; asm volatile ( " .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[data]\n" - "0: ipm %[cc]\n" - " srl %[cc],28\n" + "0: lhi %[exc],0\n" "1:\n" + CC_IPM(cc) EX_TABLE(0b, 1b) - : [cc] "+d" (cc), [len] "+d" (len) + : CC_OUT(cc, cc), [len] "+d" (len), [exc] "+d" (exception) : [ioaddr] "d" (ioaddr), [data] "Q" (*data) - : "cc"); + : CC_CLOBBER); *status = len >> 24 & 0xff; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } int zpci_write_block(volatile void __iomem *dst, diff --git a/arch/s390/pci/pci_iov.h b/arch/s390/pci/pci_iov.h index b2c828003bad..e3fa4e77fc86 100644 --- a/arch/s390/pci/pci_iov.h +++ b/arch/s390/pci/pci_iov.h @@ -10,6 +10,8 @@ #ifndef __S390_PCI_IOV_H #define __S390_PCI_IOV_H +#include <linux/pci.h> + #ifdef CONFIG_PCI_IOV void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn); diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c index 5398729bfe1b..46f99dc164ad 100644 --- a/arch/s390/pci/pci_mmio.c +++ b/arch/s390/pci/pci_mmio.c @@ -14,6 +14,7 @@ #include <asm/asm-extable.h> #include <asm/pci_io.h> #include <asm/pci_debug.h> +#include <asm/asm.h> static inline void zpci_err_mmio(u8 cc, u8 status, u64 offset) { @@ -30,20 +31,21 @@ static inline int __pcistb_mio_inuser( void __iomem *ioaddr, const void __user *src, u64 len, u8 *status) { - int cc = -ENXIO; + int cc, exception; + exception = 1; asm volatile ( - " sacf 256\n" - "0: .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n" - "1: ipm %[cc]\n" - " srl %[cc],28\n" - "2: sacf 768\n" + " sacf 256\n" + "0: .insn rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n" + "1: lhi %[exc],0\n" + "2: sacf 768\n" + CC_IPM(cc) EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) - : [cc] "+d" (cc), [len] "+d" (len) + : CC_OUT(cc, cc), [len] "+d" (len), [exc] "+d" (exception) : [ioaddr] "a" (ioaddr), [src] "Q" (*((u8 __force *)src)) - : "cc", "memory"); + : CC_CLOBBER_LIST("memory")); *status = len >> 24 & 0xff; - return cc; + return exception ? -ENXIO : CC_TRANSFORM(cc); } static inline int __pcistg_mio_inuser( @@ -51,7 +53,7 @@ static inline int __pcistg_mio_inuser( u64 ulen, u8 *status) { union register_pair ioaddr_len = {.even = (u64 __force)ioaddr, .odd = ulen}; - int cc = -ENXIO; + int cc, exception; u64 val = 0; u64 cnt = ulen; u8 tmp; @@ -61,25 +63,27 @@ static inline int __pcistg_mio_inuser( * a register, then store it to PCI at @ioaddr while in secondary * address space. pcistg then uses the user mappings. */ + exception = 1; asm volatile ( - " sacf 256\n" - "0: llgc %[tmp],0(%[src])\n" + " sacf 256\n" + "0: llgc %[tmp],0(%[src])\n" "4: sllg %[val],%[val],8\n" - " aghi %[src],1\n" - " ogr %[val],%[tmp]\n" - " brctg %[cnt],0b\n" - "1: .insn rre,0xb9d40000,%[val],%[ioaddr_len]\n" - "2: ipm %[cc]\n" - " srl %[cc],28\n" - "3: sacf 768\n" + " aghi %[src],1\n" + " ogr %[val],%[tmp]\n" + " brctg %[cnt],0b\n" + "1: .insn rre,0xb9d40000,%[val],%[ioaddr_len]\n" + "2: lhi %[exc],0\n" + "3: sacf 768\n" + CC_IPM(cc) EX_TABLE(0b, 3b) EX_TABLE(4b, 3b) EX_TABLE(1b, 3b) EX_TABLE(2b, 3b) + : [src] "+a" (src), [cnt] "+d" (cnt), + [val] "+d" (val), [tmp] "=d" (tmp), [exc] "+d" (exception), + CC_OUT(cc, cc), [ioaddr_len] "+&d" (ioaddr_len.pair) : - [src] "+a" (src), [cnt] "+d" (cnt), - [val] "+d" (val), [tmp] "=d" (tmp), - [cc] "+d" (cc), [ioaddr_len] "+&d" (ioaddr_len.pair) - :: "cc", "memory"); + : CC_CLOBBER_LIST("memory")); *status = ioaddr_len.odd >> 24 & 0xff; + cc = exception ? -ENXIO : CC_TRANSFORM(cc); /* did we read everything from user memory? */ if (!cc && cnt != 0) cc = -EFAULT; @@ -118,12 +122,11 @@ static inline int __memcpy_toio_inuser(void __iomem *dst, SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, const void __user *, user_buffer, size_t, length) { + struct follow_pfnmap_args args = { }; u8 local_buf[64]; void __iomem *io_addr; void *buf; struct vm_area_struct *vma; - pte_t *ptep; - spinlock_t *ptl; long ret; if (!zpci_is_enabled()) @@ -169,11 +172,13 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, if (!(vma->vm_flags & VM_WRITE)) goto out_unlock_mmap; - ret = follow_pte(vma, mmio_addr, &ptep, &ptl); + args.address = mmio_addr; + args.vma = vma; + ret = follow_pfnmap_start(&args); if (ret) goto out_unlock_mmap; - io_addr = (void __iomem *)((pte_pfn(*ptep) << PAGE_SHIFT) | + io_addr = (void __iomem *)((args.pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) @@ -181,7 +186,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, ret = zpci_memcpy_toio(io_addr, buf, length); out_unlock_pt: - pte_unmap_unlock(ptep, ptl); + follow_pfnmap_end(&args); out_unlock_mmap: mmap_read_unlock(current->mm); out_free: @@ -197,7 +202,7 @@ static inline int __pcilg_mio_inuser( union register_pair ioaddr_len = {.even = (u64 __force)ioaddr, .odd = ulen}; u64 cnt = ulen; int shift = ulen * 8; - int cc = -ENXIO; + int cc, exception; u64 val, tmp; /* @@ -205,27 +210,33 @@ static inline int __pcilg_mio_inuser( * user space) into a register using pcilg then store these bytes at * user address @dst */ + exception = 1; asm volatile ( - " sacf 256\n" - "0: .insn rre,0xb9d60000,%[val],%[ioaddr_len]\n" - "1: ipm %[cc]\n" - " srl %[cc],28\n" - " ltr %[cc],%[cc]\n" - " jne 4f\n" - "2: ahi %[shift],-8\n" - " srlg %[tmp],%[val],0(%[shift])\n" - "3: stc %[tmp],0(%[dst])\n" + " sacf 256\n" + "0: .insn rre,0xb9d60000,%[val],%[ioaddr_len]\n" + "1: lhi %[exc],0\n" + " jne 4f\n" + "2: ahi %[shift],-8\n" + " srlg %[tmp],%[val],0(%[shift])\n" + "3: stc %[tmp],0(%[dst])\n" "5: aghi %[dst],1\n" - " brctg %[cnt],2b\n" - "4: sacf 768\n" + " brctg %[cnt],2b\n" + /* + * Use xr to clear exc and set condition code to zero + * to ensure flag output is correct for this branch. + */ + " xr %[exc],%[exc]\n" + "4: sacf 768\n" + CC_IPM(cc) EX_TABLE(0b, 4b) EX_TABLE(1b, 4b) EX_TABLE(3b, 4b) EX_TABLE(5b, 4b) + : [ioaddr_len] "+&d" (ioaddr_len.pair), [exc] "+d" (exception), + CC_OUT(cc, cc), [val] "=d" (val), + [dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp), + [shift] "+d" (shift) : - [ioaddr_len] "+&d" (ioaddr_len.pair), - [cc] "+d" (cc), [val] "=d" (val), - [dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp), - [shift] "+d" (shift) - :: "cc", "memory"); + : CC_CLOBBER_LIST("memory")); + cc = exception ? -ENXIO : CC_TRANSFORM(cc); /* did we write everything to the user space buffer? */ if (!cc && cnt != 0) cc = -EFAULT; @@ -260,12 +271,11 @@ static inline int __memcpy_fromio_inuser(void __user *dst, SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, void __user *, user_buffer, size_t, length) { + struct follow_pfnmap_args args = { }; u8 local_buf[64]; void __iomem *io_addr; void *buf; struct vm_area_struct *vma; - pte_t *ptep; - spinlock_t *ptl; long ret; if (!zpci_is_enabled()) @@ -308,11 +318,13 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, if (!(vma->vm_flags & VM_WRITE)) goto out_unlock_mmap; - ret = follow_pte(vma, mmio_addr, &ptep, &ptl); + args.vma = vma; + args.address = mmio_addr; + ret = follow_pfnmap_start(&args); if (ret) goto out_unlock_mmap; - io_addr = (void __iomem *)((pte_pfn(*ptep) << PAGE_SHIFT) | + io_addr = (void __iomem *)((args.pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) { @@ -322,7 +334,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, ret = zpci_memcpy_fromio(buf, io_addr, length); out_unlock_pt: - pte_unmap_unlock(ptep, ptl); + follow_pfnmap_end(&args); out_unlock_mmap: mmap_read_unlock(current->mm); diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c index 0f4f1e8fc480..5f46ad58dcd1 100644 --- a/arch/s390/pci/pci_sysfs.c +++ b/arch/s390/pci/pci_sysfs.c @@ -23,7 +23,7 @@ static ssize_t name##_show(struct device *dev, \ { \ struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); \ \ - return sprintf(buf, fmt, zdev->member); \ + return sysfs_emit(buf, fmt, zdev->member); \ } \ static DEVICE_ATTR_RO(name) @@ -34,6 +34,7 @@ zpci_attr(pfgid, "0x%02x\n", pfgid); zpci_attr(vfn, "0x%04x\n", vfn); zpci_attr(pft, "0x%02x\n", pft); zpci_attr(port, "%d\n", port); +zpci_attr(fidparm, "0x%02x\n", fidparm); zpci_attr(uid, "0x%x\n", uid); zpci_attr(segment0, "0x%02x\n", pfip[0]); zpci_attr(segment1, "0x%02x\n", pfip[1]); @@ -45,7 +46,7 @@ static ssize_t mio_enabled_show(struct device *dev, { struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); - return sprintf(buf, zpci_use_mio(zdev) ? "1\n" : "0\n"); + return sysfs_emit(buf, zpci_use_mio(zdev) ? "1\n" : "0\n"); } static DEVICE_ATTR_RO(mio_enabled); @@ -197,7 +198,7 @@ static struct attribute *zpci_ident_attrs[] = { NULL, }; -static struct attribute_group zpci_ident_attr_group = { +const struct attribute_group zpci_ident_attr_group = { .attrs = zpci_ident_attrs, .is_visible = zpci_index_is_visible, }; @@ -215,6 +216,7 @@ static struct attribute *zpci_dev_attrs[] = { &dev_attr_pfgid.attr, &dev_attr_pft.attr, &dev_attr_port.attr, + &dev_attr_fidparm.attr, &dev_attr_vfn.attr, &dev_attr_uid.attr, &dev_attr_recover.attr, @@ -223,7 +225,7 @@ static struct attribute *zpci_dev_attrs[] = { NULL, }; -static struct attribute_group zpci_attr_group = { +const struct attribute_group zpci_attr_group = { .attrs = zpci_dev_attrs, .bin_attrs = zpci_bin_attrs, }; @@ -235,14 +237,8 @@ static struct attribute *pfip_attrs[] = { &dev_attr_segment3.attr, NULL, }; -static struct attribute_group pfip_attr_group = { + +const struct attribute_group pfip_attr_group = { .name = "pfip", .attrs = pfip_attrs, }; - -const struct attribute_group *zpci_attr_groups[] = { - &zpci_attr_group, - &pfip_attr_group, - &zpci_ident_attr_group, - NULL, -}; diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S index 0f93f2e72eba..db3ab2402621 100644 --- a/arch/s390/purgatory/head.S +++ b/arch/s390/purgatory/head.S @@ -156,7 +156,7 @@ SYM_CODE_START(purgatory_start) agr %r10,%r9 /* Buffer location (in crash memory) and size. As the purgatory is - * behind the point of no return it can re-use the stack as buffer. + * behind the point of no return it can reuse the stack as buffer. */ larl %r11,purgatory_end larl %r12,stack diff --git a/arch/s390/tools/opcodes.txt b/arch/s390/tools/opcodes.txt index 5f008e794898..def2659f6602 100644 --- a/arch/s390/tools/opcodes.txt +++ b/arch/s390/tools/opcodes.txt @@ -527,9 +527,9 @@ b938 sortl RRE_RR b939 dfltcc RRF_R0RR2 b93a kdsa RRE_RR b93b nnpa RRE_00 -b93c ppno RRE_RR -b93e kimd RRE_RR -b93f klmd RRE_RR +b93c prno RRE_RR +b93e kimd RRF_U0RR +b93f klmd RRF_U0RR b941 cfdtr RRF_UURF b942 clgdtr RRF_UURF b943 clfdtr RRF_UURF @@ -549,6 +549,10 @@ b964 nngrk RRF_R0RR2 b965 ocgrk RRF_R0RR2 b966 nogrk RRF_R0RR2 b967 nxgrk RRF_R0RR2 +b968 clzg RRE_RR +b969 ctzg RRE_RR +b96c bextg RRF_R0RR2 +b96d bdepg RRF_R0RR2 b972 crt RRF_U0RR b973 clrt RRF_U0RR b974 nnrk RRF_R0RR2 @@ -796,6 +800,16 @@ e35b sy RXY_RRRD e35c mfy RXY_RRRD e35e aly RXY_RRRD e35f sly RXY_RRRD +e360 lxab RXY_RRRD +e361 llxab RXY_RRRD +e362 lxah RXY_RRRD +e363 llxah RXY_RRRD +e364 lxaf RXY_RRRD +e365 llxaf RXY_RRRD +e366 lxag RXY_RRRD +e367 llxag RXY_RRRD +e368 lxaq RXY_RRRD +e369 llxaq RXY_RRRD e370 sthy RXY_RRRD e371 lay RXY_RRRD e372 stcy RXY_RRRD @@ -880,6 +894,8 @@ e63c vupkz VSI_URDV e63d vstrl VSI_URDV e63f vstrlr VRS_RRDV e649 vlip VRI_V0UU2 +e64a vcvdq VRI_VV0UU +e64e vcvbq VRR_VV0U2 e650 vcvb VRR_RV0UU e651 vclzdp VRR_VV0U2 e652 vcvbg VRR_RV0UU @@ -893,7 +909,7 @@ e65b vpsop VRI_VVUUU2 e65c vupkzl VRR_VV0U2 e65d vcfn VRR_VV0UU2 e65e vclfnl VRR_VV0UU2 -e65f vtp VRR_0V +e65f vtp VRR_0V0U e670 vpkzr VRI_VVV0UU2 e671 vap VRI_VVV0UU2 e672 vsrpr VRI_VVV0UU2 @@ -908,6 +924,7 @@ e67b vrp VRI_VVV0UU2 e67c vscshp VRR_VVV e67d vcsph VRR_VVV0U0 e67e vsdp VRI_VVV0UU2 +e67f vtz VRR_0VVU e700 vleb VRX_VRRDU e701 vleh VRX_VRRDU e702 vleg VRX_VRRDU @@ -948,6 +965,7 @@ e74d vrep VRI_VVUU e750 vpopct VRR_VV0U e752 vctz VRR_VV0U e753 vclz VRR_VV0U +e754 vgem VRR_VV0U e756 vlr VRX_VV e75c vistr VRR_VV0U0U e75f vseg VRR_VV0U @@ -985,6 +1003,8 @@ e784 vpdi VRR_VVV0U e785 vbperm VRR_VVV e786 vsld VRI_VVV0U e787 vsrd VRI_VVV0U +e788 veval VRI_VVV0UV +e789 vblend VRR_VVVU0V e78a vstrc VRR_VVVUU0V e78b vstrs VRR_VVVUU0V e78c vperm VRR_VVV0V @@ -1010,6 +1030,10 @@ e7ac vmale VRR_VVVU0V e7ad vmalo VRR_VVVU0V e7ae vmae VRR_VVVU0V e7af vmao VRR_VVVU0V +e7b0 vdl VRR_VVV0UU +e7b1 vrl VRR_VVV0UU +e7b2 vd VRR_VVV0UU +e7b3 vr VRR_VVV0UU e7b4 vgfm VRR_VVV0U e7b8 vmsl VRR_VVVUU0V e7b9 vaccc VRR_VVVU0V @@ -1017,12 +1041,12 @@ e7bb vac VRR_VVVU0V e7bc vgfma VRR_VVVU0V e7bd vsbcbi VRR_VVVU0V e7bf vsbi VRR_VVVU0V -e7c0 vclgd VRR_VV0UUU -e7c1 vcdlg VRR_VV0UUU -e7c2 vcgd VRR_VV0UUU -e7c3 vcdg VRR_VV0UUU -e7c4 vlde VRR_VV0UU2 -e7c5 vled VRR_VV0UUU +e7c0 vclfp VRR_VV0UUU +e7c1 vcfpl VRR_VV0UUU +e7c2 vcsfp VRR_VV0UUU +e7c3 vcfps VRR_VV0UUU +e7c4 vfll VRR_VV0UU2 +e7c5 vflr VRR_VV0UUU e7c7 vfi VRR_VV0UUU e7ca wfk VRR_VV0UU2 e7cb wfc VRR_VV0UU2 @@ -1094,9 +1118,9 @@ eb54 niy SIY_URD eb55 cliy SIY_URD eb56 oiy SIY_URD eb57 xiy SIY_URD -eb60 lric RSY_RDRU -eb61 stric RSY_RDRU -eb62 mric RSY_RDRU +eb60 lric RSY_RURD2 +eb61 stric RSY_RURD2 +eb62 mric RSY_RURD2 eb6a asi SIY_IRD eb6e alsi SIY_IRD eb71 lpswey SIY_RD @@ -1104,7 +1128,7 @@ eb7a agsi SIY_IRD eb7e algsi SIY_IRD eb80 icmh RSY_RURD eb81 icmy RSY_RURD -eb8a sqbs RSY_RDRU +eb8a sqbs RSY_RURD2 eb8e mvclu RSY_RRRD eb8f clclu RSY_RRRD eb90 stmy RSY_RRRD diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 1aa3c4a0c5b2..04ff5fb9242e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -14,6 +14,7 @@ config SUPERH select ARCH_HIBERNATION_POSSIBLE if MMU select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_WANT_IPC_PARSE_VERSION + select ARCH_NEED_CMPXCHG_1_EMU select CPU_NO_EFFICIENT_FFS select DMA_DECLARE_COHERENT select GENERIC_ATOMIC64 @@ -549,6 +550,9 @@ config ARCH_SUPPORTS_KEXEC config ARCH_SUPPORTS_CRASH_DUMP def_bool BROKEN_ON_SMP +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config ARCH_SUPPORTS_KEXEC_JUMP def_bool y diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h index 5d617b3ef78f..1e5dc5ccf7bf 100644 --- a/arch/sh/include/asm/cmpxchg.h +++ b/arch/sh/include/asm/cmpxchg.h @@ -9,6 +9,7 @@ #include <linux/compiler.h> #include <linux/types.h> +#include <linux/cmpxchg-emu.h> #if defined(CONFIG_GUSA_RB) #include <asm/cmpxchg-grb.h> @@ -56,6 +57,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, unsigned long new, int size) { switch (size) { + case 1: + return cmpxchg_emu_u8(ptr, old, new); case 4: return __cmpxchg_u32(ptr, old, new); } diff --git a/arch/sh/include/asm/flat.h b/arch/sh/include/asm/flat.h index fee4f25555cb..70752c7bc55f 100644 --- a/arch/sh/include/asm/flat.h +++ b/arch/sh/include/asm/flat.h @@ -9,7 +9,7 @@ #ifndef __ASM_SH_FLAT_H #define __ASM_SH_FLAT_H -#include <asm/unaligned.h> +#include <linux/unaligned.h> static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags, u32 *addr) diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index 0f384b1f45ca..53fc18a3d4c2 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h @@ -14,12 +14,6 @@ #define NO_IRQ_IGNORE ((unsigned int)-1) /* - * Simple Mask Register Support - */ -extern void make_maskreg_irq(unsigned int irq); -extern unsigned short *irq_mask_register; - -/* * PINT IRQs */ void make_imask_irq(unsigned int irq); diff --git a/arch/sh/include/asm/mmzone.h b/arch/sh/include/asm/mmzone.h index 7b8dead2723d..63f88b465e39 100644 --- a/arch/sh/include/asm/mmzone.h +++ b/arch/sh/include/asm/mmzone.h @@ -5,9 +5,6 @@ #ifdef CONFIG_NUMA #include <linux/numa.h> -extern struct pglist_data *node_data[]; -#define NODE_DATA(nid) (node_data[nid]) - static inline int pfn_to_nid(unsigned long pfn) { int nid; diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index f780b467e75d..fc39b8171bfb 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -8,10 +8,8 @@ #include <linux/const.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> + #define PTE_MASK PAGE_MASK #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 45c8ae20d109..a1b54bedc929 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@ -24,7 +24,7 @@ #include <asm/dwarf.h> #include <asm/unwinder.h> #include <asm/sections.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/stacktrace.h> /* Reserve enough memory for two stack frames */ diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index b9cee98a754e..a469a80840d3 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -18,7 +18,7 @@ #include <linux/fs.h> #include <linux/string.h> #include <linux/kernel.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <asm/dwarf.h> int apply_relocate_add(Elf32_Shdr *sechdrs, diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 620e5cf8ae1e..f2b6f16a46b8 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -255,7 +255,7 @@ void __ref sh_fdt_init(phys_addr_t dt_phys) dt_virt = phys_to_virt(dt_phys); #endif - if (!dt_virt || !early_init_dt_scan(dt_virt)) { + if (!dt_virt || !early_init_dt_scan(dt_virt, __pa(dt_virt))) { pr_crit("Error: invalid device tree blob" " at physical address %p\n", (void *)dt_phys); diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index c55fd7696d40..c8cad33bf250 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -466,3 +466,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c index 1bd85a6949c4..add35c51e017 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.c +++ b/arch/sh/kernel/vsyscall/vsyscall.c @@ -36,6 +36,10 @@ __setup("vdso=", vdso_setup); */ extern const char vsyscall_trapa_start, vsyscall_trapa_end; static struct page *syscall_pages[1]; +static struct vm_special_mapping vdso_mapping = { + .name = "[vdso]", + .pages = syscall_pages, +}; int __init vsyscall_init(void) { @@ -58,6 +62,7 @@ int __init vsyscall_init(void) int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; unsigned long addr; int ret; @@ -70,14 +75,17 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) goto up_fail; } - ret = install_special_mapping(mm, addr, PAGE_SIZE, + vdso_mapping.pages = syscall_pages; + vma = _install_special_mapping(mm, addr, PAGE_SIZE, VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, - syscall_pages); - if (unlikely(ret)) + &vdso_mapping); + ret = PTR_ERR(vma); + if (IS_ERR(vma)) goto up_fail; current->mm->context.vdso = (void *)addr; + ret = 0; up_fail: mmap_write_unlock(mm); diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index d1fe90b2f5ff..2a88b0c9e70f 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -212,12 +212,7 @@ void __init allocate_pgdat(unsigned int nid) get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); #ifdef CONFIG_NUMA - NODE_DATA(nid) = memblock_alloc_try_nid( - sizeof(struct pglist_data), - SMP_CACHE_BYTES, MEMBLOCK_LOW_LIMIT, - MEMBLOCK_ALLOC_ACCESSIBLE, nid); - if (!NODE_DATA(nid)) - panic("Can't allocate pgdat for node %d\n", nid); + alloc_node_data(nid); #endif NODE_DATA(nid)->node_start_pfn = start_pfn; diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c index bee329d4149a..c442734d9b0c 100644 --- a/arch/sh/mm/mmap.c +++ b/arch/sh/mm/mmap.c @@ -52,7 +52,8 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr, } unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, unsigned long flags, + vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; @@ -99,7 +100,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, const unsigned long len, const unsigned long pgoff, - const unsigned long flags) + const unsigned long flags, vm_flags_t vm_flags) { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 50f0dc1744d0..9bc212b5e762 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -14,9 +14,6 @@ #include <linux/pfn.h> #include <asm/sections.h> -struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; -EXPORT_SYMBOL_GPL(node_data); - /* * On SH machines the conventional approach is to stash system RAM * in node 0, and other memory blocks in to node 1 and up, ordered by diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 11bf9d312318..dcfdb7f1dae9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -14,9 +14,9 @@ config SPARC bool default y select ARCH_HAS_CPU_CACHE_ALIASING + select ARCH_HAS_DMA_OPS select ARCH_MIGHT_HAVE_PC_PARPORT if SPARC64 && PCI select ARCH_MIGHT_HAVE_PC_SERIO - select DMA_OPS select OF select OF_PROMTREE select HAVE_ASM_MODVERSIONS diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c index 688db0dcb97d..913b9a09e885 100644 --- a/arch/sparc/crypto/crc32c_glue.c +++ b/arch/sparc/crypto/crc32c_glue.c @@ -20,7 +20,7 @@ #include <asm/pstate.h> #include <asm/elf.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "opcodes.h" diff --git a/arch/sparc/include/asm/mmzone.h b/arch/sparc/include/asm/mmzone.h index a236d8aa893a..74eb2c71d077 100644 --- a/arch/sparc/include/asm/mmzone.h +++ b/arch/sparc/include/asm/mmzone.h @@ -6,10 +6,6 @@ #include <linux/cpumask.h> -extern struct pglist_data *node_data[]; - -#define NODE_DATA(nid) (node_data[nid]) - extern int numa_cpu_lookup_table[]; extern cpumask_t numa_cpumask_lookup_table[]; diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h index 9977c77374cd..9954254ea569 100644 --- a/arch/sparc/include/asm/page_32.h +++ b/arch/sparc/include/asm/page_32.h @@ -11,9 +11,7 @@ #include <linux/const.h> -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #ifndef __ASSEMBLY__ diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index e9bd24821c93..2a68ff5b6eab 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h @@ -4,9 +4,7 @@ #include <linux/const.h> -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> /* Flushing for D-cache alias handling is only needed if * the page size is smaller than 16K. diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 3fe429d73a65..2b7f358762c1 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -783,6 +783,7 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd) return __pmd(pte_val(pte)); } +#define pmd_pgprot pmd_pgprot static inline pgprot_t pmd_pgprot(pmd_t entry) { unsigned long val = pmd_val(entry); diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 682da3714686..57084ed2f3c4 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -133,6 +133,12 @@ #define SO_PASSPIDFD 0x0055 #define SO_PEERPIDFD 0x0056 +#define SO_DEVMEM_LINEAR 0x0057 +#define SCM_DEVMEM_LINEAR SO_DEVMEM_LINEAR +#define SO_DEVMEM_DMABUF 0x0058 +#define SCM_DEVMEM_DMABUF SO_DEVMEM_DMABUF +#define SO_DEVMEM_DONTNEED 0x0059 + #if !defined(__KERNEL__) diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 08a19727795c..80822f922e76 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -39,7 +39,7 @@ SYSCALL_DEFINE0(getpagesize) return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */ } -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) { struct vm_unmapped_area_info info = {}; diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index d9c3b34ca744..acade309dc2f 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -87,7 +87,7 @@ static inline unsigned long COLOR_ALIGN(unsigned long addr, return base + off; } -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; struct vm_area_struct * vma; @@ -146,7 +146,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi unsigned long arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, const unsigned long len, const unsigned long pgoff, - const unsigned long flags) + const unsigned long flags, vm_flags_t vm_flags) { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index cfdfb3707c16..727f99d333b3 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -508,3 +508,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 53d7cb5bbffe..21f8cbbd0581 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1075,14 +1075,9 @@ static void __init allocate_node_data(int nid) { struct pglist_data *p; unsigned long start_pfn, end_pfn; -#ifdef CONFIG_NUMA - NODE_DATA(nid) = memblock_alloc_node(sizeof(struct pglist_data), - SMP_CACHE_BYTES, nid); - if (!NODE_DATA(nid)) { - prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid); - prom_halt(); - } +#ifdef CONFIG_NUMA + alloc_node_data(nid); NODE_DATA(nid)->node_id = nid; #endif @@ -1115,11 +1110,9 @@ static void init_node_masks_nonnuma(void) } #ifdef CONFIG_NUMA -struct pglist_data *node_data[MAX_NUMNODES]; EXPORT_SYMBOL(numa_cpu_lookup_table); EXPORT_SYMBOL(numa_cpumask_lookup_table); -EXPORT_SYMBOL(node_data); static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio, u32 cfg_handle) diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c index ec61ff1f96b7..1dc9b3d70eda 100644 --- a/arch/sparc/mm/leon_mm.c +++ b/arch/sparc/mm/leon_mm.c @@ -39,12 +39,10 @@ unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr) unsigned int ctxtbl; unsigned int pgd, pmd, ped; unsigned int ptr; - unsigned int lvl, pte, paddrbase; + unsigned int lvl, pte; unsigned int ctx; unsigned int paddr_calc; - paddrbase = 0; - if (srmmu_swprobe_trace) printk(KERN_INFO "swprobe: trace on\n"); @@ -73,7 +71,6 @@ unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr) printk(KERN_INFO "swprobe: pgd is entry level 3\n"); lvl = 3; pte = pgd; - paddrbase = pgd & _SRMMU_PTE_PMASK_LEON; goto ready; } if (((pgd & SRMMU_ET_MASK) != SRMMU_ET_PTD)) { @@ -96,7 +93,6 @@ unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr) printk(KERN_INFO "swprobe: pmd is entry level 2\n"); lvl = 2; pte = pmd; - paddrbase = pmd & _SRMMU_PTE_PMASK_LEON; goto ready; } if (((pmd & SRMMU_ET_MASK) != SRMMU_ET_PTD)) { @@ -124,7 +120,6 @@ unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr) printk(KERN_INFO "swprobe: ped is entry level 1\n"); lvl = 1; pte = ped; - paddrbase = ped & _SRMMU_PTE_PMASK_LEON; goto ready; } if (((ped & SRMMU_ET_MASK) != SRMMU_ET_PTD)) { @@ -147,7 +142,6 @@ unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr) printk(KERN_INFO "swprobe: ptr is entry level 0\n"); lvl = 0; pte = ptr; - paddrbase = ptr & _SRMMU_PTE_PMASK_LEON; goto ready; } if (srmmu_swprobe_trace) diff --git a/arch/um/Kconfig b/arch/um/Kconfig index dca84fd6d00a..c89575d05021 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -11,7 +11,6 @@ config UML select ARCH_HAS_KCOV select ARCH_HAS_STRNCPY_FROM_USER select ARCH_HAS_STRNLEN_USER - select ARCH_NO_PREEMPT_DYNAMIC select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_KASAN if X86_64 select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 99a7144b229f..819aabb4ecdc 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -164,7 +164,6 @@ static const struct file_operations harddog_fops = { .compat_ioctl = compat_ptr_ioctl, .open = harddog_open, .release = harddog_release, - .llseek = no_llseek, }; static struct miscdevice harddog_miscdev = { diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index c42b793bce65..9d228878cea2 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -291,7 +291,6 @@ static int hostmixer_release(struct inode *inode, struct file *file) static const struct file_operations hostaudio_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .read = hostaudio_read, .write = hostaudio_write, .poll = hostaudio_poll, @@ -304,7 +303,6 @@ static const struct file_operations hostaudio_fops = { static const struct file_operations hostmixer_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .unlocked_ioctl = hostmixer_ioctl_mixdev, .open = hostmixer_open_mixdev, .release = hostmixer_release, diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c index 2d473282ab51..c992da83268d 100644 --- a/arch/um/drivers/vector_kern.c +++ b/arch/um/drivers/vector_kern.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/firmware.h> #include <linux/fs.h> +#include <asm/atomic.h> #include <uapi/linux/filter.h> #include <init.h> #include <irq_kern.h> @@ -102,18 +103,33 @@ static const struct { static void vector_reset_stats(struct vector_private *vp) { + /* We reuse the existing queue locks for stats */ + + /* RX stats are modified with RX head_lock held + * in vector_poll. + */ + + spin_lock(&vp->rx_queue->head_lock); vp->estats.rx_queue_max = 0; vp->estats.rx_queue_running_average = 0; - vp->estats.tx_queue_max = 0; - vp->estats.tx_queue_running_average = 0; vp->estats.rx_encaps_errors = 0; + vp->estats.sg_ok = 0; + vp->estats.sg_linearized = 0; + spin_unlock(&vp->rx_queue->head_lock); + + /* TX stats are modified with TX head_lock held + * in vector_send. + */ + + spin_lock(&vp->tx_queue->head_lock); vp->estats.tx_timeout_count = 0; vp->estats.tx_restart_queue = 0; vp->estats.tx_kicks = 0; vp->estats.tx_flow_control_xon = 0; vp->estats.tx_flow_control_xoff = 0; - vp->estats.sg_ok = 0; - vp->estats.sg_linearized = 0; + vp->estats.tx_queue_max = 0; + vp->estats.tx_queue_running_average = 0; + spin_unlock(&vp->tx_queue->head_lock); } static int get_mtu(struct arglist *def) @@ -232,12 +248,6 @@ static int get_transport_options(struct arglist *def) static char *drop_buffer; -/* Array backed queues optimized for bulk enqueue/dequeue and - * 1:N (small values of N) or 1:1 enqueuer/dequeuer ratios. - * For more details and full design rationale see - * http://foswiki.cambridgegreys.com/Main/EatYourTailAndEnjoyIt - */ - /* * Advance the mmsg queue head by n = advance. Resets the queue to @@ -247,27 +257,13 @@ static char *drop_buffer; static int vector_advancehead(struct vector_queue *qi, int advance) { - int queue_depth; - qi->head = (qi->head + advance) % qi->max_depth; - spin_lock(&qi->tail_lock); - qi->queue_depth -= advance; - - /* we are at 0, use this to - * reset head and tail so we can use max size vectors - */ - - if (qi->queue_depth == 0) { - qi->head = 0; - qi->tail = 0; - } - queue_depth = qi->queue_depth; - spin_unlock(&qi->tail_lock); - return queue_depth; + atomic_sub(advance, &qi->queue_depth); + return atomic_read(&qi->queue_depth); } /* Advance the queue tail by n = advance. @@ -277,16 +273,11 @@ static int vector_advancehead(struct vector_queue *qi, int advance) static int vector_advancetail(struct vector_queue *qi, int advance) { - int queue_depth; - qi->tail = (qi->tail + advance) % qi->max_depth; - spin_lock(&qi->head_lock); - qi->queue_depth += advance; - queue_depth = qi->queue_depth; - spin_unlock(&qi->head_lock); - return queue_depth; + atomic_add(advance, &qi->queue_depth); + return atomic_read(&qi->queue_depth); } static int prep_msg(struct vector_private *vp, @@ -339,9 +330,7 @@ static int vector_enqueue(struct vector_queue *qi, struct sk_buff *skb) int iov_count; spin_lock(&qi->tail_lock); - spin_lock(&qi->head_lock); - queue_depth = qi->queue_depth; - spin_unlock(&qi->head_lock); + queue_depth = atomic_read(&qi->queue_depth); if (skb) packet_len = skb->len; @@ -360,6 +349,7 @@ static int vector_enqueue(struct vector_queue *qi, struct sk_buff *skb) mmsg_vector->msg_hdr.msg_iovlen = iov_count; mmsg_vector->msg_hdr.msg_name = vp->fds->remote_addr; mmsg_vector->msg_hdr.msg_namelen = vp->fds->remote_addr_size; + wmb(); /* Make the packet visible to the NAPI poll thread */ queue_depth = vector_advancetail(qi, 1); } else goto drop; @@ -398,7 +388,7 @@ static int consume_vector_skbs(struct vector_queue *qi, int count) } /* - * Generic vector deque via sendmmsg with support for forming headers + * Generic vector dequeue via sendmmsg with support for forming headers * using transport specific callback. Allows GRE, L2TPv3, RAW and * other transports to use a common dequeue procedure in vector mode */ @@ -408,69 +398,64 @@ static int vector_send(struct vector_queue *qi) { struct vector_private *vp = netdev_priv(qi->dev); struct mmsghdr *send_from; - int result = 0, send_len, queue_depth = qi->max_depth; + int result = 0, send_len; if (spin_trylock(&qi->head_lock)) { - if (spin_trylock(&qi->tail_lock)) { - /* update queue_depth to current value */ - queue_depth = qi->queue_depth; - spin_unlock(&qi->tail_lock); - while (queue_depth > 0) { - /* Calculate the start of the vector */ - send_len = queue_depth; - send_from = qi->mmsg_vector; - send_from += qi->head; - /* Adjust vector size if wraparound */ - if (send_len + qi->head > qi->max_depth) - send_len = qi->max_depth - qi->head; - /* Try to TX as many packets as possible */ - if (send_len > 0) { - result = uml_vector_sendmmsg( - vp->fds->tx_fd, - send_from, - send_len, - 0 - ); - vp->in_write_poll = - (result != send_len); - } - /* For some of the sendmmsg error scenarios - * we may end being unsure in the TX success - * for all packets. It is safer to declare - * them all TX-ed and blame the network. - */ - if (result < 0) { - if (net_ratelimit()) - netdev_err(vp->dev, "sendmmsg err=%i\n", - result); - vp->in_error = true; - result = send_len; - } - if (result > 0) { - queue_depth = - consume_vector_skbs(qi, result); - /* This is equivalent to an TX IRQ. - * Restart the upper layers to feed us - * more packets. - */ - if (result > vp->estats.tx_queue_max) - vp->estats.tx_queue_max = result; - vp->estats.tx_queue_running_average = - (vp->estats.tx_queue_running_average + result) >> 1; - } - netif_wake_queue(qi->dev); - /* if TX is busy, break out of the send loop, - * poll write IRQ will reschedule xmit for us + /* update queue_depth to current value */ + while (atomic_read(&qi->queue_depth) > 0) { + /* Calculate the start of the vector */ + send_len = atomic_read(&qi->queue_depth); + send_from = qi->mmsg_vector; + send_from += qi->head; + /* Adjust vector size if wraparound */ + if (send_len + qi->head > qi->max_depth) + send_len = qi->max_depth - qi->head; + /* Try to TX as many packets as possible */ + if (send_len > 0) { + result = uml_vector_sendmmsg( + vp->fds->tx_fd, + send_from, + send_len, + 0 + ); + vp->in_write_poll = + (result != send_len); + } + /* For some of the sendmmsg error scenarios + * we may end being unsure in the TX success + * for all packets. It is safer to declare + * them all TX-ed and blame the network. + */ + if (result < 0) { + if (net_ratelimit()) + netdev_err(vp->dev, "sendmmsg err=%i\n", + result); + vp->in_error = true; + result = send_len; + } + if (result > 0) { + consume_vector_skbs(qi, result); + /* This is equivalent to an TX IRQ. + * Restart the upper layers to feed us + * more packets. */ - if (result != send_len) { - vp->estats.tx_restart_queue++; - break; - } + if (result > vp->estats.tx_queue_max) + vp->estats.tx_queue_max = result; + vp->estats.tx_queue_running_average = + (vp->estats.tx_queue_running_average + result) >> 1; + } + netif_wake_queue(qi->dev); + /* if TX is busy, break out of the send loop, + * poll write IRQ will reschedule xmit for us. + */ + if (result != send_len) { + vp->estats.tx_restart_queue++; + break; } } spin_unlock(&qi->head_lock); } - return queue_depth; + return atomic_read(&qi->queue_depth); } /* Queue destructor. Deliberately stateless so we can use @@ -589,7 +574,7 @@ static struct vector_queue *create_queue( } spin_lock_init(&result->head_lock); spin_lock_init(&result->tail_lock); - result->queue_depth = 0; + atomic_set(&result->queue_depth, 0); result->head = 0; result->tail = 0; return result; @@ -668,18 +653,27 @@ done: } -/* Prepare queue for recvmmsg one-shot rx - fill with fresh sk_buffs*/ +/* Prepare queue for recvmmsg one-shot rx - fill with fresh sk_buffs */ static void prep_queue_for_rx(struct vector_queue *qi) { struct vector_private *vp = netdev_priv(qi->dev); struct mmsghdr *mmsg_vector = qi->mmsg_vector; void **skbuff_vector = qi->skbuff_vector; - int i; + int i, queue_depth; + + queue_depth = atomic_read(&qi->queue_depth); - if (qi->queue_depth == 0) + if (queue_depth == 0) return; - for (i = 0; i < qi->queue_depth; i++) { + + /* RX is always emptied 100% during each cycle, so we do not + * have to do the tail wraparound math for it. + */ + + qi->head = qi->tail = 0; + + for (i = 0; i < queue_depth; i++) { /* it is OK if allocation fails - recvmmsg with NULL data in * iov argument still performs an RX, just drops the packet * This allows us stop faffing around with a "drop buffer" @@ -689,7 +683,7 @@ static void prep_queue_for_rx(struct vector_queue *qi) skbuff_vector++; mmsg_vector++; } - qi->queue_depth = 0; + atomic_set(&qi->queue_depth, 0); } static struct vector_device *find_device(int n) @@ -972,7 +966,7 @@ static int vector_mmsg_rx(struct vector_private *vp, int budget) budget = qi->max_depth; packet_count = uml_vector_recvmmsg( - vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0); + vp->fds->rx_fd, qi->mmsg_vector, budget, 0); if (packet_count < 0) vp->in_error = true; @@ -985,7 +979,7 @@ static int vector_mmsg_rx(struct vector_private *vp, int budget) * many do we need to prep the next time prep_queue_for_rx() is called. */ - qi->queue_depth = packet_count; + atomic_add(packet_count, &qi->queue_depth); for (i = 0; i < packet_count; i++) { skb = (*skbuff_vector); @@ -1172,6 +1166,7 @@ static int vector_poll(struct napi_struct *napi, int budget) if ((vp->options & VECTOR_TX) != 0) tx_enqueued = (vector_send(vp->tx_queue) > 0); + spin_lock(&vp->rx_queue->head_lock); if ((vp->options & VECTOR_RX) > 0) err = vector_mmsg_rx(vp, budget); else { @@ -1179,12 +1174,13 @@ static int vector_poll(struct napi_struct *napi, int budget) if (err > 0) err = 1; } + spin_unlock(&vp->rx_queue->head_lock); if (err > 0) work_done += err; if (tx_enqueued || err > 0) napi_schedule(napi); - if (work_done < budget) + if (work_done <= budget) napi_complete_done(napi, work_done); return work_done; } @@ -1225,7 +1221,7 @@ static int vector_net_open(struct net_device *dev) vp->rx_header_size, MAX_IOV_SIZE ); - vp->rx_queue->queue_depth = get_depth(vp->parsed); + atomic_set(&vp->rx_queue->queue_depth, get_depth(vp->parsed)); } else { vp->header_rxbuffer = kmalloc( vp->rx_header_size, @@ -1467,7 +1463,17 @@ static void vector_get_ethtool_stats(struct net_device *dev, { struct vector_private *vp = netdev_priv(dev); + /* Stats are modified in the dequeue portions of + * rx/tx which are protected by the head locks + * grabbing these locks here ensures they are up + * to date. + */ + + spin_lock(&vp->tx_queue->head_lock); + spin_lock(&vp->rx_queue->head_lock); memcpy(tmp_stats, &vp->estats, sizeof(struct vector_estats)); + spin_unlock(&vp->rx_queue->head_lock); + spin_unlock(&vp->tx_queue->head_lock); } static int vector_get_coalesce(struct net_device *netdev, diff --git a/arch/um/drivers/vector_kern.h b/arch/um/drivers/vector_kern.h index 806df551be0b..417834793658 100644 --- a/arch/um/drivers/vector_kern.h +++ b/arch/um/drivers/vector_kern.h @@ -14,6 +14,7 @@ #include <linux/ctype.h> #include <linux/workqueue.h> #include <linux/interrupt.h> +#include <asm/atomic.h> #include "vector_user.h" @@ -44,7 +45,8 @@ struct vector_queue { struct net_device *dev; spinlock_t head_lock; spinlock_t tail_lock; - int queue_depth, head, tail, max_depth, max_iov_frags; + atomic_t queue_depth; + int head, tail, max_depth, max_iov_frags; short options; }; diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c index b16a5e5619d3..2ea67e6fd067 100644 --- a/arch/um/drivers/vector_user.c +++ b/arch/um/drivers/vector_user.c @@ -46,6 +46,9 @@ #define TRANS_FD "fd" #define TRANS_FD_LEN strlen(TRANS_FD) +#define TRANS_VDE "vde" +#define TRANS_VDE_LEN strlen(TRANS_VDE) + #define VNET_HDR_FAIL "could not enable vnet headers on fd %d" #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s" #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i" @@ -434,6 +437,84 @@ fd_cleanup: return NULL; } +/* enough char to store an int type */ +#define ENOUGH(type) ((CHAR_BIT * sizeof(type) - 1) / 3 + 2) +#define ENOUGH_OCTAL(type) ((CHAR_BIT * sizeof(type) + 2) / 3) +/* vde_plug --descr xx --port2 xx --mod2 xx --group2 xx seqpacket://NN vnl (NULL) */ +#define VDE_MAX_ARGC 12 +#define VDE_SEQPACKET_HEAD "seqpacket://" +#define VDE_SEQPACKET_HEAD_LEN (sizeof(VDE_SEQPACKET_HEAD) - 1) +#define VDE_DEFAULT_DESCRIPTION "UML" + +static struct vector_fds *user_init_vde_fds(struct arglist *ifspec) +{ + char seqpacketvnl[VDE_SEQPACKET_HEAD_LEN + ENOUGH(int) + 1]; + char *argv[VDE_MAX_ARGC] = {"vde_plug"}; + int argc = 1; + int rv; + int sv[2]; + struct vector_fds *result = NULL; + + char *vnl = uml_vector_fetch_arg(ifspec,"vnl"); + char *descr = uml_vector_fetch_arg(ifspec,"descr"); + char *port = uml_vector_fetch_arg(ifspec,"port"); + char *mode = uml_vector_fetch_arg(ifspec,"mode"); + char *group = uml_vector_fetch_arg(ifspec,"group"); + if (descr == NULL) descr = VDE_DEFAULT_DESCRIPTION; + + argv[argc++] = "--descr"; + argv[argc++] = descr; + if (port != NULL) { + argv[argc++] = "--port2"; + argv[argc++] = port; + } + if (mode != NULL) { + argv[argc++] = "--mod2"; + argv[argc++] = mode; + } + if (group != NULL) { + argv[argc++] = "--group2"; + argv[argc++] = group; + } + argv[argc++] = seqpacketvnl; + argv[argc++] = vnl; + argv[argc++] = NULL; + + rv = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv); + if (rv < 0) { + printk(UM_KERN_ERR "vde: seqpacket socketpair err %d", -errno); + return NULL; + } + rv = os_set_exec_close(sv[0]); + if (rv < 0) { + printk(UM_KERN_ERR "vde: seqpacket socketpair cloexec err %d", -errno); + goto vde_cleanup_sv; + } + snprintf(seqpacketvnl, sizeof(seqpacketvnl), VDE_SEQPACKET_HEAD "%d", sv[1]); + + run_helper(NULL, NULL, argv); + + close(sv[1]); + + result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); + if (result == NULL) { + printk(UM_KERN_ERR "fd open: allocation failed"); + goto vde_cleanup; + } + + result->rx_fd = sv[0]; + result->tx_fd = sv[0]; + result->remote_addr_size = 0; + result->remote_addr = NULL; + return result; + +vde_cleanup_sv: + close(sv[1]); +vde_cleanup: + close(sv[0]); + return NULL; +} + static struct vector_fds *user_init_raw_fds(struct arglist *ifspec) { int rxfd = -1, txfd = -1; @@ -673,6 +754,8 @@ struct vector_fds *uml_vector_user_open( return user_init_unix_fds(parsed, ID_BESS); if (strncmp(transport, TRANS_FD, TRANS_FD_LEN) == 0) return user_init_fd_fds(parsed); + if (strncmp(transport, TRANS_VDE, TRANS_VDE_LEN) == 0) + return user_init_vde_fds(parsed); return NULL; } diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index 6100819681b5..744e7f31e8ef 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -14,7 +14,7 @@ #include <linux/virtio-uml.h> #include <linux/delay.h> #include <linux/msi.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <irq_kern.h> #define MAX_DEVICES 8 diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h index 9ef9a8aedfa6..834313ecd3d6 100644 --- a/arch/um/include/asm/page.h +++ b/arch/um/include/asm/page.h @@ -9,10 +9,7 @@ #include <linux/const.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #ifndef __ASSEMBLY__ diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 5bb397b65efb..83373c9963e7 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h @@ -359,11 +359,4 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) return pte; } -/* Clear a kernel PTE and flush it from the TLB */ -#define kpte_clear_flush(ptep, vaddr) \ -do { \ - pte_clear(&init_mm, (vaddr), (ptep)); \ - __flush_tlb_one((vaddr)); \ -} while (0) - #endif diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 5a7c05275aa7..bce4595798da 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h @@ -28,20 +28,10 @@ struct thread_struct { struct arch_thread arch; jmp_buf switch_buf; struct { - int op; - union { - struct { - int pid; - } fork, exec; - struct { - int (*proc)(void *); - void *arg; - } thread; - struct { - void (*proc)(void *); - void *arg; - } cb; - } u; + struct { + int (*proc)(void *); + void *arg; + } thread; } request; }; @@ -51,7 +41,7 @@ struct thread_struct { .fault_addr = NULL, \ .prev_sched = NULL, \ .arch = INIT_ARCH_THREAD, \ - .request = { 0 } \ + .request = { } \ } /* diff --git a/arch/um/include/asm/sysrq.h b/arch/um/include/asm/sysrq.h deleted file mode 100644 index 8fc8c65cd357..000000000000 --- a/arch/um/include/asm/sysrq.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __UM_SYSRQ_H -#define __UM_SYSRQ_H - -struct task_struct; -extern void show_trace(struct task_struct* task, unsigned long *stack); - -#endif diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index 7d9d60e41e4e..1d4b6bbc1b65 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -8,7 +8,7 @@ #define __UM_UACCESS_H #include <asm/elf.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ diff --git a/arch/um/include/shared/skas/mm_id.h b/arch/um/include/shared/skas/mm_id.h index 1e76ba40feba..140388c282f6 100644 --- a/arch/um/include/shared/skas/mm_id.h +++ b/arch/um/include/shared/skas/mm_id.h @@ -7,10 +7,7 @@ #define __MM_ID_H struct mm_id { - union { - int mm_fd; - int pid; - } u; + int pid; unsigned long stack; int syscall_data_len; }; diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h index ebaa116de30b..85c50122ab98 100644 --- a/arch/um/include/shared/skas/skas.h +++ b/arch/um/include/shared/skas/skas.h @@ -10,10 +10,8 @@ extern int userspace_pid[]; -extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); extern void handle_syscall(struct uml_pt_regs *regs); -extern long execute_syscall_skas(void *r); extern unsigned long current_stub_stack(void); extern struct mm_id *current_mm_id(void); extern void current_mm_sync(void); diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c index 4954188a6a09..8d78ced9e08f 100644 --- a/arch/um/kernel/dtb.c +++ b/arch/um/kernel/dtb.c @@ -17,7 +17,7 @@ void uml_dtb_init(void) area = uml_load_file(dtb, &size); if (area) { - if (!early_init_dt_scan(area)) { + if (!early_init_dt_scan(area, __pa(area))) { pr_err("invalid DTB %s\n", dtb); memblock_free(area, size); return; diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 2c15bb2c104c..cb8b5cd9285c 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -35,8 +35,5 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) PT_REGS_IP(regs) = eip; PT_REGS_SP(regs) = esp; clear_thread_flag(TIF_SINGLESTEP); -#ifdef SUBARCH_EXECVE1 - SUBARCH_EXECVE1(regs->regs); -#endif } EXPORT_SYMBOL(start_thread); diff --git a/arch/um/kernel/kmsg_dump.c b/arch/um/kernel/kmsg_dump.c index 4382cf02a6d1..419021175272 100644 --- a/arch/um/kernel/kmsg_dump.c +++ b/arch/um/kernel/kmsg_dump.c @@ -8,7 +8,7 @@ #include <os.h> static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason) + struct kmsg_dump_detail *detail) { static struct kmsg_dump_iter iter; static DEFINE_SPINLOCK(lock); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index f36b63f53bab..be2856af6d4c 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -109,8 +109,8 @@ void new_thread_handler(void) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; - fn = current->thread.request.u.thread.proc; - arg = current->thread.request.u.thread.arg; + fn = current->thread.request.thread.proc; + arg = current->thread.request.thread.arg; /* * callback returns only if the kernel thread execs a process @@ -158,8 +158,8 @@ int copy_thread(struct task_struct * p, const struct kernel_clone_args *args) arch_copy_thread(¤t->thread.arch, &p->thread.arch); } else { get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); - p->thread.request.u.thread.proc = args->fn; - p->thread.request.u.thread.arg = args->fn_arg; + p->thread.request.thread.proc = args->fn; + p->thread.request.thread.arg = args->fn_arg; handler = new_thread_handler; } diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 3736bca626ba..680bce4bd8fa 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -29,7 +29,7 @@ static void kill_off_processes(void) t = find_lock_task_mm(p); if (!t) continue; - pid = t->mm->context.id.u.pid; + pid = t->mm->context.id.pid; task_unlock(t); os_kill_ptraced_process(pid, 1); } diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 47f98d87ea3c..886ed5e65674 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -32,11 +32,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) new_id->stack = stack; block_signals_trace(); - new_id->u.pid = start_userspace(stack); + new_id->pid = start_userspace(stack); unblock_signals_trace(); - if (new_id->u.pid < 0) { - ret = new_id->u.pid; + if (new_id->pid < 0) { + ret = new_id->pid; goto out_free; } @@ -83,12 +83,12 @@ void destroy_context(struct mm_struct *mm) * whole UML suddenly dying. Also, cover negative and * 1 cases, since they shouldn't happen either. */ - if (mmu->id.u.pid < 2) { + if (mmu->id.pid < 2) { printk(KERN_ERR "corrupt mm_context - pid = %d\n", - mmu->id.u.pid); + mmu->id.pid); return; } - os_kill_ptraced_process(mmu->id.u.pid, 1); + os_kill_ptraced_process(mmu->id.pid, 1); free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES)); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 5f9c1c5f36e2..68657988c8d1 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -39,8 +39,8 @@ int __init start_uml(void) init_new_thread_signals(); - init_task.thread.request.u.thread.proc = start_kernel_proc; - init_task.thread.request.u.thread.arg = NULL; + init_task.thread.request.thread.proc = start_kernel_proc; + init_task.thread.request.thread.arg = NULL; return start_idle_thread(task_stack_page(&init_task), &init_task.thread.switch_buf); } diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 9ee19e566da3..b09e85279d2b 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -12,23 +12,13 @@ #include <sysdep/syscalls.h> #include <linux/time-internal.h> #include <asm/unistd.h> +#include <asm/delay.h> void handle_syscall(struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); int syscall; - /* - * If we have infinite CPU resources, then make every syscall also a - * preemption point, since we don't have any other preemption in this - * case, and kernel threads would basically never run until userspace - * went to sleep, even if said userspace interacts with the kernel in - * various ways. - */ - if (time_travel_mode == TT_MODE_INFCPU || - time_travel_mode == TT_MODE_EXTERNAL) - schedule(); - /* Initialize the syscall number and default return value. */ UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp); PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS); @@ -41,9 +31,25 @@ void handle_syscall(struct uml_pt_regs *r) goto out; syscall = UPT_SYSCALL_NR(r); - if (syscall >= 0 && syscall < __NR_syscalls) - PT_REGS_SET_SYSCALL_RETURN(regs, - EXECUTE_SYSCALL(syscall, regs)); + if (syscall >= 0 && syscall < __NR_syscalls) { + unsigned long ret = EXECUTE_SYSCALL(syscall, regs); + + PT_REGS_SET_SYSCALL_RETURN(regs, ret); + + /* + * An error value here can be some form of -ERESTARTSYS + * and then we'd just loop. Make any error syscalls take + * some time, so that it won't just loop if something is + * not ready, and hopefully other things will make some + * progress. + */ + if (IS_ERR_VALUE(ret) && + (time_travel_mode == TT_MODE_INFCPU || + time_travel_mode == TT_MODE_EXTERNAL)) { + um_udelay(1); + schedule(); + } + } out: syscall_trace_leave(regs); diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 746715379f12..4bb8622dc512 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -11,7 +11,6 @@ #include <linux/sched/debug.h> #include <linux/sched/task_stack.h> -#include <asm/sysrq.h> #include <asm/stacktrace.h> #include <os.h> diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 47b9f5e63566..29b27b90581f 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -839,7 +839,7 @@ static irqreturn_t um_timer(int irq, void *dev) if (get_current()->mm != NULL) { /* userspace - relay signal, results in correct userspace timers */ - os_alarm_process(get_current()->mm->context.id.u.pid); + os_alarm_process(get_current()->mm->context.id.pid); } (*timer_clockevent.event_handler)(&timer_clockevent); diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 44c6fc697f3a..548af31d4111 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -82,16 +82,12 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, (x ? UM_PROT_EXEC : 0)); if (pte_newpage(*pte)) { if (pte_present(*pte)) { - if (pte_newpage(*pte)) { - __u64 offset; - unsigned long phys = - pte_val(*pte) & PAGE_MASK; - int fd = phys_mapping(phys, &offset); - - ret = ops->mmap(ops->mm_idp, addr, - PAGE_SIZE, prot, fd, - offset); - } + __u64 offset; + unsigned long phys = pte_val(*pte) & PAGE_MASK; + int fd = phys_mapping(phys, &offset); + + ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE, + prot, fd, offset); } else ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE); } else if (pte_newprot(*pte)) diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 5adf8f630049..f1d03cf3957f 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -528,7 +528,8 @@ int os_shutdown_socket(int fd, int r, int w) ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds, void *data, size_t data_len) { - char buf[CMSG_SPACE(sizeof(*fds) * n_fds)]; +#define MAX_RCV_FDS 2 + char buf[CMSG_SPACE(sizeof(*fds) * MAX_RCV_FDS)]; struct cmsghdr *cmsg; struct iovec iov = { .iov_base = data, @@ -538,10 +539,13 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = buf, - .msg_controllen = sizeof(buf), + .msg_controllen = CMSG_SPACE(sizeof(*fds) * n_fds), }; int n; + if (n_fds > MAX_RCV_FDS) + return -EINVAL; + n = recvmsg(fd, &msg, 0); if (n < 0) return -errno; diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index c55430775efd..9a13ac23c606 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -78,7 +78,7 @@ static inline long do_syscall_stub(struct mm_id *mm_idp) { struct stub_data *proc_data = (void *)mm_idp->stack; int n, i; - int err, pid = mm_idp->u.pid; + int err, pid = mm_idp->pid; n = ptrace_setregs(pid, syscall_regs); if (n < 0) { diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index f7088345b3fc..b6f656bcffb1 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -588,5 +588,5 @@ void reboot_skas(void) void __switch_mm(struct mm_id *mm_idp) { - userspace_pid[0] = mm_idp->u.pid; + userspace_pid[0] = mm_idp->pid; } diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 007bab9f2a0e..a3c31b784edc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -28,6 +28,7 @@ config X86_64 select ARCH_HAS_GIGANTIC_PAGE select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 select ARCH_SUPPORTS_PER_VMA_LOCK + select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE select HAVE_ARCH_SOFT_DIRTY select MODULES_USE_ELF_RELA select NEED_DMA_MAP_STATE @@ -79,6 +80,7 @@ config X86 select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE select ARCH_HAS_DEVMEM_IS_ALLOWED + select ARCH_HAS_DMA_OPS if GART_IOMMU || XEN select ARCH_HAS_EARLY_DEBUG if KGDB select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FAST_MULTIPLIER @@ -91,6 +93,7 @@ config X86 select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_PMEM_API if X86_64 + select ARCH_HAS_PREEMPT_LAZY select ARCH_HAS_PTE_DEVMAP if X86_64 select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_HW_PTE_YOUNG @@ -107,6 +110,7 @@ config X86 select ARCH_HAS_DEBUG_WX select ARCH_HAS_ZONE_DMA_SET if EXPERT select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_HAVE_EXTRA_ELF_NOTES select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI select ARCH_MIGHT_HAVE_PC_PARPORT @@ -122,6 +126,7 @@ config X86 select ARCH_USES_CFI_TRAPS if X86_64 && CFI_CLANG select ARCH_SUPPORTS_LTO_CLANG select ARCH_SUPPORTS_LTO_CLANG_THIN + select ARCH_SUPPORTS_RT select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF if X86_CMPXCHG64 select ARCH_USE_MEMTEST @@ -141,7 +146,6 @@ config X86 select ARCH_HAS_PARANOID_L1D_FLUSH select BUILDTIME_TABLE_SORT select CLKEVT_I8253 - select CLOCKSOURCE_VALIDATE_LAST_CYCLE select CLOCKSOURCE_WATCHDOG # Word-size accesses may read uninitialized data past the trailing \0 # in strings and cause false KMSAN reports. @@ -296,6 +300,7 @@ config X86 select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK select NEED_SG_DMA_LENGTH + select NUMA_MEMBLKS if NUMA select PCI_DOMAINS if PCI select PCI_LOCKLESS_CONFIG if PCI select PERF_EVENTS @@ -943,7 +948,6 @@ config DMI config GART_IOMMU bool "Old AMD GART IOMMU support" - select DMA_OPS select IOMMU_HELPER select SWIOTLB depends on X86_64 && PCI && AMD_NB @@ -1599,14 +1603,6 @@ config X86_64_ACPI_NUMA help Enable ACPI SRAT based node topology detection. -config NUMA_EMU - bool "NUMA emulation" - depends on NUMA - help - Enable NUMA emulation. A flat machine will be split - into virtual nodes when booted with "numa=fake=N", where N is the - number of nodes. This is only useful for debugging. - config NODES_SHIFT int "Maximum NUMA Nodes (as a power of 2)" if !MAXSMP range 1 10 @@ -1806,6 +1802,7 @@ config X86_PAT def_bool y prompt "x86 PAT support" if EXPERT depends on MTRR + select ARCH_USES_PG_ARCH_2 help Use PAT attributes to setup page level cache control. @@ -1817,10 +1814,6 @@ config X86_PAT If unsure, say Y. -config ARCH_USES_PG_UNCACHED - def_bool y - depends on X86_PAT - config X86_UMIP def_bool y prompt "User Mode Instruction Prevention" if EXPERT @@ -1889,6 +1882,10 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS If unsure, say y. +config ARCH_PKEY_BITS + int + default 4 + choice prompt "TSX enable mode" depends on CPU_SUP_INTEL @@ -1957,6 +1954,7 @@ config X86_USER_SHADOW_STACK depends on AS_WRUSS depends on X86_64 select ARCH_USES_HIGH_VMA_FLAGS + select ARCH_HAS_USER_SHADOW_STACK select X86_CET help Shadow stack protection is a hardware feature that detects function @@ -2087,6 +2085,9 @@ config ARCH_SUPPORTS_KEXEC_JUMP config ARCH_SUPPORTS_CRASH_DUMP def_bool X86_64 || (X86_32 && HIGHMEM) +config ARCH_DEFAULT_CRASH_DUMP + def_bool y + config ARCH_SUPPORTS_CRASH_HOTPLUG def_bool y @@ -2260,6 +2261,7 @@ config RANDOMIZE_MEMORY_PHYSICAL_PADDING config ADDRESS_MASKING bool "Linear Address Masking support" depends on X86_64 + depends on COMPILE_TEST || !CPU_MITIGATIONS # wait for LASS help Linear Address Masking (LAM) modifies the checking that is applied to 64-bit linear addresses, allowing software to use of the @@ -2426,6 +2428,14 @@ config CFI_AUTO_DEFAULT source "kernel/livepatch/Kconfig" +config X86_BUS_LOCK_DETECT + bool "Split Lock Detect and Bus Lock Detect support" + depends on CPU_SUP_INTEL || CPU_SUP_AMD + default y + help + Enable Split Lock Detect and Bus Lock Detect functionalities. + See <file:Documentation/arch/x86/buslock.rst> for more information. + endmenu config CC_HAS_NAMED_AS @@ -2610,24 +2620,15 @@ config MITIGATION_SLS against straight line speculation. The kernel image might be slightly larger. -config MITIGATION_GDS_FORCE - bool "Force GDS Mitigation" +config MITIGATION_GDS + bool "Mitigate Gather Data Sampling" depends on CPU_SUP_INTEL - default n + default y help - Gather Data Sampling (GDS) is a hardware vulnerability which allows - unprivileged speculative access to data which was previously stored in - vector registers. - - This option is equivalent to setting gather_data_sampling=force on the - command line. The microcode mitigation is used if present, otherwise - AVX is disabled as a mitigation. On affected systems that are missing - the microcode any userspace code that unconditionally uses AVX will - break with this option set. - - Setting this option on systems not vulnerable to GDS has no effect. - - If in doubt, say N. + Enable mitigation for Gather Data Sampling (GDS). GDS is a hardware + vulnerability which allows unprivileged speculative access to data + which was previously stored in vector registers. The attacker uses gather + instructions to infer the stale vector register data. config MITIGATION_RFDS bool "RFDS Mitigation" @@ -2650,6 +2651,107 @@ config MITIGATION_SPECTRE_BHI indirect branches. See <file:Documentation/admin-guide/hw-vuln/spectre.rst> +config MITIGATION_MDS + bool "Mitigate Microarchitectural Data Sampling (MDS) hardware bug" + depends on CPU_SUP_INTEL + default y + help + Enable mitigation for Microarchitectural Data Sampling (MDS). MDS is + a hardware vulnerability which allows unprivileged speculative access + to data which is available in various CPU internal buffers. + See also <file:Documentation/admin-guide/hw-vuln/mds.rst> + +config MITIGATION_TAA + bool "Mitigate TSX Asynchronous Abort (TAA) hardware bug" + depends on CPU_SUP_INTEL + default y + help + Enable mitigation for TSX Asynchronous Abort (TAA). TAA is a hardware + vulnerability that allows unprivileged speculative access to data + which is available in various CPU internal buffers by using + asynchronous aborts within an Intel TSX transactional region. + See also <file:Documentation/admin-guide/hw-vuln/tsx_async_abort.rst> + +config MITIGATION_MMIO_STALE_DATA + bool "Mitigate MMIO Stale Data hardware bug" + depends on CPU_SUP_INTEL + default y + help + Enable mitigation for MMIO Stale Data hardware bugs. Processor MMIO + Stale Data Vulnerabilities are a class of memory-mapped I/O (MMIO) + vulnerabilities that can expose data. The vulnerabilities require the + attacker to have access to MMIO. + See also + <file:Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst> + +config MITIGATION_L1TF + bool "Mitigate L1 Terminal Fault (L1TF) hardware bug" + depends on CPU_SUP_INTEL + default y + help + Mitigate L1 Terminal Fault (L1TF) hardware bug. L1 Terminal Fault is a + hardware vulnerability which allows unprivileged speculative access to data + available in the Level 1 Data Cache. + See <file:Documentation/admin-guide/hw-vuln/l1tf.rst + +config MITIGATION_RETBLEED + bool "Mitigate RETBleed hardware bug" + depends on (CPU_SUP_INTEL && MITIGATION_SPECTRE_V2) || MITIGATION_UNRET_ENTRY || MITIGATION_IBPB_ENTRY + default y + help + Enable mitigation for RETBleed (Arbitrary Speculative Code Execution + with Return Instructions) vulnerability. RETBleed is a speculative + execution attack which takes advantage of microarchitectural behavior + in many modern microprocessors, similar to Spectre v2. An + unprivileged attacker can use these flaws to bypass conventional + memory security restrictions to gain read access to privileged memory + that would otherwise be inaccessible. + +config MITIGATION_SPECTRE_V1 + bool "Mitigate SPECTRE V1 hardware bug" + default y + help + Enable mitigation for Spectre V1 (Bounds Check Bypass). Spectre V1 is a + class of side channel attacks that takes advantage of speculative + execution that bypasses conditional branch instructions used for + memory access bounds check. + See also <file:Documentation/admin-guide/hw-vuln/spectre.rst> + +config MITIGATION_SPECTRE_V2 + bool "Mitigate SPECTRE V2 hardware bug" + default y + help + Enable mitigation for Spectre V2 (Branch Target Injection). Spectre + V2 is a class of side channel attacks that takes advantage of + indirect branch predictors inside the processor. In Spectre variant 2 + attacks, the attacker can steer speculative indirect branches in the + victim to gadget code by poisoning the branch target buffer of a CPU + used for predicting indirect branch addresses. + See also <file:Documentation/admin-guide/hw-vuln/spectre.rst> + +config MITIGATION_SRBDS + bool "Mitigate Special Register Buffer Data Sampling (SRBDS) hardware bug" + depends on CPU_SUP_INTEL + default y + help + Enable mitigation for Special Register Buffer Data Sampling (SRBDS). + SRBDS is a hardware vulnerability that allows Microarchitectural Data + Sampling (MDS) techniques to infer values returned from special + register accesses. An unprivileged user can extract values returned + from RDRAND and RDSEED executed on another core or sibling thread + using MDS techniques. + See also + <file:Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst> + +config MITIGATION_SSB + bool "Mitigate Speculative Store Bypass (SSB) hardware bug" + default y + help + Enable mitigation for Speculative Store Bypass (SSB). SSB is a + hardware security vulnerability and its exploitation takes advantage + of speculative execution in a similar way to the Meltdown and Spectre + security vulnerabilities. + endif config ARCH_HAS_ADD_PAGES @@ -2979,9 +3081,13 @@ config OLPC_XO15_SCI - AC adapter status updates - Battery status updates +config GEODE_COMMON + bool + config ALIX bool "PCEngines ALIX System Support (LED setup)" select GPIOLIB + select GEODE_COMMON help This option enables system support for the PCEngines ALIX. At present this just sets up LEDs for GPIO control on @@ -2996,12 +3102,14 @@ config ALIX config NET5501 bool "Soekris Engineering net5501 System Support (LEDS, GPIO, etc)" select GPIOLIB + select GEODE_COMMON help This option enables system support for the Soekris Engineering net5501. config GEOS bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)" select GPIOLIB + select GEODE_COMMON depends on DMI help This option enables system support for the Traverse Technologies GEOS. diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 801fd85c3ef6..5b773b34768d 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -24,11 +24,15 @@ RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix) ifdef CONFIG_MITIGATION_RETHUNK RETHUNK_CFLAGS := -mfunction-return=thunk-extern +RETHUNK_RUSTFLAGS := -Zfunction-return=thunk-extern RETPOLINE_CFLAGS += $(RETHUNK_CFLAGS) +RETPOLINE_RUSTFLAGS += $(RETHUNK_RUSTFLAGS) endif export RETHUNK_CFLAGS +export RETHUNK_RUSTFLAGS export RETPOLINE_CFLAGS +export RETPOLINE_RUSTFLAGS export RETPOLINE_VDSO_CFLAGS # For gcc stack alignment is specified with -mpreferred-stack-boundary, @@ -138,9 +142,10 @@ ifeq ($(CONFIG_X86_32),y) ifeq ($(CONFIG_STACKPROTECTOR),y) ifeq ($(CONFIG_SMP),y) - KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard + KBUILD_CFLAGS += -mstack-protector-guard-reg=fs \ + -mstack-protector-guard-symbol=__ref_stack_chk_guard else - KBUILD_CFLAGS += -mstack-protector-guard=global + KBUILD_CFLAGS += -mstack-protector-guard=global endif endif else @@ -218,9 +223,10 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables # Avoid indirect branches in kernel to deal with Spectre ifdef CONFIG_MITIGATION_RETPOLINE KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) + KBUILD_RUSTFLAGS += $(RETPOLINE_RUSTFLAGS) # Additionally, avoid generating expensive indirect jumps which # are subject to retpolines for small number of switch cases. - # clang turns off jump table generation by default when under + # LLVM turns off jump table generation by default when under # retpoline builds, however, gcc does not for x86. This has # only been fixed starting from gcc stable version 8.4.0 and # onwards, but not for older ones. See gcc bug #86952. @@ -237,6 +243,10 @@ ifdef CONFIG_CALL_PADDING PADDING_CFLAGS := -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES) KBUILD_CFLAGS += $(PADDING_CFLAGS) export PADDING_CFLAGS + +PADDING_RUSTFLAGS := -Zpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES) +KBUILD_RUSTFLAGS += $(PADDING_RUSTFLAGS) +export PADDING_RUSTFLAGS endif KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE) diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 148ba5c5106e..0f24f7ebec9b 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -305,7 +305,6 @@ void initregs(struct biosregs *regs); int strcmp(const char *str1, const char *str2); int strncmp(const char *cs, const char *ct, size_t count); size_t strnlen(const char *s, size_t maxlen); -unsigned int atou(const char *s); unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); size_t strlen(const char *s); char *strchr(const char *s, int c); diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 944454306ef4..0d37420cad02 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -385,6 +385,19 @@ static void parse_mem_encrypt(struct setup_header *hdr) hdr->xloadflags |= XLF_MEM_ENCRYPTION; } +static void early_sev_detect(void) +{ + /* + * Accessing video memory causes guest termination because + * the boot stage2 #VC handler of SEV-ES/SNP guests does not + * support MMIO handling and kexec -c adds screen_info to the + * boot parameters passed to the kexec kernel, which causes + * console output to be dumped to both video and serial. + */ + if (sev_status & MSR_AMD64_SEV_ES_ENABLED) + lines = cols = 0; +} + /* * The compressed kernel image (ZO), has been moved so that its position * is against the end of the buffer used to hold the uncompressed kernel @@ -440,6 +453,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) */ early_tdx_detect(); + early_sev_detect(); + console_init(); /* @@ -511,7 +526,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) if (init_unaccepted_memory()) { debug_putstr("Accepting memory... "); - accept_memory(__pa(output), __pa(output) + needed_size); + accept_memory(__pa(output), needed_size); } entry_offset = decompress_kernel(output, virt_addr, error); diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index b353a7be380c..dd8d1a85f671 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -256,6 +256,6 @@ static inline bool init_unaccepted_memory(void) { return false; } /* Defined in EFI stub */ extern struct efi_unaccepted_memory *unaccepted_table; -void accept_memory(phys_addr_t start, phys_addr_t end); +void accept_memory(phys_addr_t start, unsigned long size); #endif /* BOOT_COMPRESSED_MISC_H */ diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c index c23f3b9c84fe..84f7a883ce1e 100644 --- a/arch/x86/boot/string.c +++ b/arch/x86/boot/string.c @@ -88,14 +88,6 @@ size_t strnlen(const char *s, size_t maxlen) return (es - s); } -unsigned int atou(const char *s) -{ - unsigned int i = 0; - while (isdigit(*s)) - i = i * 10 + (*s++ - '0'); - return i; -} - /* Works only for digits and letters, but small and fast */ #define TOLOWER(x) ((x) | 0x20) diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h index e5d2c6b8c2f1..a5b05ebc037d 100644 --- a/arch/x86/boot/string.h +++ b/arch/x86/boot/string.h @@ -24,7 +24,6 @@ extern size_t strlen(const char *s); extern char *strstr(const char *s1, const char *s2); extern char *strchr(const char *s, int c); extern size_t strnlen(const char *s, size_t maxlen); -extern unsigned int atou(const char *s); extern unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); long simple_strtol(const char *cp, char **endp, unsigned int base); diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index de1df0cb45da..c5b0148b8c0a 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -92,6 +92,9 @@ static struct ghcb *boot_ghcb __section(".data"); /* Bitmap of SEV features supported by the hypervisor */ static u64 sev_hv_features __ro_after_init; +/* Secrets page physical address from the CC blob */ +static u64 secrets_pa __ro_after_init; + /* #VC handler runtime per-CPU data */ struct sev_es_runtime_data { struct ghcb ghcb_page; @@ -141,33 +144,6 @@ static DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa); static DEFINE_PER_CPU(struct svsm_ca *, svsm_caa); static DEFINE_PER_CPU(u64, svsm_caa_pa); -struct sev_config { - __u64 debug : 1, - - /* - * Indicates when the per-CPU GHCB has been created and registered - * and thus can be used by the BSP instead of the early boot GHCB. - * - * For APs, the per-CPU GHCB is created before they are started - * and registered upon startup, so this flag can be used globally - * for the BSP and APs. - */ - ghcbs_initialized : 1, - - /* - * Indicates when the per-CPU SVSM CA is to be used instead of the - * boot SVSM CA. - * - * For APs, the per-CPU SVSM CA is created as part of the AP - * bringup, so this flag can be used globally for the BSP and APs. - */ - use_cas : 1, - - __reserved : 61; -}; - -static struct sev_config sev_cfg __read_mostly; - static __always_inline bool on_vc_stack(struct pt_regs *regs) { unsigned long sp = regs->sp; @@ -722,45 +698,13 @@ void noinstr __sev_es_nmi_complete(void) __sev_put_ghcb(&state); } -static u64 __init get_secrets_page(void) -{ - u64 pa_data = boot_params.cc_blob_address; - struct cc_blob_sev_info info; - void *map; - - /* - * The CC blob contains the address of the secrets page, check if the - * blob is present. - */ - if (!pa_data) - return 0; - - map = early_memremap(pa_data, sizeof(info)); - if (!map) { - pr_err("Unable to locate SNP secrets page: failed to map the Confidential Computing blob.\n"); - return 0; - } - memcpy(&info, map, sizeof(info)); - early_memunmap(map, sizeof(info)); - - /* smoke-test the secrets page passed */ - if (!info.secrets_phys || info.secrets_len != PAGE_SIZE) - return 0; - - return info.secrets_phys; -} - static u64 __init get_snp_jump_table_addr(void) { struct snp_secrets_page *secrets; void __iomem *mem; - u64 pa, addr; + u64 addr; - pa = get_secrets_page(); - if (!pa) - return 0; - - mem = ioremap_encrypted(pa, PAGE_SIZE); + mem = ioremap_encrypted(secrets_pa, PAGE_SIZE); if (!mem) { pr_err("Unable to locate AP jump table address: failed to map the SNP secrets page.\n"); return 0; @@ -1010,6 +954,137 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end) set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE); } +static void set_pte_enc(pte_t *kpte, int level, void *va) +{ + struct pte_enc_desc d = { + .kpte = kpte, + .pte_level = level, + .va = va, + .encrypt = true + }; + + prepare_pte_enc(&d); + set_pte_enc_mask(kpte, d.pfn, d.new_pgprot); +} + +static void unshare_all_memory(void) +{ + unsigned long addr, end, size, ghcb; + struct sev_es_runtime_data *data; + unsigned int npages, level; + bool skipped_addr; + pte_t *pte; + int cpu; + + /* Unshare the direct mapping. */ + addr = PAGE_OFFSET; + end = PAGE_OFFSET + get_max_mapped(); + + while (addr < end) { + pte = lookup_address(addr, &level); + size = page_level_size(level); + npages = size / PAGE_SIZE; + skipped_addr = false; + + if (!pte || !pte_decrypted(*pte) || pte_none(*pte)) { + addr += size; + continue; + } + + /* + * Ensure that all the per-CPU GHCBs are made private at the + * end of the unsharing loop so that the switch to the slower + * MSR protocol happens last. + */ + for_each_possible_cpu(cpu) { + data = per_cpu(runtime_data, cpu); + ghcb = (unsigned long)&data->ghcb_page; + + if (addr <= ghcb && ghcb <= addr + size) { + skipped_addr = true; + break; + } + } + + if (!skipped_addr) { + set_pte_enc(pte, level, (void *)addr); + snp_set_memory_private(addr, npages); + } + addr += size; + } + + /* Unshare all bss decrypted memory. */ + addr = (unsigned long)__start_bss_decrypted; + end = (unsigned long)__start_bss_decrypted_unused; + npages = (end - addr) >> PAGE_SHIFT; + + for (; addr < end; addr += PAGE_SIZE) { + pte = lookup_address(addr, &level); + if (!pte || !pte_decrypted(*pte) || pte_none(*pte)) + continue; + + set_pte_enc(pte, level, (void *)addr); + } + addr = (unsigned long)__start_bss_decrypted; + snp_set_memory_private(addr, npages); + + __flush_tlb_all(); +} + +/* Stop new private<->shared conversions */ +void snp_kexec_begin(void) +{ + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) + return; + + if (!IS_ENABLED(CONFIG_KEXEC_CORE)) + return; + + /* + * Crash kernel ends up here with interrupts disabled: can't wait for + * conversions to finish. + * + * If race happened, just report and proceed. + */ + if (!set_memory_enc_stop_conversion()) + pr_warn("Failed to stop shared<->private conversions\n"); +} + +void snp_kexec_finish(void) +{ + struct sev_es_runtime_data *data; + unsigned int level, cpu; + unsigned long size; + struct ghcb *ghcb; + pte_t *pte; + + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) + return; + + if (!IS_ENABLED(CONFIG_KEXEC_CORE)) + return; + + unshare_all_memory(); + + /* + * Switch to using the MSR protocol to change per-CPU GHCBs to + * private. All the per-CPU GHCBs have been switched back to private, + * so can't do any more GHCB calls to the hypervisor beyond this point + * until the kexec'ed kernel starts running. + */ + boot_ghcb = NULL; + sev_cfg.ghcbs_initialized = false; + + for_each_possible_cpu(cpu) { + data = per_cpu(runtime_data, cpu); + ghcb = &data->ghcb_page; + pte = lookup_address((unsigned long)ghcb, &level); + size = page_level_size(level); + set_pte_enc(pte, level, (void *)ghcb); + snp_set_memory_private((unsigned long)ghcb, (size / PAGE_SIZE)); + } +} + static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa) { int ret; @@ -1331,35 +1406,39 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd) return 0; } +/* Writes to the SVSM CAA MSR are ignored */ +static enum es_result __vc_handle_msr_caa(struct pt_regs *regs, bool write) +{ + if (write) + return ES_OK; + + regs->ax = lower_32_bits(this_cpu_read(svsm_caa_pa)); + regs->dx = upper_32_bits(this_cpu_read(svsm_caa_pa)); + + return ES_OK; +} + static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) { struct pt_regs *regs = ctxt->regs; enum es_result ret; - u64 exit_info_1; + bool write; /* Is it a WRMSR? */ - exit_info_1 = (ctxt->insn.opcode.bytes[1] == 0x30) ? 1 : 0; + write = ctxt->insn.opcode.bytes[1] == 0x30; - if (regs->cx == MSR_SVSM_CAA) { - /* Writes to the SVSM CAA msr are ignored */ - if (exit_info_1) - return ES_OK; - - regs->ax = lower_32_bits(this_cpu_read(svsm_caa_pa)); - regs->dx = upper_32_bits(this_cpu_read(svsm_caa_pa)); - - return ES_OK; - } + if (regs->cx == MSR_SVSM_CAA) + return __vc_handle_msr_caa(regs, write); ghcb_set_rcx(ghcb, regs->cx); - if (exit_info_1) { + if (write) { ghcb_set_rax(ghcb, regs->ax); ghcb_set_rdx(ghcb, regs->dx); } - ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, exit_info_1, 0); + ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, write, 0); - if ((ret == ES_OK) && (!exit_info_1)) { + if ((ret == ES_OK) && !write) { regs->ax = ghcb->save.rax; regs->dx = ghcb->save.rdx; } @@ -2300,6 +2379,11 @@ bool __head snp_init(struct boot_params *bp) if (!cc_info) return false; + if (cc_info->secrets_phys && cc_info->secrets_len == PAGE_SIZE) + secrets_pa = cc_info->secrets_phys; + else + return false; + setup_cpuid_table(cc_info); svsm_setup(cc_info); @@ -2374,23 +2458,6 @@ static int __init report_snp_info(void) } arch_initcall(report_snp_info); -static int __init init_sev_config(char *str) -{ - char *s; - - while ((s = strsep(&str, ","))) { - if (!strcmp(s, "debug")) { - sev_cfg.debug = true; - continue; - } - - pr_info("SEV command-line option '%s' was not recognized\n", s); - } - - return 1; -} -__setup("sev=", init_sev_config); - static void update_attest_input(struct svsm_call *call, struct svsm_attest_call *input) { /* If (new) lengths have been returned, propagate them up */ @@ -2441,7 +2508,8 @@ int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, } EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req); -int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) +int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input, + struct snp_guest_request_ioctl *rio) { struct ghcb_state state; struct es_em_ctxt ctxt; @@ -2465,12 +2533,12 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn vc_ghcb_invalidate(ghcb); - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { + if (req->exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { ghcb_set_rax(ghcb, input->data_gpa); ghcb_set_rbx(ghcb, input->data_npages); } - ret = sev_es_ghcb_hv_call(ghcb, &ctxt, exit_code, input->req_gpa, input->resp_gpa); + ret = sev_es_ghcb_hv_call(ghcb, &ctxt, req->exit_code, input->req_gpa, input->resp_gpa); if (ret) goto e_put; @@ -2485,7 +2553,7 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN): /* Number of expected pages are returned in RBX */ - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { + if (req->exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { input->data_npages = ghcb_get_rbx(ghcb); ret = -ENOSPC; break; @@ -2513,16 +2581,11 @@ static struct platform_device sev_guest_device = { static int __init snp_init_platform_device(void) { struct sev_guest_platform_data data; - u64 gpa; if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) return -ENODEV; - gpa = get_secrets_page(); - if (!gpa) - return -ENODEV; - - data.secrets_gpa = gpa; + data.secrets_gpa = secrets_pa; if (platform_device_add_data(&sev_guest_device, &data, sizeof(data))) return -ENODEV; diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 078e2bac2553..327c45c5013f 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -16,6 +16,7 @@ #include <asm/insn-eval.h> #include <asm/pgtable.h> #include <asm/set_memory.h> +#include <asm/traps.h> /* MMIO direction */ #define EPT_READ 0 @@ -389,7 +390,6 @@ static bool mmio_read(int size, unsigned long addr, unsigned long *val) .r12 = size, .r13 = EPT_READ, .r14 = addr, - .r15 = *val, }; if (__tdx_hypercall(&args)) @@ -434,6 +434,11 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) return -EINVAL; } + if (!fault_in_kernel_space(ve->gla)) { + WARN_ONCE(1, "Access to userspace address is not supported"); + return -EINVAL; + } + /* * Reject EPT violation #VEs that split pages. * diff --git a/arch/x86/configs/tiny.config b/arch/x86/configs/tiny.config index be3ee4294903..aabafa3faa6d 100644 --- a/arch/x86/configs/tiny.config +++ b/arch/x86/configs/tiny.config @@ -1,6 +1,2 @@ CONFIG_NOHIGHMEM=y -# CONFIG_HIGHMEM4G is not set -# CONFIG_HIGHMEM64G is not set -# CONFIG_UNWINDER_ORC is not set CONFIG_UNWINDER_GUESS=y -# CONFIG_UNWINDER_FRAME_POINTER is not set diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig index 24875e6295f2..3d2e38ba5240 100644 --- a/arch/x86/crypto/Kconfig +++ b/arch/x86/crypto/Kconfig @@ -14,7 +14,7 @@ config CRYPTO_CURVE25519_X86 - ADX (large integer arithmetic) config CRYPTO_AES_NI_INTEL - tristate "Ciphers: AES, modes: ECB, CBC, CTS, CTR, XTR, XTS, GCM (AES-NI)" + tristate "Ciphers: AES, modes: ECB, CBC, CTS, CTR, XCTR, XTS, GCM (AES-NI/VAES)" depends on X86 select CRYPTO_AEAD select CRYPTO_LIB_AES @@ -25,10 +25,14 @@ config CRYPTO_AES_NI_INTEL help Block cipher: AES cipher algorithms AEAD cipher: AES with GCM - Length-preserving ciphers: AES with ECB, CBC, CTS, CTR, XTR, XTS + Length-preserving ciphers: AES with ECB, CBC, CTS, CTR, XCTR, XTS Architecture: x86 (32-bit and 64-bit) using: - AES-NI (AES new instructions) + - VAES (Vector AES) + + Some algorithm implementations are supported only in 64-bit builds, + and some have additional prerequisites such as AVX2 or AVX512. config CRYPTO_BLOWFISH_X86_64 tristate "Ciphers: Blowfish, modes: ECB, CBC" @@ -359,7 +363,7 @@ config CRYPTO_CHACHA20_X86_64 - AVX-512VL (Advanced Vector Extensions-512VL) config CRYPTO_AEGIS128_AESNI_SSE2 - tristate "AEAD ciphers: AEGIS-128 (AES-NI/SSE2)" + tristate "AEAD ciphers: AEGIS-128 (AES-NI/SSE4.1)" depends on X86 && 64BIT select CRYPTO_AEAD select CRYPTO_SIMD @@ -368,7 +372,7 @@ config CRYPTO_AEGIS128_AESNI_SSE2 Architecture: x86_64 using: - AES-NI (AES New Instructions) - - SSE2 (Streaming SIMD Extensions 2) + - SSE4.1 (Streaming SIMD Extensions 4.1) config CRYPTO_NHPOLY1305_SSE2 tristate "Hash functions: NHPoly1305 (SSE2)" diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S index ad7f4c891625..7294dc0ee7ba 100644 --- a/arch/x86/crypto/aegis128-aesni-asm.S +++ b/arch/x86/crypto/aegis128-aesni-asm.S @@ -1,14 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * AES-NI + SSE2 implementation of AEGIS-128 + * AES-NI + SSE4.1 implementation of AEGIS-128 * * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com> * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. + * Copyright 2024 Google LLC */ #include <linux/linkage.h> -#include <linux/cfi_types.h> -#include <asm/frame.h> #define STATE0 %xmm0 #define STATE1 %xmm1 @@ -20,11 +19,6 @@ #define T0 %xmm6 #define T1 %xmm7 -#define STATEP %rdi -#define LEN %rsi -#define SRC %rdx -#define DST %rcx - .section .rodata.cst16.aegis128_const, "aM", @progbits, 32 .align 16 .Laegis128_const_0: @@ -34,11 +28,11 @@ .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1 .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd -.section .rodata.cst16.aegis128_counter, "aM", @progbits, 16 -.align 16 -.Laegis128_counter: - .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 - .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +.section .rodata.cst32.zeropad_mask, "aM", @progbits, 32 +.align 32 +.Lzeropad_mask: + .octa 0xffffffffffffffffffffffffffffffff + .octa 0 .text @@ -61,140 +55,102 @@ .endm /* - * __load_partial: internal ABI - * input: - * LEN - bytes - * SRC - src - * output: - * MSG - message block - * changed: - * T0 - * %r8 - * %r9 + * Load 1 <= LEN (%ecx) <= 15 bytes from the pointer SRC into the xmm register + * MSG and zeroize any remaining bytes. Clobbers %rax, %rcx, and %r8. */ -SYM_FUNC_START_LOCAL(__load_partial) - xor %r9d, %r9d - pxor MSG, MSG - - mov LEN, %r8 - and $0x1, %r8 - jz .Lld_partial_1 - - mov LEN, %r8 - and $0x1E, %r8 - add SRC, %r8 - mov (%r8), %r9b - -.Lld_partial_1: - mov LEN, %r8 - and $0x2, %r8 - jz .Lld_partial_2 - - mov LEN, %r8 - and $0x1C, %r8 - add SRC, %r8 - shl $0x10, %r9 - mov (%r8), %r9w - -.Lld_partial_2: - mov LEN, %r8 - and $0x4, %r8 - jz .Lld_partial_4 - - mov LEN, %r8 - and $0x18, %r8 - add SRC, %r8 - shl $32, %r9 - mov (%r8), %r8d - xor %r8, %r9 - -.Lld_partial_4: - movq %r9, MSG - - mov LEN, %r8 - and $0x8, %r8 - jz .Lld_partial_8 - - mov LEN, %r8 - and $0x10, %r8 - add SRC, %r8 - pslldq $8, MSG - movq (%r8), T0 - pxor T0, MSG - -.Lld_partial_8: - RET -SYM_FUNC_END(__load_partial) +.macro load_partial + sub $8, %ecx /* LEN - 8 */ + jle .Lle8\@ + + /* Load 9 <= LEN <= 15 bytes: */ + movq (SRC), MSG /* Load first 8 bytes */ + mov (SRC, %rcx), %rax /* Load last 8 bytes */ + neg %ecx + shl $3, %ecx + shr %cl, %rax /* Discard overlapping bytes */ + pinsrq $1, %rax, MSG + jmp .Ldone\@ + +.Lle8\@: + add $4, %ecx /* LEN - 4 */ + jl .Llt4\@ + + /* Load 4 <= LEN <= 8 bytes: */ + mov (SRC), %eax /* Load first 4 bytes */ + mov (SRC, %rcx), %r8d /* Load last 4 bytes */ + jmp .Lcombine\@ + +.Llt4\@: + /* Load 1 <= LEN <= 3 bytes: */ + add $2, %ecx /* LEN - 2 */ + movzbl (SRC), %eax /* Load first byte */ + jl .Lmovq\@ + movzwl (SRC, %rcx), %r8d /* Load last 2 bytes */ +.Lcombine\@: + shl $3, %ecx + shl %cl, %r8 + or %r8, %rax /* Combine the two parts */ +.Lmovq\@: + movq %rax, MSG +.Ldone\@: +.endm /* - * __store_partial: internal ABI - * input: - * LEN - bytes - * DST - dst - * output: - * T0 - message block - * changed: - * %r8 - * %r9 - * %r10 + * Store 1 <= LEN (%ecx) <= 15 bytes from the xmm register \msg to the pointer + * DST. Clobbers %rax, %rcx, and %r8. */ -SYM_FUNC_START_LOCAL(__store_partial) - mov LEN, %r8 - mov DST, %r9 - - movq T0, %r10 - - cmp $8, %r8 - jl .Lst_partial_8 - - mov %r10, (%r9) - psrldq $8, T0 - movq T0, %r10 - - sub $8, %r8 - add $8, %r9 - -.Lst_partial_8: - cmp $4, %r8 - jl .Lst_partial_4 - - mov %r10d, (%r9) - shr $32, %r10 - - sub $4, %r8 - add $4, %r9 - -.Lst_partial_4: - cmp $2, %r8 - jl .Lst_partial_2 - - mov %r10w, (%r9) - shr $0x10, %r10 - - sub $2, %r8 - add $2, %r9 - -.Lst_partial_2: - cmp $1, %r8 - jl .Lst_partial_1 - - mov %r10b, (%r9) - -.Lst_partial_1: - RET -SYM_FUNC_END(__store_partial) +.macro store_partial msg + sub $8, %ecx /* LEN - 8 */ + jl .Llt8\@ + + /* Store 8 <= LEN <= 15 bytes: */ + pextrq $1, \msg, %rax + mov %ecx, %r8d + shl $3, %ecx + ror %cl, %rax + mov %rax, (DST, %r8) /* Store last LEN - 8 bytes */ + movq \msg, (DST) /* Store first 8 bytes */ + jmp .Ldone\@ + +.Llt8\@: + add $4, %ecx /* LEN - 4 */ + jl .Llt4\@ + + /* Store 4 <= LEN <= 7 bytes: */ + pextrd $1, \msg, %eax + mov %ecx, %r8d + shl $3, %ecx + ror %cl, %eax + mov %eax, (DST, %r8) /* Store last LEN - 4 bytes */ + movd \msg, (DST) /* Store first 4 bytes */ + jmp .Ldone\@ + +.Llt4\@: + /* Store 1 <= LEN <= 3 bytes: */ + pextrb $0, \msg, 0(DST) + cmp $-2, %ecx /* LEN - 4 == -2, i.e. LEN == 2? */ + jl .Ldone\@ + pextrb $1, \msg, 1(DST) + je .Ldone\@ + pextrb $2, \msg, 2(DST) +.Ldone\@: +.endm /* - * void crypto_aegis128_aesni_init(void *state, const void *key, const void *iv); + * void aegis128_aesni_init(struct aegis_state *state, + * const struct aegis_block *key, + * const u8 iv[AEGIS128_NONCE_SIZE]); */ -SYM_FUNC_START(crypto_aegis128_aesni_init) - FRAME_BEGIN +SYM_FUNC_START(aegis128_aesni_init) + .set STATEP, %rdi + .set KEYP, %rsi + .set IVP, %rdx /* load IV: */ - movdqu (%rdx), T1 + movdqu (IVP), T1 /* load key: */ - movdqa (%rsi), KEY + movdqa (KEYP), KEY pxor KEY, T1 movdqa T1, STATE0 movdqa KEY, STATE3 @@ -224,20 +180,22 @@ SYM_FUNC_START(crypto_aegis128_aesni_init) movdqu STATE2, 0x20(STATEP) movdqu STATE3, 0x30(STATEP) movdqu STATE4, 0x40(STATEP) - - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_init) +SYM_FUNC_END(aegis128_aesni_init) /* - * void crypto_aegis128_aesni_ad(void *state, unsigned int length, - * const void *data); + * void aegis128_aesni_ad(struct aegis_state *state, const u8 *data, + * unsigned int len); + * + * len must be a multiple of 16. */ -SYM_FUNC_START(crypto_aegis128_aesni_ad) - FRAME_BEGIN +SYM_FUNC_START(aegis128_aesni_ad) + .set STATEP, %rdi + .set SRC, %rsi + .set LEN, %edx - cmp $0x10, LEN - jb .Lad_out + test LEN, LEN + jz .Lad_out /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -246,89 +204,40 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu 0x30(STATEP), STATE3 movdqu 0x40(STATEP), STATE4 - mov SRC, %r8 - and $0xF, %r8 - jnz .Lad_u_loop - -.align 8 -.Lad_a_loop: - movdqa 0x00(SRC), MSG - aegis128_update - pxor MSG, STATE4 - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_1 - - movdqa 0x10(SRC), MSG - aegis128_update - pxor MSG, STATE3 - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_2 - - movdqa 0x20(SRC), MSG - aegis128_update - pxor MSG, STATE2 - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_3 - - movdqa 0x30(SRC), MSG - aegis128_update - pxor MSG, STATE1 - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_4 - - movdqa 0x40(SRC), MSG - aegis128_update - pxor MSG, STATE0 - sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_0 - - add $0x50, SRC - jmp .Lad_a_loop - .align 8 -.Lad_u_loop: +.Lad_loop: movdqu 0x00(SRC), MSG aegis128_update pxor MSG, STATE4 sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_1 + jz .Lad_out_1 movdqu 0x10(SRC), MSG aegis128_update pxor MSG, STATE3 sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_2 + jz .Lad_out_2 movdqu 0x20(SRC), MSG aegis128_update pxor MSG, STATE2 sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_3 + jz .Lad_out_3 movdqu 0x30(SRC), MSG aegis128_update pxor MSG, STATE1 sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_4 + jz .Lad_out_4 movdqu 0x40(SRC), MSG aegis128_update pxor MSG, STATE0 sub $0x10, LEN - cmp $0x10, LEN - jl .Lad_out_0 + jz .Lad_out_0 add $0x50, SRC - jmp .Lad_u_loop + jmp .Lad_loop /* store the state: */ .Lad_out_0: @@ -337,7 +246,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu STATE2, 0x20(STATEP) movdqu STATE3, 0x30(STATEP) movdqu STATE4, 0x40(STATEP) - FRAME_END RET .Lad_out_1: @@ -346,7 +254,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu STATE1, 0x20(STATEP) movdqu STATE2, 0x30(STATEP) movdqu STATE3, 0x40(STATEP) - FRAME_END RET .Lad_out_2: @@ -355,7 +262,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu STATE0, 0x20(STATEP) movdqu STATE1, 0x30(STATEP) movdqu STATE2, 0x40(STATEP) - FRAME_END RET .Lad_out_3: @@ -364,7 +270,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu STATE4, 0x20(STATEP) movdqu STATE0, 0x30(STATEP) movdqu STATE1, 0x40(STATEP) - FRAME_END RET .Lad_out_4: @@ -373,41 +278,38 @@ SYM_FUNC_START(crypto_aegis128_aesni_ad) movdqu STATE3, 0x20(STATEP) movdqu STATE4, 0x30(STATEP) movdqu STATE0, 0x40(STATEP) - FRAME_END - RET - .Lad_out: - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_ad) +SYM_FUNC_END(aegis128_aesni_ad) -.macro encrypt_block a s0 s1 s2 s3 s4 i - movdq\a (\i * 0x10)(SRC), MSG +.macro encrypt_block s0 s1 s2 s3 s4 i + movdqu (\i * 0x10)(SRC), MSG movdqa MSG, T0 pxor \s1, T0 pxor \s4, T0 movdqa \s2, T1 pand \s3, T1 pxor T1, T0 - movdq\a T0, (\i * 0x10)(DST) + movdqu T0, (\i * 0x10)(DST) aegis128_update pxor MSG, \s4 sub $0x10, LEN - cmp $0x10, LEN - jl .Lenc_out_\i + jz .Lenc_out_\i .endm /* - * void crypto_aegis128_aesni_enc(void *state, unsigned int length, - * const void *src, void *dst); + * void aegis128_aesni_enc(struct aegis_state *state, const u8 *src, u8 *dst, + * unsigned int len); + * + * len must be nonzero and a multiple of 16. */ -SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) - FRAME_BEGIN - - cmp $0x10, LEN - jb .Lenc_out +SYM_FUNC_START(aegis128_aesni_enc) + .set STATEP, %rdi + .set SRC, %rsi + .set DST, %rdx + .set LEN, %ecx /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -416,34 +318,17 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu 0x30(STATEP), STATE3 movdqu 0x40(STATEP), STATE4 - mov SRC, %r8 - or DST, %r8 - and $0xF, %r8 - jnz .Lenc_u_loop - .align 8 -.Lenc_a_loop: - encrypt_block a STATE0 STATE1 STATE2 STATE3 STATE4 0 - encrypt_block a STATE4 STATE0 STATE1 STATE2 STATE3 1 - encrypt_block a STATE3 STATE4 STATE0 STATE1 STATE2 2 - encrypt_block a STATE2 STATE3 STATE4 STATE0 STATE1 3 - encrypt_block a STATE1 STATE2 STATE3 STATE4 STATE0 4 +.Lenc_loop: + encrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0 + encrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1 + encrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2 + encrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3 + encrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4 add $0x50, SRC add $0x50, DST - jmp .Lenc_a_loop - -.align 8 -.Lenc_u_loop: - encrypt_block u STATE0 STATE1 STATE2 STATE3 STATE4 0 - encrypt_block u STATE4 STATE0 STATE1 STATE2 STATE3 1 - encrypt_block u STATE3 STATE4 STATE0 STATE1 STATE2 2 - encrypt_block u STATE2 STATE3 STATE4 STATE0 STATE1 3 - encrypt_block u STATE1 STATE2 STATE3 STATE4 STATE0 4 - - add $0x50, SRC - add $0x50, DST - jmp .Lenc_u_loop + jmp .Lenc_loop /* store the state: */ .Lenc_out_0: @@ -452,7 +337,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu STATE1, 0x20(STATEP) movdqu STATE2, 0x30(STATEP) movdqu STATE3, 0x40(STATEP) - FRAME_END RET .Lenc_out_1: @@ -461,7 +345,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu STATE0, 0x20(STATEP) movdqu STATE1, 0x30(STATEP) movdqu STATE2, 0x40(STATEP) - FRAME_END RET .Lenc_out_2: @@ -470,7 +353,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu STATE4, 0x20(STATEP) movdqu STATE0, 0x30(STATEP) movdqu STATE1, 0x40(STATEP) - FRAME_END RET .Lenc_out_3: @@ -479,7 +361,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu STATE3, 0x20(STATEP) movdqu STATE4, 0x30(STATEP) movdqu STATE0, 0x40(STATEP) - FRAME_END RET .Lenc_out_4: @@ -488,20 +369,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc) movdqu STATE2, 0x20(STATEP) movdqu STATE3, 0x30(STATEP) movdqu STATE4, 0x40(STATEP) - FRAME_END - RET - .Lenc_out: - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_enc) +SYM_FUNC_END(aegis128_aesni_enc) /* - * void crypto_aegis128_aesni_enc_tail(void *state, unsigned int length, - * const void *src, void *dst); + * void aegis128_aesni_enc_tail(struct aegis_state *state, const u8 *src, + * u8 *dst, unsigned int len); */ -SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail) - FRAME_BEGIN +SYM_FUNC_START(aegis128_aesni_enc_tail) + .set STATEP, %rdi + .set SRC, %rsi + .set DST, %rdx + .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */ /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -511,7 +391,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail) movdqu 0x40(STATEP), STATE4 /* encrypt message: */ - call __load_partial + mov LEN, %r9d + load_partial movdqa MSG, T0 pxor STATE1, T0 @@ -520,7 +401,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail) pand STATE3, T1 pxor T1, T0 - call __store_partial + mov %r9d, LEN + store_partial T0 aegis128_update pxor MSG, STATE4 @@ -531,37 +413,36 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_enc_tail) movdqu STATE1, 0x20(STATEP) movdqu STATE2, 0x30(STATEP) movdqu STATE3, 0x40(STATEP) - - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_enc_tail) +SYM_FUNC_END(aegis128_aesni_enc_tail) -.macro decrypt_block a s0 s1 s2 s3 s4 i - movdq\a (\i * 0x10)(SRC), MSG +.macro decrypt_block s0 s1 s2 s3 s4 i + movdqu (\i * 0x10)(SRC), MSG pxor \s1, MSG pxor \s4, MSG movdqa \s2, T1 pand \s3, T1 pxor T1, MSG - movdq\a MSG, (\i * 0x10)(DST) + movdqu MSG, (\i * 0x10)(DST) aegis128_update pxor MSG, \s4 sub $0x10, LEN - cmp $0x10, LEN - jl .Ldec_out_\i + jz .Ldec_out_\i .endm /* - * void crypto_aegis128_aesni_dec(void *state, unsigned int length, - * const void *src, void *dst); + * void aegis128_aesni_dec(struct aegis_state *state, const u8 *src, u8 *dst, + * unsigned int len); + * + * len must be nonzero and a multiple of 16. */ -SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) - FRAME_BEGIN - - cmp $0x10, LEN - jb .Ldec_out +SYM_FUNC_START(aegis128_aesni_dec) + .set STATEP, %rdi + .set SRC, %rsi + .set DST, %rdx + .set LEN, %ecx /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -570,34 +451,17 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu 0x30(STATEP), STATE3 movdqu 0x40(STATEP), STATE4 - mov SRC, %r8 - or DST, %r8 - and $0xF, %r8 - jnz .Ldec_u_loop - .align 8 -.Ldec_a_loop: - decrypt_block a STATE0 STATE1 STATE2 STATE3 STATE4 0 - decrypt_block a STATE4 STATE0 STATE1 STATE2 STATE3 1 - decrypt_block a STATE3 STATE4 STATE0 STATE1 STATE2 2 - decrypt_block a STATE2 STATE3 STATE4 STATE0 STATE1 3 - decrypt_block a STATE1 STATE2 STATE3 STATE4 STATE0 4 +.Ldec_loop: + decrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0 + decrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1 + decrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2 + decrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3 + decrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4 add $0x50, SRC add $0x50, DST - jmp .Ldec_a_loop - -.align 8 -.Ldec_u_loop: - decrypt_block u STATE0 STATE1 STATE2 STATE3 STATE4 0 - decrypt_block u STATE4 STATE0 STATE1 STATE2 STATE3 1 - decrypt_block u STATE3 STATE4 STATE0 STATE1 STATE2 2 - decrypt_block u STATE2 STATE3 STATE4 STATE0 STATE1 3 - decrypt_block u STATE1 STATE2 STATE3 STATE4 STATE0 4 - - add $0x50, SRC - add $0x50, DST - jmp .Ldec_u_loop + jmp .Ldec_loop /* store the state: */ .Ldec_out_0: @@ -606,7 +470,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu STATE1, 0x20(STATEP) movdqu STATE2, 0x30(STATEP) movdqu STATE3, 0x40(STATEP) - FRAME_END RET .Ldec_out_1: @@ -615,7 +478,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu STATE0, 0x20(STATEP) movdqu STATE1, 0x30(STATEP) movdqu STATE2, 0x40(STATEP) - FRAME_END RET .Ldec_out_2: @@ -624,7 +486,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu STATE4, 0x20(STATEP) movdqu STATE0, 0x30(STATEP) movdqu STATE1, 0x40(STATEP) - FRAME_END RET .Ldec_out_3: @@ -633,7 +494,6 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu STATE3, 0x20(STATEP) movdqu STATE4, 0x30(STATEP) movdqu STATE0, 0x40(STATEP) - FRAME_END RET .Ldec_out_4: @@ -642,20 +502,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec) movdqu STATE2, 0x20(STATEP) movdqu STATE3, 0x30(STATEP) movdqu STATE4, 0x40(STATEP) - FRAME_END - RET - .Ldec_out: - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_dec) +SYM_FUNC_END(aegis128_aesni_dec) /* - * void crypto_aegis128_aesni_dec_tail(void *state, unsigned int length, - * const void *src, void *dst); + * void aegis128_aesni_dec_tail(struct aegis_state *state, const u8 *src, + * u8 *dst, unsigned int len); */ -SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail) - FRAME_BEGIN +SYM_FUNC_START(aegis128_aesni_dec_tail) + .set STATEP, %rdi + .set SRC, %rsi + .set DST, %rdx + .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */ /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -665,7 +524,8 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail) movdqu 0x40(STATEP), STATE4 /* decrypt message: */ - call __load_partial + mov LEN, %r9d + load_partial pxor STATE1, MSG pxor STATE4, MSG @@ -673,17 +533,13 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail) pand STATE3, T1 pxor T1, MSG - movdqa MSG, T0 - call __store_partial + mov %r9d, LEN + store_partial MSG /* mask with byte count: */ - movq LEN, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - punpcklbw T0, T0 - movdqa .Laegis128_counter(%rip), T1 - pcmpgtb T1, T0 + lea .Lzeropad_mask+16(%rip), %rax + sub %r9, %rax + movdqu (%rax), T0 pand T0, MSG aegis128_update @@ -695,17 +551,19 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail) movdqu STATE1, 0x20(STATEP) movdqu STATE2, 0x30(STATEP) movdqu STATE3, 0x40(STATEP) - - FRAME_END RET -SYM_FUNC_END(crypto_aegis128_aesni_dec_tail) +SYM_FUNC_END(aegis128_aesni_dec_tail) /* - * void crypto_aegis128_aesni_final(void *state, void *tag_xor, - * u64 assoclen, u64 cryptlen); + * void aegis128_aesni_final(struct aegis_state *state, + * struct aegis_block *tag_xor, + * unsigned int assoclen, unsigned int cryptlen); */ -SYM_FUNC_START(crypto_aegis128_aesni_final) - FRAME_BEGIN +SYM_FUNC_START(aegis128_aesni_final) + .set STATEP, %rdi + .set TAG_XOR, %rsi + .set ASSOCLEN, %edx + .set CRYPTLEN, %ecx /* load the state: */ movdqu 0x00(STATEP), STATE0 @@ -715,10 +573,8 @@ SYM_FUNC_START(crypto_aegis128_aesni_final) movdqu 0x40(STATEP), STATE4 /* prepare length block: */ - movq %rdx, MSG - movq %rcx, T0 - pslldq $8, T0 - pxor T0, MSG + movd ASSOCLEN, MSG + pinsrd $2, CRYPTLEN, MSG psllq $3, MSG /* multiply by 8 (to get bit count) */ pxor STATE3, MSG @@ -733,7 +589,7 @@ SYM_FUNC_START(crypto_aegis128_aesni_final) aegis128_update; pxor MSG, STATE3 /* xor tag: */ - movdqu (%rsi), MSG + movdqu (TAG_XOR), MSG pxor STATE0, MSG pxor STATE1, MSG @@ -741,8 +597,6 @@ SYM_FUNC_START(crypto_aegis128_aesni_final) pxor STATE3, MSG pxor STATE4, MSG - movdqu MSG, (%rsi) - - FRAME_END + movdqu MSG, (TAG_XOR) RET -SYM_FUNC_END(crypto_aegis128_aesni_final) +SYM_FUNC_END(aegis128_aesni_final) diff --git a/arch/x86/crypto/aegis128-aesni-glue.c b/arch/x86/crypto/aegis128-aesni-glue.c index 4623189000d8..c19d8e3d96a3 100644 --- a/arch/x86/crypto/aegis128-aesni-glue.c +++ b/arch/x86/crypto/aegis128-aesni-glue.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * The AEGIS-128 Authenticated-Encryption Algorithm - * Glue for AES-NI + SSE2 implementation + * Glue for AES-NI + SSE4.1 implementation * * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com> * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved. @@ -23,27 +23,6 @@ #define AEGIS128_MIN_AUTH_SIZE 8 #define AEGIS128_MAX_AUTH_SIZE 16 -asmlinkage void crypto_aegis128_aesni_init(void *state, void *key, void *iv); - -asmlinkage void crypto_aegis128_aesni_ad( - void *state, unsigned int length, const void *data); - -asmlinkage void crypto_aegis128_aesni_enc( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128_aesni_dec( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128_aesni_enc_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128_aesni_dec_tail( - void *state, unsigned int length, const void *src, void *dst); - -asmlinkage void crypto_aegis128_aesni_final( - void *state, void *tag_xor, unsigned int cryptlen, - unsigned int assoclen); - struct aegis_block { u8 bytes[AEGIS128_BLOCK_SIZE] __aligned(AEGIS128_BLOCK_ALIGN); }; @@ -56,15 +35,31 @@ struct aegis_ctx { struct aegis_block key; }; -struct aegis_crypt_ops { - int (*skcipher_walk_init)(struct skcipher_walk *walk, - struct aead_request *req, bool atomic); +asmlinkage void aegis128_aesni_init(struct aegis_state *state, + const struct aegis_block *key, + const u8 iv[AEGIS128_NONCE_SIZE]); - void (*crypt_blocks)(void *state, unsigned int length, const void *src, - void *dst); - void (*crypt_tail)(void *state, unsigned int length, const void *src, - void *dst); -}; +asmlinkage void aegis128_aesni_ad(struct aegis_state *state, const u8 *data, + unsigned int len); + +asmlinkage void aegis128_aesni_enc(struct aegis_state *state, const u8 *src, + u8 *dst, unsigned int len); + +asmlinkage void aegis128_aesni_dec(struct aegis_state *state, const u8 *src, + u8 *dst, unsigned int len); + +asmlinkage void aegis128_aesni_enc_tail(struct aegis_state *state, + const u8 *src, u8 *dst, + unsigned int len); + +asmlinkage void aegis128_aesni_dec_tail(struct aegis_state *state, + const u8 *src, u8 *dst, + unsigned int len); + +asmlinkage void aegis128_aesni_final(struct aegis_state *state, + struct aegis_block *tag_xor, + unsigned int assoclen, + unsigned int cryptlen); static void crypto_aegis128_aesni_process_ad( struct aegis_state *state, struct scatterlist *sg_src, @@ -85,16 +80,15 @@ static void crypto_aegis128_aesni_process_ad( if (pos > 0) { unsigned int fill = AEGIS128_BLOCK_SIZE - pos; memcpy(buf.bytes + pos, src, fill); - crypto_aegis128_aesni_ad(state, - AEGIS128_BLOCK_SIZE, - buf.bytes); + aegis128_aesni_ad(state, buf.bytes, + AEGIS128_BLOCK_SIZE); pos = 0; left -= fill; src += fill; } - crypto_aegis128_aesni_ad(state, left, src); - + aegis128_aesni_ad(state, src, + left & ~(AEGIS128_BLOCK_SIZE - 1)); src += left & ~(AEGIS128_BLOCK_SIZE - 1); left &= AEGIS128_BLOCK_SIZE - 1; } @@ -110,24 +104,37 @@ static void crypto_aegis128_aesni_process_ad( if (pos > 0) { memset(buf.bytes + pos, 0, AEGIS128_BLOCK_SIZE - pos); - crypto_aegis128_aesni_ad(state, AEGIS128_BLOCK_SIZE, buf.bytes); + aegis128_aesni_ad(state, buf.bytes, AEGIS128_BLOCK_SIZE); } } -static void crypto_aegis128_aesni_process_crypt( - struct aegis_state *state, struct skcipher_walk *walk, - const struct aegis_crypt_ops *ops) +static __always_inline void +crypto_aegis128_aesni_process_crypt(struct aegis_state *state, + struct skcipher_walk *walk, bool enc) { while (walk->nbytes >= AEGIS128_BLOCK_SIZE) { - ops->crypt_blocks(state, - round_down(walk->nbytes, AEGIS128_BLOCK_SIZE), - walk->src.virt.addr, walk->dst.virt.addr); + if (enc) + aegis128_aesni_enc(state, walk->src.virt.addr, + walk->dst.virt.addr, + round_down(walk->nbytes, + AEGIS128_BLOCK_SIZE)); + else + aegis128_aesni_dec(state, walk->src.virt.addr, + walk->dst.virt.addr, + round_down(walk->nbytes, + AEGIS128_BLOCK_SIZE)); skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); } if (walk->nbytes) { - ops->crypt_tail(state, walk->nbytes, walk->src.virt.addr, - walk->dst.virt.addr); + if (enc) + aegis128_aesni_enc_tail(state, walk->src.virt.addr, + walk->dst.virt.addr, + walk->nbytes); + else + aegis128_aesni_dec_tail(state, walk->src.virt.addr, + walk->dst.virt.addr, + walk->nbytes); skcipher_walk_done(walk, 0); } } @@ -162,42 +169,39 @@ static int crypto_aegis128_aesni_setauthsize(struct crypto_aead *tfm, return 0; } -static void crypto_aegis128_aesni_crypt(struct aead_request *req, - struct aegis_block *tag_xor, - unsigned int cryptlen, - const struct aegis_crypt_ops *ops) +static __always_inline void +crypto_aegis128_aesni_crypt(struct aead_request *req, + struct aegis_block *tag_xor, + unsigned int cryptlen, bool enc) { struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm); struct skcipher_walk walk; struct aegis_state state; - ops->skcipher_walk_init(&walk, req, true); + if (enc) + skcipher_walk_aead_encrypt(&walk, req, true); + else + skcipher_walk_aead_decrypt(&walk, req, true); kernel_fpu_begin(); - crypto_aegis128_aesni_init(&state, ctx->key.bytes, req->iv); + aegis128_aesni_init(&state, &ctx->key, req->iv); crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen); - crypto_aegis128_aesni_process_crypt(&state, &walk, ops); - crypto_aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); + crypto_aegis128_aesni_process_crypt(&state, &walk, enc); + aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); kernel_fpu_end(); } static int crypto_aegis128_aesni_encrypt(struct aead_request *req) { - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_encrypt, - .crypt_blocks = crypto_aegis128_aesni_enc, - .crypt_tail = crypto_aegis128_aesni_enc_tail, - }; - struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aegis_block tag = {}; unsigned int authsize = crypto_aead_authsize(tfm); unsigned int cryptlen = req->cryptlen; - crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS); + crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true); scatterwalk_map_and_copy(tag.bytes, req->dst, req->assoclen + cryptlen, authsize, 1); @@ -208,12 +212,6 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req) { static const struct aegis_block zeros = {}; - static const struct aegis_crypt_ops OPS = { - .skcipher_walk_init = skcipher_walk_aead_decrypt, - .crypt_blocks = crypto_aegis128_aesni_dec, - .crypt_tail = crypto_aegis128_aesni_dec_tail, - }; - struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aegis_block tag; unsigned int authsize = crypto_aead_authsize(tfm); @@ -222,27 +220,16 @@ static int crypto_aegis128_aesni_decrypt(struct aead_request *req) scatterwalk_map_and_copy(tag.bytes, req->src, req->assoclen + cryptlen, authsize, 0); - crypto_aegis128_aesni_crypt(req, &tag, cryptlen, &OPS); + crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false); return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0; } -static int crypto_aegis128_aesni_init_tfm(struct crypto_aead *aead) -{ - return 0; -} - -static void crypto_aegis128_aesni_exit_tfm(struct crypto_aead *aead) -{ -} - static struct aead_alg crypto_aegis128_aesni_alg = { .setkey = crypto_aegis128_aesni_setkey, .setauthsize = crypto_aegis128_aesni_setauthsize, .encrypt = crypto_aegis128_aesni_encrypt, .decrypt = crypto_aegis128_aesni_decrypt, - .init = crypto_aegis128_aesni_init_tfm, - .exit = crypto_aegis128_aesni_exit_tfm, .ivsize = AEGIS128_NONCE_SIZE, .maxauthsize = AEGIS128_MAX_AUTH_SIZE, @@ -267,7 +254,7 @@ static struct simd_aead_alg *simd_alg; static int __init crypto_aegis128_aesni_module_init(void) { - if (!boot_cpu_has(X86_FEATURE_XMM2) || + if (!boot_cpu_has(X86_FEATURE_XMM4_1) || !boot_cpu_has(X86_FEATURE_AES) || !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) return -ENODEV; @@ -286,6 +273,6 @@ module_exit(crypto_aegis128_aesni_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ondrej Mosnacek <omosnacek@gmail.com>"); -MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm -- AESNI+SSE2 implementation"); +MODULE_DESCRIPTION("AEGIS-128 AEAD algorithm -- AESNI+SSE4.1 implementation"); MODULE_ALIAS_CRYPTO("aegis128"); MODULE_ALIAS_CRYPTO("aegis128-aesni"); diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index cd37de5ec404..fbf43482e1f5 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -1366,6 +1366,8 @@ gcm_crypt(struct aead_request *req, int flags) err = skcipher_walk_aead_encrypt(&walk, req, false); else err = skcipher_walk_aead_decrypt(&walk, req, false); + if (err) + return err; /* * Since the AES-GCM assembly code requires that at least three assembly @@ -1381,37 +1383,31 @@ gcm_crypt(struct aead_request *req, int flags) gcm_process_assoc(key, ghash_acc, req->src, assoclen, flags); /* En/decrypt the data and pass the ciphertext through GHASH. */ - while ((nbytes = walk.nbytes) != 0) { - if (unlikely(nbytes < walk.total)) { - /* - * Non-last segment. In this case, the assembly - * function requires that the length be a multiple of 16 - * (AES_BLOCK_SIZE) bytes. The needed buffering of up - * to 16 bytes is handled by the skcipher_walk. Here we - * just need to round down to a multiple of 16. - */ - nbytes = round_down(nbytes, AES_BLOCK_SIZE); - aes_gcm_update(key, le_ctr, ghash_acc, - walk.src.virt.addr, walk.dst.virt.addr, - nbytes, flags); - le_ctr[0] += nbytes / AES_BLOCK_SIZE; - kernel_fpu_end(); - err = skcipher_walk_done(&walk, walk.nbytes - nbytes); - kernel_fpu_begin(); - } else { - /* Last segment: process all remaining data. */ - aes_gcm_update(key, le_ctr, ghash_acc, - walk.src.virt.addr, walk.dst.virt.addr, - nbytes, flags); - err = skcipher_walk_done(&walk, 0); - /* - * The low word of the counter isn't used by the - * finalize, so there's no need to increment it here. - */ - } + while (unlikely((nbytes = walk.nbytes) < walk.total)) { + /* + * Non-last segment. In this case, the assembly function + * requires that the length be a multiple of 16 (AES_BLOCK_SIZE) + * bytes. The needed buffering of up to 16 bytes is handled by + * the skcipher_walk. Here we just need to round down to a + * multiple of 16. + */ + nbytes = round_down(nbytes, AES_BLOCK_SIZE); + aes_gcm_update(key, le_ctr, ghash_acc, walk.src.virt.addr, + walk.dst.virt.addr, nbytes, flags); + le_ctr[0] += nbytes / AES_BLOCK_SIZE; + kernel_fpu_end(); + err = skcipher_walk_done(&walk, walk.nbytes - nbytes); + if (err) + return err; + kernel_fpu_begin(); } - if (err) - goto out; + /* Last segment: process all remaining data. */ + aes_gcm_update(key, le_ctr, ghash_acc, walk.src.virt.addr, + walk.dst.virt.addr, nbytes, flags); + /* + * The low word of the counter isn't used by the finalize, so there's no + * need to increment it here. + */ /* Finalize */ taglen = crypto_aead_authsize(tfm); @@ -1439,8 +1435,9 @@ gcm_crypt(struct aead_request *req, int flags) datalen, tag, taglen, flags)) err = -EBADMSG; } -out: kernel_fpu_end(); + if (nbytes) + skcipher_walk_done(&walk, 0); return err; } @@ -1750,9 +1747,9 @@ static void __exit aesni_exit(void) unregister_avx_algs(); } -late_initcall(aesni_init); +module_init(aesni_init); module_exit(aesni_exit); -MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, Intel AES-NI instructions optimized"); +MODULE_DESCRIPTION("AES cipher and modes, optimized with AES-NI or VAES instructions"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CRYPTO("aes"); diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c index d45e9c0c42ac..f110708c8038 100644 --- a/arch/x86/crypto/camellia_glue.c +++ b/arch/x86/crypto/camellia_glue.c @@ -8,7 +8,7 @@ * Copyright (C) 2006 NTT (Nippon Telegraph and Telephone Corporation) */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/crypto.h> #include <linux/init.h> #include <linux/module.h> diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S index b4e460a87f18..fb95a614249d 100644 --- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S @@ -487,79 +487,3 @@ SYM_FUNC_START(cast5_cbc_dec_16way) FRAME_END RET; SYM_FUNC_END(cast5_cbc_dec_16way) - -SYM_FUNC_START(cast5_ctr_16way) - /* input: - * %rdi: ctx - * %rsi: dst - * %rdx: src - * %rcx: iv (big endian, 64bit) - */ - FRAME_BEGIN - pushq %r12; - pushq %r15; - - movq %rdi, CTX; - movq %rsi, %r11; - movq %rdx, %r12; - - vpcmpeqd RTMP, RTMP, RTMP; - vpsrldq $8, RTMP, RTMP; /* low: -1, high: 0 */ - - vpcmpeqd RKR, RKR, RKR; - vpaddq RKR, RKR, RKR; /* low: -2, high: -2 */ - vmovdqa .Lbswap_iv_mask(%rip), R1ST; - vmovdqa .Lbswap128_mask(%rip), RKM; - - /* load IV and byteswap */ - vmovq (%rcx), RX; - vpshufb R1ST, RX, RX; - - /* construct IVs */ - vpsubq RTMP, RX, RX; /* le: IV1, IV0 */ - vpshufb RKM, RX, RL1; /* be: IV0, IV1 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RR1; /* be: IV2, IV3 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RL2; /* be: IV4, IV5 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RR2; /* be: IV6, IV7 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RL3; /* be: IV8, IV9 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RR3; /* be: IV10, IV11 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RL4; /* be: IV12, IV13 */ - vpsubq RKR, RX, RX; - vpshufb RKM, RX, RR4; /* be: IV14, IV15 */ - - /* store last IV */ - vpsubq RTMP, RX, RX; /* le: IV16, IV14 */ - vpshufb R1ST, RX, RX; /* be: IV16, IV16 */ - vmovq RX, (%rcx); - - call __cast5_enc_blk16; - - /* dst = src ^ iv */ - vpxor (0*16)(%r12), RR1, RR1; - vpxor (1*16)(%r12), RL1, RL1; - vpxor (2*16)(%r12), RR2, RR2; - vpxor (3*16)(%r12), RL2, RL2; - vpxor (4*16)(%r12), RR3, RR3; - vpxor (5*16)(%r12), RL3, RL3; - vpxor (6*16)(%r12), RR4, RR4; - vpxor (7*16)(%r12), RL4, RL4; - vmovdqu RR1, (0*16)(%r11); - vmovdqu RL1, (1*16)(%r11); - vmovdqu RR2, (2*16)(%r11); - vmovdqu RL2, (3*16)(%r11); - vmovdqu RR3, (4*16)(%r11); - vmovdqu RL3, (5*16)(%r11); - vmovdqu RR4, (6*16)(%r11); - vmovdqu RL4, (7*16)(%r11); - - popq %r15; - popq %r12; - FRAME_END - RET; -SYM_FUNC_END(cast5_ctr_16way) diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c index feccb5254c7e..52c5d47ef5a1 100644 --- a/arch/x86/crypto/crc32c-intel_glue.c +++ b/arch/x86/crypto/crc32c-intel_glue.c @@ -41,7 +41,7 @@ */ #define CRC32C_PCL_BREAKEVEN 512 -asmlinkage unsigned int crc_pcl(const u8 *buffer, int len, +asmlinkage unsigned int crc_pcl(const u8 *buffer, unsigned int len, unsigned int crc_init); #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S index bbcff1fb78cb..752812bc4991 100644 --- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S @@ -7,6 +7,7 @@ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-paper.pdf * * Copyright (C) 2012 Intel Corporation. + * Copyright 2024 Google LLC * * Authors: * Wajdi Feghali <wajdi.k.feghali@intel.com> @@ -44,185 +45,129 @@ */ #include <linux/linkage.h> -#include <asm/nospec-branch.h> ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction -.macro LABEL prefix n -.L\prefix\n\(): -.endm - -.macro JMPTBL_ENTRY i -.quad .Lcrc_\i -.endm - -.macro JNC_LESS_THAN j - jnc .Lless_than_\j -.endm - -# Define threshold where buffers are considered "small" and routed to more -# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so -# SMALL_SIZE can be no larger than 255. - +# Define threshold below which buffers are considered "small" and routed to +# regular CRC code that does not interleave the CRC instructions. #define SMALL_SIZE 200 -.if (SMALL_SIZE > 255) -.error "SMALL_ SIZE must be < 256" -.endif - -# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init); +# unsigned int crc_pcl(const u8 *buffer, unsigned int len, unsigned int crc_init); .text SYM_FUNC_START(crc_pcl) -#define bufp rdi -#define bufp_dw %edi -#define bufp_w %di -#define bufp_b %dil -#define bufptmp %rcx -#define block_0 %rcx -#define block_1 %rdx -#define block_2 %r11 -#define len %rsi -#define len_dw %esi -#define len_w %si -#define len_b %sil -#define crc_init_arg %rdx -#define tmp %rbx -#define crc_init %r8 -#define crc_init_dw %r8d -#define crc1 %r9 -#define crc2 %r10 - - pushq %rbx - pushq %rdi - pushq %rsi - - ## Move crc_init for Linux to a different - mov crc_init_arg, crc_init +#define bufp %rdi +#define bufp_d %edi +#define len %esi +#define crc_init %edx +#define crc_init_q %rdx +#define n_misaligned %ecx /* overlaps chunk_bytes! */ +#define n_misaligned_q %rcx +#define chunk_bytes %ecx /* overlaps n_misaligned! */ +#define chunk_bytes_q %rcx +#define crc1 %r8 +#define crc2 %r9 + + cmp $SMALL_SIZE, len + jb .Lsmall ################################################################ ## 1) ALIGN: ################################################################ - - mov %bufp, bufptmp # rdi = *buf - neg %bufp - and $7, %bufp # calculate the unalignment amount of + mov bufp_d, n_misaligned + neg n_misaligned + and $7, n_misaligned # calculate the misalignment amount of # the address - je .Lproc_block # Skip if aligned - - ## If len is less than 8 and we're unaligned, we need to jump - ## to special code to avoid reading beyond the end of the buffer - cmp $8, len - jae .Ldo_align - # less_than_8 expects length in upper 3 bits of len_dw - # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30] - shl $32-3+1, len_dw - jmp .Lless_than_8_post_shl1 + je .Laligned # Skip if aligned + # Process 1 <= n_misaligned <= 7 bytes individually in order to align + # the remaining data to an 8-byte boundary. .Ldo_align: - #### Calculate CRC of unaligned bytes of the buffer (if any) - movq (bufptmp), tmp # load a quadward from the buffer - add %bufp, bufptmp # align buffer pointer for quadword - # processing - sub %bufp, len # update buffer length + movq (bufp), %rax + add n_misaligned_q, bufp + sub n_misaligned, len .Lalign_loop: - crc32b %bl, crc_init_dw # compute crc32 of 1-byte - shr $8, tmp # get next byte - dec %bufp + crc32b %al, crc_init # compute crc32 of 1-byte + shr $8, %rax # get next byte + dec n_misaligned jne .Lalign_loop - -.Lproc_block: +.Laligned: ################################################################ - ## 2) PROCESS BLOCKS: + ## 2) PROCESS BLOCK: ################################################################ - ## compute num of bytes to be processed - movq len, tmp # save num bytes in tmp - - cmpq $128*24, len + cmp $128*24, len jae .Lfull_block -.Lcontinue_block: - cmpq $SMALL_SIZE, len - jb .Lsmall - - ## len < 128*24 - movq $2731, %rax # 2731 = ceil(2^16 / 24) - mul len_dw - shrq $16, %rax - - ## eax contains floor(bytes / 24) = num 24-byte chunks to do - - ## process rax 24-byte chunks (128 >= rax >= 0) - - ## compute end address of each block - ## block 0 (base addr + RAX * 8) - ## block 1 (base addr + RAX * 16) - ## block 2 (base addr + RAX * 24) - lea (bufptmp, %rax, 8), block_0 - lea (block_0, %rax, 8), block_1 - lea (block_1, %rax, 8), block_2 +.Lpartial_block: + # Compute floor(len / 24) to get num qwords to process from each lane. + imul $2731, len, %eax # 2731 = ceil(2^16 / 24) + shr $16, %eax + jmp .Lcrc_3lanes - xor crc1, crc1 - xor crc2, crc2 - - ## branch into array - leaq jump_table(%rip), %bufp - mov (%bufp,%rax,8), %bufp - JMP_NOSPEC bufp - - ################################################################ - ## 2a) PROCESS FULL BLOCKS: - ################################################################ .Lfull_block: - movl $128,%eax - lea 128*8*2(block_0), block_1 - lea 128*8*3(block_0), block_2 - add $128*8*1, block_0 - - xor crc1,crc1 - xor crc2,crc2 - - # Fall through into top of crc array (crc_128) + # Processing 128 qwords from each lane. + mov $128, %eax ################################################################ - ## 3) CRC Array: + ## 3) CRC each of three lanes: ################################################################ - i=128 -.rept 128-1 -.altmacro -LABEL crc_ %i -.noaltmacro - ENDBR - crc32q -i*8(block_0), crc_init - crc32q -i*8(block_1), crc1 - crc32q -i*8(block_2), crc2 - i=(i-1) -.endr - -.altmacro -LABEL crc_ %i -.noaltmacro - ENDBR - crc32q -i*8(block_0), crc_init - crc32q -i*8(block_1), crc1 -# SKIP crc32 -i*8(block_2), crc2 ; Don't do this one yet - - mov block_2, block_0 +.Lcrc_3lanes: + xor crc1,crc1 + xor crc2,crc2 + mov %eax, chunk_bytes + shl $3, chunk_bytes # num bytes to process from each lane + sub $5, %eax # 4 for 4x_loop, 1 for special last iter + jl .Lcrc_3lanes_4x_done + + # Unroll the loop by a factor of 4 to reduce the overhead of the loop + # bookkeeping instructions, which can compete with crc32q for the ALUs. +.Lcrc_3lanes_4x_loop: + crc32q (bufp), crc_init_q + crc32q (bufp,chunk_bytes_q), crc1 + crc32q (bufp,chunk_bytes_q,2), crc2 + crc32q 8(bufp), crc_init_q + crc32q 8(bufp,chunk_bytes_q), crc1 + crc32q 8(bufp,chunk_bytes_q,2), crc2 + crc32q 16(bufp), crc_init_q + crc32q 16(bufp,chunk_bytes_q), crc1 + crc32q 16(bufp,chunk_bytes_q,2), crc2 + crc32q 24(bufp), crc_init_q + crc32q 24(bufp,chunk_bytes_q), crc1 + crc32q 24(bufp,chunk_bytes_q,2), crc2 + add $32, bufp + sub $4, %eax + jge .Lcrc_3lanes_4x_loop + +.Lcrc_3lanes_4x_done: + add $4, %eax + jz .Lcrc_3lanes_last_qword + +.Lcrc_3lanes_1x_loop: + crc32q (bufp), crc_init_q + crc32q (bufp,chunk_bytes_q), crc1 + crc32q (bufp,chunk_bytes_q,2), crc2 + add $8, bufp + dec %eax + jnz .Lcrc_3lanes_1x_loop + +.Lcrc_3lanes_last_qword: + crc32q (bufp), crc_init_q + crc32q (bufp,chunk_bytes_q), crc1 +# SKIP crc32q (bufp,chunk_bytes_q,2), crc2 ; Don't do this one yet ################################################################ ## 4) Combine three results: ################################################################ - lea (K_table-8)(%rip), %bufp # first entry is for idx 1 - shlq $3, %rax # rax *= 8 - pmovzxdq (%bufp,%rax), %xmm0 # 2 consts: K1:K2 - leal (%eax,%eax,2), %eax # rax *= 3 (total *24) - subq %rax, tmp # tmp -= rax*24 + lea (K_table-8)(%rip), %rax # first entry is for idx 1 + pmovzxdq (%rax,chunk_bytes_q), %xmm0 # 2 consts: K1:K2 + lea (chunk_bytes,chunk_bytes,2), %eax # chunk_bytes * 3 + sub %eax, len # len -= chunk_bytes * 3 - movq crc_init, %xmm1 # CRC for block 1 + movq crc_init_q, %xmm1 # CRC for block 1 pclmulqdq $0x00, %xmm0, %xmm1 # Multiply by K2 movq crc1, %xmm2 # CRC for block 2 @@ -230,103 +175,54 @@ LABEL crc_ %i pxor %xmm2,%xmm1 movq %xmm1, %rax - xor -i*8(block_2), %rax - mov crc2, crc_init - crc32 %rax, crc_init + xor (bufp,chunk_bytes_q,2), %rax + mov crc2, crc_init_q + crc32 %rax, crc_init_q + lea 8(bufp,chunk_bytes_q,2), bufp ################################################################ - ## 5) Check for end: + ## 5) If more blocks remain, goto (2): ################################################################ -LABEL crc_ 0 - ENDBR - mov tmp, len - cmp $128*24, tmp - jae .Lfull_block - cmp $24, tmp - jae .Lcontinue_block - -.Lless_than_24: - shl $32-4, len_dw # less_than_16 expects length - # in upper 4 bits of len_dw - jnc .Lless_than_16 - crc32q (bufptmp), crc_init - crc32q 8(bufptmp), crc_init - jz .Ldo_return - add $16, bufptmp - # len is less than 8 if we got here - # less_than_8 expects length in upper 3 bits of len_dw - # less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30] - shl $2, len_dw - jmp .Lless_than_8_post_shl1 + cmp $128*24, len + jae .Lfull_block + cmp $SMALL_SIZE, len + jae .Lpartial_block ####################################################################### - ## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full) + ## 6) Process any remainder without interleaving: ####################################################################### .Lsmall: - shl $32-8, len_dw # Prepare len_dw for less_than_256 - j=256 -.rept 5 # j = {256, 128, 64, 32, 16} -.altmacro -LABEL less_than_ %j # less_than_j: Length should be in - # upper lg(j) bits of len_dw - j=(j/2) - shl $1, len_dw # Get next MSB - JNC_LESS_THAN %j -.noaltmacro - i=0 -.rept (j/8) - crc32q i(bufptmp), crc_init # Compute crc32 of 8-byte data - i=i+8 -.endr - jz .Ldo_return # Return if remaining length is zero - add $j, bufptmp # Advance buf -.endr - -.Lless_than_8: # Length should be stored in - # upper 3 bits of len_dw - shl $1, len_dw -.Lless_than_8_post_shl1: - jnc .Lless_than_4 - crc32l (bufptmp), crc_init_dw # CRC of 4 bytes - jz .Ldo_return # return if remaining data is zero - add $4, bufptmp -.Lless_than_4: # Length should be stored in - # upper 2 bits of len_dw - shl $1, len_dw - jnc .Lless_than_2 - crc32w (bufptmp), crc_init_dw # CRC of 2 bytes - jz .Ldo_return # return if remaining data is zero - add $2, bufptmp -.Lless_than_2: # Length should be stored in the MSB - # of len_dw - shl $1, len_dw - jnc .Lless_than_1 - crc32b (bufptmp), crc_init_dw # CRC of 1 byte -.Lless_than_1: # Length should be zero -.Ldo_return: - movq crc_init, %rax - popq %rsi - popq %rdi - popq %rbx + test len, len + jz .Ldone + mov len, %eax + shr $3, %eax + jz .Ldo_dword +.Ldo_qwords: + crc32q (bufp), crc_init_q + add $8, bufp + dec %eax + jnz .Ldo_qwords +.Ldo_dword: + test $4, len + jz .Ldo_word + crc32l (bufp), crc_init + add $4, bufp +.Ldo_word: + test $2, len + jz .Ldo_byte + crc32w (bufp), crc_init + add $2, bufp +.Ldo_byte: + test $1, len + jz .Ldone + crc32b (bufp), crc_init +.Ldone: + mov crc_init, %eax RET SYM_FUNC_END(crc_pcl) .section .rodata, "a", @progbits - ################################################################ - ## jump table Table is 129 entries x 2 bytes each - ################################################################ -.align 4 -jump_table: - i=0 -.rept 129 -.altmacro -JMPTBL_ENTRY %i -.noaltmacro - i=i+1 -.endr - - ################################################################ ## PCLMULQDQ tables ## Table is 128 entries x 2 words (8 bytes) each diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c index 700ecaee9a08..41bc02e48916 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_glue.c +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c @@ -19,7 +19,7 @@ #include <crypto/internal/simd.h> #include <asm/cpu_device_id.h> #include <asm/simd.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define GHASH_BLOCK_SIZE 16 #define GHASH_DIGEST_SIZE 16 diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S index 0ffb072be956..0bbec1c75cd0 100644 --- a/arch/x86/crypto/sha256-avx2-asm.S +++ b/arch/x86/crypto/sha256-avx2-asm.S @@ -592,22 +592,22 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx) leaq K256+0*32(%rip), INP ## reuse INP as scratch reg vpaddd (INP, SRND), X0, XFER vmovdqa XFER, 0*32+_XFER(%rsp, SRND) - FOUR_ROUNDS_AND_SCHED _XFER + 0*32 + FOUR_ROUNDS_AND_SCHED (_XFER + 0*32) leaq K256+1*32(%rip), INP vpaddd (INP, SRND), X0, XFER vmovdqa XFER, 1*32+_XFER(%rsp, SRND) - FOUR_ROUNDS_AND_SCHED _XFER + 1*32 + FOUR_ROUNDS_AND_SCHED (_XFER + 1*32) leaq K256+2*32(%rip), INP vpaddd (INP, SRND), X0, XFER vmovdqa XFER, 2*32+_XFER(%rsp, SRND) - FOUR_ROUNDS_AND_SCHED _XFER + 2*32 + FOUR_ROUNDS_AND_SCHED (_XFER + 2*32) leaq K256+3*32(%rip), INP vpaddd (INP, SRND), X0, XFER vmovdqa XFER, 3*32+_XFER(%rsp, SRND) - FOUR_ROUNDS_AND_SCHED _XFER + 3*32 + FOUR_ROUNDS_AND_SCHED (_XFER + 3*32) add $4*32, SRND cmp $3*4*32, SRND @@ -618,12 +618,12 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx) leaq K256+0*32(%rip), INP vpaddd (INP, SRND), X0, XFER vmovdqa XFER, 0*32+_XFER(%rsp, SRND) - DO_4ROUNDS _XFER + 0*32 + DO_4ROUNDS (_XFER + 0*32) leaq K256+1*32(%rip), INP vpaddd (INP, SRND), X1, XFER vmovdqa XFER, 1*32+_XFER(%rsp, SRND) - DO_4ROUNDS _XFER + 1*32 + DO_4ROUNDS (_XFER + 1*32) add $2*32, SRND vmovdqa X2, X0 @@ -651,8 +651,8 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx) xor SRND, SRND .align 16 .Lloop3: - DO_4ROUNDS _XFER + 0*32 + 16 - DO_4ROUNDS _XFER + 1*32 + 16 + DO_4ROUNDS (_XFER + 0*32 + 16) + DO_4ROUNDS (_XFER + 1*32 + 16) add $2*32, SRND cmp $4*4*32, SRND jb .Lloop3 diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 51cc9c7cb9bd..94941c5a10ac 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -150,7 +150,7 @@ early_param("ia32_emulation", ia32_emulation_override_cmdline); #endif /* - * Invoke a 32-bit syscall. Called with IRQs on in CONTEXT_KERNEL. + * Invoke a 32-bit syscall. Called with IRQs on in CT_STATE_KERNEL. */ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr) { diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S index d9feadffa972..b7ea3e8e9ecc 100644 --- a/arch/x86/entry/entry.S +++ b/arch/x86/entry/entry.S @@ -9,6 +9,8 @@ #include <asm/unwind_hints.h> #include <asm/segment.h> #include <asm/cache.h> +#include <asm/cpufeatures.h> +#include <asm/nospec-branch.h> #include "calling.h" @@ -19,6 +21,9 @@ SYM_FUNC_START(entry_ibpb) movl $PRED_CMD_IBPB, %eax xorl %edx, %edx wrmsr + + /* Make sure IBPB clears return stack preductions too. */ + FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_BUG_IBPB_NO_RET RET SYM_FUNC_END(entry_ibpb) /* For KVM */ @@ -46,3 +51,19 @@ EXPORT_SYMBOL_GPL(mds_verw_sel); .popsection THUNK warn_thunk_thunk, __warn_thunk + +#ifndef CONFIG_X86_64 +/* + * Clang's implementation of TLS stack cookies requires the variable in + * question to be a TLS variable. If the variable happens to be defined as an + * ordinary variable with external linkage in the same compilation unit (which + * amounts to the whole of vmlinux with LTO enabled), Clang will drop the + * segment register prefix from the references, resulting in broken code. Work + * around this by avoiding the symbol used in -mstack-protector-guard-symbol= + * entirely in the C code, and use an alias emitted by the linker script + * instead. + */ +#ifdef CONFIG_STACKPROTECTOR +EXPORT_SYMBOL(__ref_stack_chk_guard); +#endif +#endif diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index d3a814efbff6..20be5758c2d2 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -871,6 +871,8 @@ SYM_FUNC_START(entry_SYSENTER_32) /* Now ready to switch the cr3 */ SWITCH_TO_USER_CR3 scratch_reg=%eax + /* Clobbers ZF */ + CLEAR_CPU_BUFFERS /* * Restore all flags except IF. (We restore IF separately because @@ -881,7 +883,6 @@ SYM_FUNC_START(entry_SYSENTER_32) BUG_IF_WRONG_CR3 no_user_check=1 popfl popl %eax - CLEAR_CPU_BUFFERS /* * Return back to the vDSO, which will pop ecx and edx. @@ -1144,7 +1145,6 @@ SYM_CODE_START(asm_exc_nmi) /* Not on SYSENTER stack. */ call exc_nmi - CLEAR_CPU_BUFFERS jmp .Lnmi_return .Lnmi_from_sysenter_stack: @@ -1165,6 +1165,7 @@ SYM_CODE_START(asm_exc_nmi) CHECK_AND_APPLY_ESPFIX RESTORE_ALL_NMI cr3_reg=%edi pop=4 + CLEAR_CPU_BUFFERS jmp .Lirq_return #ifdef CONFIG_X86_ESPFIX32 @@ -1206,6 +1207,7 @@ SYM_CODE_START(asm_exc_nmi) * 1 - orig_ax */ lss (1+5+6)*4(%esp), %esp # back to espfix stack + CLEAR_CPU_BUFFERS jmp .Lirq_return #endif SYM_CODE_END(asm_exc_nmi) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 534c74b14fab..4d0fb2fba7e2 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -468,3 +468,7 @@ 460 i386 lsm_set_self_attr sys_lsm_set_self_attr 461 i386 lsm_list_modules sys_lsm_list_modules 462 i386 mseal sys_mseal +463 i386 setxattrat sys_setxattrat +464 i386 getxattrat sys_getxattrat +465 i386 listxattrat sys_listxattrat +466 i386 removexattrat sys_removexattrat diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 7093ee21c0d1..5eb708bff1c7 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -386,6 +386,10 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S index bafa73f09e92..872947c1004c 100644 --- a/arch/x86/entry/vdso/vdso-layout.lds.S +++ b/arch/x86/entry/vdso/vdso-layout.lds.S @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include <asm/vdso.h> +#include <asm/vdso/vsyscall.h> /* * Linker script for vDSO. This is an ELF shared object prelinked to @@ -16,23 +17,16 @@ SECTIONS * segment. */ - vvar_start = . - 4 * PAGE_SIZE; + vvar_start = . - __VVAR_PAGES * PAGE_SIZE; vvar_page = vvar_start; - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset; -#include <asm/vvar.h> -#undef EMIT_VVAR + vdso_rng_data = vvar_page + __VDSO_RND_DATA_OFFSET; - pvclock_page = vvar_start + PAGE_SIZE; - hvclock_page = vvar_start + 2 * PAGE_SIZE; - timens_page = vvar_start + 3 * PAGE_SIZE; + timens_page = vvar_start + PAGE_SIZE; -#undef _ASM_X86_VVAR_H - /* Place all vvars in timens too at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) timens_ ## name = timens_page + offset; -#include <asm/vvar.h> -#undef EMIT_VVAR + vclock_pages = vvar_start + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE; + pvclock_page = vclock_pages + VDSO_PAGE_PVCLOCK_OFFSET * PAGE_SIZE; + hvclock_page = vclock_pages + VDSO_PAGE_HVCLOCK_OFFSET * PAGE_SIZE; . = SIZEOF_HEADERS; diff --git a/arch/x86/entry/vdso/vgetrandom.c b/arch/x86/entry/vdso/vgetrandom.c index 52d3c7faae2e..430862b8977c 100644 --- a/arch/x86/entry/vdso/vgetrandom.c +++ b/arch/x86/entry/vdso/vgetrandom.c @@ -6,8 +6,6 @@ #include "../../../../lib/vdso/getrandom.c" -ssize_t __vdso_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len); - ssize_t __vdso_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len) { return __cvdso_getrandom(buffer, len, flags, opaque_state, opaque_len); diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 6d83ceb7f1ba..bfc7cabf4017 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -20,23 +20,20 @@ #include <asm/vgtod.h> #include <asm/proto.h> #include <asm/vdso.h> -#include <asm/vvar.h> #include <asm/tlb.h> #include <asm/page.h> #include <asm/desc.h> #include <asm/cpufeature.h> +#include <asm/vdso/vsyscall.h> #include <clocksource/hyperv_timer.h> -#undef _ASM_X86_VVAR_H -#define EMIT_VVAR(name, offset) \ - const size_t name ## _offset = offset; -#include <asm/vvar.h> - struct vdso_data *arch_get_vdso_data(void *vvar_page) { - return (struct vdso_data *)(vvar_page + _vdso_data_offset); + return (struct vdso_data *)vvar_page; } -#undef EMIT_VVAR + +static union vdso_data_store vdso_data_store __page_aligned_data; +struct vdso_data *vdso_data = vdso_data_store.data; unsigned int vclocks_used __read_mostly; @@ -151,7 +148,7 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, if (sym_offset == image->sym_vvar_page) { struct page *timens_page = find_timens_vvar_page(vma); - pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT; + pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT; /* * If a task belongs to a time namespace then a namespace @@ -179,32 +176,52 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, } return vmf_insert_pfn(vma, vmf->address, pfn); - } else if (sym_offset == image->sym_pvclock_page) { - struct pvclock_vsyscall_time_info *pvti = - pvclock_get_pvti_cpu0_va(); - if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)) { - return vmf_insert_pfn_prot(vma, vmf->address, - __pa(pvti) >> PAGE_SHIFT, - pgprot_decrypted(vma->vm_page_prot)); - } - } else if (sym_offset == image->sym_hvclock_page) { - pfn = hv_get_tsc_pfn(); - if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK)) - return vmf_insert_pfn(vma, vmf->address, pfn); } else if (sym_offset == image->sym_timens_page) { struct page *timens_page = find_timens_vvar_page(vma); if (!timens_page) return VM_FAULT_SIGBUS; - pfn = __pa_symbol(&__vvar_page) >> PAGE_SHIFT; + pfn = __pa_symbol(vdso_data) >> PAGE_SHIFT; return vmf_insert_pfn(vma, vmf->address, pfn); } return VM_FAULT_SIGBUS; } +static vm_fault_t vvar_vclock_fault(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, struct vm_fault *vmf) +{ + switch (vmf->pgoff) { +#ifdef CONFIG_PARAVIRT_CLOCK + case VDSO_PAGE_PVCLOCK_OFFSET: + { + struct pvclock_vsyscall_time_info *pvti = + pvclock_get_pvti_cpu0_va(); + + if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)) + return vmf_insert_pfn_prot(vma, vmf->address, + __pa(pvti) >> PAGE_SHIFT, + pgprot_decrypted(vma->vm_page_prot)); + break; + } +#endif /* CONFIG_PARAVIRT_CLOCK */ +#ifdef CONFIG_HYPERV_TIMER + case VDSO_PAGE_HVCLOCK_OFFSET: + { + unsigned long pfn = hv_get_tsc_pfn(); + + if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK)) + return vmf_insert_pfn(vma, vmf->address, pfn); + break; + } +#endif /* CONFIG_HYPERV_TIMER */ + } + + return VM_FAULT_SIGBUS; +} + static const struct vm_special_mapping vdso_mapping = { .name = "[vdso]", .fault = vdso_fault, @@ -214,6 +231,10 @@ static const struct vm_special_mapping vvar_mapping = { .name = "[vvar]", .fault = vvar_fault, }; +static const struct vm_special_mapping vvar_vclock_mapping = { + .name = "[vvar_vclock]", + .fault = vvar_vclock_fault, +}; /* * Add vdso and vvar mappings to current process. @@ -256,7 +277,7 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) vma = _install_special_mapping(mm, addr, - -image->sym_vvar_start, + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE, VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| VM_PFNMAP, &vvar_mapping); @@ -264,11 +285,26 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) if (IS_ERR(vma)) { ret = PTR_ERR(vma); do_munmap(mm, text_start, image->size, NULL); - } else { - current->mm->context.vdso = (void __user *)text_start; - current->mm->context.vdso_image = image; + goto up_fail; + } + + vma = _install_special_mapping(mm, + addr + (__VVAR_PAGES - VDSO_NR_VCLOCK_PAGES) * PAGE_SIZE, + VDSO_NR_VCLOCK_PAGES * PAGE_SIZE, + VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| + VM_PFNMAP, + &vvar_vclock_mapping); + + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + do_munmap(mm, text_start, image->size, NULL); + do_munmap(mm, addr, image->size, NULL); + goto up_fail; } + current->mm->context.vdso = (void __user *)text_start; + current->mm->context.vdso_image = image; + up_fail: mmap_write_unlock(mm); return ret; @@ -290,7 +326,8 @@ int map_vdso_once(const struct vdso_image *image, unsigned long addr) */ for_each_vma(vmi, vma) { if (vma_is_special_mapping(vma, &vdso_mapping) || - vma_is_special_mapping(vma, &vvar_mapping)) { + vma_is_special_mapping(vma, &vvar_mapping) || + vma_is_special_mapping(vma, &vvar_vclock_mapping)) { mmap_write_unlock(mm); return -EEXIST; } diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index 920e3a640cad..b4a1a2576510 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c @@ -943,11 +943,12 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u static int amd_pmu_v2_handle_irq(struct pt_regs *regs) { struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); + static atomic64_t status_warned = ATOMIC64_INIT(0); + u64 reserved, status, mask, new_bits, prev_bits; struct perf_sample_data data; struct hw_perf_event *hwc; struct perf_event *event; int handled = 0, idx; - u64 reserved, status, mask; bool pmu_enabled; /* @@ -1012,7 +1013,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) * the corresponding PMCs are expected to be inactive according to the * active_mask */ - WARN_ON(status > 0); + if (status > 0) { + prev_bits = atomic64_fetch_or(status, &status_warned); + // A new bit was set for the very first time. + new_bits = status & ~prev_bits; + WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits); + } /* Clear overflow and freeze bits */ amd_pmu_ack_global_status(~status); diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index 0bfde2ea5cb8..49c26ce2b115 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -916,7 +916,8 @@ int amd_uncore_umc_ctx_init(struct amd_uncore *uncore, unsigned int cpu) u8 group_num_pmcs[UNCORE_GROUP_MAX] = { 0 }; union amd_uncore_info info; struct amd_uncore_pmu *pmu; - int index = 0, gid, i; + int gid, i; + u16 index = 0; if (pmu_version < 2) return 0; @@ -948,7 +949,7 @@ int amd_uncore_umc_ctx_init(struct amd_uncore *uncore, unsigned int cpu) for_each_set_bit(gid, gmask, UNCORE_GROUP_MAX) { for (i = 0; i < group_num_pmus[gid]; i++) { pmu = &uncore->pmus[index]; - snprintf(pmu->name, sizeof(pmu->name), "amd_umc_%d", index); + snprintf(pmu->name, sizeof(pmu->name), "amd_umc_%hu", index); pmu->num_counters = group_num_pmcs[gid] / group_num_pmus[gid]; pmu->msr_base = MSR_F19H_UMC_PERF_CTL + i * pmu->num_counters * 2; pmu->rdpmc_base = -1; diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index be01823b1bb4..c75c482d4c52 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -41,6 +41,8 @@ #include <asm/desc.h> #include <asm/ldt.h> #include <asm/unwind.h> +#include <asm/uprobes.h> +#include <asm/ibt.h> #include "perf_event.h" @@ -2816,6 +2818,46 @@ static unsigned long get_segment_base(unsigned int segment) return get_desc_base(desc); } +#ifdef CONFIG_UPROBES +/* + * Heuristic-based check if uprobe is installed at the function entry. + * + * Under assumption of user code being compiled with frame pointers, + * `push %rbp/%ebp` is a good indicator that we indeed are. + * + * Similarly, `endbr64` (assuming 64-bit mode) is also a common pattern. + * If we get this wrong, captured stack trace might have one extra bogus + * entry, but the rest of stack trace will still be meaningful. + */ +static bool is_uprobe_at_func_entry(struct pt_regs *regs) +{ + struct arch_uprobe *auprobe; + + if (!current->utask) + return false; + + auprobe = current->utask->auprobe; + if (!auprobe) + return false; + + /* push %rbp/%ebp */ + if (auprobe->insn[0] == 0x55) + return true; + + /* endbr64 (64-bit only) */ + if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn)) + return true; + + return false; +} + +#else +static bool is_uprobe_at_func_entry(struct pt_regs *regs) +{ + return false; +} +#endif /* CONFIG_UPROBES */ + #ifdef CONFIG_IA32_EMULATION #include <linux/compat.h> @@ -2827,6 +2869,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent unsigned long ss_base, cs_base; struct stack_frame_ia32 frame; const struct stack_frame_ia32 __user *fp; + u32 ret_addr; if (user_64bit_mode(regs)) return 0; @@ -2836,6 +2879,12 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent fp = compat_ptr(ss_base + regs->bp); pagefault_disable(); + + /* see perf_callchain_user() below for why we do this */ + if (is_uprobe_at_func_entry(regs) && + !get_user(ret_addr, (const u32 __user *)regs->sp)) + perf_callchain_store(entry, ret_addr); + while (entry->nr < entry->max_stack) { if (!valid_user_frame(fp, sizeof(frame))) break; @@ -2864,6 +2913,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs { struct stack_frame frame; const struct stack_frame __user *fp; + unsigned long ret_addr; if (perf_guest_state()) { /* TODO: We don't support guest os callchain now */ @@ -2887,6 +2937,19 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs return; pagefault_disable(); + + /* + * If we are called from uprobe handler, and we are indeed at the very + * entry to user function (which is normally a `push %rbp` instruction, + * under assumption of application being compiled with frame pointers), + * we should read return address from *regs->sp before proceeding + * to follow frame pointers, otherwise we'll skip immediate caller + * as %rbp is not yet setup. + */ + if (is_uprobe_at_func_entry(regs) && + !get_user(ret_addr, (const unsigned long __user *)regs->sp)) + perf_callchain_store(entry, ret_addr); + while (entry->nr < entry->max_stack) { if (!valid_user_frame(fp, sizeof(frame))) break; @@ -2940,35 +3003,57 @@ static unsigned long code_segment_base(struct pt_regs *regs) return 0; } -unsigned long perf_instruction_pointer(struct pt_regs *regs) +unsigned long perf_arch_instruction_pointer(struct pt_regs *regs) { - if (perf_guest_state()) - return perf_guest_get_ip(); - return regs->ip + code_segment_base(regs); } -unsigned long perf_misc_flags(struct pt_regs *regs) +static unsigned long common_misc_flags(struct pt_regs *regs) { - unsigned int guest_state = perf_guest_state(); - int misc = 0; + if (regs->flags & PERF_EFLAGS_EXACT) + return PERF_RECORD_MISC_EXACT_IP; - if (guest_state) { - if (guest_state & PERF_GUEST_USER) - misc |= PERF_RECORD_MISC_GUEST_USER; - else - misc |= PERF_RECORD_MISC_GUEST_KERNEL; - } else { - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - } + return 0; +} - if (regs->flags & PERF_EFLAGS_EXACT) - misc |= PERF_RECORD_MISC_EXACT_IP; +static unsigned long guest_misc_flags(struct pt_regs *regs) +{ + unsigned long guest_state = perf_guest_state(); + + if (!(guest_state & PERF_GUEST_ACTIVE)) + return 0; + + if (guest_state & PERF_GUEST_USER) + return PERF_RECORD_MISC_GUEST_USER; + else + return PERF_RECORD_MISC_GUEST_KERNEL; + +} + +static unsigned long host_misc_flags(struct pt_regs *regs) +{ + if (user_mode(regs)) + return PERF_RECORD_MISC_USER; + else + return PERF_RECORD_MISC_KERNEL; +} + +unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs) +{ + unsigned long flags = common_misc_flags(regs); + + flags |= guest_misc_flags(regs); + + return flags; +} + +unsigned long perf_arch_misc_flags(struct pt_regs *regs) +{ + unsigned long flags = common_misc_flags(regs); + + flags |= host_misc_flags(regs); - return misc; + return flags; } void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap) diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c index 974e917e65b2..8f78b0c900ef 100644 --- a/arch/x86/events/intel/bts.c +++ b/arch/x86/events/intel/bts.c @@ -557,9 +557,6 @@ static int bts_event_init(struct perf_event *event) * disabled, so disallow intel_bts driver for unprivileged * users on paranoid systems since it provides trace data * to the user in a zero-copy fashion. - * - * Note that the default paranoia setting permits unprivileged - * users to profile the kernel. */ if (event->attr.exclude_kernel) { ret = perf_allow_kernel(&event->attr); diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 0c9c2706d4ec..bb284aff7bfd 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -3962,8 +3962,8 @@ static int intel_pmu_hw_config(struct perf_event *event) if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) { event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD; - if (!(event->attr.sample_type & - ~intel_pmu_large_pebs_flags(event))) { + if (!(event->attr.sample_type & ~intel_pmu_large_pebs_flags(event)) && + !has_aux_action(event)) { event->hw.flags |= PERF_X86_EVENT_LARGE_PEBS; event->attach_state |= PERF_ATTACH_SCHED_CB; } @@ -3972,8 +3972,12 @@ static int intel_pmu_hw_config(struct perf_event *event) x86_pmu.pebs_aliases(event); } - if (needs_branch_stack(event) && is_sampling_event(event)) - event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK; + if (needs_branch_stack(event)) { + /* Avoid branch stack setup for counting events in SAMPLE READ */ + if (is_sampling_event(event) || + !(event->attr.sample_type & PERF_SAMPLE_READ)) + event->hw.flags |= PERF_X86_EVENT_NEEDS_BRANCH_STACK; + } if (branch_sample_counters(event)) { struct perf_event *leader, *sibling; @@ -4589,6 +4593,47 @@ static enum hybrid_cpu_type adl_get_hybrid_cpu_type(void) return HYBRID_INTEL_CORE; } +static inline bool erratum_hsw11(struct perf_event *event) +{ + return (event->hw.config & INTEL_ARCH_EVENT_MASK) == + X86_CONFIG(.event=0xc0, .umask=0x01); +} + +static struct event_constraint * +arl_h_get_event_constraints(struct cpu_hw_events *cpuc, int idx, + struct perf_event *event) +{ + struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); + + if (pmu->pmu_type == hybrid_tiny) + return cmt_get_event_constraints(cpuc, idx, event); + + return mtl_get_event_constraints(cpuc, idx, event); +} + +static int arl_h_hw_config(struct perf_event *event) +{ + struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); + + if (pmu->pmu_type == hybrid_tiny) + return intel_pmu_hw_config(event); + + return adl_hw_config(event); +} + +/* + * The HSW11 requires a period larger than 100 which is the same as the BDM11. + * A minimum period of 128 is enforced as well for the INST_RETIRED.ALL. + * + * The message 'interrupt took too long' can be observed on any counter which + * was armed with a period < 32 and two events expired in the same NMI. + * A minimum period of 32 is enforced for the rest of the events. + */ +static void hsw_limit_period(struct perf_event *event, s64 *left) +{ + *left = max(*left, erratum_hsw11(event) ? 128 : 32); +} + /* * Broadwell: * @@ -4606,8 +4651,7 @@ static enum hybrid_cpu_type adl_get_hybrid_cpu_type(void) */ static void bdw_limit_period(struct perf_event *event, s64 *left) { - if ((event->hw.config & INTEL_ARCH_EVENT_MASK) == - X86_CONFIG(.event=0xc0, .umask=0x01)) { + if (erratum_hsw11(event)) { if (*left < 128) *left = 128; *left &= ~0x3fULL; @@ -4902,17 +4946,26 @@ static struct x86_hybrid_pmu *find_hybrid_pmu_for_cpu(void) /* * This essentially just maps between the 'hybrid_cpu_type' - * and 'hybrid_pmu_type' enums: + * and 'hybrid_pmu_type' enums except for ARL-H processor + * which needs to compare atom uarch native id since ARL-H + * contains two different atom uarchs. */ for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) { enum hybrid_pmu_type pmu_type = x86_pmu.hybrid_pmu[i].pmu_type; + u32 native_id; - if (cpu_type == HYBRID_INTEL_CORE && - pmu_type == hybrid_big) - return &x86_pmu.hybrid_pmu[i]; - if (cpu_type == HYBRID_INTEL_ATOM && - pmu_type == hybrid_small) + if (cpu_type == HYBRID_INTEL_CORE && pmu_type == hybrid_big) return &x86_pmu.hybrid_pmu[i]; + if (cpu_type == HYBRID_INTEL_ATOM) { + if (x86_pmu.num_hybrid_pmus == 2 && pmu_type == hybrid_small) + return &x86_pmu.hybrid_pmu[i]; + + native_id = get_this_hybrid_cpu_native_id(); + if (native_id == skt_native_id && pmu_type == hybrid_small) + return &x86_pmu.hybrid_pmu[i]; + if (native_id == cmt_native_id && pmu_type == hybrid_tiny) + return &x86_pmu.hybrid_pmu[i]; + } } return NULL; @@ -5943,6 +5996,37 @@ static struct attribute *lnl_hybrid_events_attrs[] = { NULL }; +/* The event string must be in PMU IDX order. */ +EVENT_ATTR_STR_HYBRID(topdown-retiring, + td_retiring_arl_h, + "event=0xc2,umask=0x02;event=0x00,umask=0x80;event=0xc2,umask=0x0", + hybrid_big_small_tiny); +EVENT_ATTR_STR_HYBRID(topdown-bad-spec, + td_bad_spec_arl_h, + "event=0x73,umask=0x0;event=0x00,umask=0x81;event=0x73,umask=0x0", + hybrid_big_small_tiny); +EVENT_ATTR_STR_HYBRID(topdown-fe-bound, + td_fe_bound_arl_h, + "event=0x9c,umask=0x01;event=0x00,umask=0x82;event=0x71,umask=0x0", + hybrid_big_small_tiny); +EVENT_ATTR_STR_HYBRID(topdown-be-bound, + td_be_bound_arl_h, + "event=0xa4,umask=0x02;event=0x00,umask=0x83;event=0x74,umask=0x0", + hybrid_big_small_tiny); + +static struct attribute *arl_h_hybrid_events_attrs[] = { + EVENT_PTR(slots_adl), + EVENT_PTR(td_retiring_arl_h), + EVENT_PTR(td_bad_spec_arl_h), + EVENT_PTR(td_fe_bound_arl_h), + EVENT_PTR(td_be_bound_arl_h), + EVENT_PTR(td_heavy_ops_adl), + EVENT_PTR(td_br_mis_adl), + EVENT_PTR(td_fetch_lat_adl), + EVENT_PTR(td_mem_bound_adl), + NULL, +}; + /* Must be in IDX order */ EVENT_ATTR_STR_HYBRID(mem-loads, mem_ld_adl, "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3", hybrid_big_small); EVENT_ATTR_STR_HYBRID(mem-stores, mem_st_adl, "event=0xd0,umask=0x6;event=0xcd,umask=0x2", hybrid_big_small); @@ -5961,6 +6045,21 @@ static struct attribute *mtl_hybrid_mem_attrs[] = { NULL }; +EVENT_ATTR_STR_HYBRID(mem-loads, + mem_ld_arl_h, + "event=0xd0,umask=0x5,ldlat=3;event=0xcd,umask=0x1,ldlat=3;event=0xd0,umask=0x5,ldlat=3", + hybrid_big_small_tiny); +EVENT_ATTR_STR_HYBRID(mem-stores, + mem_st_arl_h, + "event=0xd0,umask=0x6;event=0xcd,umask=0x2;event=0xd0,umask=0x6", + hybrid_big_small_tiny); + +static struct attribute *arl_h_hybrid_mem_attrs[] = { + EVENT_PTR(mem_ld_arl_h), + EVENT_PTR(mem_st_arl_h), + NULL, +}; + EVENT_ATTR_STR_HYBRID(tx-start, tx_start_adl, "event=0xc9,umask=0x1", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-commit, tx_commit_adl, "event=0xc9,umask=0x2", hybrid_big); EVENT_ATTR_STR_HYBRID(tx-abort, tx_abort_adl, "event=0xc9,umask=0x4", hybrid_big); @@ -5984,8 +6083,8 @@ static struct attribute *adl_hybrid_tsx_attrs[] = { FORMAT_ATTR_HYBRID(in_tx, hybrid_big); FORMAT_ATTR_HYBRID(in_tx_cp, hybrid_big); -FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small); -FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small); +FORMAT_ATTR_HYBRID(offcore_rsp, hybrid_big_small_tiny); +FORMAT_ATTR_HYBRID(ldlat, hybrid_big_small_tiny); FORMAT_ATTR_HYBRID(frontend, hybrid_big); #define ADL_HYBRID_RTM_FORMAT_ATTR \ @@ -6008,7 +6107,7 @@ static struct attribute *adl_hybrid_extra_attr[] = { NULL }; -FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small); +FORMAT_ATTR_HYBRID(snoop_rsp, hybrid_small_tiny); static struct attribute *mtl_hybrid_extra_attr_rtm[] = { ADL_HYBRID_RTM_FORMAT_ATTR, @@ -6216,8 +6315,9 @@ static inline int intel_pmu_v6_addr_offset(int index, bool eventsel) } static const struct { enum hybrid_pmu_type id; char *name; } intel_hybrid_pmu_type_map[] __initconst = { - { hybrid_small, "cpu_atom" }, - { hybrid_big, "cpu_core" }, + { hybrid_small, "cpu_atom" }, + { hybrid_big, "cpu_core" }, + { hybrid_tiny, "cpu_lowpower" }, }; static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) @@ -6250,7 +6350,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) 0, x86_pmu_num_counters(&pmu->pmu), 0, 0); pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; - if (pmu->pmu_type & hybrid_small) { + if (pmu->pmu_type & hybrid_small_tiny) { pmu->intel_cap.perf_metrics = 0; pmu->intel_cap.pebs_output_pt_available = 1; pmu->mid_ack = true; @@ -6766,6 +6866,7 @@ __init int intel_pmu_init(void) x86_pmu.hw_config = hsw_hw_config; x86_pmu.get_event_constraints = hsw_get_event_constraints; + x86_pmu.limit_period = hsw_limit_period; x86_pmu.lbr_double_abort = true; extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? hsw_format_attr : nhm_format_attr; @@ -7088,6 +7189,37 @@ __init int intel_pmu_init(void) name = "lunarlake_hybrid"; break; + case INTEL_ARROWLAKE_H: + intel_pmu_init_hybrid(hybrid_big_small_tiny); + + x86_pmu.pebs_latency_data = arl_h_latency_data; + x86_pmu.get_event_constraints = arl_h_get_event_constraints; + x86_pmu.hw_config = arl_h_hw_config; + + td_attr = arl_h_hybrid_events_attrs; + mem_attr = arl_h_hybrid_mem_attrs; + tsx_attr = adl_hybrid_tsx_attrs; + extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? + mtl_hybrid_extra_attr_rtm : mtl_hybrid_extra_attr; + + /* Initialize big core specific PerfMon capabilities. */ + pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX]; + intel_pmu_init_lnc(&pmu->pmu); + + /* Initialize Atom core specific PerfMon capabilities. */ + pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX]; + intel_pmu_init_skt(&pmu->pmu); + + /* Initialize Lower Power Atom specific PerfMon capabilities. */ + pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX]; + intel_pmu_init_grt(&pmu->pmu); + pmu->extra_regs = intel_cmt_extra_regs; + + intel_pmu_pebs_data_source_arl_h(); + pr_cont("ArrowLake-H Hybrid events, "); + name = "arrowlake_h_hybrid"; + break; + default: switch (x86_pmu.version) { case 1: diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 9f116dfc4728..ae4ec16156bb 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -128,10 +128,6 @@ static ssize_t __cstate_##_var##_show(struct device *dev, \ static struct device_attribute format_attr_##_var = \ __ATTR(_name, 0444, __cstate_##_var##_show, NULL) -static ssize_t cstate_get_attr_cpumask(struct device *dev, - struct device_attribute *attr, - char *buf); - /* Model -> events mapping */ struct cstate_model { unsigned long core_events; @@ -206,22 +202,9 @@ static struct attribute_group cstate_format_attr_group = { .attrs = cstate_format_attrs, }; -static cpumask_t cstate_core_cpu_mask; -static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL); - -static struct attribute *cstate_cpumask_attrs[] = { - &dev_attr_cpumask.attr, - NULL, -}; - -static struct attribute_group cpumask_attr_group = { - .attrs = cstate_cpumask_attrs, -}; - static const struct attribute_group *cstate_attr_groups[] = { &cstate_events_attr_group, &cstate_format_attr_group, - &cpumask_attr_group, NULL, }; @@ -269,8 +252,6 @@ static struct perf_msr pkg_msr[] = { [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &group_cstate_pkg_c10, test_msr }, }; -static cpumask_t cstate_pkg_cpu_mask; - /* cstate_module PMU */ static struct pmu cstate_module_pmu; static bool has_cstate_module; @@ -291,28 +272,9 @@ static struct perf_msr module_msr[] = { [PERF_CSTATE_MODULE_C6_RES] = { MSR_MODULE_C6_RES_MS, &group_cstate_module_c6, test_msr }, }; -static cpumask_t cstate_module_cpu_mask; - -static ssize_t cstate_get_attr_cpumask(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct pmu *pmu = dev_get_drvdata(dev); - - if (pmu == &cstate_core_pmu) - return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask); - else if (pmu == &cstate_pkg_pmu) - return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask); - else if (pmu == &cstate_module_pmu) - return cpumap_print_to_pagebuf(true, buf, &cstate_module_cpu_mask); - else - return 0; -} - static int cstate_pmu_event_init(struct perf_event *event) { u64 cfg = event->attr.config; - int cpu; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -331,20 +293,13 @@ static int cstate_pmu_event_init(struct perf_event *event) if (!(core_msr_mask & (1 << cfg))) return -EINVAL; event->hw.event_base = core_msr[cfg].msr; - cpu = cpumask_any_and(&cstate_core_cpu_mask, - topology_sibling_cpumask(event->cpu)); } else if (event->pmu == &cstate_pkg_pmu) { if (cfg >= PERF_CSTATE_PKG_EVENT_MAX) return -EINVAL; cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX); if (!(pkg_msr_mask & (1 << cfg))) return -EINVAL; - - event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG; - event->hw.event_base = pkg_msr[cfg].msr; - cpu = cpumask_any_and(&cstate_pkg_cpu_mask, - topology_die_cpumask(event->cpu)); } else if (event->pmu == &cstate_module_pmu) { if (cfg >= PERF_CSTATE_MODULE_EVENT_MAX) return -EINVAL; @@ -352,16 +307,10 @@ static int cstate_pmu_event_init(struct perf_event *event) if (!(module_msr_mask & (1 << cfg))) return -EINVAL; event->hw.event_base = module_msr[cfg].msr; - cpu = cpumask_any_and(&cstate_module_cpu_mask, - topology_cluster_cpumask(event->cpu)); } else { return -ENOENT; } - if (cpu >= nr_cpu_ids) - return -ENODEV; - - event->cpu = cpu; event->hw.config = cfg; event->hw.idx = -1; return 0; @@ -412,84 +361,6 @@ static int cstate_pmu_event_add(struct perf_event *event, int mode) return 0; } -/* - * Check if exiting cpu is the designated reader. If so migrate the - * events when there is a valid target available - */ -static int cstate_cpu_exit(unsigned int cpu) -{ - unsigned int target; - - if (has_cstate_core && - cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) { - - target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); - /* Migrate events if there is a valid target */ - if (target < nr_cpu_ids) { - cpumask_set_cpu(target, &cstate_core_cpu_mask); - perf_pmu_migrate_context(&cstate_core_pmu, cpu, target); - } - } - - if (has_cstate_pkg && - cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) { - - target = cpumask_any_but(topology_die_cpumask(cpu), cpu); - /* Migrate events if there is a valid target */ - if (target < nr_cpu_ids) { - cpumask_set_cpu(target, &cstate_pkg_cpu_mask); - perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target); - } - } - - if (has_cstate_module && - cpumask_test_and_clear_cpu(cpu, &cstate_module_cpu_mask)) { - - target = cpumask_any_but(topology_cluster_cpumask(cpu), cpu); - /* Migrate events if there is a valid target */ - if (target < nr_cpu_ids) { - cpumask_set_cpu(target, &cstate_module_cpu_mask); - perf_pmu_migrate_context(&cstate_module_pmu, cpu, target); - } - } - return 0; -} - -static int cstate_cpu_init(unsigned int cpu) -{ - unsigned int target; - - /* - * If this is the first online thread of that core, set it in - * the core cpu mask as the designated reader. - */ - target = cpumask_any_and(&cstate_core_cpu_mask, - topology_sibling_cpumask(cpu)); - - if (has_cstate_core && target >= nr_cpu_ids) - cpumask_set_cpu(cpu, &cstate_core_cpu_mask); - - /* - * If this is the first online thread of that package, set it - * in the package cpu mask as the designated reader. - */ - target = cpumask_any_and(&cstate_pkg_cpu_mask, - topology_die_cpumask(cpu)); - if (has_cstate_pkg && target >= nr_cpu_ids) - cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); - - /* - * If this is the first online thread of that cluster, set it - * in the cluster cpu mask as the designated reader. - */ - target = cpumask_any_and(&cstate_module_cpu_mask, - topology_cluster_cpumask(cpu)); - if (has_cstate_module && target >= nr_cpu_ids) - cpumask_set_cpu(cpu, &cstate_module_cpu_mask); - - return 0; -} - static const struct attribute_group *core_attr_update[] = { &group_cstate_core_c1, &group_cstate_core_c3, @@ -526,6 +397,7 @@ static struct pmu cstate_core_pmu = { .stop = cstate_pmu_event_stop, .read = cstate_pmu_event_update, .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, + .scope = PERF_PMU_SCOPE_CORE, .module = THIS_MODULE, }; @@ -541,6 +413,7 @@ static struct pmu cstate_pkg_pmu = { .stop = cstate_pmu_event_stop, .read = cstate_pmu_event_update, .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, + .scope = PERF_PMU_SCOPE_PKG, .module = THIS_MODULE, }; @@ -556,6 +429,7 @@ static struct pmu cstate_module_pmu = { .stop = cstate_pmu_event_stop, .read = cstate_pmu_event_update, .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, + .scope = PERF_PMU_SCOPE_CLUSTER, .module = THIS_MODULE, }; @@ -810,9 +684,6 @@ static int __init cstate_probe(const struct cstate_model *cm) static inline void cstate_cleanup(void) { - cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE); - cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING); - if (has_cstate_core) perf_pmu_unregister(&cstate_core_pmu); @@ -827,11 +698,6 @@ static int __init cstate_init(void) { int err; - cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING, - "perf/x86/cstate:starting", cstate_cpu_init, NULL); - cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE, - "perf/x86/cstate:online", NULL, cstate_cpu_exit); - if (has_cstate_core) { err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1); if (err) { @@ -844,6 +710,8 @@ static int __init cstate_init(void) if (has_cstate_pkg) { if (topology_max_dies_per_package() > 1) { + /* CLX-AP is multi-die and the cstate is die-scope */ + cstate_pkg_pmu.scope = PERF_PMU_SCOPE_DIE; err = perf_pmu_register(&cstate_pkg_pmu, "cstate_die", -1); } else { diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index fa5ea65de0d0..8afc4ad3cd16 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -177,6 +177,17 @@ void __init intel_pmu_pebs_data_source_mtl(void) __intel_pmu_pebs_data_source_cmt(data_source); } +void __init intel_pmu_pebs_data_source_arl_h(void) +{ + u64 *data_source; + + intel_pmu_pebs_data_source_lnl(); + + data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_TINY_IDX].pebs_data_source; + memcpy(data_source, pebs_data_source, sizeof(pebs_data_source)); + __intel_pmu_pebs_data_source_cmt(data_source); +} + void __init intel_pmu_pebs_data_source_cmt(void) { __intel_pmu_pebs_data_source_cmt(pebs_data_source); @@ -388,6 +399,16 @@ u64 lnl_latency_data(struct perf_event *event, u64 status) return lnc_latency_data(event, status); } +u64 arl_h_latency_data(struct perf_event *event, u64 status) +{ + struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu); + + if (pmu->pmu_type == hybrid_tiny) + return cmt_latency_data(event, status); + + return lnl_latency_data(event, status); +} + static u64 load_latency_data(struct perf_event *event, u64 status) { union intel_x86_pebs_dse dse; diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index b4aa8daa4773..4b0373bc8ab4 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -416,7 +416,10 @@ static bool pt_event_valid(struct perf_event *event) static void pt_config_start(struct perf_event *event) { struct pt *pt = this_cpu_ptr(&pt_ctx); - u64 ctl = event->hw.config; + u64 ctl = event->hw.aux_config; + + if (READ_ONCE(event->hw.aux_paused)) + return; ctl |= RTIT_CTL_TRACEEN; if (READ_ONCE(pt->vmx_on)) @@ -424,7 +427,7 @@ static void pt_config_start(struct perf_event *event) else wrmsrl(MSR_IA32_RTIT_CTL, ctl); - WRITE_ONCE(event->hw.config, ctl); + WRITE_ONCE(event->hw.aux_config, ctl); } /* Address ranges and their corresponding msr configuration registers */ @@ -503,7 +506,7 @@ static void pt_config(struct perf_event *event) u64 reg; /* First round: clear STATUS, in particular the PSB byte counter. */ - if (!event->hw.config) { + if (!event->hw.aux_config) { perf_event_itrace_started(event); wrmsrl(MSR_IA32_RTIT_STATUS, 0); } @@ -533,14 +536,31 @@ static void pt_config(struct perf_event *event) reg |= (event->attr.config & PT_CONFIG_MASK); - event->hw.config = reg; + event->hw.aux_config = reg; + + /* + * Allow resume before starting so as not to overwrite a value set by a + * PMI. + */ + barrier(); + WRITE_ONCE(pt->resume_allowed, 1); + /* Configuration is complete, it is now OK to handle an NMI */ + barrier(); + WRITE_ONCE(pt->handle_nmi, 1); + barrier(); pt_config_start(event); + barrier(); + /* + * Allow pause after starting so its pt_config_stop() doesn't race with + * pt_config_start(). + */ + WRITE_ONCE(pt->pause_allowed, 1); } static void pt_config_stop(struct perf_event *event) { struct pt *pt = this_cpu_ptr(&pt_ctx); - u64 ctl = READ_ONCE(event->hw.config); + u64 ctl = READ_ONCE(event->hw.aux_config); /* may be already stopped by a PMI */ if (!(ctl & RTIT_CTL_TRACEEN)) @@ -550,7 +570,7 @@ static void pt_config_stop(struct perf_event *event) if (!READ_ONCE(pt->vmx_on)) wrmsrl(MSR_IA32_RTIT_CTL, ctl); - WRITE_ONCE(event->hw.config, ctl); + WRITE_ONCE(event->hw.aux_config, ctl); /* * A wrmsr that disables trace generation serializes other PT @@ -828,11 +848,13 @@ static void pt_buffer_advance(struct pt_buffer *buf) buf->cur_idx++; if (buf->cur_idx == buf->cur->last) { - if (buf->cur == buf->last) + if (buf->cur == buf->last) { buf->cur = buf->first; - else + buf->wrapped = true; + } else { buf->cur = list_entry(buf->cur->list.next, struct topa, list); + } buf->cur_idx = 0; } } @@ -846,8 +868,11 @@ static void pt_buffer_advance(struct pt_buffer *buf) static void pt_update_head(struct pt *pt) { struct pt_buffer *buf = perf_get_aux(&pt->handle); + bool wrapped = buf->wrapped; u64 topa_idx, base, old; + buf->wrapped = false; + if (buf->single) { local_set(&buf->data_size, buf->output_off); return; @@ -865,7 +890,7 @@ static void pt_update_head(struct pt *pt) } else { old = (local64_xchg(&buf->head, base) & ((buf->nr_pages << PAGE_SHIFT) - 1)); - if (base < old) + if (base < old || (base == old && wrapped)) base += buf->nr_pages << PAGE_SHIFT; local_add(base - old, &buf->data_size); @@ -1511,6 +1536,7 @@ void intel_pt_interrupt(void) buf = perf_aux_output_begin(&pt->handle, event); if (!buf) { event->hw.state = PERF_HES_STOPPED; + WRITE_ONCE(pt->resume_allowed, 0); return; } @@ -1519,6 +1545,7 @@ void intel_pt_interrupt(void) ret = pt_buffer_reset_markers(buf, &pt->handle); if (ret) { perf_aux_output_end(&pt->handle, 0); + WRITE_ONCE(pt->resume_allowed, 0); return; } @@ -1557,7 +1584,7 @@ void intel_pt_handle_vmx(int on) /* Turn PTs back on */ if (!on && event) - wrmsrl(MSR_IA32_RTIT_CTL, event->hw.config); + wrmsrl(MSR_IA32_RTIT_CTL, event->hw.aux_config); local_irq_restore(flags); } @@ -1573,6 +1600,26 @@ static void pt_event_start(struct perf_event *event, int mode) struct pt *pt = this_cpu_ptr(&pt_ctx); struct pt_buffer *buf; + if (mode & PERF_EF_RESUME) { + if (READ_ONCE(pt->resume_allowed)) { + u64 status; + + /* + * Only if the trace is not active and the error and + * stopped bits are clear, is it safe to start, but a + * PMI might have just cleared these, so resume_allowed + * must be checked again also. + */ + rdmsrl(MSR_IA32_RTIT_STATUS, status); + if (!(status & (RTIT_STATUS_TRIGGEREN | + RTIT_STATUS_ERROR | + RTIT_STATUS_STOPPED)) && + READ_ONCE(pt->resume_allowed)) + pt_config_start(event); + } + return; + } + buf = perf_aux_output_begin(&pt->handle, event); if (!buf) goto fail_stop; @@ -1583,7 +1630,6 @@ static void pt_event_start(struct perf_event *event, int mode) goto fail_end_stop; } - WRITE_ONCE(pt->handle_nmi, 1); hwc->state = 0; pt_config_buffer(buf); @@ -1601,11 +1647,27 @@ static void pt_event_stop(struct perf_event *event, int mode) { struct pt *pt = this_cpu_ptr(&pt_ctx); + if (mode & PERF_EF_PAUSE) { + if (READ_ONCE(pt->pause_allowed)) + pt_config_stop(event); + return; + } + /* * Protect against the PMI racing with disabling wrmsr, * see comment in intel_pt_interrupt(). */ WRITE_ONCE(pt->handle_nmi, 0); + barrier(); + + /* + * Prevent a resume from attempting to restart tracing, or a pause + * during a subsequent start. Do this after clearing handle_nmi so that + * pt_event_snapshot_aux() will not re-allow them. + */ + WRITE_ONCE(pt->pause_allowed, 0); + WRITE_ONCE(pt->resume_allowed, 0); + barrier(); pt_config_stop(event); @@ -1656,12 +1718,15 @@ static long pt_event_snapshot_aux(struct perf_event *event, if (WARN_ON_ONCE(!buf->snapshot)) return 0; + /* Prevent pause/resume from attempting to start/stop tracing */ + WRITE_ONCE(pt->pause_allowed, 0); + WRITE_ONCE(pt->resume_allowed, 0); + barrier(); /* - * Here, handle_nmi tells us if the tracing is on + * There is no PT interrupt in this mode, so stop the trace and it will + * remain stopped while the buffer is copied. */ - if (READ_ONCE(pt->handle_nmi)) - pt_config_stop(event); - + pt_config_stop(event); pt_read_offset(buf); pt_update_head(pt); @@ -1673,12 +1738,16 @@ static long pt_event_snapshot_aux(struct perf_event *event, ret = perf_output_copy_aux(&pt->handle, handle, from, to); /* - * If the tracing was on when we turned up, restart it. - * Compiler barrier not needed as we couldn't have been - * preempted by anything that touches pt->handle_nmi. + * Here, handle_nmi tells us if the tracing was on. + * If the tracing was on, restart it. */ - if (pt->handle_nmi) + if (READ_ONCE(pt->handle_nmi)) { + WRITE_ONCE(pt->resume_allowed, 1); + barrier(); pt_config_start(event); + barrier(); + WRITE_ONCE(pt->pause_allowed, 1); + } return ret; } @@ -1794,7 +1863,9 @@ static __init int pt_init(void) if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) pt_pmu.pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG; - pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE; + pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | + PERF_PMU_CAP_ITRACE | + PERF_PMU_CAP_AUX_PAUSE; pt_pmu.pmu.attr_groups = pt_attr_groups; pt_pmu.pmu.task_ctx_nr = perf_sw_context; pt_pmu.pmu.event_init = pt_event_init; diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h index f5e46c04c145..7ee94fc6d7cb 100644 --- a/arch/x86/events/intel/pt.h +++ b/arch/x86/events/intel/pt.h @@ -65,6 +65,7 @@ struct pt_pmu { * @head: logical write offset inside the buffer * @snapshot: if this is for a snapshot/overwrite counter * @single: use Single Range Output instead of ToPA + * @wrapped: buffer advance wrapped back to the first topa table * @stop_pos: STOP topa entry index * @intr_pos: INT topa entry index * @stop_te: STOP topa entry pointer @@ -82,6 +83,7 @@ struct pt_buffer { local64_t head; bool snapshot; bool single; + bool wrapped; long stop_pos, intr_pos; struct topa_entry *stop_te, *intr_te; void **data_pages; @@ -117,6 +119,8 @@ struct pt_filters { * @filters: last configured filters * @handle_nmi: do handle PT PMI on this cpu, there's an active event * @vmx_on: 1 if VMX is ON on this cpu + * @pause_allowed: PERF_EF_PAUSE is allowed to stop tracing + * @resume_allowed: PERF_EF_RESUME is allowed to start tracing * @output_base: cached RTIT_OUTPUT_BASE MSR value * @output_mask: cached RTIT_OUTPUT_MASK MSR value */ @@ -125,6 +129,8 @@ struct pt { struct pt_filters filters; int handle_nmi; int vmx_on; + int pause_allowed; + int resume_allowed; u64 output_base; u64 output_mask; }; diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 64ca8625eb58..d98fac567684 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -1816,6 +1816,11 @@ static const struct intel_uncore_init_fun mtl_uncore_init __initconst = { .mmio_init = adl_uncore_mmio_init, }; +static const struct intel_uncore_init_fun lnl_uncore_init __initconst = { + .cpu_init = lnl_uncore_cpu_init, + .mmio_init = lnl_uncore_mmio_init, +}; + static const struct intel_uncore_init_fun icx_uncore_init __initconst = { .cpu_init = icx_uncore_cpu_init, .pci_init = icx_uncore_pci_init, @@ -1893,6 +1898,10 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = { X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &adl_uncore_init), X86_MATCH_VFM(INTEL_METEORLAKE, &mtl_uncore_init), X86_MATCH_VFM(INTEL_METEORLAKE_L, &mtl_uncore_init), + X86_MATCH_VFM(INTEL_ARROWLAKE, &mtl_uncore_init), + X86_MATCH_VFM(INTEL_ARROWLAKE_U, &mtl_uncore_init), + X86_MATCH_VFM(INTEL_ARROWLAKE_H, &mtl_uncore_init), + X86_MATCH_VFM(INTEL_LUNARLAKE_M, &lnl_uncore_init), X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, &spr_uncore_init), X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, &spr_uncore_init), X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, &gnr_uncore_init), diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index 027ef292c602..79ff32e13dcc 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h @@ -611,10 +611,12 @@ void skl_uncore_cpu_init(void); void icl_uncore_cpu_init(void); void tgl_uncore_cpu_init(void); void adl_uncore_cpu_init(void); +void lnl_uncore_cpu_init(void); void mtl_uncore_cpu_init(void); void tgl_uncore_mmio_init(void); void tgl_l_uncore_mmio_init(void); void adl_uncore_mmio_init(void); +void lnl_uncore_mmio_init(void); int snb_pci2phy_map_init(int devid); /* uncore_snbep.c */ diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c index 9462fd9f3b7a..3934e1e4e3b1 100644 --- a/arch/x86/events/intel/uncore_snb.c +++ b/arch/x86/events/intel/uncore_snb.c @@ -252,6 +252,7 @@ DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28"); DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31"); DEFINE_UNCORE_FORMAT_ATTR(threshold, threshold, "config:24-29"); +DEFINE_UNCORE_FORMAT_ATTR(threshold2, threshold, "config:24-31"); /* Sandy Bridge uncore support */ static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event) @@ -746,6 +747,34 @@ void mtl_uncore_cpu_init(void) uncore_msr_uncores = mtl_msr_uncores; } +static struct intel_uncore_type *lnl_msr_uncores[] = { + &mtl_uncore_cbox, + &mtl_uncore_arb, + NULL +}; + +#define LNL_UNC_MSR_GLOBAL_CTL 0x240e + +static void lnl_uncore_msr_init_box(struct intel_uncore_box *box) +{ + if (box->pmu->pmu_idx == 0) + wrmsrl(LNL_UNC_MSR_GLOBAL_CTL, SNB_UNC_GLOBAL_CTL_EN); +} + +static struct intel_uncore_ops lnl_uncore_msr_ops = { + .init_box = lnl_uncore_msr_init_box, + .disable_event = snb_uncore_msr_disable_event, + .enable_event = snb_uncore_msr_enable_event, + .read_counter = uncore_msr_read_counter, +}; + +void lnl_uncore_cpu_init(void) +{ + mtl_uncore_cbox.num_boxes = 4; + mtl_uncore_cbox.ops = &lnl_uncore_msr_ops; + uncore_msr_uncores = lnl_msr_uncores; +} + enum { SNB_PCI_UNCORE_IMC, }; @@ -1475,39 +1504,45 @@ static struct pci_dev *tgl_uncore_get_mc_dev(void) ids++; } + /* Just try to grab 00:00.0 device */ + if (!mc_dev) + mc_dev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); + return mc_dev; } #define TGL_UNCORE_MMIO_IMC_MEM_OFFSET 0x10000 #define TGL_UNCORE_PCI_IMC_MAP_SIZE 0xe000 -static void __uncore_imc_init_box(struct intel_uncore_box *box, - unsigned int base_offset) +static void +uncore_get_box_mmio_addr(struct intel_uncore_box *box, + unsigned int base_offset, + int bar_offset, int step) { struct pci_dev *pdev = tgl_uncore_get_mc_dev(); struct intel_uncore_pmu *pmu = box->pmu; struct intel_uncore_type *type = pmu->type; resource_size_t addr; - u32 mch_bar; + u32 bar; if (!pdev) { pr_warn("perf uncore: Cannot find matched IMC device.\n"); return; } - pci_read_config_dword(pdev, SNB_UNCORE_PCI_IMC_BAR_OFFSET, &mch_bar); - /* MCHBAR is disabled */ - if (!(mch_bar & BIT(0))) { - pr_warn("perf uncore: MCHBAR is disabled. Failed to map IMC free-running counters.\n"); + pci_read_config_dword(pdev, bar_offset, &bar); + if (!(bar & BIT(0))) { + pr_warn("perf uncore: BAR 0x%x is disabled. Failed to map %s counters.\n", + bar_offset, type->name); pci_dev_put(pdev); return; } - mch_bar &= ~BIT(0); - addr = (resource_size_t)(mch_bar + TGL_UNCORE_MMIO_IMC_MEM_OFFSET * pmu->pmu_idx); + bar &= ~BIT(0); + addr = (resource_size_t)(bar + step * pmu->pmu_idx); #ifdef CONFIG_PHYS_ADDR_T_64BIT - pci_read_config_dword(pdev, SNB_UNCORE_PCI_IMC_BAR_OFFSET + 4, &mch_bar); - addr |= ((resource_size_t)mch_bar << 32); + pci_read_config_dword(pdev, bar_offset + 4, &bar); + addr |= ((resource_size_t)bar << 32); #endif addr += base_offset; @@ -1518,6 +1553,14 @@ static void __uncore_imc_init_box(struct intel_uncore_box *box, pci_dev_put(pdev); } +static void __uncore_imc_init_box(struct intel_uncore_box *box, + unsigned int base_offset) +{ + uncore_get_box_mmio_addr(box, base_offset, + SNB_UNCORE_PCI_IMC_BAR_OFFSET, + TGL_UNCORE_MMIO_IMC_MEM_OFFSET); +} + static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box) { __uncore_imc_init_box(box, 0); @@ -1612,14 +1655,17 @@ static void adl_uncore_mmio_enable_box(struct intel_uncore_box *box) writel(0, box->io_addr + uncore_mmio_box_ctl(box)); } +#define MMIO_UNCORE_COMMON_OPS() \ + .exit_box = uncore_mmio_exit_box, \ + .disable_box = adl_uncore_mmio_disable_box, \ + .enable_box = adl_uncore_mmio_enable_box, \ + .disable_event = intel_generic_uncore_mmio_disable_event, \ + .enable_event = intel_generic_uncore_mmio_enable_event, \ + .read_counter = uncore_mmio_read_counter, + static struct intel_uncore_ops adl_uncore_mmio_ops = { .init_box = adl_uncore_imc_init_box, - .exit_box = uncore_mmio_exit_box, - .disable_box = adl_uncore_mmio_disable_box, - .enable_box = adl_uncore_mmio_enable_box, - .disable_event = intel_generic_uncore_mmio_disable_event, - .enable_event = intel_generic_uncore_mmio_enable_event, - .read_counter = uncore_mmio_read_counter, + MMIO_UNCORE_COMMON_OPS() }; #define ADL_UNC_CTL_CHMASK_MASK 0x00000f00 @@ -1703,3 +1749,108 @@ void adl_uncore_mmio_init(void) } /* end of Alder Lake MMIO uncore support */ + +/* Lunar Lake MMIO uncore support */ +#define LNL_UNCORE_PCI_SAFBAR_OFFSET 0x68 +#define LNL_UNCORE_MAP_SIZE 0x1000 +#define LNL_UNCORE_SNCU_BASE 0xE4B000 +#define LNL_UNCORE_SNCU_CTR 0x390 +#define LNL_UNCORE_SNCU_CTRL 0x398 +#define LNL_UNCORE_SNCU_BOX_CTL 0x380 +#define LNL_UNCORE_GLOBAL_CTL 0x700 +#define LNL_UNCORE_HBO_BASE 0xE54000 +#define LNL_UNCORE_HBO_OFFSET -4096 +#define LNL_UNCORE_HBO_CTR 0x570 +#define LNL_UNCORE_HBO_CTRL 0x550 +#define LNL_UNCORE_HBO_BOX_CTL 0x548 + +#define LNL_UNC_CTL_THRESHOLD 0xff000000 +#define LNL_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \ + SNB_UNC_CTL_UMASK_MASK | \ + SNB_UNC_CTL_EDGE_DET | \ + SNB_UNC_CTL_INVERT | \ + LNL_UNC_CTL_THRESHOLD) + +static struct attribute *lnl_uncore_formats_attr[] = { + &format_attr_event.attr, + &format_attr_umask.attr, + &format_attr_edge.attr, + &format_attr_inv.attr, + &format_attr_threshold2.attr, + NULL +}; + +static const struct attribute_group lnl_uncore_format_group = { + .name = "format", + .attrs = lnl_uncore_formats_attr, +}; + +static void lnl_uncore_hbo_init_box(struct intel_uncore_box *box) +{ + uncore_get_box_mmio_addr(box, LNL_UNCORE_HBO_BASE, + LNL_UNCORE_PCI_SAFBAR_OFFSET, + LNL_UNCORE_HBO_OFFSET); +} + +static struct intel_uncore_ops lnl_uncore_hbo_ops = { + .init_box = lnl_uncore_hbo_init_box, + MMIO_UNCORE_COMMON_OPS() +}; + +static struct intel_uncore_type lnl_uncore_hbo = { + .name = "hbo", + .num_counters = 4, + .num_boxes = 2, + .perf_ctr_bits = 64, + .perf_ctr = LNL_UNCORE_HBO_CTR, + .event_ctl = LNL_UNCORE_HBO_CTRL, + .event_mask = LNL_UNC_RAW_EVENT_MASK, + .box_ctl = LNL_UNCORE_HBO_BOX_CTL, + .mmio_map_size = LNL_UNCORE_MAP_SIZE, + .ops = &lnl_uncore_hbo_ops, + .format_group = &lnl_uncore_format_group, +}; + +static void lnl_uncore_sncu_init_box(struct intel_uncore_box *box) +{ + uncore_get_box_mmio_addr(box, LNL_UNCORE_SNCU_BASE, + LNL_UNCORE_PCI_SAFBAR_OFFSET, + 0); + + if (box->io_addr) + writel(ADL_UNCORE_IMC_CTL_INT, box->io_addr + LNL_UNCORE_GLOBAL_CTL); +} + +static struct intel_uncore_ops lnl_uncore_sncu_ops = { + .init_box = lnl_uncore_sncu_init_box, + MMIO_UNCORE_COMMON_OPS() +}; + +static struct intel_uncore_type lnl_uncore_sncu = { + .name = "sncu", + .num_counters = 2, + .num_boxes = 1, + .perf_ctr_bits = 64, + .perf_ctr = LNL_UNCORE_SNCU_CTR, + .event_ctl = LNL_UNCORE_SNCU_CTRL, + .event_mask = LNL_UNC_RAW_EVENT_MASK, + .box_ctl = LNL_UNCORE_SNCU_BOX_CTL, + .mmio_map_size = LNL_UNCORE_MAP_SIZE, + .ops = &lnl_uncore_sncu_ops, + .format_group = &lnl_uncore_format_group, +}; + +static struct intel_uncore_type *lnl_mmio_uncores[] = { + &adl_uncore_imc, + &lnl_uncore_hbo, + &lnl_uncore_sncu, + &adl_uncore_imc_free_running, + NULL +}; + +void lnl_uncore_mmio_init(void) +{ + uncore_mmio_uncores = lnl_mmio_uncores; +} + +/* end of Lunar Lake MMIO uncore support */ diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index ac1182141bf6..82c6f45ce975 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -668,24 +668,38 @@ enum { #define PERF_PEBS_DATA_SOURCE_GRT_MAX 0x10 #define PERF_PEBS_DATA_SOURCE_GRT_MASK (PERF_PEBS_DATA_SOURCE_GRT_MAX - 1) +/* + * CPUID.1AH.EAX[31:0] uniquely identifies the microarchitecture + * of the core. Bits 31-24 indicates its core type (Core or Atom) + * and Bits [23:0] indicates the native model ID of the core. + * Core type and native model ID are defined in below enumerations. + */ enum hybrid_cpu_type { HYBRID_INTEL_NONE, HYBRID_INTEL_ATOM = 0x20, HYBRID_INTEL_CORE = 0x40, }; +#define X86_HYBRID_PMU_ATOM_IDX 0 +#define X86_HYBRID_PMU_CORE_IDX 1 +#define X86_HYBRID_PMU_TINY_IDX 2 + enum hybrid_pmu_type { not_hybrid, - hybrid_small = BIT(0), - hybrid_big = BIT(1), - - hybrid_big_small = hybrid_big | hybrid_small, /* only used for matching */ + hybrid_small = BIT(X86_HYBRID_PMU_ATOM_IDX), + hybrid_big = BIT(X86_HYBRID_PMU_CORE_IDX), + hybrid_tiny = BIT(X86_HYBRID_PMU_TINY_IDX), + + /* The belows are only used for matching */ + hybrid_big_small = hybrid_big | hybrid_small, + hybrid_small_tiny = hybrid_small | hybrid_tiny, + hybrid_big_small_tiny = hybrid_big | hybrid_small_tiny, }; -#define X86_HYBRID_PMU_ATOM_IDX 0 -#define X86_HYBRID_PMU_CORE_IDX 1 - -#define X86_HYBRID_NUM_PMUS 2 +enum atom_native_id { + cmt_native_id = 0x2, /* Crestmont */ + skt_native_id = 0x3, /* Skymont */ +}; struct x86_hybrid_pmu { struct pmu pmu; @@ -1578,6 +1592,8 @@ u64 cmt_latency_data(struct perf_event *event, u64 status); u64 lnl_latency_data(struct perf_event *event, u64 status); +u64 arl_h_latency_data(struct perf_event *event, u64 status); + extern struct event_constraint intel_core2_pebs_event_constraints[]; extern struct event_constraint intel_atom_pebs_event_constraints[]; @@ -1697,6 +1713,8 @@ void intel_pmu_pebs_data_source_grt(void); void intel_pmu_pebs_data_source_mtl(void); +void intel_pmu_pebs_data_source_arl_h(void); + void intel_pmu_pebs_data_source_cmt(void); void intel_pmu_pebs_data_source_lnl(void); diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c index b985ca79cf97..a8defc813c36 100644 --- a/arch/x86/events/rapl.c +++ b/arch/x86/events/rapl.c @@ -103,6 +103,19 @@ static struct perf_pmu_events_attr event_attr_##v = { \ .event_str = str, \ }; +/* + * RAPL Package energy counter scope: + * 1. AMD/HYGON platforms have a per-PKG package energy counter + * 2. For Intel platforms + * 2.1. CLX-AP is multi-die and its RAPL MSRs are die-scope + * 2.2. Other Intel platforms are single die systems so the scope can be + * considered as either pkg-scope or die-scope, and we are considering + * them as die-scope. + */ +#define rapl_pmu_is_pkg_scope() \ + (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || \ + boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) + struct rapl_pmu { raw_spinlock_t lock; int n_active; @@ -135,14 +148,29 @@ struct rapl_model { /* 1/2^hw_unit Joule */ static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly; static struct rapl_pmus *rapl_pmus; -static cpumask_t rapl_cpu_mask; static unsigned int rapl_cntr_mask; static u64 rapl_timer_ms; static struct perf_msr *rapl_msrs; +/* + * Helper functions to get the correct topology macros according to the + * RAPL PMU scope. + */ +static inline unsigned int get_rapl_pmu_idx(int cpu) +{ + return rapl_pmu_is_pkg_scope() ? topology_logical_package_id(cpu) : + topology_logical_die_id(cpu); +} + +static inline const struct cpumask *get_rapl_pmu_cpumask(int cpu) +{ + return rapl_pmu_is_pkg_scope() ? topology_core_cpumask(cpu) : + topology_die_cpumask(cpu); +} + static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu) { - unsigned int rapl_pmu_idx = topology_logical_die_id(cpu); + unsigned int rapl_pmu_idx = get_rapl_pmu_idx(cpu); /* * The unsigned check also catches the '-1' return value for non @@ -340,8 +368,6 @@ static int rapl_pmu_event_init(struct perf_event *event) if (event->cpu < 0) return -EINVAL; - event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG; - if (!cfg || cfg >= NR_RAPL_DOMAINS + 1) return -EINVAL; @@ -360,7 +386,6 @@ static int rapl_pmu_event_init(struct perf_event *event) pmu = cpu_to_rapl_pmu(event->cpu); if (!pmu) return -EINVAL; - event->cpu = pmu->cpu; event->pmu_private = pmu; event->hw.event_base = rapl_msrs[bit].msr; event->hw.config = cfg; @@ -374,23 +399,6 @@ static void rapl_pmu_event_read(struct perf_event *event) rapl_event_update(event); } -static ssize_t rapl_get_attr_cpumask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return cpumap_print_to_pagebuf(true, buf, &rapl_cpu_mask); -} - -static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL); - -static struct attribute *rapl_pmu_attrs[] = { - &dev_attr_cpumask.attr, - NULL, -}; - -static struct attribute_group rapl_pmu_attr_group = { - .attrs = rapl_pmu_attrs, -}; - RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); @@ -438,7 +446,6 @@ static struct attribute_group rapl_pmu_format_group = { }; static const struct attribute_group *rapl_attr_groups[] = { - &rapl_pmu_attr_group, &rapl_pmu_format_group, &rapl_pmu_events_group, NULL, @@ -541,60 +548,6 @@ static struct perf_msr amd_rapl_msrs[] = { [PERF_RAPL_PSYS] = { 0, &rapl_events_psys_group, NULL, false, 0 }, }; -static int rapl_cpu_offline(unsigned int cpu) -{ - struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu); - int target; - - /* Check if exiting cpu is used for collecting rapl events */ - if (!cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask)) - return 0; - - pmu->cpu = -1; - /* Find a new cpu to collect rapl events */ - target = cpumask_any_but(topology_die_cpumask(cpu), cpu); - - /* Migrate rapl events to the new target */ - if (target < nr_cpu_ids) { - cpumask_set_cpu(target, &rapl_cpu_mask); - pmu->cpu = target; - perf_pmu_migrate_context(pmu->pmu, cpu, target); - } - return 0; -} - -static int rapl_cpu_online(unsigned int cpu) -{ - struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu); - int target; - - if (!pmu) { - pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu)); - if (!pmu) - return -ENOMEM; - - raw_spin_lock_init(&pmu->lock); - INIT_LIST_HEAD(&pmu->active_list); - pmu->pmu = &rapl_pmus->pmu; - pmu->timer_interval = ms_to_ktime(rapl_timer_ms); - rapl_hrtimer_init(pmu); - - rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu; - } - - /* - * Check if there is an online cpu in the package which collects rapl - * events already. - */ - target = cpumask_any_and(&rapl_cpu_mask, topology_die_cpumask(cpu)); - if (target < nr_cpu_ids) - return 0; - - cpumask_set_cpu(cpu, &rapl_cpu_mask); - pmu->cpu = cpu; - return 0; -} - static int rapl_check_hw_unit(struct rapl_model *rm) { u64 msr_rapl_power_unit_bits; @@ -673,9 +626,41 @@ static const struct attribute_group *rapl_attr_update[] = { NULL, }; +static int __init init_rapl_pmu(void) +{ + struct rapl_pmu *pmu; + int idx; + + for (idx = 0; idx < rapl_pmus->nr_rapl_pmu; idx++) { + pmu = kzalloc(sizeof(*pmu), GFP_KERNEL); + if (!pmu) + goto free; + + raw_spin_lock_init(&pmu->lock); + INIT_LIST_HEAD(&pmu->active_list); + pmu->pmu = &rapl_pmus->pmu; + pmu->timer_interval = ms_to_ktime(rapl_timer_ms); + rapl_hrtimer_init(pmu); + + rapl_pmus->pmus[idx] = pmu; + } + + return 0; +free: + for (; idx > 0; idx--) + kfree(rapl_pmus->pmus[idx - 1]); + return -ENOMEM; +} + static int __init init_rapl_pmus(void) { - int nr_rapl_pmu = topology_max_packages() * topology_max_dies_per_package(); + int nr_rapl_pmu = topology_max_packages(); + int rapl_pmu_scope = PERF_PMU_SCOPE_PKG; + + if (!rapl_pmu_is_pkg_scope()) { + nr_rapl_pmu *= topology_max_dies_per_package(); + rapl_pmu_scope = PERF_PMU_SCOPE_DIE; + } rapl_pmus = kzalloc(struct_size(rapl_pmus, pmus, nr_rapl_pmu), GFP_KERNEL); if (!rapl_pmus) @@ -691,9 +676,11 @@ static int __init init_rapl_pmus(void) rapl_pmus->pmu.start = rapl_pmu_event_start; rapl_pmus->pmu.stop = rapl_pmu_event_stop; rapl_pmus->pmu.read = rapl_pmu_event_read; + rapl_pmus->pmu.scope = rapl_pmu_scope; rapl_pmus->pmu.module = THIS_MODULE; rapl_pmus->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE; - return 0; + + return init_rapl_pmu(); } static struct rapl_model model_snb = { @@ -839,24 +826,13 @@ static int __init rapl_pmu_init(void) if (ret) return ret; - /* - * Install callbacks. Core will call them for each online cpu. - */ - ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE, - "perf/x86/rapl:online", - rapl_cpu_online, rapl_cpu_offline); - if (ret) - goto out; - ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1); if (ret) - goto out1; + goto out; rapl_advertise(); return 0; -out1: - cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE); out: pr_warn("Initialization failed (%d), disabled\n", ret); cleanup_rapl_pmus(); @@ -866,7 +842,6 @@ module_init(rapl_pmu_init); static void __exit intel_rapl_exit(void) { - cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE); perf_pmu_unregister(&rapl_pmus->pmu); cleanup_rapl_pmus(); } diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 17a71e92a343..95eada2994e1 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -35,7 +35,6 @@ #include <clocksource/hyperv_timer.h> #include <linux/highmem.h> -int hyperv_init_cpuhp; u64 hv_current_partition_id = ~0ull; EXPORT_SYMBOL_GPL(hv_current_partition_id); @@ -607,8 +606,6 @@ skip_hypercall_pg_init: register_syscore_ops(&hv_syscore_ops); - hyperv_init_cpuhp = cpuhp; - if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) hv_get_partition_id(); @@ -637,7 +634,7 @@ skip_hypercall_pg_init: clean_guest_os_id: wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0); - cpuhp_remove_state(cpuhp); + cpuhp_remove_state(CPUHP_AP_HYPERV_ONLINE); free_ghcb_page: free_percpu(hv_ghcb_pg); free_vp_assist_page: diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index b4a851d27c7c..60fc3ed72830 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -321,9 +321,9 @@ int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) vmsa->efer = native_read_msr(MSR_EFER); - asm volatile("movq %%cr4, %%rax;" : "=a" (vmsa->cr4)); - asm volatile("movq %%cr3, %%rax;" : "=a" (vmsa->cr3)); - asm volatile("movq %%cr0, %%rax;" : "=a" (vmsa->cr0)); + vmsa->cr4 = native_read_cr4(); + vmsa->cr3 = __native_read_cr3(); + vmsa->cr0 = native_read_cr0(); vmsa->xcr0 = 1; vmsa->g_pat = HV_AP_INIT_GPAT_DEFAULT; diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild index a192bdea69e2..6c23d1661b17 100644 --- a/arch/x86/include/asm/Kbuild +++ b/arch/x86/include/asm/Kbuild @@ -11,3 +11,4 @@ generated-y += xen-hypercalls.h generic-y += early_ioremap.h generic-y += mcs_spinlock.h +generic-y += mmzone.h diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 21bc53f5ed0c..5ab1a4598d00 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -174,6 +174,14 @@ void acpi_generic_reduced_hw_init(void); void x86_default_set_root_pointer(u64 addr); u64 x86_default_get_root_pointer(void); +#ifdef CONFIG_XEN_PV +/* A Xen PV domain needs a special acpi_os_ioremap() handling. */ +extern void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, + acpi_size size); +void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size); +#define acpi_os_ioremap acpi_os_ioremap +#endif + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 6f3b6aef47ba..d0caac26533f 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h @@ -116,7 +116,10 @@ static inline bool amd_gart_present(void) #define amd_nb_num(x) 0 #define amd_nb_has_feature(x) false -#define node_to_amd_nb(x) NULL +static inline struct amd_northbridge *node_to_amd_nb(int node) +{ + return NULL; +} #define amd_gart_present(x) false #endif diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 9327eb00e96d..f21ff1932699 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -18,6 +18,11 @@ #define ARCH_APICTIMER_STOPS_ON_C3 1 +/* Macros for apic_extnmi which controls external NMI masking */ +#define APIC_EXTNMI_BSP 0 /* Default */ +#define APIC_EXTNMI_ALL 1 +#define APIC_EXTNMI_NONE 2 + /* * Debugging macros */ @@ -25,22 +30,22 @@ #define APIC_VERBOSE 1 #define APIC_DEBUG 2 -/* Macros for apic_extnmi which controls external NMI masking */ -#define APIC_EXTNMI_BSP 0 /* Default */ -#define APIC_EXTNMI_ALL 1 -#define APIC_EXTNMI_NONE 2 - /* - * Define the default level of output to be very little - * This can be turned up by using apic=verbose for more - * information and apic=debug for _lots_ of information. - * apic_verbosity is defined in apic.c + * Define the default level of output to be very little This can be turned + * up by using apic=verbose for more information and apic=debug for _lots_ + * of information. apic_verbosity is defined in apic.c */ -#define apic_printk(v, s, a...) do { \ - if ((v) <= apic_verbosity) \ - printk(s, ##a); \ - } while (0) - +#define apic_printk(v, s, a...) \ +do { \ + if ((v) <= apic_verbosity) \ + printk(s, ##a); \ +} while (0) + +#define apic_pr_verbose(s, a...) apic_printk(APIC_VERBOSE, KERN_INFO s, ##a) +#define apic_pr_debug(s, a...) apic_printk(APIC_DEBUG, KERN_DEBUG s, ##a) +#define apic_pr_debug_cont(s, a...) apic_printk(APIC_DEBUG, KERN_CONT s, ##a) +/* Unconditional debug prints for code which is guarded by apic_verbosity already */ +#define apic_dbg(s, a...) printk(KERN_DEBUG s, ##a) #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) extern void x86_32_probe_apic(void); @@ -122,8 +127,6 @@ static inline bool apic_is_x2apic_enabled(void) extern void enable_IR_x2apic(void); -extern int get_physical_broadcast(void); - extern int lapic_get_maxlvt(void); extern void clear_local_APIC(void); extern void disconnect_bsp_APIC(int virt_wire_setup); @@ -345,20 +348,12 @@ extern struct apic *apic; * APIC drivers are probed based on how they are listed in the .apicdrivers * section. So the order is important and enforced by the ordering * of different apic driver files in the Makefile. - * - * For the files having two apic drivers, we use apic_drivers() - * to enforce the order with in them. */ #define apic_driver(sym) \ static const struct apic *__apicdrivers_##sym __used \ __aligned(sizeof(struct apic *)) \ __section(".apicdrivers") = { &sym } -#define apic_drivers(sym1, sym2) \ - static struct apic *__apicdrivers_##sym1##sym2[2] __used \ - __aligned(sizeof(struct apic *)) \ - __section(".apicdrivers") = { &sym1, &sym2 } - extern struct apic *__apicdrivers[], *__apicdrivers_end[]; /* @@ -484,7 +479,6 @@ static inline u64 apic_icr_read(void) { return 0; } static inline void apic_icr_write(u32 low, u32 high) { } static inline void apic_wait_icr_idle(void) { } static inline u32 safe_apic_wait_icr_idle(void) { return 0; } -static inline void apic_set_eoi_cb(void (*eoi)(void)) {} static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); } static inline void apic_setup_apic_calls(void) { } @@ -512,8 +506,6 @@ static inline bool is_vector_pending(unsigned int vector) #define TRAMPOLINE_PHYS_LOW 0x467 #define TRAMPOLINE_PHYS_HIGH 0x469 -extern void generic_bigsmp_probe(void); - #ifdef CONFIG_X86_LOCAL_APIC #include <asm/smp.h> @@ -536,8 +528,6 @@ static inline int default_acpi_madt_oem_check(char *a, char *b) { return 0; } static inline void x86_64_probe_apic(void) { } #endif -extern int default_apic_id_valid(u32 apicid); - extern u32 apic_default_calc_apicid(unsigned int cpu); extern u32 apic_flat_calc_apicid(unsigned int cpu); diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h index 25466c4d2134..3674006e3974 100644 --- a/arch/x86/include/asm/asm-prototypes.h +++ b/arch/x86/include/asm/asm-prototypes.h @@ -20,3 +20,6 @@ extern void cmpxchg8b_emu(void); #endif +#if defined(__GENKSYMS__) && defined(CONFIG_STACKPROTECTOR) +extern unsigned long __ref_stack_chk_guard; +#endif diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index 8db2ec4d6cda..6c6e9b9f98a4 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h @@ -51,7 +51,8 @@ static __always_inline s64 arch_atomic64_read_nonatomic(const atomic64_t *v) #ifdef CONFIG_X86_CMPXCHG64 #define __alternative_atomic64(f, g, out, in...) \ asm volatile("call %c[func]" \ - : out : [func] "i" (atomic64_##g##_cx8), ## in) + : ALT_OUTPUT_SP(out) \ + : [func] "i" (atomic64_##g##_cx8), ## in) #define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8) #else @@ -163,20 +164,18 @@ static __always_inline s64 arch_atomic64_dec_return(atomic64_t *v) } #define arch_atomic64_dec_return arch_atomic64_dec_return -static __always_inline s64 arch_atomic64_add(s64 i, atomic64_t *v) +static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v) { __alternative_atomic64(add, add_return, ASM_OUTPUT2("+A" (i), "+c" (v)), ASM_NO_INPUT_CLOBBER("memory")); - return i; } -static __always_inline s64 arch_atomic64_sub(s64 i, atomic64_t *v) +static __always_inline void arch_atomic64_sub(s64 i, atomic64_t *v) { __alternative_atomic64(sub, sub_return, ASM_OUTPUT2("+A" (i), "+c" (v)), ASM_NO_INPUT_CLOBBER("memory")); - return i; } static __always_inline void arch_atomic64_inc(atomic64_t *v) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index a3ec87d198ac..806649c7f23d 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -13,6 +13,18 @@ #define INSN_UD2 0x0b0f #define LEN_UD2 2 +/* + * In clang we have UD1s reporting UBSAN failures on X86, 64 and 32bit. + */ +#define INSN_ASOP 0x67 +#define OPCODE_ESCAPE 0x0f +#define SECOND_BYTE_OPCODE_UD1 0xb9 +#define SECOND_BYTE_OPCODE_UD2 0x0b + +#define BUG_NONE 0xffff +#define BUG_UD1 0xfffe +#define BUG_UD2 0xfffd + #ifdef CONFIG_GENERIC_BUG #ifdef CONFIG_X86_32 diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index 62cef2113ca7..fd1282a783dd 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -94,7 +94,7 @@ static __always_inline bool __try_cmpxchg64_local(volatile u64 *ptr, u64 *oldp, asm volatile(ALTERNATIVE(_lock_loc \ "call cmpxchg8b_emu", \ _lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \ - : "+a" (o.low), "+d" (o.high) \ + : ALT_OUTPUT_SP("+a" (o.low), "+d" (o.high)) \ : "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \ : "memory"); \ \ @@ -123,8 +123,8 @@ static __always_inline u64 arch_cmpxchg64_local(volatile u64 *ptr, u64 old, u64 "call cmpxchg8b_emu", \ _lock "cmpxchg8b %a[ptr]", X86_FEATURE_CX8) \ CC_SET(e) \ - : CC_OUT(e) (ret), \ - "+a" (o.low), "+d" (o.high) \ + : ALT_OUTPUT_SP(CC_OUT(e) (ret), \ + "+a" (o.low), "+d" (o.high)) \ : "b" (n.low), "c" (n.high), [ptr] "S" (_ptr) \ : "memory"); \ \ diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index aa30fd8cad7f..98eced5084ca 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -26,12 +26,13 @@ int mwait_usable(const struct cpuinfo_x86 *); unsigned int x86_family(unsigned int sig); unsigned int x86_model(unsigned int sig); unsigned int x86_stepping(unsigned int sig); -#ifdef CONFIG_CPU_SUP_INTEL +#ifdef CONFIG_X86_BUS_LOCK_DETECT extern void __init sld_setup(struct cpuinfo_x86 *c); extern bool handle_user_split_lock(struct pt_regs *regs, long error_code); extern bool handle_guest_split_lock(unsigned long ip); extern void handle_bus_lock(struct pt_regs *regs); -u8 get_this_hybrid_cpu_type(void); +void split_lock_init(void); +void bus_lock_init(void); #else static inline void __init sld_setup(struct cpuinfo_x86 *c) {} static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code) @@ -45,11 +46,23 @@ static inline bool handle_guest_split_lock(unsigned long ip) } static inline void handle_bus_lock(struct pt_regs *regs) {} +static inline void split_lock_init(void) {} +static inline void bus_lock_init(void) {} +#endif +#ifdef CONFIG_CPU_SUP_INTEL +u8 get_this_hybrid_cpu_type(void); +u32 get_this_hybrid_cpu_native_id(void); +#else static inline u8 get_this_hybrid_cpu_type(void) { return 0; } + +static inline u32 get_this_hybrid_cpu_native_id(void) +{ + return 0; +} #endif #ifdef CONFIG_IA32_FEAT_CTL void init_ia32_feat_ctl(struct cpuinfo_x86 *c); diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h index 3831f612e89c..e4121d9aa9e1 100644 --- a/arch/x86/include/asm/cpu_device_id.h +++ b/arch/x86/include/asm/cpu_device_id.h @@ -193,26 +193,6 @@ X86_MATCH_VENDOR_FAM_MODEL(vendor, family, X86_MODEL_ANY, data) /** - * X86_MATCH_INTEL_FAM6_MODEL - Match vendor INTEL, family 6 and model - * @model: The model name without the INTEL_FAM6_ prefix or ANY - * The model name is expanded to INTEL_FAM6_@model internally - * @data: Driver specific data or NULL. The internal storage - * format is unsigned long. The supplied value, pointer - * etc. is casted to unsigned long internally. - * - * The vendor is set to INTEL, the family to 6 and all other missing - * arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are set to wildcards. - * - * See X86_MATCH_VENDOR_FAM_MODEL_FEATURE() for further information. - */ -#define X86_MATCH_INTEL_FAM6_MODEL(model, data) \ - X86_MATCH_VENDOR_FAM_MODEL(INTEL, 6, INTEL_FAM6_##model, data) - -#define X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(model, steppings, data) \ - X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6, INTEL_FAM6_##model, \ - steppings, X86_FEATURE_ANY, data) - -/** * X86_MATCH_VFM - Match encoded vendor/family/model * @vfm: Encoded 8-bits each for vendor, family, model * @data: Driver specific data or NULL. The internal storage diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index dd4682857c12..ea33439a5d00 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -215,7 +215,7 @@ #define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* Disable Speculative Store Bypass. */ #define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* AMD SSBD implementation via LS_CFG MSR */ #define X86_FEATURE_IBRS ( 7*32+25) /* "ibrs" Indirect Branch Restricted Speculation */ -#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier */ +#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier without a guaranteed RSB flush */ #define X86_FEATURE_STIBP ( 7*32+27) /* "stibp" Single Thread Indirect Branch Predictors */ #define X86_FEATURE_ZEN ( 7*32+28) /* Generic flag for all Zen and newer */ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* L1TF workaround PTE inversion */ @@ -348,6 +348,7 @@ #define X86_FEATURE_CPPC (13*32+27) /* "cppc" Collaborative Processor Performance Control */ #define X86_FEATURE_AMD_PSFD (13*32+28) /* Predictive Store Forwarding Disable */ #define X86_FEATURE_BTC_NO (13*32+29) /* Not vulnerable to Branch Type Confusion */ +#define X86_FEATURE_AMD_IBPB_RET (13*32+30) /* IBPB clears return address predictor */ #define X86_FEATURE_BRS (13*32+31) /* "brs" Branch Sampling available */ /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */ @@ -472,7 +473,9 @@ #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */ #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */ #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */ -#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */ +#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */ +#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */ +#define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32 + 7) /* Workload Classification */ /* * BUG word(s) @@ -523,4 +526,5 @@ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* "div0" AMD DIV0 speculation bug */ #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* "rfds" CPU is vulnerable to Register File Data Sampling */ #define X86_BUG_BHI X86_BUG(1*32 + 3) /* "bhi" CPU is affected by Branch History Injection */ +#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/cpuid.h b/arch/x86/include/asm/cpuid.h index 6b122a31da06..ca4243318aad 100644 --- a/arch/x86/include/asm/cpuid.h +++ b/arch/x86/include/asm/cpuid.h @@ -179,6 +179,7 @@ static __always_inline bool cpuid_function_is_indexed(u32 function) case 0x1d: case 0x1e: case 0x1f: + case 0x24: case 0x8000001d: return true; } @@ -196,7 +197,12 @@ static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) for_each_possible_hypervisor_cpuid_base(base) { cpuid(base, &eax, &signature[0], &signature[1], &signature[2]); - if (!memcmp(sig, signature, 12) && + /* + * This must not compile to "call memcmp" because it's called + * from PVH early boot code before instrumentation is set up + * and memcmp() itself may be instrumented. + */ + if (!__builtin_memcmp(sig, signature, 12) && (leaves == 0 || ((eax - base) >= leaves))) return base; } diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h index fb2809b20b0a..77d20555e04d 100644 --- a/arch/x86/include/asm/entry-common.h +++ b/arch/x86/include/asm/entry-common.h @@ -8,6 +8,7 @@ #include <asm/nospec-branch.h> #include <asm/io_bitmap.h> #include <asm/fpu/api.h> +#include <asm/fred.h> /* Check that the stack and regs on entry from user mode are sane. */ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs) @@ -44,8 +45,7 @@ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs) } #define arch_enter_from_user_mode arch_enter_from_user_mode -static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, - unsigned long ti_work) +static inline void arch_exit_work(unsigned long ti_work) { if (ti_work & _TIF_USER_RETURN_NOTIFY) fire_user_return_notifiers(); @@ -56,6 +56,15 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, fpregs_assert_state_consistent(); if (unlikely(ti_work & _TIF_NEED_FPU_LOAD)) switch_fpu_return(); +} + +static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs, + unsigned long ti_work) +{ + if (IS_ENABLED(CONFIG_X86_DEBUG_FPU) || unlikely(ti_work)) + arch_exit_work(ti_work); + + fred_update_rsp0(); #ifdef CONFIG_COMPAT /* diff --git a/arch/x86/include/asm/extable.h b/arch/x86/include/asm/extable.h index eeed395c3177..a0e0c6b50155 100644 --- a/arch/x86/include/asm/extable.h +++ b/arch/x86/include/asm/extable.h @@ -37,7 +37,6 @@ struct pt_regs; extern int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, unsigned long fault_addr); -extern int fixup_bug(struct pt_regs *regs, int trapnr); extern int ex_get_fixup_type(unsigned long ip); extern void early_fixup_exception(struct pt_regs *regs, int trapnr); diff --git a/arch/x86/include/asm/fpu/signal.h b/arch/x86/include/asm/fpu/signal.h index 611fa41711af..eccc75bc9c4f 100644 --- a/arch/x86/include/asm/fpu/signal.h +++ b/arch/x86/include/asm/fpu/signal.h @@ -29,7 +29,7 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long fpu__get_fpstate_size(void); -extern bool copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size); +extern bool copy_fpstate_to_sigframe(void __user *buf, void __user *fp, int size, u32 pkru); extern void fpu__clear_user_states(struct fpu *fpu); extern bool fpu__restore_sig(void __user *buf, int ia32_frame); diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h index eb17f31b06d2..de16862bf230 100644 --- a/arch/x86/include/asm/fpu/types.h +++ b/arch/x86/include/asm/fpu/types.h @@ -591,6 +591,13 @@ struct fpu_state_config { * even without XSAVE support, i.e. legacy features FP + SSE */ u64 legacy_features; + /* + * @independent_features: + * + * Features that are supported by XSAVES, but not managed as part of + * the FPU core, such as LBR + */ + u64 independent_features; }; /* FPU state configuration information */ diff --git a/arch/x86/include/asm/fred.h b/arch/x86/include/asm/fred.h index e86c7ba32435..25ca00bd70e8 100644 --- a/arch/x86/include/asm/fred.h +++ b/arch/x86/include/asm/fred.h @@ -36,6 +36,7 @@ #ifdef CONFIG_X86_FRED #include <linux/kernel.h> +#include <linux/sched/task_stack.h> #include <asm/ptrace.h> @@ -84,13 +85,33 @@ static __always_inline void fred_entry_from_kvm(unsigned int type, unsigned int } void cpu_init_fred_exceptions(void); +void cpu_init_fred_rsps(void); void fred_complete_exception_setup(void); +DECLARE_PER_CPU(unsigned long, fred_rsp0); + +static __always_inline void fred_sync_rsp0(unsigned long rsp0) +{ + __this_cpu_write(fred_rsp0, rsp0); +} + +static __always_inline void fred_update_rsp0(void) +{ + unsigned long rsp0 = (unsigned long) task_stack_page(current) + THREAD_SIZE; + + if (cpu_feature_enabled(X86_FEATURE_FRED) && (__this_cpu_read(fred_rsp0) != rsp0)) { + wrmsrns(MSR_IA32_FRED_RSP0, rsp0); + __this_cpu_write(fred_rsp0, rsp0); + } +} #else /* CONFIG_X86_FRED */ static __always_inline unsigned long fred_event_data(struct pt_regs *regs) { return 0; } static inline void cpu_init_fred_exceptions(void) { } +static inline void cpu_init_fred_rsps(void) { } static inline void fred_complete_exception_setup(void) { } -static __always_inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { } +static inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { } +static inline void fred_sync_rsp0(unsigned long rsp0) { } +static inline void fred_update_rsp0(void) { } #endif /* CONFIG_X86_FRED */ #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 0152a81d9b4a..6e8cf0fa48fc 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_FTRACE_H #define _ASM_X86_FTRACE_H +#include <asm/ptrace.h> + #ifdef CONFIG_FUNCTION_TRACER #ifndef CC_USING_FENTRY # error Compiler does not support fentry? @@ -33,37 +35,21 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) } #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS -struct ftrace_regs { - struct pt_regs regs; -}; + +#include <linux/ftrace_regs.h> static __always_inline struct pt_regs * arch_ftrace_get_regs(struct ftrace_regs *fregs) { /* Only when FL_SAVE_REGS is set, cs will be non zero */ - if (!fregs->regs.cs) + if (!arch_ftrace_regs(fregs)->regs.cs) return NULL; - return &fregs->regs; + return &arch_ftrace_regs(fregs)->regs; } #define ftrace_regs_set_instruction_pointer(fregs, _ip) \ - do { (fregs)->regs.ip = (_ip); } while (0) - -#define ftrace_regs_get_instruction_pointer(fregs) \ - ((fregs)->regs.ip) - -#define ftrace_regs_get_argument(fregs, n) \ - regs_get_kernel_argument(&(fregs)->regs, n) -#define ftrace_regs_get_stack_pointer(fregs) \ - kernel_stack_pointer(&(fregs)->regs) -#define ftrace_regs_return_value(fregs) \ - regs_return_value(&(fregs)->regs) -#define ftrace_regs_set_return_value(fregs, ret) \ - regs_set_return_value(&(fregs)->regs, ret) -#define ftrace_override_function_with_return(fregs) \ - override_function_with_return(&(fregs)->regs) -#define ftrace_regs_query_register_offset(name) \ - regs_query_register_offset(name) + do { arch_ftrace_regs(fregs)->regs.ip = (_ip); } while (0) + struct ftrace_ops; #define ftrace_graph_func ftrace_graph_func @@ -88,7 +74,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) regs->orig_ax = addr; } #define arch_ftrace_set_direct_caller(fregs, addr) \ - __arch_ftrace_set_direct_caller(&(fregs)->regs, addr) + __arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr) #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ #ifdef CONFIG_DYNAMIC_FTRACE diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index c67fa6ad098a..6ffa8b75f4cd 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -69,7 +69,11 @@ extern u64 arch_irq_stat(void); #define local_softirq_pending_ref pcpu_hot.softirq_pending #if IS_ENABLED(CONFIG_KVM_INTEL) -static inline void kvm_set_cpu_l1tf_flush_l1d(void) +/* + * This function is called from noinstr interrupt contexts + * and must be inlined to not get instrumentation. + */ +static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) { __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); } @@ -84,7 +88,7 @@ static __always_inline bool kvm_get_cpu_l1tf_flush_l1d(void) return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); } #else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ -static inline void kvm_set_cpu_l1tf_flush_l1d(void) { } +static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) { } #endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ #endif /* _ASM_X86_HARDIRQ_H */ diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index d4f24499b256..ad5c68f0509d 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -212,8 +212,8 @@ __visible noinstr void func(struct pt_regs *regs, \ irqentry_state_t state = irqentry_enter(regs); \ u32 vector = (u32)(u8)error_code; \ \ + kvm_set_cpu_l1tf_flush_l1d(); \ instrumentation_begin(); \ - kvm_set_cpu_l1tf_flush_l1d(); \ run_irq_on_irqstack_cond(__##func, regs, vector); \ instrumentation_end(); \ irqentry_exit(regs, state); \ @@ -250,7 +250,6 @@ static void __##func(struct pt_regs *regs); \ \ static __always_inline void instr_##func(struct pt_regs *regs) \ { \ - kvm_set_cpu_l1tf_flush_l1d(); \ run_sysvec_on_irqstack_cond(__##func, regs); \ } \ \ @@ -258,6 +257,7 @@ __visible noinstr void func(struct pt_regs *regs) \ { \ irqentry_state_t state = irqentry_enter(regs); \ \ + kvm_set_cpu_l1tf_flush_l1d(); \ instrumentation_begin(); \ instr_##func (regs); \ instrumentation_end(); \ @@ -288,7 +288,6 @@ static __always_inline void __##func(struct pt_regs *regs); \ static __always_inline void instr_##func(struct pt_regs *regs) \ { \ __irq_enter_raw(); \ - kvm_set_cpu_l1tf_flush_l1d(); \ __##func (regs); \ __irq_exit_raw(); \ } \ @@ -297,6 +296,7 @@ __visible noinstr void func(struct pt_regs *regs) \ { \ irqentry_state_t state = irqentry_enter(regs); \ \ + kvm_set_cpu_l1tf_flush_l1d(); \ instrumentation_begin(); \ instr_##func (regs); \ instrumentation_end(); \ diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index f81a851c46dc..6d7b04ffc5fd 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -10,7 +10,7 @@ * that group keep the CPUID for the variants sorted by model number. * * The defined symbol names have the following form: - * INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF} + * INTEL_{OPTFAMILY}_{MICROARCH}{OPTDIFF} * where: * OPTFAMILY Describes the family of CPUs that this belongs to. Default * is assumed to be "_CORE" (and should be omitted). Other values @@ -42,219 +42,150 @@ #define IFM(_fam, _model) VFM_MAKE(X86_VENDOR_INTEL, _fam, _model) -/* Wildcard match for FAM6 so X86_MATCH_INTEL_FAM6_MODEL(ANY) works */ -#define INTEL_FAM6_ANY X86_MODEL_ANY -/* Wildcard match for FAM6 so X86_MATCH_VFM(ANY) works */ +/* Wildcard match so X86_MATCH_VFM(ANY) works */ #define INTEL_ANY IFM(X86_FAMILY_ANY, X86_MODEL_ANY) -#define INTEL_FAM6_CORE_YONAH 0x0E +#define INTEL_PENTIUM_PRO IFM(6, 0x01) + #define INTEL_CORE_YONAH IFM(6, 0x0E) -#define INTEL_FAM6_CORE2_MEROM 0x0F #define INTEL_CORE2_MEROM IFM(6, 0x0F) -#define INTEL_FAM6_CORE2_MEROM_L 0x16 #define INTEL_CORE2_MEROM_L IFM(6, 0x16) -#define INTEL_FAM6_CORE2_PENRYN 0x17 #define INTEL_CORE2_PENRYN IFM(6, 0x17) -#define INTEL_FAM6_CORE2_DUNNINGTON 0x1D #define INTEL_CORE2_DUNNINGTON IFM(6, 0x1D) -#define INTEL_FAM6_NEHALEM 0x1E #define INTEL_NEHALEM IFM(6, 0x1E) -#define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ #define INTEL_NEHALEM_G IFM(6, 0x1F) /* Auburndale / Havendale */ -#define INTEL_FAM6_NEHALEM_EP 0x1A #define INTEL_NEHALEM_EP IFM(6, 0x1A) -#define INTEL_FAM6_NEHALEM_EX 0x2E #define INTEL_NEHALEM_EX IFM(6, 0x2E) -#define INTEL_FAM6_WESTMERE 0x25 #define INTEL_WESTMERE IFM(6, 0x25) -#define INTEL_FAM6_WESTMERE_EP 0x2C #define INTEL_WESTMERE_EP IFM(6, 0x2C) -#define INTEL_FAM6_WESTMERE_EX 0x2F #define INTEL_WESTMERE_EX IFM(6, 0x2F) -#define INTEL_FAM6_SANDYBRIDGE 0x2A #define INTEL_SANDYBRIDGE IFM(6, 0x2A) -#define INTEL_FAM6_SANDYBRIDGE_X 0x2D #define INTEL_SANDYBRIDGE_X IFM(6, 0x2D) -#define INTEL_FAM6_IVYBRIDGE 0x3A #define INTEL_IVYBRIDGE IFM(6, 0x3A) -#define INTEL_FAM6_IVYBRIDGE_X 0x3E #define INTEL_IVYBRIDGE_X IFM(6, 0x3E) -#define INTEL_FAM6_HASWELL 0x3C #define INTEL_HASWELL IFM(6, 0x3C) -#define INTEL_FAM6_HASWELL_X 0x3F #define INTEL_HASWELL_X IFM(6, 0x3F) -#define INTEL_FAM6_HASWELL_L 0x45 #define INTEL_HASWELL_L IFM(6, 0x45) -#define INTEL_FAM6_HASWELL_G 0x46 #define INTEL_HASWELL_G IFM(6, 0x46) -#define INTEL_FAM6_BROADWELL 0x3D #define INTEL_BROADWELL IFM(6, 0x3D) -#define INTEL_FAM6_BROADWELL_G 0x47 #define INTEL_BROADWELL_G IFM(6, 0x47) -#define INTEL_FAM6_BROADWELL_X 0x4F #define INTEL_BROADWELL_X IFM(6, 0x4F) -#define INTEL_FAM6_BROADWELL_D 0x56 #define INTEL_BROADWELL_D IFM(6, 0x56) -#define INTEL_FAM6_SKYLAKE_L 0x4E /* Sky Lake */ #define INTEL_SKYLAKE_L IFM(6, 0x4E) /* Sky Lake */ -#define INTEL_FAM6_SKYLAKE 0x5E /* Sky Lake */ #define INTEL_SKYLAKE IFM(6, 0x5E) /* Sky Lake */ -#define INTEL_FAM6_SKYLAKE_X 0x55 /* Sky Lake */ #define INTEL_SKYLAKE_X IFM(6, 0x55) /* Sky Lake */ /* CASCADELAKE_X 0x55 Sky Lake -- s: 7 */ /* COOPERLAKE_X 0x55 Sky Lake -- s: 11 */ -#define INTEL_FAM6_KABYLAKE_L 0x8E /* Sky Lake */ #define INTEL_KABYLAKE_L IFM(6, 0x8E) /* Sky Lake */ /* AMBERLAKE_L 0x8E Sky Lake -- s: 9 */ /* COFFEELAKE_L 0x8E Sky Lake -- s: 10 */ /* WHISKEYLAKE_L 0x8E Sky Lake -- s: 11,12 */ -#define INTEL_FAM6_KABYLAKE 0x9E /* Sky Lake */ #define INTEL_KABYLAKE IFM(6, 0x9E) /* Sky Lake */ /* COFFEELAKE 0x9E Sky Lake -- s: 10-13 */ -#define INTEL_FAM6_COMETLAKE 0xA5 /* Sky Lake */ #define INTEL_COMETLAKE IFM(6, 0xA5) /* Sky Lake */ -#define INTEL_FAM6_COMETLAKE_L 0xA6 /* Sky Lake */ #define INTEL_COMETLAKE_L IFM(6, 0xA6) /* Sky Lake */ -#define INTEL_FAM6_CANNONLAKE_L 0x66 /* Palm Cove */ #define INTEL_CANNONLAKE_L IFM(6, 0x66) /* Palm Cove */ -#define INTEL_FAM6_ICELAKE_X 0x6A /* Sunny Cove */ #define INTEL_ICELAKE_X IFM(6, 0x6A) /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_D 0x6C /* Sunny Cove */ #define INTEL_ICELAKE_D IFM(6, 0x6C) /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE 0x7D /* Sunny Cove */ #define INTEL_ICELAKE IFM(6, 0x7D) /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_L 0x7E /* Sunny Cove */ #define INTEL_ICELAKE_L IFM(6, 0x7E) /* Sunny Cove */ -#define INTEL_FAM6_ICELAKE_NNPI 0x9D /* Sunny Cove */ #define INTEL_ICELAKE_NNPI IFM(6, 0x9D) /* Sunny Cove */ -#define INTEL_FAM6_ROCKETLAKE 0xA7 /* Cypress Cove */ #define INTEL_ROCKETLAKE IFM(6, 0xA7) /* Cypress Cove */ -#define INTEL_FAM6_TIGERLAKE_L 0x8C /* Willow Cove */ #define INTEL_TIGERLAKE_L IFM(6, 0x8C) /* Willow Cove */ -#define INTEL_FAM6_TIGERLAKE 0x8D /* Willow Cove */ #define INTEL_TIGERLAKE IFM(6, 0x8D) /* Willow Cove */ -#define INTEL_FAM6_SAPPHIRERAPIDS_X 0x8F /* Golden Cove */ #define INTEL_SAPPHIRERAPIDS_X IFM(6, 0x8F) /* Golden Cove */ -#define INTEL_FAM6_EMERALDRAPIDS_X 0xCF #define INTEL_EMERALDRAPIDS_X IFM(6, 0xCF) -#define INTEL_FAM6_GRANITERAPIDS_X 0xAD #define INTEL_GRANITERAPIDS_X IFM(6, 0xAD) -#define INTEL_FAM6_GRANITERAPIDS_D 0xAE #define INTEL_GRANITERAPIDS_D IFM(6, 0xAE) /* "Hybrid" Processors (P-Core/E-Core) */ -#define INTEL_FAM6_LAKEFIELD 0x8A /* Sunny Cove / Tremont */ #define INTEL_LAKEFIELD IFM(6, 0x8A) /* Sunny Cove / Tremont */ -#define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ #define INTEL_ALDERLAKE IFM(6, 0x97) /* Golden Cove / Gracemont */ -#define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ #define INTEL_ALDERLAKE_L IFM(6, 0x9A) /* Golden Cove / Gracemont */ -#define INTEL_FAM6_RAPTORLAKE 0xB7 /* Raptor Cove / Enhanced Gracemont */ #define INTEL_RAPTORLAKE IFM(6, 0xB7) /* Raptor Cove / Enhanced Gracemont */ -#define INTEL_FAM6_RAPTORLAKE_P 0xBA #define INTEL_RAPTORLAKE_P IFM(6, 0xBA) -#define INTEL_FAM6_RAPTORLAKE_S 0xBF #define INTEL_RAPTORLAKE_S IFM(6, 0xBF) -#define INTEL_FAM6_METEORLAKE 0xAC #define INTEL_METEORLAKE IFM(6, 0xAC) -#define INTEL_FAM6_METEORLAKE_L 0xAA #define INTEL_METEORLAKE_L IFM(6, 0xAA) -#define INTEL_FAM6_ARROWLAKE_H 0xC5 #define INTEL_ARROWLAKE_H IFM(6, 0xC5) -#define INTEL_FAM6_ARROWLAKE 0xC6 #define INTEL_ARROWLAKE IFM(6, 0xC6) -#define INTEL_FAM6_ARROWLAKE_U 0xB5 #define INTEL_ARROWLAKE_U IFM(6, 0xB5) -#define INTEL_FAM6_LUNARLAKE_M 0xBD #define INTEL_LUNARLAKE_M IFM(6, 0xBD) +#define INTEL_PANTHERLAKE_L IFM(6, 0xCC) + /* "Small Core" Processors (Atom/E-Core) */ -#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ #define INTEL_ATOM_BONNELL IFM(6, 0x1C) /* Diamondville, Pineview */ -#define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ #define INTEL_ATOM_BONNELL_MID IFM(6, 0x26) /* Silverthorne, Lincroft */ -#define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ #define INTEL_ATOM_SALTWELL IFM(6, 0x36) /* Cedarview */ -#define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ #define INTEL_ATOM_SALTWELL_MID IFM(6, 0x27) /* Penwell */ -#define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ #define INTEL_ATOM_SALTWELL_TABLET IFM(6, 0x35) /* Cloverview */ -#define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ #define INTEL_ATOM_SILVERMONT IFM(6, 0x37) /* Bay Trail, Valleyview */ -#define INTEL_FAM6_ATOM_SILVERMONT_D 0x4D /* Avaton, Rangely */ #define INTEL_ATOM_SILVERMONT_D IFM(6, 0x4D) /* Avaton, Rangely */ -#define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ #define INTEL_ATOM_SILVERMONT_MID IFM(6, 0x4A) /* Merriefield */ -#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ #define INTEL_ATOM_AIRMONT IFM(6, 0x4C) /* Cherry Trail, Braswell */ -#define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ #define INTEL_ATOM_AIRMONT_MID IFM(6, 0x5A) /* Moorefield */ -#define INTEL_FAM6_ATOM_AIRMONT_NP 0x75 /* Lightning Mountain */ #define INTEL_ATOM_AIRMONT_NP IFM(6, 0x75) /* Lightning Mountain */ -#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ #define INTEL_ATOM_GOLDMONT IFM(6, 0x5C) /* Apollo Lake */ -#define INTEL_FAM6_ATOM_GOLDMONT_D 0x5F /* Denverton */ #define INTEL_ATOM_GOLDMONT_D IFM(6, 0x5F) /* Denverton */ /* Note: the micro-architecture is "Goldmont Plus" */ -#define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ #define INTEL_ATOM_GOLDMONT_PLUS IFM(6, 0x7A) /* Gemini Lake */ -#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */ #define INTEL_ATOM_TREMONT_D IFM(6, 0x86) /* Jacobsville */ -#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */ #define INTEL_ATOM_TREMONT IFM(6, 0x96) /* Elkhart Lake */ -#define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */ #define INTEL_ATOM_TREMONT_L IFM(6, 0x9C) /* Jasper Lake */ -#define INTEL_FAM6_ATOM_GRACEMONT 0xBE /* Alderlake N */ #define INTEL_ATOM_GRACEMONT IFM(6, 0xBE) /* Alderlake N */ -#define INTEL_FAM6_ATOM_CRESTMONT_X 0xAF /* Sierra Forest */ #define INTEL_ATOM_CRESTMONT_X IFM(6, 0xAF) /* Sierra Forest */ -#define INTEL_FAM6_ATOM_CRESTMONT 0xB6 /* Grand Ridge */ #define INTEL_ATOM_CRESTMONT IFM(6, 0xB6) /* Grand Ridge */ -#define INTEL_FAM6_ATOM_DARKMONT_X 0xDD /* Clearwater Forest */ #define INTEL_ATOM_DARKMONT_X IFM(6, 0xDD) /* Clearwater Forest */ /* Xeon Phi */ -#define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ #define INTEL_XEON_PHI_KNL IFM(6, 0x57) /* Knights Landing */ -#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ #define INTEL_XEON_PHI_KNM IFM(6, 0x85) /* Knights Mill */ /* Family 5 */ -#define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */ #define INTEL_QUARK_X1000 IFM(5, 0x09) /* Quark X1000 SoC */ +/* Family 19 */ +#define INTEL_PANTHERCOVE_X IFM(19, 0x01) /* Diamond Rapids */ + +/* CPU core types */ +enum intel_cpu_type { + INTEL_CPU_TYPE_ATOM = 0x20, + INTEL_CPU_TYPE_CORE = 0x40, +}; + #endif /* _ASM_X86_INTEL_FAMILY_H */ diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h deleted file mode 100644 index 8537f597d20a..000000000000 --- a/arch/x86/include/asm/intel_scu_ipc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_X86_INTEL_SCU_IPC_H_ -#define _ASM_X86_INTEL_SCU_IPC_H_ - -#include <linux/ioport.h> - -struct device; -struct intel_scu_ipc_dev; - -/** - * struct intel_scu_ipc_data - Data used to configure SCU IPC - * @mem: Base address of SCU IPC MMIO registers - * @irq: The IRQ number used for SCU (optional) - */ -struct intel_scu_ipc_data { - struct resource mem; - int irq; -}; - -struct intel_scu_ipc_dev * -__intel_scu_ipc_register(struct device *parent, - const struct intel_scu_ipc_data *scu_data, - struct module *owner); - -#define intel_scu_ipc_register(parent, scu_data) \ - __intel_scu_ipc_register(parent, scu_data, THIS_MODULE) - -void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu); - -struct intel_scu_ipc_dev * -__devm_intel_scu_ipc_register(struct device *parent, - const struct intel_scu_ipc_data *scu_data, - struct module *owner); - -#define devm_intel_scu_ipc_register(parent, scu_data) \ - __devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE) - -struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void); -void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu); -struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev); - -int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, - u8 *data); -int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, - u8 data); -int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, - u8 *data, size_t len); -int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, - u8 *data, size_t len); - -int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, - u8 data, u8 mask); - -int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, - int sub); -int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, - int sub, const void *in, size_t inlen, - size_t size, void *out, size_t outlen); - -static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd, - int sub, const void *in, size_t inlen, - void *out, size_t outlen) -{ - return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen, - inlen, out, outlen); -} - -#endif diff --git a/arch/x86/include/asm/intel_telemetry.h b/arch/x86/include/asm/intel_telemetry.h index 8046e70dfd7c..43b7657febca 100644 --- a/arch/x86/include/asm/intel_telemetry.h +++ b/arch/x86/include/asm/intel_telemetry.h @@ -10,7 +10,7 @@ #define TELEM_MAX_EVENTS_SRAM 28 #define TELEM_MAX_OS_ALLOCATED_EVENTS 20 -#include <asm/intel_scu_ipc.h> +#include <linux/platform_data/x86/intel_scu_ipc.h> enum telemetry_unit { TELEM_PSS = 0, diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 13aea8fc3d45..47051871b436 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -18,8 +18,8 @@ * Vectors 0 ... 31 : system traps and exceptions - hardcoded events * Vectors 32 ... 127 : device interrupts * Vector 128 : legacy int80 syscall interface - * Vectors 129 ... LOCAL_TIMER_VECTOR-1 - * Vectors LOCAL_TIMER_VECTOR ... 255 : special interrupts + * Vectors 129 ... FIRST_SYSTEM_VECTOR-1 : device interrupts + * Vectors FIRST_SYSTEM_VECTOR ... 255 : special interrupts * * 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table. * diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index 68ad4f923664..861d080ed4c6 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -14,8 +14,8 @@ BUILD_BUG_ON(1) * be __static_call_return0. */ KVM_X86_OP(check_processor_compatibility) -KVM_X86_OP(hardware_enable) -KVM_X86_OP(hardware_disable) +KVM_X86_OP(enable_virtualization_cpu) +KVM_X86_OP(disable_virtualization_cpu) KVM_X86_OP(hardware_unsetup) KVM_X86_OP(has_emulated_msr) KVM_X86_OP(vcpu_after_set_cpuid) @@ -125,7 +125,7 @@ KVM_X86_OP_OPTIONAL(mem_enc_unregister_region) KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from) KVM_X86_OP_OPTIONAL(vm_move_enc_context_from) KVM_X86_OP_OPTIONAL(guest_memory_reclaimed) -KVM_X86_OP(get_msr_feature) +KVM_X86_OP(get_feature_msr) KVM_X86_OP(check_emulate_instruction) KVM_X86_OP(apic_init_signal_blocked) KVM_X86_OP_OPTIONAL(enable_l2_tlb_flush) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4a68cb3eba78..6d9f763a7bb9 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -36,6 +36,7 @@ #include <asm/kvm_page_track.h> #include <asm/kvm_vcpu_regs.h> #include <asm/hyperv-tlfs.h> +#include <asm/reboot.h> #define __KVM_HAVE_ARCH_VCPU_DEBUGFS @@ -211,6 +212,7 @@ enum exit_fastpath_completion { EXIT_FASTPATH_NONE, EXIT_FASTPATH_REENTER_GUEST, EXIT_FASTPATH_EXIT_HANDLED, + EXIT_FASTPATH_EXIT_USERSPACE, }; typedef enum exit_fastpath_completion fastpath_t; @@ -280,10 +282,6 @@ enum x86_intercept_stage; #define PFERR_PRIVATE_ACCESS BIT_ULL(49) #define PFERR_SYNTHETIC_MASK (PFERR_IMPLICIT_ACCESS | PFERR_PRIVATE_ACCESS) -#define PFERR_NESTED_GUEST_PAGE (PFERR_GUEST_PAGE_MASK | \ - PFERR_WRITE_MASK | \ - PFERR_PRESENT_MASK) - /* apic attention bits */ #define KVM_APIC_CHECK_VAPIC 0 /* @@ -1629,8 +1627,10 @@ struct kvm_x86_ops { int (*check_processor_compatibility)(void); - int (*hardware_enable)(void); - void (*hardware_disable)(void); + int (*enable_virtualization_cpu)(void); + void (*disable_virtualization_cpu)(void); + cpu_emergency_virt_cb *emergency_disable_virtualization_cpu; + void (*hardware_unsetup)(void); bool (*has_emulated_msr)(struct kvm *kvm, u32 index); void (*vcpu_after_set_cpuid)(struct kvm_vcpu *vcpu); @@ -1727,6 +1727,8 @@ struct kvm_x86_ops { void (*enable_nmi_window)(struct kvm_vcpu *vcpu); void (*enable_irq_window)(struct kvm_vcpu *vcpu); void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr); + + const bool x2apic_icr_is_split; const unsigned long required_apicv_inhibits; bool allow_apicv_in_x2apic_without_x2apic_virtualization; void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu); @@ -1806,7 +1808,7 @@ struct kvm_x86_ops { int (*vm_move_enc_context_from)(struct kvm *kvm, unsigned int source_fd); void (*guest_memory_reclaimed)(struct kvm *kvm); - int (*get_msr_feature)(struct kvm_msr_entry *entry); + int (*get_feature_msr)(u32 msr, u64 *data); int (*check_emulate_instruction)(struct kvm_vcpu *vcpu, int emul_type, void *insn, int insn_len); @@ -2060,6 +2062,8 @@ void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu); void kvm_enable_efer_bits(u64); bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer); +int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data); +int kvm_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 data); int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, bool host_initiated); int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data); int kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data); @@ -2136,7 +2140,15 @@ int kvm_get_nr_pending_nmis(struct kvm_vcpu *vcpu); void kvm_update_dr7(struct kvm_vcpu *vcpu); -int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn); +bool __kvm_mmu_unprotect_gfn_and_retry(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + bool always_retry); + +static inline bool kvm_mmu_unprotect_gfn_and_retry(struct kvm_vcpu *vcpu, + gpa_t cr2_or_gpa) +{ + return __kvm_mmu_unprotect_gfn_and_retry(vcpu, cr2_or_gpa, false); +} + void kvm_mmu_free_roots(struct kvm *kvm, struct kvm_mmu *mmu, ulong roots_to_free); void kvm_mmu_free_guest_mode_roots(struct kvm *kvm, struct kvm_mmu *mmu); @@ -2254,6 +2266,7 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v); int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); int kvm_cpu_has_extint(struct kvm_vcpu *v); int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); +int kvm_cpu_get_extint(struct kvm_vcpu *v); int kvm_cpu_get_interrupt(struct kvm_vcpu *v); void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); @@ -2345,7 +2358,8 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages); KVM_X86_QUIRK_OUT_7E_INC_RIP | \ KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT | \ KVM_X86_QUIRK_FIX_HYPERCALL_INSN | \ - KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS) + KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS | \ + KVM_X86_QUIRK_SLOT_ZAP_ALL) /* * KVM previously used a u32 field in kvm_run to indicate the hypercall was diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 3ad29b128943..4543cf2eb5e8 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -61,6 +61,7 @@ * - TCC bit is present in MCx_STATUS. */ #define MCI_CONFIG_MCAX 0x1 +#define MCI_CONFIG_FRUTEXT BIT_ULL(9) #define MCI_IPID_MCATYPE 0xFFFF0000 #define MCI_IPID_HWID 0xFFF @@ -122,6 +123,9 @@ #define MSR_AMD64_SMCA_MC0_DESTAT 0xc0002008 #define MSR_AMD64_SMCA_MC0_DEADDR 0xc0002009 #define MSR_AMD64_SMCA_MC0_MISC1 0xc000200a +/* Registers MISC2 to MISC4 are at offsets B to D. */ +#define MSR_AMD64_SMCA_MC0_SYND1 0xc000200e +#define MSR_AMD64_SMCA_MC0_SYND2 0xc000200f #define MSR_AMD64_SMCA_MCx_CTL(x) (MSR_AMD64_SMCA_MC0_CTL + 0x10*(x)) #define MSR_AMD64_SMCA_MCx_STATUS(x) (MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x)) #define MSR_AMD64_SMCA_MCx_ADDR(x) (MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x)) @@ -132,6 +136,8 @@ #define MSR_AMD64_SMCA_MCx_DESTAT(x) (MSR_AMD64_SMCA_MC0_DESTAT + 0x10*(x)) #define MSR_AMD64_SMCA_MCx_DEADDR(x) (MSR_AMD64_SMCA_MC0_DEADDR + 0x10*(x)) #define MSR_AMD64_SMCA_MCx_MISCy(x, y) ((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x))) +#define MSR_AMD64_SMCA_MCx_SYND1(x) (MSR_AMD64_SMCA_MC0_SYND1 + 0x10*(x)) +#define MSR_AMD64_SMCA_MCx_SYND2(x) (MSR_AMD64_SMCA_MC0_SYND2 + 0x10*(x)) #define XEC(x, mask) (((x) >> 16) & mask) @@ -187,6 +193,32 @@ enum mce_notifier_prios { MCE_PRIO_HIGHEST = MCE_PRIO_CEC }; +/** + * struct mce_hw_err - Hardware Error Record. + * @m: Machine Check record. + * @vendor: Vendor-specific error information. + * + * Vendor-specific fields should not be added to struct mce. Instead, vendors + * should export their vendor-specific data through their structure in the + * vendor union below. + * + * AMD's vendor data is parsed by error decoding tools for supplemental error + * information. Thus, current offsets of existing fields must be maintained. + * Only add new fields at the end of AMD's vendor structure. + */ +struct mce_hw_err { + struct mce m; + + union vendor_info { + struct { + u64 synd1; /* MCA_SYND1 MSR */ + u64 synd2; /* MCA_SYND2 MSR */ + } amd; + } vendor; +}; + +#define to_mce_hw_err(mce) container_of(mce, struct mce_hw_err, m) + struct notifier_block; extern void mce_register_decode_chain(struct notifier_block *nb); extern void mce_unregister_decode_chain(struct notifier_block *nb); @@ -221,8 +253,8 @@ static inline int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id) { return -EINVAL; } #endif -void mce_setup(struct mce *m); -void mce_log(struct mce *m); +void mce_prep_record(struct mce_hw_err *err); +void mce_log(struct mce_hw_err *err); DECLARE_PER_CPU(struct device *, mce_device); /* Maximum number of MCA banks per CPU. */ diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 8dac45a2c7fc..2886cb668d7f 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -88,7 +88,13 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next) #ifdef CONFIG_ADDRESS_MASKING static inline unsigned long mm_lam_cr3_mask(struct mm_struct *mm) { - return mm->context.lam_cr3_mask; + /* + * When switch_mm_irqs_off() is called for a kthread, it may race with + * LAM enablement. switch_mm_irqs_off() uses the LAM mask to do two + * things: populate CR3 and populate 'cpu_tlbstate.lam'. Make sure it + * reads a single value for both. + */ + return READ_ONCE(mm->context.lam_cr3_mask); } static inline void dup_lam(struct mm_struct *oldmm, struct mm_struct *mm) @@ -232,11 +238,6 @@ static inline bool is_64bit_mm(struct mm_struct *mm) } #endif -static inline void arch_unmap(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ -} - /* * We only want to enforce protection keys on the current process * because we effectively have no access to PKRU for other diff --git a/arch/x86/include/asm/mmzone.h b/arch/x86/include/asm/mmzone.h deleted file mode 100644 index c41b41edd691..000000000000 --- a/arch/x86/include/asm/mmzone.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifdef CONFIG_X86_32 -# include <asm/mmzone_32.h> -#else -# include <asm/mmzone_64.h> -#endif diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h deleted file mode 100644 index 2d4515e8b7df..000000000000 --- a/arch/x86/include/asm/mmzone_32.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Written by Pat Gaughen (gone@us.ibm.com) Mar 2002 - * - */ - -#ifndef _ASM_X86_MMZONE_32_H -#define _ASM_X86_MMZONE_32_H - -#include <asm/smp.h> - -#ifdef CONFIG_NUMA -extern struct pglist_data *node_data[]; -#define NODE_DATA(nid) (node_data[nid]) -#endif /* CONFIG_NUMA */ - -#endif /* _ASM_X86_MMZONE_32_H */ diff --git a/arch/x86/include/asm/mmzone_64.h b/arch/x86/include/asm/mmzone_64.h deleted file mode 100644 index 0c585046f744..000000000000 --- a/arch/x86/include/asm/mmzone_64.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* K8 NUMA support */ -/* Copyright 2002,2003 by Andi Kleen, SuSE Labs */ -/* 2.5 Version loosely based on the NUMAQ Code by Pat Gaughen. */ -#ifndef _ASM_X86_MMZONE_64_H -#define _ASM_X86_MMZONE_64_H - -#ifdef CONFIG_NUMA - -#include <linux/mmdebug.h> -#include <asm/smp.h> - -extern struct pglist_data *node_data[]; - -#define NODE_DATA(nid) (node_data[nid]) - -#endif -#endif /* _ASM_X86_MMZONE_64_H */ diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 390c4d13956d..5f0bc6a6d025 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -40,7 +40,6 @@ static inline unsigned char hv_get_nmi_reason(void) } #if IS_ENABLED(CONFIG_HYPERV) -extern int hyperv_init_cpuhp; extern bool hyperv_paravisor_present; extern void *hv_hypercall_pg; diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 82c6a4d350e0..3ae84c3b8e6d 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -36,6 +36,20 @@ #define EFER_FFXSR (1<<_EFER_FFXSR) #define EFER_AUTOIBRS (1<<_EFER_AUTOIBRS) +/* + * Architectural memory types that are common to MTRRs, PAT, VMX MSRs, etc. + * Most MSRs support/allow only a subset of memory types, but the values + * themselves are common across all relevant MSRs. + */ +#define X86_MEMTYPE_UC 0ull /* Uncacheable, a.k.a. Strong Uncacheable */ +#define X86_MEMTYPE_WC 1ull /* Write Combining */ +/* RESERVED 2 */ +/* RESERVED 3 */ +#define X86_MEMTYPE_WT 4ull /* Write Through */ +#define X86_MEMTYPE_WP 5ull /* Write Protected */ +#define X86_MEMTYPE_WB 6ull /* Write Back */ +#define X86_MEMTYPE_UC_MINUS 7ull /* Weak Uncacheabled (PAT only) */ + /* FRED MSRs */ #define MSR_IA32_FRED_RSP0 0x1cc /* Level 0 stack pointer */ #define MSR_IA32_FRED_RSP1 0x1cd /* Level 1 stack pointer */ @@ -247,6 +261,8 @@ #define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT) #define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 #define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) +#define MSR_INTEGRITY_CAPS_SBAF_BIT 8 +#define MSR_INTEGRITY_CAPS_SBAF BIT(MSR_INTEGRITY_CAPS_SBAF_BIT) #define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9) #define MSR_LBR_NHM_FROM 0x00000680 @@ -363,6 +379,12 @@ #define MSR_IA32_CR_PAT 0x00000277 +#define PAT_VALUE(p0, p1, p2, p3, p4, p5, p6, p7) \ + ((X86_MEMTYPE_ ## p0) | (X86_MEMTYPE_ ## p1 << 8) | \ + (X86_MEMTYPE_ ## p2 << 16) | (X86_MEMTYPE_ ## p3 << 24) | \ + (X86_MEMTYPE_ ## p4 << 32) | (X86_MEMTYPE_ ## p5 << 40) | \ + (X86_MEMTYPE_ ## p6 << 48) | (X86_MEMTYPE_ ## p7 << 56)) + #define MSR_IA32_DEBUGCTLMSR 0x000001d9 #define MSR_IA32_LASTBRANCHFROMIP 0x000001db #define MSR_IA32_LASTBRANCHTOIP 0x000001dc @@ -1157,15 +1179,6 @@ #define MSR_IA32_VMX_VMFUNC 0x00000491 #define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492 -/* VMX_BASIC bits and bitmasks */ -#define VMX_BASIC_VMCS_SIZE_SHIFT 32 -#define VMX_BASIC_TRUE_CTLS (1ULL << 55) -#define VMX_BASIC_64 0x0001000000000000LLU -#define VMX_BASIC_MEM_TYPE_SHIFT 50 -#define VMX_BASIC_MEM_TYPE_MASK 0x003c000000000000LLU -#define VMX_BASIC_MEM_TYPE_WB 6LLU -#define VMX_BASIC_INOUT 0x0040000000000000LLU - /* Resctrl MSRs: */ /* - Intel: */ #define MSR_IA32_L3_QOS_CFG 0xc81 @@ -1183,11 +1196,6 @@ #define MSR_IA32_SMBA_BW_BASE 0xc0000280 #define MSR_IA32_EVT_CFG_BASE 0xc0000400 -/* MSR_IA32_VMX_MISC bits */ -#define MSR_IA32_VMX_MISC_INTEL_PT (1ULL << 14) -#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29) -#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE 0x1F - /* AMD-V MSRs */ #define MSR_VM_CR 0xc0010114 #define MSR_VM_IGNNE 0xc0010115 diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index d642037f9ed5..001853541f1e 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -99,19 +99,6 @@ static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high) : : "c" (msr), "a"(low), "d" (high) : "memory"); } -/* - * WRMSRNS behaves exactly like WRMSR with the only difference being - * that it is not a serializing instruction by default. - */ -static __always_inline void __wrmsrns(u32 msr, u32 low, u32 high) -{ - /* Instruction opcode for WRMSRNS; supported in binutils >= 2.40. */ - asm volatile("1: .byte 0x0f,0x01,0xc6\n" - "2:\n" - _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR) - : : "c" (msr), "a"(low), "d" (high)); -} - #define native_rdmsr(msr, val1, val2) \ do { \ u64 __val = __rdmsr((msr)); \ @@ -312,9 +299,19 @@ do { \ #endif /* !CONFIG_PARAVIRT_XXL */ +/* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */ +#define WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6) + +/* Non-serializing WRMSR, when available. Falls back to a serializing WRMSR. */ static __always_inline void wrmsrns(u32 msr, u64 val) { - __wrmsrns(msr, val, val >> 32); + /* + * WRMSR is 2 bytes. WRMSRNS is 3 bytes. Pad WRMSR with a redundant + * DS prefix to avoid a trailing NOP. + */ + asm volatile("1: " ALTERNATIVE("ds wrmsr", WRMSRNS, X86_FEATURE_WRMSRNS) + "2: " _ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_WRMSR) + : : "c" (msr), "a" ((u32)val), "d" ((u32)(val >> 32))); } /* diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 090d658a85a6..4218248083d9 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -69,7 +69,6 @@ extern int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, bool increment); extern int mtrr_del(int reg, unsigned long base, unsigned long size); extern int mtrr_del_page(int reg, unsigned long base, unsigned long size); -extern void mtrr_bp_restore(void); extern int mtrr_trim_uncached_memory(unsigned long end_pfn); extern int amd_special_default_mtrr(void); void mtrr_disable(void); @@ -117,7 +116,6 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) return 0; } #define mtrr_bp_init() do {} while (0) -#define mtrr_bp_restore() do {} while (0) #define mtrr_disable() do {} while (0) #define mtrr_enable() do {} while (0) #define mtrr_generic_set_state() do {} while (0) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index ff5f1ecc7d1e..96b410b1d4e8 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -323,7 +323,16 @@ * Note: Only the memory operand variant of VERW clears the CPU buffers. */ .macro CLEAR_CPU_BUFFERS - ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF +#ifdef CONFIG_X86_64 + ALTERNATIVE "", "verw mds_verw_sel(%rip)", X86_FEATURE_CLEAR_CPU_BUF +#else + /* + * In 32bit mode, the memory operand must be a %cs reference. The data + * segments may not be usable (vm86 mode), and the stack segment may not + * be flat (ESPFIX32). + */ + ALTERNATIVE "", "verw %cs:mds_verw_sel", X86_FEATURE_CLEAR_CPU_BUF +#endif .endm #ifdef CONFIG_X86_64 diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h index ef2844d69173..5469d7a7c40f 100644 --- a/arch/x86/include/asm/numa.h +++ b/arch/x86/include/asm/numa.h @@ -10,8 +10,6 @@ #ifdef CONFIG_NUMA -#define NR_NODE_MEMBLKS (MAX_NUMNODES*2) - extern int numa_off; /* @@ -25,9 +23,6 @@ extern int numa_off; extern s16 __apicid_to_node[MAX_LOCAL_APIC]; extern nodemask_t numa_nodes_parsed __initdata; -extern int __init numa_add_memblk(int nodeid, u64 start, u64 end); -extern void __init numa_set_distance(int from, int to, int distance); - static inline void set_apicid_to_node(int apicid, s16 node) { __apicid_to_node[apicid] = node; @@ -54,31 +49,20 @@ static inline int numa_cpu_node(int cpu) extern void numa_set_node(int cpu, int node); extern void numa_clear_node(int cpu); extern void __init init_cpu_to_node(void); -extern void numa_add_cpu(int cpu); -extern void numa_remove_cpu(int cpu); +extern void numa_add_cpu(unsigned int cpu); +extern void numa_remove_cpu(unsigned int cpu); extern void init_gi_nodes(void); #else /* CONFIG_NUMA */ static inline void numa_set_node(int cpu, int node) { } static inline void numa_clear_node(int cpu) { } static inline void init_cpu_to_node(void) { } -static inline void numa_add_cpu(int cpu) { } -static inline void numa_remove_cpu(int cpu) { } +static inline void numa_add_cpu(unsigned int cpu) { } +static inline void numa_remove_cpu(unsigned int cpu) { } static inline void init_gi_nodes(void) { } #endif /* CONFIG_NUMA */ #ifdef CONFIG_DEBUG_PER_CPU_MAPS -void debug_cpumask_set_cpu(int cpu, int node, bool enable); +void debug_cpumask_set_cpu(unsigned int cpu, int node, bool enable); #endif -#ifdef CONFIG_NUMA_EMU -#define FAKE_NODE_MIN_SIZE ((u64)32 << 20) -#define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL)) -int numa_emu_cmdline(char *str); -#else /* CONFIG_NUMA_EMU */ -static inline int numa_emu_cmdline(char *str) -{ - return -EINVAL; -} -#endif /* CONFIG_NUMA_EMU */ - #endif /* _ASM_X86_NUMA_H */ diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index af4302d79b59..f3d257c45225 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h @@ -17,6 +17,7 @@ extern unsigned long phys_base; extern unsigned long page_offset_base; extern unsigned long vmalloc_base; extern unsigned long vmemmap_base; +extern unsigned long physmem_end; static __always_inline unsigned long __phys_addr_nodebug(unsigned long x) { diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h index 52f1b4ff0cc1..974688973cf6 100644 --- a/arch/x86/include/asm/page_types.h +++ b/arch/x86/include/asm/page_types.h @@ -6,10 +6,7 @@ #include <linux/types.h> #include <linux/mem_encrypt.h> -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 91b73571412f..d95f902acc52 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -536,15 +536,17 @@ struct x86_perf_regs { u64 *xmm_regs; }; -extern unsigned long perf_instruction_pointer(struct pt_regs *regs); -extern unsigned long perf_misc_flags(struct pt_regs *regs); -#define perf_misc_flags(regs) perf_misc_flags(regs) +extern unsigned long perf_arch_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_arch_misc_flags(struct pt_regs *regs); +extern unsigned long perf_arch_guest_misc_flags(struct pt_regs *regs); +#define perf_arch_misc_flags(regs) perf_arch_misc_flags(regs) +#define perf_arch_guest_misc_flags(regs) perf_arch_guest_misc_flags(regs) #include <asm/stacktrace.h> /* - * We abuse bit 3 from flags to pass exact information, see perf_misc_flags - * and the comment with PERF_EFLAGS_EXACT. + * We abuse bit 3 from flags to pass exact information, see + * perf_arch_misc_flags() and the comment with PERF_EFLAGS_EXACT. */ #define perf_arch_fetch_caller_regs(regs, __ip) { \ (regs)->ip = (__ip); \ diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index e39311a89bf4..4c2d080d26b4 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -120,6 +120,34 @@ extern pmdval_t early_pmd_flags; #define arch_end_context_switch(prev) do {} while(0) #endif /* CONFIG_PARAVIRT_XXL */ +static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set) +{ + pmdval_t v = native_pmd_val(pmd); + + return native_make_pmd(v | set); +} + +static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear) +{ + pmdval_t v = native_pmd_val(pmd); + + return native_make_pmd(v & ~clear); +} + +static inline pud_t pud_set_flags(pud_t pud, pudval_t set) +{ + pudval_t v = native_pud_val(pud); + + return native_make_pud(v | set); +} + +static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear) +{ + pudval_t v = native_pud_val(pud); + + return native_make_pud(v & ~clear); +} + /* * The following only work if pte_present() is true. * Undefined behaviour if not.. @@ -174,6 +202,13 @@ static inline int pud_young(pud_t pud) return pud_flags(pud) & _PAGE_ACCESSED; } +static inline bool pud_shstk(pud_t pud) +{ + return cpu_feature_enabled(X86_FEATURE_SHSTK) && + (pud_flags(pud) & (_PAGE_RW | _PAGE_DIRTY | _PAGE_PSE)) == + (_PAGE_DIRTY | _PAGE_PSE); +} + static inline int pte_write(pte_t pte) { /* @@ -310,6 +345,30 @@ static inline int pud_devmap(pud_t pud) } #endif +#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP +static inline bool pmd_special(pmd_t pmd) +{ + return pmd_flags(pmd) & _PAGE_SPECIAL; +} + +static inline pmd_t pmd_mkspecial(pmd_t pmd) +{ + return pmd_set_flags(pmd, _PAGE_SPECIAL); +} +#endif /* CONFIG_ARCH_SUPPORTS_PMD_PFNMAP */ + +#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP +static inline bool pud_special(pud_t pud) +{ + return pud_flags(pud) & _PAGE_SPECIAL; +} + +static inline pud_t pud_mkspecial(pud_t pud) +{ + return pud_set_flags(pud, _PAGE_SPECIAL); +} +#endif /* CONFIG_ARCH_SUPPORTS_PUD_PFNMAP */ + static inline int pgd_devmap(pgd_t pgd) { return 0; @@ -480,20 +539,6 @@ static inline pte_t pte_mkdevmap(pte_t pte) return pte_set_flags(pte, _PAGE_SPECIAL|_PAGE_DEVMAP); } -static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set) -{ - pmdval_t v = native_pmd_val(pmd); - - return native_make_pmd(v | set); -} - -static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear) -{ - pmdval_t v = native_pmd_val(pmd); - - return native_make_pmd(v & ~clear); -} - /* See comments above mksaveddirty_shift() */ static inline pmd_t pmd_mksaveddirty(pmd_t pmd) { @@ -588,20 +633,6 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd) pmd_t pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma); #define pmd_mkwrite pmd_mkwrite -static inline pud_t pud_set_flags(pud_t pud, pudval_t set) -{ - pudval_t v = native_pud_val(pud); - - return native_make_pud(v | set); -} - -static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear) -{ - pudval_t v = native_pud_val(pud); - - return native_make_pud(v & ~clear); -} - /* See comments above mksaveddirty_shift() */ static inline pud_t pud_mksaveddirty(pud_t pud) { @@ -780,6 +811,12 @@ static inline pmd_t pmd_mkinvalid(pmd_t pmd) __pgprot(pmd_flags(pmd) & ~(_PAGE_PRESENT|_PAGE_PROTNONE))); } +static inline pud_t pud_mkinvalid(pud_t pud) +{ + return pfn_pud(pud_pfn(pud), + __pgprot(pud_flags(pud) & ~(_PAGE_PRESENT|_PAGE_PROTNONE))); +} + static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask); static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) @@ -827,14 +864,8 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) pmd_result = __pmd(val); /* - * To avoid creating Write=0,Dirty=1 PMDs, pte_modify() needs to avoid: - * 1. Marking Write=0 PMDs Dirty=1 - * 2. Marking Dirty=1 PMDs Write=0 - * - * The first case cannot happen because the _PAGE_CHG_MASK will filter - * out any Dirty bit passed in newprot. Handle the second case by - * going through the mksaveddirty exercise. Only do this if the old - * value was Write=1 to avoid doing this on Shadow Stack PTEs. + * Avoid creating shadow stack PMD by accident. See comment in + * pte_modify(). */ if (oldval & _PAGE_RW) pmd_result = pmd_mksaveddirty(pmd_result); @@ -844,6 +875,29 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) return pmd_result; } +static inline pud_t pud_modify(pud_t pud, pgprot_t newprot) +{ + pudval_t val = pud_val(pud), oldval = val; + pud_t pud_result; + + val &= _HPAGE_CHG_MASK; + val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK; + val = flip_protnone_guard(oldval, val, PHYSICAL_PUD_PAGE_MASK); + + pud_result = __pud(val); + + /* + * Avoid creating shadow stack PUD by accident. See comment in + * pte_modify(). + */ + if (oldval & _PAGE_RW) + pud_result = pud_mksaveddirty(pud_result); + else + pud_result = pud_clear_saveddirty(pud_result); + + return pud_result; +} + /* * mprotect needs to preserve PAT and encryption bits when updating * vm_page_prot @@ -1078,8 +1132,7 @@ static inline pmd_t *pud_pgtable(pud_t pud) #define pud_leaf pud_leaf static inline bool pud_leaf(pud_t pud) { - return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == - (_PAGE_PSE | _PAGE_PRESENT); + return pud_val(pud) & _PAGE_PSE; } static inline int pud_bad(pud_t pud) @@ -1383,10 +1436,28 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, } #endif +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +static inline pud_t pudp_establish(struct vm_area_struct *vma, + unsigned long address, pud_t *pudp, pud_t pud) +{ + page_table_check_pud_set(vma->vm_mm, pudp, pud); + if (IS_ENABLED(CONFIG_SMP)) { + return xchg(pudp, pud); + } else { + pud_t old = *pudp; + WRITE_ONCE(*pudp, pud); + return old; + } +} +#endif + #define __HAVE_ARCH_PMDP_INVALIDATE_AD extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); +pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp); + /* * Page table pages are page-aligned. The lower half of the top * level is used for userspace and the top half for the kernel. @@ -1668,6 +1739,9 @@ void arch_check_zapped_pte(struct vm_area_struct *vma, pte_t pte); #define arch_check_zapped_pmd arch_check_zapped_pmd void arch_check_zapped_pmd(struct vm_area_struct *vma, pmd_t pmd); +#define arch_check_zapped_pud arch_check_zapped_pud +void arch_check_zapped_pud(struct vm_area_struct *vma, pud_t pud); + #ifdef CONFIG_XEN_PV #define arch_has_hw_nonleaf_pmd_young arch_has_hw_nonleaf_pmd_young static inline bool arch_has_hw_nonleaf_pmd_young(void) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index 3c4407271d08..d1426b64c1b9 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -245,7 +245,6 @@ extern void cleanup_highmap(void); #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN -#define HAVE_ARCH_UNMAPPED_AREA_VMFLAGS #define PAGE_AGP PAGE_KERNEL_NOCACHE #define HAVE_PAGE_AGP 1 @@ -271,5 +270,26 @@ static inline bool gup_fast_permitted(unsigned long start, unsigned long end) #include <asm/pgtable-invert.h> -#endif /* !__ASSEMBLY__ */ +#else /* __ASSEMBLY__ */ + +#define l4_index(x) (((x) >> 39) & 511) +#define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) + +L4_PAGE_OFFSET = l4_index(__PAGE_OFFSET_BASE_L4) +L4_START_KERNEL = l4_index(__START_KERNEL_map) + +L3_START_KERNEL = pud_index(__START_KERNEL_map) + +#define SYM_DATA_START_PAGE_ALIGNED(name) \ + SYM_START(name, SYM_L_GLOBAL, .balign PAGE_SIZE) + +/* Automate the creation of 1 to 1 mapping pmd entries */ +#define PMDS(START, PERM, COUNT) \ + i = 0 ; \ + .rept (COUNT) ; \ + .quad (START) + (i << PMD_SHIFT) + (PERM) ; \ + i = i + 1 ; \ + .endr + +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_PGTABLE_64_H */ diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h index 9053dfe9fa03..a98e53491a4e 100644 --- a/arch/x86/include/asm/pgtable_64_types.h +++ b/arch/x86/include/asm/pgtable_64_types.h @@ -140,6 +140,10 @@ extern unsigned int ptrs_per_p4d; # define VMEMMAP_START __VMEMMAP_BASE_L4 #endif /* CONFIG_DYNAMIC_MEMORY_LAYOUT */ +#ifdef CONFIG_RANDOMIZE_MEMORY +# define PHYSMEM_END physmem_end +#endif + /* * End of the region for which vmalloc page tables are pre-allocated. * For non-KMSAN builds, this is the same as VMALLOC_END. diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 2f321137736c..6f82e75b6149 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -517,8 +517,6 @@ typedef struct page *pgtable_t; extern pteval_t __supported_pte_mask; extern pteval_t __default_kernel_pte_mask; -extern void set_nx(void); -extern int nx_enabled; #define pgprot_writecombine pgprot_writecombine extern pgprot_t pgprot_writecombine(pgprot_t prot); diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a75a07f4931f..c0975815980c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -105,6 +105,24 @@ struct cpuinfo_topology { // Cache level topology IDs u32 llc_id; u32 l2c_id; + + // Hardware defined CPU-type + union { + u32 cpu_type; + struct { + // CPUID.1A.EAX[23-0] + u32 intel_native_model_id :24; + // CPUID.1A.EAX[31-24] + u32 intel_type :8; + }; + struct { + // CPUID 0x80000026.EBX + u32 amd_num_processors :16, + amd_power_eff_ranking :8, + amd_native_model_id :4, + amd_type :4; + }; + }; }; struct cpuinfo_x86 { @@ -582,7 +600,8 @@ extern void switch_gdt_and_percpu_base(int); extern void load_direct_gdt(int); extern void load_fixmap_gdt(int); extern void cpu_init(void); -extern void cpu_init_exception_handling(void); +extern void cpu_init_exception_handling(bool boot_cpu); +extern void cpu_init_replace_early_idt(void); extern void cr4_init(void); extern void set_task_blockstep(struct task_struct *task, bool on); @@ -691,8 +710,6 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu) } #ifdef CONFIG_CPU_SUP_AMD -extern u32 amd_get_highest_perf(void); - /* * Issue a DIV 0/1 insn to clear any division data from previous DIV * operations. @@ -705,7 +722,6 @@ static __always_inline void amd_clear_divider(void) extern void amd_check_microcode(void); #else -static inline u32 amd_get_highest_perf(void) { return 0; } static inline void amd_clear_divider(void) { } static inline void amd_check_microcode(void) { } #endif diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 0c92db84469d..6e4f8fae3ce9 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -5,6 +5,7 @@ #include <asm/clocksource.h> #include <asm/pvclock-abi.h> +struct timespec64; /* some helper functions for xen and kvm pv clock sources */ u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); u64 pvclock_clocksource_read_nowd(struct pvclock_vcpu_time_info *src); diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index 6536873f8fc0..ecd58ea9a837 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -25,14 +25,16 @@ void __noreturn machine_real_restart(unsigned int type); #define MRR_BIOS 0 #define MRR_APM 1 -#if IS_ENABLED(CONFIG_KVM_INTEL) || IS_ENABLED(CONFIG_KVM_AMD) typedef void (cpu_emergency_virt_cb)(void); +#if IS_ENABLED(CONFIG_KVM_X86) void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback); void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback); void cpu_emergency_disable_virtualization(void); #else +static inline void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback) {} +static inline void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback) {} static inline void cpu_emergency_disable_virtualization(void) {} -#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */ +#endif /* CONFIG_KVM_X86 */ typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); void nmi_shootdown_cpus(nmi_shootdown_cb callback); diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 12dbd2588ca7..8b1b6ce1e51b 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -156,12 +156,6 @@ static inline void resctrl_sched_in(struct task_struct *tsk) __resctrl_sched_in(tsk); } -static inline u32 resctrl_arch_system_num_rmid_idx(void) -{ - /* RMID are independent numbers for x86. num_rmid_idx == num_rmid */ - return boot_cpu_data.x86_cache_max_rmid + 1; -} - static inline void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid) { *rmid = idx; diff --git a/arch/x86/include/asm/runtime-const.h b/arch/x86/include/asm/runtime-const.h index 24e3a53ca255..6652ebddfd02 100644 --- a/arch/x86/include/asm/runtime-const.h +++ b/arch/x86/include/asm/runtime-const.h @@ -6,7 +6,7 @@ typeof(sym) __ret; \ asm_inline("mov %1,%0\n1:\n" \ ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \ - ".long 1b - %c2 - .\n\t" \ + ".long 1b - %c2 - .\n" \ ".popsection" \ :"=r" (__ret) \ :"i" ((unsigned long)0x0123456789abcdefull), \ @@ -20,7 +20,7 @@ typeof(0u+(val)) __ret = (val); \ asm_inline("shrl $12,%k0\n1:\n" \ ".pushsection runtime_shift_" #sym ",\"a\"\n\t" \ - ".long 1b - 1 - .\n\t" \ + ".long 1b - 1 - .\n" \ ".popsection" \ :"+r" (__ret)); \ __ret; }) diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h index 98726c2b04f8..50f5666938c0 100644 --- a/arch/x86/include/asm/sev-common.h +++ b/arch/x86/include/asm/sev-common.h @@ -220,4 +220,31 @@ struct snp_psc_desc { #define GHCB_ERR_INVALID_INPUT 5 #define GHCB_ERR_INVALID_EVENT 6 +struct sev_config { + __u64 debug : 1, + + /* + * Indicates when the per-CPU GHCB has been created and registered + * and thus can be used by the BSP instead of the early boot GHCB. + * + * For APs, the per-CPU GHCB is created before they are started + * and registered upon startup, so this flag can be used globally + * for the BSP and APs. + */ + ghcbs_initialized : 1, + + /* + * Indicates when the per-CPU SVSM CA is to be used instead of the + * boot SVSM CA. + * + * For APs, the per-CPU SVSM CA is created as part of the AP + * bringup, so this flag can be used globally for the BSP and APs. + */ + use_cas : 1, + + __reserved : 61; +}; + +extern struct sev_config sev_cfg; + #endif diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 79bbe2be900e..91f08af31078 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -120,6 +120,9 @@ struct snp_req_data { }; #define MAX_AUTHTAG_LEN 32 +#define AUTHTAG_LEN 16 +#define AAD_LEN 48 +#define MSG_HDR_VER 1 /* See SNP spec SNP_GUEST_REQUEST section for the structure */ enum msg_type { @@ -164,13 +167,26 @@ struct snp_guest_msg_hdr { struct snp_guest_msg { struct snp_guest_msg_hdr hdr; - u8 payload[4000]; + u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)]; } __packed; struct sev_guest_platform_data { u64 secrets_gpa; }; +struct snp_guest_req { + void *req_buf; + size_t req_sz; + + void *resp_buf; + size_t resp_sz; + + u64 exit_code; + unsigned int vmpck_id; + u8 msg_version; + u8 msg_type; +}; + /* * The secrets page contains 96-bytes of reserved field that can be used by * the guest OS. The guest OS uses the area to save the message sequence @@ -218,6 +234,27 @@ struct snp_secrets_page { u8 rsvd4[3744]; } __packed; +struct snp_msg_desc { + /* request and response are in unencrypted memory */ + struct snp_guest_msg *request, *response; + + /* + * Avoid information leakage by double-buffering shared messages + * in fields that are in regular encrypted memory. + */ + struct snp_guest_msg secret_request, secret_response; + + struct snp_secrets_page *secrets; + struct snp_req_data input; + + void *certs_data; + + struct aesgcm_ctx *ctx; + + u32 *os_area_msg_seqno; + u8 *vmpck; +}; + /* * The SVSM Calling Area (CA) related structures. */ @@ -285,6 +322,22 @@ struct svsm_attest_call { u8 rsvd[4]; }; +/* PTE descriptor used for the prepare_pte_enc() operations. */ +struct pte_enc_desc { + pte_t *kpte; + int pte_level; + bool encrypt; + /* pfn of the kpte above */ + unsigned long pfn; + /* physical address of @pfn */ + unsigned long pa; + /* virtual address of @pfn */ + void *va; + /* memory covered by the pte */ + unsigned long size; + pgprot_t new_pgprot; +}; + /* * SVSM protocol structure */ @@ -392,13 +445,18 @@ void snp_set_wakeup_secondary_cpu(void); bool snp_init(struct boot_params *bp); void __noreturn snp_abort(void); void snp_dmi_setup(void); -int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio); +int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input, + struct snp_guest_request_ioctl *rio); int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input); void snp_accept_memory(phys_addr_t start, phys_addr_t end); u64 snp_get_unsupported_features(u64 status); u64 sev_get_status(void); void sev_show_status(void); void snp_update_svsm_ca(void); +int prepare_pte_enc(struct pte_enc_desc *d); +void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot); +void snp_kexec_finish(void); +void snp_kexec_begin(void); #else /* !CONFIG_AMD_MEM_ENCRYPT */ @@ -422,7 +480,8 @@ static inline void snp_set_wakeup_secondary_cpu(void) { } static inline bool snp_init(struct boot_params *bp) { return false; } static inline void snp_abort(void) { } static inline void snp_dmi_setup(void) { } -static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) +static inline int snp_issue_guest_request(struct snp_guest_req *req, struct snp_req_data *input, + struct snp_guest_request_ioctl *rio) { return -ENOTTY; } @@ -435,6 +494,10 @@ static inline u64 snp_get_unsupported_features(u64 status) { return 0; } static inline u64 sev_get_status(void) { return 0; } static inline void sev_show_status(void) { } static inline void snp_update_svsm_ca(void) { } +static inline int prepare_pte_enc(struct pte_enc_desc *d) { return 0; } +static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { } +static inline void snp_kexec_finish(void) { } +static inline void snp_kexec_begin(void) { } #endif /* CONFIG_AMD_MEM_ENCRYPT */ diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h index 64df897c0ee3..3918c7a434f5 100644 --- a/arch/x86/include/asm/sparsemem.h +++ b/arch/x86/include/asm/sparsemem.h @@ -31,13 +31,4 @@ #endif /* CONFIG_SPARSEMEM */ -#ifndef __ASSEMBLY__ -#ifdef CONFIG_NUMA_KEEP_MEMINFO -extern int phys_to_target_node(phys_addr_t start); -#define phys_to_target_node phys_to_target_node -extern int memory_add_physaddr_to_nid(u64 start); -#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid -#endif -#endif /* __ASSEMBLY__ */ - #endif /* _ASM_X86_SPARSEMEM_H */ diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index f0dea3750ca9..2b59b9951c90 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -516,6 +516,20 @@ struct ghcb { u32 ghcb_usage; } __packed; +struct vmcb { + struct vmcb_control_area control; + union { + struct vmcb_save_area save; + + /* + * For SEV-ES VMs, the save area in the VMCB is used only to + * save/load host state. Guest state resides in a separate + * page, the aptly named VM Save Area (VMSA), that is encrypted + * with the guest's private key. + */ + struct sev_es_save_area host_sev_es_save; + }; +} __packed; #define EXPECTED_VMCB_SAVE_AREA_SIZE 744 #define EXPECTED_GHCB_SAVE_AREA_SIZE 1032 @@ -532,6 +546,7 @@ static inline void __unused_size_checks(void) BUILD_BUG_ON(sizeof(struct ghcb_save_area) != EXPECTED_GHCB_SAVE_AREA_SIZE); BUILD_BUG_ON(sizeof(struct sev_es_save_area) != EXPECTED_SEV_ES_SAVE_AREA_SIZE); BUILD_BUG_ON(sizeof(struct vmcb_control_area) != EXPECTED_VMCB_CONTROL_AREA_SIZE); + BUILD_BUG_ON(offsetof(struct vmcb, save) != EXPECTED_VMCB_CONTROL_AREA_SIZE); BUILD_BUG_ON(sizeof(struct ghcb) != EXPECTED_GHCB_SIZE); /* Check offsets of reserved fields */ @@ -568,11 +583,6 @@ static inline void __unused_size_checks(void) BUILD_BUG_RESERVED_OFFSET(ghcb, 0xff0); } -struct vmcb { - struct vmcb_control_area control; - struct vmcb_save_area save; -} __packed; - #define SVM_CPUID_FUNC 0x8000000a #define SVM_SELECTOR_S_SHIFT 4 diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h index c3bd0c0758c9..75248546403d 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -70,13 +70,9 @@ static inline void update_task_stack(struct task_struct *task) #ifdef CONFIG_X86_32 this_cpu_write(cpu_tss_rw.x86_tss.sp1, task->thread.sp0); #else - if (cpu_feature_enabled(X86_FEATURE_FRED)) { - /* WRMSRNS is a baseline feature for FRED. */ - wrmsrns(MSR_IA32_FRED_RSP0, (unsigned long)task_stack_page(task) + THREAD_SIZE); - } else if (cpu_feature_enabled(X86_FEATURE_XENPV)) { + if (!cpu_feature_enabled(X86_FEATURE_FRED) && cpu_feature_enabled(X86_FEATURE_XENPV)) /* Xen PV enters the kernel on the thread stack. */ load_sp0(task_top_of_stack(task)); - } #endif } diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 2fc7bc3863ff..7c488ff0c764 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -82,7 +82,12 @@ static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned long *args) { - memcpy(args, ®s->bx, 6 * sizeof(args[0])); + args[0] = regs->bx; + args[1] = regs->cx; + args[2] = regs->dx; + args[3] = regs->si; + args[4] = regs->di; + args[5] = regs->bp; } static inline int syscall_get_arch(struct task_struct *task) diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 12da7dfd5ef1..a55c214f3ba6 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -87,8 +87,9 @@ struct thread_info { #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ -#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ -#define TIF_SSBD 5 /* Speculative store bypass disable */ +#define TIF_NEED_RESCHED_LAZY 4 /* Lazy rescheduling needed */ +#define TIF_SINGLESTEP 5 /* reenable singlestep on user return*/ +#define TIF_SSBD 6 /* Speculative store bypass disable */ #define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */ #define TIF_SPEC_L1D_FLUSH 10 /* Flush L1D on mm switches (processes) */ #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ @@ -110,6 +111,7 @@ struct thread_info { #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_SSBD (1 << TIF_SSBD) #define _TIF_SPEC_IB (1 << TIF_SPEC_IB) diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index 7365dd4acffb..23baf8c9b34c 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -6,8 +6,6 @@ #include <linux/interrupt.h> #include <linux/math64.h> -#define TICK_SIZE (tick_nsec / 1000) - unsigned long long native_sched_clock(void); extern void recalibrate_cpu_khz(void); diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 25726893c6f4..69e79fff41b8 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -399,11 +399,10 @@ static inline u64 tlbstate_lam_cr3_mask(void) return lam << X86_CR3_LAM_U57_BIT; } -static inline void set_tlbstate_lam_mode(struct mm_struct *mm) +static inline void cpu_tlbstate_update_lam(unsigned long lam, u64 untag_mask) { - this_cpu_write(cpu_tlbstate.lam, - mm->context.lam_cr3_mask >> X86_CR3_LAM_U57_BIT); - this_cpu_write(tlbstate_untag_mask, mm->context.untag_mask); + this_cpu_write(cpu_tlbstate.lam, lam >> X86_CR3_LAM_U57_BIT); + this_cpu_write(tlbstate_untag_mask, untag_mask); } #else @@ -413,7 +412,7 @@ static inline u64 tlbstate_lam_cr3_mask(void) return 0; } -static inline void set_tlbstate_lam_mode(struct mm_struct *mm) +static inline void cpu_tlbstate_update_lam(unsigned long lam, u64 untag_mask) { } #endif diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index abe3a8f22cbd..fd41103ad342 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -114,6 +114,12 @@ enum x86_topology_domains { TOPO_MAX_DOMAIN, }; +enum x86_topology_cpu_type { + TOPO_CPU_TYPE_PERFORMANCE, + TOPO_CPU_TYPE_EFFICIENCY, + TOPO_CPU_TYPE_UNKNOWN, +}; + struct x86_topology_system { unsigned int dom_shifts[TOPO_MAX_DOMAIN]; unsigned int dom_size[TOPO_MAX_DOMAIN]; @@ -149,6 +155,9 @@ extern unsigned int __max_threads_per_core; extern unsigned int __num_threads_per_package; extern unsigned int __num_cores_per_package; +const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); +enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); + static inline unsigned int topology_max_packages(void) { return __max_logical_packages; @@ -282,9 +291,22 @@ static inline long arch_scale_freq_capacity(int cpu) } #define arch_scale_freq_capacity arch_scale_freq_capacity +bool arch_enable_hybrid_capacity_scale(void); +void arch_set_cpu_capacity(int cpu, unsigned long cap, unsigned long max_cap, + unsigned long cap_freq, unsigned long base_freq); + +unsigned long arch_scale_cpu_capacity(int cpu); +#define arch_scale_cpu_capacity arch_scale_cpu_capacity + extern void arch_set_max_freq_ratio(bool turbo_disabled); extern void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled); #else +static inline bool arch_enable_hybrid_capacity_scale(void) { return false; } +static inline void arch_set_cpu_capacity(int cpu, unsigned long cap, + unsigned long max_cap, + unsigned long cap_freq, + unsigned long base_freq) { } + static inline void arch_set_max_freq_ratio(bool turbo_disabled) { } static inline void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled) { } #endif @@ -292,9 +314,4 @@ static inline void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled extern void arch_scale_freq_tick(void); #define arch_scale_freq_tick arch_scale_freq_tick -#ifdef CONFIG_ACPI_CPPC_LIB -void init_freq_invariance_cppc(void); -#define arch_init_invariance_cppc init_freq_invariance_cppc -#endif - #endif /* _ASM_X86_TOPOLOGY_H */ diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 04789f45ab2b..b0a887209400 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -12,6 +12,13 @@ #include <asm/cpufeatures.h> #include <asm/page.h> #include <asm/percpu.h> +#include <asm/runtime-const.h> + +/* + * Virtual variable: there's no actual backing store for this, + * it can purely be used as 'runtime_const_ptr(USER_PTR_MAX)' + */ +extern unsigned long USER_PTR_MAX; #ifdef CONFIG_ADDRESS_MASKING /* @@ -46,35 +53,44 @@ static inline unsigned long __untagged_addr_remote(struct mm_struct *mm, #endif +#define valid_user_address(x) \ + ((__force unsigned long)(x) <= runtime_const_ptr(USER_PTR_MAX)) + /* - * The virtual address space space is logically divided into a kernel - * half and a user half. When cast to a signed type, user pointers - * are positive and kernel pointers are negative. + * Masking the user address is an alternative to a conditional + * user_access_begin that can avoid the fencing. This only works + * for dense accesses starting at the address. */ -#define valid_user_address(x) ((__force long)(x) >= 0) +static inline void __user *mask_user_address(const void __user *ptr) +{ + unsigned long mask; + asm("cmp %1,%0\n\t" + "sbb %0,%0" + :"=r" (mask) + :"r" (ptr), + "0" (runtime_const_ptr(USER_PTR_MAX))); + return (__force void __user *)(mask | (__force unsigned long)ptr); +} +#define masked_user_access_begin(x) ({ \ + __auto_type __masked_ptr = (x); \ + __masked_ptr = mask_user_address(__masked_ptr); \ + __uaccess_begin(); __masked_ptr; }) /* * User pointers can have tag bits on x86-64. This scheme tolerates * arbitrary values in those bits rather then masking them off. * * Enforce two rules: - * 1. 'ptr' must be in the user half of the address space + * 1. 'ptr' must be in the user part of the address space * 2. 'ptr+size' must not overflow into kernel addresses * - * Note that addresses around the sign change are not valid addresses, - * and will GP-fault even with LAM enabled if the sign bit is set (see - * "CR3.LAM_SUP" that can narrow the canonicality check if we ever - * enable it, but not remove it entirely). - * - * So the "overflow into kernel addresses" does not imply some sudden - * exact boundary at the sign bit, and we can allow a lot of slop on the - * size check. + * Note that we always have at least one guard page between the + * max user address and the non-canonical gap, allowing us to + * ignore small sizes entirely. * * In fact, we could probably remove the size check entirely, since * any kernel accesses will be in increasing address order starting - * at 'ptr', and even if the end might be in kernel space, we'll - * hit the GP faults for non-canonical accesses before we ever get - * there. + * at 'ptr'. * * That's a separate optimization, for now just handle the small * constant case. diff --git a/arch/x86/include/asm/uv/uv_irq.h b/arch/x86/include/asm/uv/uv_irq.h index d6b17c760622..1876b5edd142 100644 --- a/arch/x86/include/asm/uv/uv_irq.h +++ b/arch/x86/include/asm/uv/uv_irq.h @@ -31,7 +31,6 @@ enum { UV_AFFINITY_CPU }; -extern int uv_irq_2_mmr_info(int, unsigned long *, int *); extern int uv_setup_irq(char *, int, int, unsigned long, int); extern void uv_teardown_irq(unsigned int); diff --git a/arch/x86/include/asm/vdso/getrandom.h b/arch/x86/include/asm/vdso/getrandom.h index b96e674cafde..2bf9c0e970c3 100644 --- a/arch/x86/include/asm/vdso/getrandom.h +++ b/arch/x86/include/asm/vdso/getrandom.h @@ -8,7 +8,6 @@ #ifndef __ASSEMBLY__ #include <asm/unistd.h> -#include <asm/vvar.h> /** * getrandom_syscall - Invoke the getrandom() syscall. @@ -28,28 +27,16 @@ static __always_inline ssize_t getrandom_syscall(void *buffer, size_t len, unsig return ret; } -#define __vdso_rng_data (VVAR(_vdso_rng_data)) +extern struct vdso_rng_data vdso_rng_data + __attribute__((visibility("hidden"))); static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void) { - if (IS_ENABLED(CONFIG_TIME_NS) && __vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS) - return (void *)&__vdso_rng_data + ((void *)&__timens_vdso_data - (void *)&__vdso_data); - return &__vdso_rng_data; + if (IS_ENABLED(CONFIG_TIME_NS) && __arch_get_vdso_data()->clock_mode == VDSO_CLOCKMODE_TIMENS) + return (void *)&vdso_rng_data + ((void *)&timens_page - (void *)__arch_get_vdso_data()); + return &vdso_rng_data; } -/** - * __arch_chacha20_blocks_nostack - Generate ChaCha20 stream without using the stack. - * @dst_bytes: Destination buffer to hold @nblocks * 64 bytes of output. - * @key: 32-byte input key. - * @counter: 8-byte counter, read on input and updated on return. - * @nblocks: Number of blocks to generate. - * - * Generates a given positive number of blocks of ChaCha20 output with nonce=0, and does not write - * to any stack or memory outside of the parameters passed to it, in order to mitigate stack data - * leaking into forked child processes. - */ -extern void __arch_chacha20_blocks_nostack(u8 *dst_bytes, const u32 *key, u32 *counter, size_t nblocks); - #endif /* !__ASSEMBLY__ */ #endif /* __ASM_VDSO_GETRANDOM_H */ diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h index b2d2df026f6e..375a34b0f365 100644 --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -14,14 +14,16 @@ #include <uapi/linux/time.h> #include <asm/vgtod.h> -#include <asm/vvar.h> #include <asm/unistd.h> #include <asm/msr.h> #include <asm/pvclock.h> #include <clocksource/hyperv_timer.h> -#define __vdso_data (VVAR(_vdso_data)) -#define __timens_vdso_data (TIMENS(_vdso_data)) +extern struct vdso_data vvar_page + __attribute__((visibility("hidden"))); + +extern struct vdso_data timens_page + __attribute__((visibility("hidden"))); #define VDSO_HAS_TIME 1 @@ -61,7 +63,7 @@ extern struct ms_hyperv_tsc_page hvclock_page static __always_inline const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) { - return __timens_vdso_data; + return &timens_page; } #endif @@ -275,7 +277,7 @@ static inline u64 __arch_get_hw_counter(s32 clock_mode, static __always_inline const struct vdso_data *__arch_get_vdso_data(void) { - return __vdso_data; + return &vvar_page; } static inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd) diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso/vsyscall.h index 972415a8be31..37b4a70559a8 100644 --- a/arch/x86/include/asm/vdso/vsyscall.h +++ b/arch/x86/include/asm/vdso/vsyscall.h @@ -2,15 +2,19 @@ #ifndef __ASM_VDSO_VSYSCALL_H #define __ASM_VDSO_VSYSCALL_H +#define __VDSO_RND_DATA_OFFSET 640 +#define __VVAR_PAGES 4 + +#define VDSO_NR_VCLOCK_PAGES 2 +#define VDSO_PAGE_PVCLOCK_OFFSET 0 +#define VDSO_PAGE_HVCLOCK_OFFSET 1 + #ifndef __ASSEMBLY__ -#include <linux/timekeeper_internal.h> #include <vdso/datapage.h> #include <asm/vgtod.h> -#include <asm/vvar.h> -DEFINE_VVAR(struct vdso_data, _vdso_data); -DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data); +extern struct vdso_data *vdso_data; /* * Update the vDSO data page to keep in sync with kernel timekeeping. @@ -18,10 +22,17 @@ DEFINE_VVAR_SINGLE(struct vdso_rng_data, _vdso_rng_data); static __always_inline struct vdso_data *__x86_get_k_vdso_data(void) { - return _vdso_data; + return vdso_data; } #define __arch_get_k_vdso_data __x86_get_k_vdso_data +static __always_inline +struct vdso_rng_data *__x86_get_k_vdso_rng_data(void) +{ + return (void *)vdso_data + __VDSO_RND_DATA_OFFSET; +} +#define __arch_get_k_vdso_rng_data __x86_get_k_vdso_rng_data + /* The asm-generic header needs to be included after the definitions above */ #include <asm-generic/vdso/vsyscall.h> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index d77a31039f24..f7fd4369b821 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -122,19 +122,17 @@ #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff -#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f -#define VMX_MISC_SAVE_EFER_LMA 0x00000020 -#define VMX_MISC_ACTIVITY_HLT 0x00000040 -#define VMX_MISC_ACTIVITY_WAIT_SIPI 0x00000100 -#define VMX_MISC_ZERO_LEN_INS 0x40000000 -#define VMX_MISC_MSR_LIST_MULTIPLIER 512 - /* VMFUNC functions */ #define VMFUNC_CONTROL_BIT(x) BIT((VMX_FEATURE_##x & 0x1f) - 28) #define VMX_VMFUNC_EPTP_SWITCHING VMFUNC_CONTROL_BIT(EPTP_SWITCHING) #define VMFUNC_EPTP_ENTRIES 512 +#define VMX_BASIC_32BIT_PHYS_ADDR_ONLY BIT_ULL(48) +#define VMX_BASIC_DUAL_MONITOR_TREATMENT BIT_ULL(49) +#define VMX_BASIC_INOUT BIT_ULL(54) +#define VMX_BASIC_TRUE_CTLS BIT_ULL(55) + static inline u32 vmx_basic_vmcs_revision_id(u64 vmx_basic) { return vmx_basic & GENMASK_ULL(30, 0); @@ -145,9 +143,30 @@ static inline u32 vmx_basic_vmcs_size(u64 vmx_basic) return (vmx_basic & GENMASK_ULL(44, 32)) >> 32; } +static inline u32 vmx_basic_vmcs_mem_type(u64 vmx_basic) +{ + return (vmx_basic & GENMASK_ULL(53, 50)) >> 50; +} + +static inline u64 vmx_basic_encode_vmcs_info(u32 revision, u16 size, u8 memtype) +{ + return revision | ((u64)size << 32) | ((u64)memtype << 50); +} + +#define VMX_MISC_SAVE_EFER_LMA BIT_ULL(5) +#define VMX_MISC_ACTIVITY_HLT BIT_ULL(6) +#define VMX_MISC_ACTIVITY_SHUTDOWN BIT_ULL(7) +#define VMX_MISC_ACTIVITY_WAIT_SIPI BIT_ULL(8) +#define VMX_MISC_INTEL_PT BIT_ULL(14) +#define VMX_MISC_RDMSR_IN_SMM BIT_ULL(15) +#define VMX_MISC_VMXOFF_BLOCK_SMI BIT_ULL(28) +#define VMX_MISC_VMWRITE_SHADOW_RO_FIELDS BIT_ULL(29) +#define VMX_MISC_ZERO_LEN_INS BIT_ULL(30) +#define VMX_MISC_MSR_LIST_MULTIPLIER 512 + static inline int vmx_misc_preemption_timer_rate(u64 vmx_misc) { - return vmx_misc & VMX_MISC_PREEMPTION_TIMER_RATE_MASK; + return vmx_misc & GENMASK_ULL(4, 0); } static inline int vmx_misc_cr3_count(u64 vmx_misc) @@ -508,9 +527,10 @@ enum vmcs_field { #define VMX_EPTP_PWL_4 0x18ull #define VMX_EPTP_PWL_5 0x20ull #define VMX_EPTP_AD_ENABLE_BIT (1ull << 6) +/* The EPTP memtype is encoded in bits 2:0, i.e. doesn't need to be shifted. */ #define VMX_EPTP_MT_MASK 0x7ull -#define VMX_EPTP_MT_WB 0x6ull -#define VMX_EPTP_MT_UC 0x0ull +#define VMX_EPTP_MT_WB X86_MEMTYPE_WB +#define VMX_EPTP_MT_UC X86_MEMTYPE_UC #define VMX_EPT_READABLE_MASK 0x1ull #define VMX_EPT_WRITABLE_MASK 0x2ull #define VMX_EPT_EXECUTABLE_MASK 0x4ull diff --git a/arch/x86/include/asm/vvar.h b/arch/x86/include/asm/vvar.h deleted file mode 100644 index 9d9af37f7cab..000000000000 --- a/arch/x86/include/asm/vvar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * vvar.h: Shared vDSO/kernel variable declarations - * Copyright (c) 2011 Andy Lutomirski - * - * A handful of variables are accessible (read-only) from userspace - * code in the vsyscall page and the vdso. They are declared here. - * Some other file must define them with DEFINE_VVAR. - * - * In normal kernel code, they are used like any other variable. - * In user code, they are accessed through the VVAR macro. - * - * These variables live in a page of kernel data that has an extra RO - * mapping for userspace. Each variable needs a unique offset within - * that page; specify that offset with the DECLARE_VVAR macro. (If - * you mess up, the linker will catch it.) - */ - -#ifndef _ASM_X86_VVAR_H -#define _ASM_X86_VVAR_H - -#ifdef EMIT_VVAR -/* - * EMIT_VVAR() is used by the kernel linker script to put vvars in the - * right place. Also, it's used by kernel code to import offsets values. - */ -#define DECLARE_VVAR(offset, type, name) \ - EMIT_VVAR(name, offset) -#define DECLARE_VVAR_SINGLE(offset, type, name) \ - EMIT_VVAR(name, offset) - -#else - -extern char __vvar_page; - -#define DECLARE_VVAR(offset, type, name) \ - extern type vvar_ ## name[CS_BASES] \ - __attribute__((visibility("hidden"))); \ - extern type timens_ ## name[CS_BASES] \ - __attribute__((visibility("hidden"))); \ - -#define DECLARE_VVAR_SINGLE(offset, type, name) \ - extern type vvar_ ## name \ - __attribute__((visibility("hidden"))); \ - -#define VVAR(name) (vvar_ ## name) -#define TIMENS(name) (timens_ ## name) - -#define DEFINE_VVAR(type, name) \ - type name[CS_BASES] \ - __attribute__((section(".vvar_" #name), aligned(16))) __visible - -#define DEFINE_VVAR_SINGLE(type, name) \ - type name \ - __attribute__((section(".vvar_" #name), aligned(16))) __visible - -#endif - -/* DECLARE_VVAR(offset, type, name) */ - -DECLARE_VVAR(128, struct vdso_data, _vdso_data) - -#if !defined(_SINGLE_DATA) -#define _SINGLE_DATA -DECLARE_VVAR_SINGLE(640, struct vdso_rng_data, _vdso_rng_data) -#endif - -#undef DECLARE_VVAR -#undef DECLARE_VVAR_SINGLE - -#endif diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h index e5d182c7373c..4a7cace06204 100644 --- a/arch/x86/include/uapi/asm/amd_hsmp.h +++ b/arch/x86/include/uapi/asm/amd_hsmp.h @@ -88,7 +88,8 @@ struct hsmp_msg_desc { * * Not supported messages would return -ENOMSG. */ -static const struct hsmp_msg_desc hsmp_msg_desc_table[] = { +static const struct hsmp_msg_desc hsmp_msg_desc_table[] + __attribute__((unused)) = { /* RESERVED */ {0, 0, HSMP_RSVD}, diff --git a/arch/x86/include/uapi/asm/elf.h b/arch/x86/include/uapi/asm/elf.h new file mode 100644 index 000000000000..468e135fa285 --- /dev/null +++ b/arch/x86/include/uapi/asm/elf.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_X86_ELF_H +#define _UAPI_ASM_X86_ELF_H + +#include <linux/types.h> + +struct x86_xfeat_component { + __u32 type; + __u32 size; + __u32 offset; + __u32 flags; +} __packed; + +_Static_assert(sizeof(struct x86_xfeat_component) % 4 == 0, "x86_xfeat_component is not aligned"); + +#endif /* _UAPI_ASM_X86_ELF_H */ diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index bf57a824f722..a8debbf2f702 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -439,6 +439,7 @@ struct kvm_sync_regs { #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5) #define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6) +#define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7) #define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_SVM 1 diff --git a/arch/x86/include/uapi/asm/mce.h b/arch/x86/include/uapi/asm/mce.h index db9adc081c5a..cb6b48a7c22b 100644 --- a/arch/x86/include/uapi/asm/mce.h +++ b/arch/x86/include/uapi/asm/mce.h @@ -8,7 +8,8 @@ /* * Fields are zero when not available. Also, this struct is shared with * userspace mcelog and thus must keep existing fields at current offsets. - * Only add new fields to the end of the structure + * Only add new, shared fields to the end of the structure. + * Do not add vendor-specific fields. */ struct mce { __u64 status; /* Bank's MCi_STATUS MSR */ diff --git a/arch/x86/include/uapi/asm/mman.h b/arch/x86/include/uapi/asm/mman.h index 46cdc941f958..ac1e6277212b 100644 --- a/arch/x86/include/uapi/asm/mman.h +++ b/arch/x86/include/uapi/asm/mman.h @@ -5,9 +5,6 @@ #define MAP_32BIT 0x40 /* only give out 32bit addresses */ #define MAP_ABOVE4G 0x80 /* only map above 4GB */ -/* Flags for map_shadow_stack(2) */ -#define SHADOW_STACK_SET_TOKEN (1ULL << 0) /* Set up a restore token in the shadow stack */ - #include <asm-generic/mman.h> #endif /* _ASM_X86_MMAN_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a847180836e4..f7918980667a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -35,6 +35,14 @@ KMSAN_SANITIZE_nmi.o := n # If instrumentation of the following files is enabled, boot hangs during # first second. KCOV_INSTRUMENT_head$(BITS).o := n +# These are called from save_stack_trace() on debug paths, +# and produce large amounts of uninteresting coverage. +KCOV_INSTRUMENT_stacktrace.o := n +KCOV_INSTRUMENT_dumpstack.o := n +KCOV_INSTRUMENT_dumpstack_$(BITS).o := n +KCOV_INSTRUMENT_unwind_orc.o := n +KCOV_INSTRUMENT_unwind_frame.o := n +KCOV_INSTRUMENT_unwind_guess.o := n CFLAGS_irq.o := -I $(src)/../include/asm/trace diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 9f4618dcd704..3a44a9dc3fb7 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1171,7 +1171,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) } count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, - acpi_parse_int_src_ovr, nr_irqs); + acpi_parse_int_src_ovr, + irq_get_nr_irqs()); if (count < 0) { pr_err("Error parsing interrupt source overrides entry\n"); /* TBD: Cleanup to allow fallback to MPS */ @@ -1191,7 +1192,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) mp_config_acpi_legacy_irqs(); count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, - acpi_parse_nmi_src, nr_irqs); + acpi_parse_nmi_src, + irq_get_nr_irqs()); if (count < 0) { pr_err("Error parsing NMI SRC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ @@ -1778,3 +1780,14 @@ u64 x86_default_get_root_pointer(void) { return boot_params.acpi_rsdp_addr; } + +#ifdef CONFIG_XEN_PV +void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size) +{ + return ioremap_cache(phys, size); +} + +void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, acpi_size size) = + x86_acpi_os_ioremap; +EXPORT_SYMBOL_GPL(acpi_os_ioremap); +#endif diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c index ff8f25faca3d..d745dd586303 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -9,6 +9,17 @@ #include <asm/processor.h> #include <asm/topology.h> +#define CPPC_HIGHEST_PERF_PERFORMANCE 196 +#define CPPC_HIGHEST_PERF_PREFCORE 166 + +enum amd_pref_core { + AMD_PREF_CORE_UNKNOWN = 0, + AMD_PREF_CORE_SUPPORTED, + AMD_PREF_CORE_UNSUPPORTED, +}; +static enum amd_pref_core amd_pref_core_detected; +static u64 boost_numerator; + /* Refer to drivers/acpi/cppc_acpi.c for the description of functions */ bool cpc_supported_by_cpu(void) @@ -69,38 +80,37 @@ int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) static void amd_set_max_freq_ratio(void) { struct cppc_perf_caps perf_caps; - u64 highest_perf, nominal_perf; + u64 numerator, nominal_perf; u64 perf_ratio; int rc; rc = cppc_get_perf_caps(0, &perf_caps); if (rc) { - pr_debug("Could not retrieve perf counters (%d)\n", rc); + pr_warn("Could not retrieve perf counters (%d)\n", rc); return; } - highest_perf = amd_get_highest_perf(); + rc = amd_get_boost_ratio_numerator(0, &numerator); + if (rc) { + pr_warn("Could not retrieve highest performance (%d)\n", rc); + return; + } nominal_perf = perf_caps.nominal_perf; - if (!highest_perf || !nominal_perf) { - pr_debug("Could not retrieve highest or nominal performance\n"); + if (!nominal_perf) { + pr_warn("Could not retrieve nominal performance\n"); return; } - perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf); /* midpoint between max_boost and max_P */ - perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1; - if (!perf_ratio) { - pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n"); - return; - } + perf_ratio = (div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf) + SCHED_CAPACITY_SCALE) >> 1; freq_invariance_set_perf_ratio(perf_ratio, false); } static DEFINE_MUTEX(freq_invariance_lock); -void init_freq_invariance_cppc(void) +static inline void init_freq_invariance_cppc(void) { static bool init_done; @@ -116,3 +126,171 @@ void init_freq_invariance_cppc(void) init_done = true; mutex_unlock(&freq_invariance_lock); } + +void acpi_processor_init_invariance_cppc(void) +{ + init_freq_invariance_cppc(); +} + +/* + * Get the highest performance register value. + * @cpu: CPU from which to get highest performance. + * @highest_perf: Return address for highest performance value. + * + * Return: 0 for success, negative error code otherwise. + */ +int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf) +{ + u64 val; + int ret; + + if (cpu_feature_enabled(X86_FEATURE_CPPC)) { + ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &val); + if (ret) + goto out; + + val = AMD_CPPC_HIGHEST_PERF(val); + } else { + ret = cppc_get_highest_perf(cpu, &val); + if (ret) + goto out; + } + + WRITE_ONCE(*highest_perf, (u32)val); +out: + return ret; +} +EXPORT_SYMBOL_GPL(amd_get_highest_perf); + +/** + * amd_detect_prefcore: Detect if CPUs in the system support preferred cores + * @detected: Output variable for the result of the detection. + * + * Determine whether CPUs in the system support preferred cores. On systems + * that support preferred cores, different highest perf values will be found + * on different cores. On other systems, the highest perf value will be the + * same on all cores. + * + * The result of the detection will be stored in the 'detected' parameter. + * + * Return: 0 for success, negative error code otherwise + */ +int amd_detect_prefcore(bool *detected) +{ + int cpu, count = 0; + u64 highest_perf[2] = {0}; + + if (WARN_ON(!detected)) + return -EINVAL; + + switch (amd_pref_core_detected) { + case AMD_PREF_CORE_SUPPORTED: + *detected = true; + return 0; + case AMD_PREF_CORE_UNSUPPORTED: + *detected = false; + return 0; + default: + break; + } + + for_each_present_cpu(cpu) { + u32 tmp; + int ret; + + ret = amd_get_highest_perf(cpu, &tmp); + if (ret) + return ret; + + if (!count || (count == 1 && tmp != highest_perf[0])) + highest_perf[count++] = tmp; + + if (count == 2) + break; + } + + *detected = (count == 2); + boost_numerator = highest_perf[0]; + + amd_pref_core_detected = *detected ? AMD_PREF_CORE_SUPPORTED : + AMD_PREF_CORE_UNSUPPORTED; + + pr_debug("AMD CPPC preferred core is %ssupported (highest perf: 0x%llx)\n", + *detected ? "" : "un", highest_perf[0]); + + return 0; +} +EXPORT_SYMBOL_GPL(amd_detect_prefcore); + +/** + * amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation + * @cpu: CPU to get numerator for. + * @numerator: Output variable for numerator. + * + * Determine the numerator to use for calculating the boost ratio on + * a CPU. On systems that support preferred cores, this will be a hardcoded + * value. On other systems this will the highest performance register value. + * + * If booting the system with amd-pstate enabled but preferred cores disabled then + * the correct boost numerator will be returned to match hardware capabilities + * even if the preferred cores scheduling hints are not enabled. + * + * Return: 0 for success, negative error code otherwise. + */ +int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) +{ + enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu)); + bool prefcore; + int ret; + u32 tmp; + + ret = amd_detect_prefcore(&prefcore); + if (ret) + return ret; + + /* without preferred cores, return the highest perf register value */ + if (!prefcore) { + *numerator = boost_numerator; + return 0; + } + + /* + * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f, + * the highest performance level is set to 196. + * https://bugzilla.kernel.org/show_bug.cgi?id=218759 + */ + if (cpu_feature_enabled(X86_FEATURE_ZEN4)) { + switch (boot_cpu_data.x86_model) { + case 0x70 ... 0x7f: + *numerator = CPPC_HIGHEST_PERF_PERFORMANCE; + return 0; + default: + break; + } + } + + /* detect if running on heterogeneous design */ + if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) { + switch (core_type) { + case TOPO_CPU_TYPE_UNKNOWN: + pr_warn("Undefined core type found for cpu %d\n", cpu); + break; + case TOPO_CPU_TYPE_PERFORMANCE: + /* use the max scale for performance cores */ + *numerator = CPPC_HIGHEST_PERF_PERFORMANCE; + return 0; + case TOPO_CPU_TYPE_EFFICIENCY: + /* use the highest perf value for efficiency cores */ + ret = amd_get_highest_perf(cpu, &tmp); + if (ret) + return ret; + *numerator = tmp; + return 0; + } + } + + *numerator = CPPC_HIGHEST_PERF_PREFCORE; + + return 0; +} +EXPORT_SYMBOL_GPL(amd_get_boost_ratio_numerator); diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 94ff83f3d3fe..b200a193beeb 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -87,6 +87,7 @@ SYM_FUNC_START(do_suspend_lowlevel) .align 4 .Lresume_point: + ANNOTATE_NOENDBR /* We don't restore %rax, it must be 0 anyway */ movq $saved_context, %rax movq saved_context_cr4(%rax), %rbx diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 059e5c16af05..9fe9972d2071 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -26,6 +26,7 @@ #define PCI_DEVICE_ID_AMD_19H_M70H_ROOT 0x14e8 #define PCI_DEVICE_ID_AMD_1AH_M00H_ROOT 0x153a #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 +#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 #define PCI_DEVICE_ID_AMD_MI200_ROOT 0x14bb #define PCI_DEVICE_ID_AMD_MI300_ROOT 0x14f8 @@ -43,6 +44,9 @@ #define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4 #define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc #define PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4 0x12c4 +#define PCI_DEVICE_ID_AMD_1AH_M20H_DF_F4 0x16fc +#define PCI_DEVICE_ID_AMD_1AH_M60H_DF_F4 0x124c +#define PCI_DEVICE_ID_AMD_1AH_M70H_DF_F4 0x12bc #define PCI_DEVICE_ID_AMD_MI200_DF_F4 0x14d4 #define PCI_DEVICE_ID_AMD_MI300_DF_F4 0x152c @@ -63,6 +67,7 @@ static const struct pci_device_id amd_root_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_ROOT) }, {} @@ -95,6 +100,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M70H_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F3) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_DF_F3) }, @@ -122,6 +128,9 @@ static const struct pci_device_id amd_nb_link_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_DF_F4) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M70H_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F4) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_DF_F4) }, {} diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 66fd4b2a37a3..c5fb28e6451a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -440,7 +440,19 @@ static int lapic_timer_shutdown(struct clock_event_device *evt) v = apic_read(APIC_LVTT); v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); apic_write(APIC_LVTT, v); - apic_write(APIC_TMICT, 0); + + /* + * Setting APIC_LVT_MASKED (above) should be enough to tell + * the hardware that this timer will never fire. But AMD + * erratum 411 and some Intel CPU behavior circa 2024 say + * otherwise. Time for belt and suspenders programming: mask + * the timer _and_ zero the counter registers: + */ + if (v & APIC_LVT_TIMER_TSCDEADLINE) + wrmsrl(MSR_IA32_TSC_DEADLINE, 0); + else + apic_write(APIC_TMICT, 0); + return 0; } @@ -677,7 +689,7 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc) return -1; #endif - apic_printk(APIC_VERBOSE, "... PM-Timer delta = %u\n", deltapm); + apic_pr_verbose("... PM-Timer delta = %u\n", deltapm); /* Check, if the PM timer is available */ if (!deltapm) @@ -687,14 +699,14 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc) if (deltapm > (pm_100ms - pm_thresh) && deltapm < (pm_100ms + pm_thresh)) { - apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n"); + apic_pr_verbose("... PM-Timer result ok\n"); return 0; } res = (((u64)deltapm) * mult) >> 22; do_div(res, 1000000); - pr_warn("APIC calibration not consistent " - "with PM-Timer: %ldms instead of 100ms\n", (long)res); + pr_warn("APIC calibration not consistent with PM-Timer: %ldms instead of 100ms\n", + (long)res); /* Correct the lapic counter value */ res = (((u64)(*delta)) * pm_100ms); @@ -707,9 +719,8 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc) if (boot_cpu_has(X86_FEATURE_TSC)) { res = (((u64)(*deltatsc)) * pm_100ms); do_div(res, deltapm); - apic_printk(APIC_VERBOSE, "TSC delta adjusted to " - "PM-Timer: %lu (%ld)\n", - (unsigned long)res, *deltatsc); + apic_pr_verbose("TSC delta adjusted to PM-Timer: %lu (%ld)\n", + (unsigned long)res, *deltatsc); *deltatsc = (long)res; } @@ -792,8 +803,7 @@ static int __init calibrate_APIC_clock(void) * in the clockevent structure and return. */ if (!lapic_init_clockevent()) { - apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n", - lapic_timer_period); + apic_pr_verbose("lapic timer already calibrated %d\n", lapic_timer_period); /* * Direct calibration methods must have an always running * local APIC timer, no need for broadcast timer. @@ -802,8 +812,7 @@ static int __init calibrate_APIC_clock(void) return 0; } - apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" - "calibrating APIC timer ...\n"); + apic_pr_verbose("Using local APIC timer interrupts. Calibrating APIC timer ...\n"); /* * There are platforms w/o global clockevent devices. Instead of @@ -866,7 +875,7 @@ static int __init calibrate_APIC_clock(void) /* Build delta t1-t2 as apic timer counts down */ delta = lapic_cal_t1 - lapic_cal_t2; - apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); + apic_pr_verbose("... lapic delta = %ld\n", delta); deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); @@ -877,22 +886,19 @@ static int __init calibrate_APIC_clock(void) lapic_timer_period = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; lapic_init_clockevent(); - apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta); - apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult); - apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", - lapic_timer_period); + apic_pr_verbose("..... delta %ld\n", delta); + apic_pr_verbose("..... mult: %u\n", lapic_clockevent.mult); + apic_pr_verbose("..... calibration result: %u\n", lapic_timer_period); if (boot_cpu_has(X86_FEATURE_TSC)) { - apic_printk(APIC_VERBOSE, "..... CPU clock speed is " - "%ld.%04ld MHz.\n", - (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), - (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); + apic_pr_verbose("..... CPU clock speed is %ld.%04ld MHz.\n", + (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), + (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); } - apic_printk(APIC_VERBOSE, "..... host bus clock speed is " - "%u.%04u MHz.\n", - lapic_timer_period / (1000000 / HZ), - lapic_timer_period % (1000000 / HZ)); + apic_pr_verbose("..... host bus clock speed is %u.%04u MHz.\n", + lapic_timer_period / (1000000 / HZ), + lapic_timer_period % (1000000 / HZ)); /* * Do a sanity check on the APIC calibration result @@ -911,7 +917,7 @@ static int __init calibrate_APIC_clock(void) * available. */ if (!pm_referenced && global_clock_event) { - apic_printk(APIC_VERBOSE, "... verify APIC timer\n"); + apic_pr_verbose("... verify APIC timer\n"); /* * Setup the apic timer manually @@ -932,11 +938,11 @@ static int __init calibrate_APIC_clock(void) /* Jiffies delta */ deltaj = lapic_cal_j2 - lapic_cal_j1; - apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj); + apic_pr_verbose("... jiffies delta = %lu\n", deltaj); /* Check, if the jiffies result is consistent */ if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2) - apic_printk(APIC_VERBOSE, "... jiffies result ok\n"); + apic_pr_verbose("... jiffies result ok\n"); else levt->features |= CLOCK_EVT_FEAT_DUMMY; } @@ -1221,9 +1227,8 @@ void __init sync_Arb_IDs(void) */ apic_wait_icr_idle(); - apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); - apic_write(APIC_ICR, APIC_DEST_ALLINC | - APIC_INT_LEVELTRIG | APIC_DM_INIT); + apic_pr_debug("Synchronizing Arb IDs.\n"); + apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } enum apic_intr_mode_id apic_intr_mode __ro_after_init; @@ -1409,10 +1414,10 @@ static void lapic_setup_esr(void) if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - if (value != oldvalue) - apic_printk(APIC_VERBOSE, "ESR value before enabling " - "vector: 0x%08x after: 0x%08x\n", - oldvalue, value); + if (value != oldvalue) { + apic_pr_verbose("ESR value before enabling vector: 0x%08x after: 0x%08x\n", + oldvalue, value); + } } #define APIC_IR_REGS APIC_ISR_NR @@ -1599,10 +1604,10 @@ static void setup_local_APIC(void) value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; if (!cpu && (pic_mode || !value || ioapic_is_disabled)) { value = APIC_DM_EXTINT; - apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu); + apic_pr_verbose("Enabled ExtINT on CPU#%d\n", cpu); } else { value = APIC_DM_EXTINT | APIC_LVT_MASKED; - apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu); + apic_pr_verbose("Masked ExtINT on CPU#%d\n", cpu); } apic_write(APIC_LVT0, value); @@ -1775,12 +1780,9 @@ static __init void apic_set_fixmap(bool read_apic); static __init void x2apic_disable(void) { - u32 x2apic_id, state = x2apic_state; + u32 x2apic_id; - x2apic_mode = 0; - x2apic_state = X2APIC_DISABLED; - - if (state != X2APIC_ON) + if (x2apic_state < X2APIC_ON) return; x2apic_id = read_apic_id(); @@ -1793,6 +1795,10 @@ static __init void x2apic_disable(void) } __x2apic_disable(); + + x2apic_mode = 0; + x2apic_state = X2APIC_DISABLED; + /* * Don't reread the APIC ID as it was already done from * check_x2apic() and the APIC driver still is a x2APIC variant, @@ -2066,8 +2072,7 @@ static __init void apic_set_fixmap(bool read_apic) { set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); apic_mmio_base = APIC_BASE; - apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", - apic_mmio_base, mp_lapic_addr); + apic_pr_verbose("Mapped APIC to %16lx (%16lx)\n", apic_mmio_base, mp_lapic_addr); if (read_apic) apic_read_boot_cpu_id(false); } @@ -2170,18 +2175,17 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_error_interrupt) apic_eoi(); atomic_inc(&irq_err_count); - apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x", - smp_processor_id(), v); + apic_pr_debug("APIC error on CPU%d: %02x", smp_processor_id(), v); v &= 0xff; while (v) { if (v & 0x1) - apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); + apic_pr_debug_cont(" : %s", error_interrupt_reason[i]); i++; v >>= 1; } - apic_printk(APIC_DEBUG, KERN_CONT "\n"); + apic_pr_debug_cont("\n"); trace_error_apic_exit(ERROR_APIC_VECTOR); } @@ -2201,8 +2205,7 @@ static void __init connect_bsp_APIC(void) * PIC mode, enable APIC mode in the IMCR, i.e. connect BSP's * local APIC to INT and NMI lines. */ - apic_printk(APIC_VERBOSE, "leaving PIC mode, " - "enabling APIC mode.\n"); + apic_pr_verbose("Leaving PIC mode, enabling APIC mode.\n"); imcr_pic_to_apic(); } #endif @@ -2227,8 +2230,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) * IPIs, won't work beyond this point! The only exception are * INIT IPIs. */ - apic_printk(APIC_VERBOSE, "disabling APIC mode, " - "entering PIC mode.\n"); + apic_pr_verbose("Disabling APIC mode, entering PIC mode.\n"); imcr_apic_to_pic(); return; } diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index f37ad3392fec..e0308d8c4e6c 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -8,129 +8,25 @@ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. */ -#include <linux/cpumask.h> #include <linux/export.h> -#include <linux/acpi.h> -#include <asm/jailhouse_para.h> #include <asm/apic.h> #include "local.h" -static struct apic apic_physflat; -static struct apic apic_flat; - -struct apic *apic __ro_after_init = &apic_flat; -EXPORT_SYMBOL_GPL(apic); - -static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) -{ - return 1; -} - -static void _flat_send_IPI_mask(unsigned long mask, int vector) -{ - unsigned long flags; - - local_irq_save(flags); - __default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL); - local_irq_restore(flags); -} - -static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector) -{ - unsigned long mask = cpumask_bits(cpumask)[0]; - - _flat_send_IPI_mask(mask, vector); -} - -static void -flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) -{ - unsigned long mask = cpumask_bits(cpumask)[0]; - int cpu = smp_processor_id(); - - if (cpu < BITS_PER_LONG) - __clear_bit(cpu, &mask); - - _flat_send_IPI_mask(mask, vector); -} - -static u32 flat_get_apic_id(u32 x) +static u32 physflat_get_apic_id(u32 x) { return (x >> 24) & 0xFF; } -static int flat_probe(void) +static int physflat_probe(void) { return 1; } -static struct apic apic_flat __ro_after_init = { - .name = "flat", - .probe = flat_probe, - .acpi_madt_oem_check = flat_acpi_madt_oem_check, - - .dest_mode_logical = true, - - .disable_esr = 0, - - .init_apic_ldr = default_init_apic_ldr, - .cpu_present_to_apicid = default_cpu_present_to_apicid, - - .max_apic_id = 0xFE, - .get_apic_id = flat_get_apic_id, - - .calc_dest_apicid = apic_flat_calc_apicid, - - .send_IPI = default_send_IPI_single, - .send_IPI_mask = flat_send_IPI_mask, - .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself, - .send_IPI_allbutself = default_send_IPI_allbutself, - .send_IPI_all = default_send_IPI_all, - .send_IPI_self = default_send_IPI_self, - .nmi_to_offline_cpu = true, - - .read = native_apic_mem_read, - .write = native_apic_mem_write, - .eoi = native_apic_mem_eoi, - .icr_read = native_apic_icr_read, - .icr_write = native_apic_icr_write, - .wait_icr_idle = apic_mem_wait_icr_idle, - .safe_wait_icr_idle = apic_mem_wait_icr_idle_timeout, -}; - -/* - * Physflat mode is used when there are more than 8 CPUs on a system. - * We cannot use logical delivery in this case because the mask - * overflows, so use physical mode. - */ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { -#ifdef CONFIG_ACPI - /* - * Quirk: some x86_64 machines can only use physical APIC mode - * regardless of how many processors are present (x86_64 ES7000 - * is an example). - */ - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { - printk(KERN_DEBUG "system APIC only can use physical flat"); - return 1; - } - - if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) { - printk(KERN_DEBUG "IBM Summit detected, will use apic physical"); - return 1; - } -#endif - - return 0; -} - -static int physflat_probe(void) -{ - return apic == &apic_physflat || num_possible_cpus() > 8 || jailhouse_paravirt(); + return 1; } static struct apic apic_physflat __ro_after_init = { @@ -146,7 +42,7 @@ static struct apic apic_physflat __ro_after_init = { .cpu_present_to_apicid = default_cpu_present_to_apicid, .max_apic_id = 0xFE, - .get_apic_id = flat_get_apic_id, + .get_apic_id = physflat_get_apic_id, .calc_dest_apicid = apic_default_calc_apicid, @@ -166,8 +62,7 @@ static struct apic apic_physflat __ro_after_init = { .wait_icr_idle = apic_mem_wait_icr_idle, .safe_wait_icr_idle = apic_mem_wait_icr_idle_timeout, }; +apic_driver(apic_physflat); -/* - * We need to check for physflat first, so this order is important. - */ -apic_drivers(apic_physflat, apic_flat); +struct apic *apic __ro_after_init = &apic_physflat; +EXPORT_SYMBOL_GPL(apic); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 477b740b2f26..1029ea4ac8ba 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -86,8 +86,8 @@ static unsigned int ioapic_dynirq_base; static int ioapic_initialized; struct irq_pin_list { - struct list_head list; - int apic, pin; + struct list_head list; + int apic, pin; }; struct mp_chip_data { @@ -96,7 +96,7 @@ struct mp_chip_data { bool is_level; bool active_low; bool isa_irq; - u32 count; + u32 count; }; struct mp_ioapic_gsi { @@ -105,21 +105,17 @@ struct mp_ioapic_gsi { }; static struct ioapic { - /* - * # of IRQ routing registers - */ - int nr_registers; - /* - * Saved state during suspend/resume, or while enabling intr-remap. - */ - struct IO_APIC_route_entry *saved_registers; + /* # of IRQ routing registers */ + int nr_registers; + /* Saved state during suspend/resume, or while enabling intr-remap. */ + struct IO_APIC_route_entry *saved_registers; /* I/O APIC config */ - struct mpc_ioapic mp_config; + struct mpc_ioapic mp_config; /* IO APIC gsi routing info */ - struct mp_ioapic_gsi gsi_config; - struct ioapic_domain_cfg irqdomain_cfg; - struct irq_domain *irqdomain; - struct resource *iomem_res; + struct mp_ioapic_gsi gsi_config; + struct ioapic_domain_cfg irqdomain_cfg; + struct irq_domain *irqdomain; + struct resource *iomem_res; } ioapics[MAX_IO_APICS]; #define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver @@ -205,10 +201,9 @@ void mp_save_irq(struct mpc_intsrc *m) { int i; - apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x," - " IRQ %02x, APIC ID %x, APIC INT %02x\n", - m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus, - m->srcbusirq, m->dstapic, m->dstirq); + apic_pr_verbose("Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n", + m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus, + m->srcbusirq, m->dstapic, m->dstirq); for (i = 0; i < mp_irq_entries; i++) { if (!memcmp(&mp_irqs[i], m, sizeof(*m))) @@ -269,12 +264,14 @@ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) static inline void io_apic_eoi(unsigned int apic, unsigned int vector) { struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(vector, &io_apic->eoi); } unsigned int native_io_apic_read(unsigned int apic, unsigned int reg) { struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); return readl(&io_apic->data); } @@ -300,14 +297,8 @@ static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin) static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) { - struct IO_APIC_route_entry entry; - unsigned long flags; - - raw_spin_lock_irqsave(&ioapic_lock, flags); - entry = __ioapic_read_entry(apic, pin); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - - return entry; + guard(raw_spinlock_irqsave)(&ioapic_lock); + return __ioapic_read_entry(apic, pin); } /* @@ -324,11 +315,8 @@ static void __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { - unsigned long flags; - - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); __ioapic_write_entry(apic, pin, e); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } /* @@ -339,12 +327,10 @@ static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) static void ioapic_mask_entry(int apic, int pin) { struct IO_APIC_route_entry e = { .masked = true }; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); io_apic_write(apic, 0x10 + 2*pin, e.w1); io_apic_write(apic, 0x11 + 2*pin, e.w2); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } /* @@ -352,68 +338,39 @@ static void ioapic_mask_entry(int apic, int pin) * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static int __add_pin_to_irq_node(struct mp_chip_data *data, - int node, int apic, int pin) +static bool add_pin_to_irq_node(struct mp_chip_data *data, int node, int apic, int pin) { struct irq_pin_list *entry; - /* don't allow duplicates */ - for_each_irq_pin(entry, data->irq_2_pin) + /* Don't allow duplicates */ + for_each_irq_pin(entry, data->irq_2_pin) { if (entry->apic == apic && entry->pin == pin) - return 0; + return true; + } entry = kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node); if (!entry) { - pr_err("can not alloc irq_pin_list (%d,%d,%d)\n", - node, apic, pin); - return -ENOMEM; + pr_err("Cannot allocate irq_pin_list (%d,%d,%d)\n", node, apic, pin); + return false; } + entry->apic = apic; entry->pin = pin; list_add_tail(&entry->list, &data->irq_2_pin); - - return 0; + return true; } static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin) { struct irq_pin_list *tmp, *entry; - list_for_each_entry_safe(entry, tmp, &data->irq_2_pin, list) + list_for_each_entry_safe(entry, tmp, &data->irq_2_pin, list) { if (entry->apic == apic && entry->pin == pin) { list_del(&entry->list); kfree(entry); return; } -} - -static void add_pin_to_irq_node(struct mp_chip_data *data, - int node, int apic, int pin) -{ - if (__add_pin_to_irq_node(data, node, apic, pin)) - panic("IO-APIC: failed to add irq-pin. Can not proceed\n"); -} - -/* - * Reroute an IRQ to a different pin. - */ -static void __init replace_pin_at_irq_node(struct mp_chip_data *data, int node, - int oldapic, int oldpin, - int newapic, int newpin) -{ - struct irq_pin_list *entry; - - for_each_irq_pin(entry, data->irq_2_pin) { - if (entry->apic == oldapic && entry->pin == oldpin) { - entry->apic = newapic; - entry->pin = newpin; - /* every one is different, right? */ - return; - } } - - /* old apic/pin didn't exist, so just add new ones */ - add_pin_to_irq_node(data, node, newapic, newpin); } static void io_apic_modify_irq(struct mp_chip_data *data, bool masked, @@ -430,12 +387,12 @@ static void io_apic_modify_irq(struct mp_chip_data *data, bool masked, } } +/* + * Synchronize the IO-APIC and the CPU by doing a dummy read from the + * IO-APIC + */ static void io_apic_sync(struct irq_pin_list *entry) { - /* - * Synchronize the IO-APIC and the CPU by doing - * a dummy read from the IO-APIC - */ struct io_apic __iomem *io_apic; io_apic = io_apic_base(entry->apic); @@ -445,11 +402,9 @@ static void io_apic_sync(struct irq_pin_list *entry) static void mask_ioapic_irq(struct irq_data *irq_data) { struct mp_chip_data *data = irq_data->chip_data; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); io_apic_modify_irq(data, true, &io_apic_sync); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } static void __unmask_ioapic(struct mp_chip_data *data) @@ -460,11 +415,9 @@ static void __unmask_ioapic(struct mp_chip_data *data) static void unmask_ioapic_irq(struct irq_data *irq_data) { struct mp_chip_data *data = irq_data->chip_data; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); __unmask_ioapic(data); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } /* @@ -492,30 +445,24 @@ static void __eoi_ioapic_pin(int apic, int pin, int vector) entry = entry1 = __ioapic_read_entry(apic, pin); - /* - * Mask the entry and change the trigger mode to edge. - */ + /* Mask the entry and change the trigger mode to edge. */ entry1.masked = true; entry1.is_level = false; __ioapic_write_entry(apic, pin, entry1); - /* - * Restore the previous level triggered entry. - */ + /* Restore the previous level triggered entry. */ __ioapic_write_entry(apic, pin, entry); } } static void eoi_ioapic_pin(int vector, struct mp_chip_data *data) { - unsigned long flags; struct irq_pin_list *entry; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); for_each_irq_pin(entry, data->irq_2_pin) __eoi_ioapic_pin(entry->apic, entry->pin, vector); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) @@ -538,8 +485,6 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) } if (entry.irr) { - unsigned long flags; - /* * Make sure the trigger mode is set to level. Explicit EOI * doesn't clear the remote-IRR if the trigger mode is not @@ -549,9 +494,8 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) entry.is_level = true; ioapic_write_entry(apic, pin, entry); } - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); __eoi_ioapic_pin(apic, pin, entry.vector); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } /* @@ -586,28 +530,23 @@ static int pirq_entries[MAX_PIRQS] = { static int __init ioapic_pirq_setup(char *str) { - int i, max; - int ints[MAX_PIRQS+1]; + int i, max, ints[MAX_PIRQS+1]; get_options(str, ARRAY_SIZE(ints), ints); - apic_printk(APIC_VERBOSE, KERN_INFO - "PIRQ redirection, working around broken MP-BIOS.\n"); + apic_pr_verbose("PIRQ redirection, working around broken MP-BIOS.\n"); + max = MAX_PIRQS; if (ints[0] < MAX_PIRQS) max = ints[0]; for (i = 0; i < max; i++) { - apic_printk(APIC_VERBOSE, KERN_DEBUG - "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); - /* - * PIRQs are mapped upside down, usually. - */ + apic_pr_verbose("... PIRQ%d -> IRQ %d\n", i, ints[i + 1]); + /* PIRQs are mapped upside down, usually */ pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; } return 1; } - __setup("pirq=", ioapic_pirq_setup); #endif /* CONFIG_X86_32 */ @@ -626,8 +565,7 @@ int save_ioapic_entries(void) } for_each_pin(apic, pin) - ioapics[apic].saved_registers[pin] = - ioapic_read_entry(apic, pin); + ioapics[apic].saved_registers[pin] = ioapic_read_entry(apic, pin); } return err; @@ -668,8 +606,7 @@ int restore_ioapic_entries(void) continue; for_each_pin(apic, pin) - ioapic_write_entry(apic, pin, - ioapics[apic].saved_registers[pin]); + ioapic_write_entry(apic, pin, ioapics[apic].saved_registers[pin]); } return 0; } @@ -681,12 +618,13 @@ static int find_irq_entry(int ioapic_idx, int pin, int type) { int i; - for (i = 0; i < mp_irq_entries; i++) + for (i = 0; i < mp_irq_entries; i++) { if (mp_irqs[i].irqtype == type && (mp_irqs[i].dstapic == mpc_ioapic_id(ioapic_idx) || mp_irqs[i].dstapic == MP_APIC_ALL) && mp_irqs[i].dstirq == pin) return i; + } return -1; } @@ -701,10 +639,8 @@ static int __init find_isa_irq_pin(int irq, int type) for (i = 0; i < mp_irq_entries; i++) { int lbus = mp_irqs[i].srcbus; - if (test_bit(lbus, mp_bus_not_pci) && - (mp_irqs[i].irqtype == type) && + if (test_bit(lbus, mp_bus_not_pci) && (mp_irqs[i].irqtype == type) && (mp_irqs[i].srcbusirq == irq)) - return mp_irqs[i].dstirq; } return -1; @@ -717,8 +653,7 @@ static int __init find_isa_irq_apic(int irq, int type) for (i = 0; i < mp_irq_entries; i++) { int lbus = mp_irqs[i].srcbus; - if (test_bit(lbus, mp_bus_not_pci) && - (mp_irqs[i].irqtype == type) && + if (test_bit(lbus, mp_bus_not_pci) && (mp_irqs[i].irqtype == type) && (mp_irqs[i].srcbusirq == irq)) break; } @@ -726,9 +661,10 @@ static int __init find_isa_irq_apic(int irq, int type) if (i < mp_irq_entries) { int ioapic_idx; - for_each_ioapic(ioapic_idx) + for_each_ioapic(ioapic_idx) { if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic) return ioapic_idx; + } } return -1; @@ -769,8 +705,7 @@ static bool EISA_ELCR(unsigned int irq) unsigned int port = PIC_ELCR1 + (irq >> 3); return (inb(port) >> (irq & 7)) & 1; } - apic_printk(APIC_VERBOSE, KERN_INFO - "Broken MPtable reports ISA irq %d\n", irq); + apic_pr_verbose("Broken MPtable reports ISA irq %d\n", irq); return false; } @@ -947,9 +882,9 @@ static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info) static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi, struct irq_alloc_info *info) { + int type = ioapics[ioapic].irqdomain_cfg.type; bool legacy = false; int irq = -1; - int type = ioapics[ioapic].irqdomain_cfg.type; switch (type) { case IOAPIC_DOMAIN_LEGACY: @@ -971,8 +906,7 @@ static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi, return -1; } - return __irq_domain_alloc_irqs(domain, irq, 1, - ioapic_alloc_attr_node(info), + return __irq_domain_alloc_irqs(domain, irq, 1, ioapic_alloc_attr_node(info), info, legacy, NULL); } @@ -986,13 +920,12 @@ static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi, * PIRQs instead of reprogramming the interrupt routing logic. Thus there may be * multiple pins sharing the same legacy IRQ number when ACPI is disabled. */ -static int alloc_isa_irq_from_domain(struct irq_domain *domain, - int irq, int ioapic, int pin, +static int alloc_isa_irq_from_domain(struct irq_domain *domain, int irq, int ioapic, int pin, struct irq_alloc_info *info) { - struct mp_chip_data *data; struct irq_data *irq_data = irq_get_irq_data(irq); int node = ioapic_alloc_attr_node(info); + struct mp_chip_data *data; /* * Legacy ISA IRQ has already been allocated, just add pin to @@ -1002,13 +935,11 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain, if (irq_data && irq_data->parent_data) { if (!mp_check_pin_attr(irq, info)) return -EBUSY; - if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic, - info->ioapic.pin)) + if (!add_pin_to_irq_node(irq_data->chip_data, node, ioapic, info->ioapic.pin)) return -ENOMEM; } else { info->flags |= X86_IRQ_ALLOC_LEGACY; - irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true, - NULL); + irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true, NULL); if (irq >= 0) { irq_data = irq_domain_get_irq_data(domain, irq); data = irq_data->chip_data; @@ -1022,11 +953,11 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain, static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, unsigned int flags, struct irq_alloc_info *info) { - int irq; - bool legacy = false; + struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); struct irq_alloc_info tmp; struct mp_chip_data *data; - struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); + bool legacy = false; + int irq; if (!domain) return -ENOSYS; @@ -1046,7 +977,7 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, return -EINVAL; } - mutex_lock(&ioapic_mutex); + guard(mutex)(&ioapic_mutex); if (!(flags & IOAPIC_MAP_ALLOC)) { if (!legacy) { irq = irq_find_mapping(domain, pin); @@ -1067,8 +998,6 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, data->count++; } } - mutex_unlock(&ioapic_mutex); - return irq; } @@ -1076,26 +1005,20 @@ static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags) { u32 gsi = mp_pin_to_gsi(ioapic, pin); - /* - * Debugging check, we are in big trouble if this message pops up! - */ + /* Debugging check, we are in big trouble if this message pops up! */ if (mp_irqs[idx].dstirq != pin) pr_err("broken BIOS or MPTABLE parser, ayiee!!\n"); #ifdef CONFIG_X86_32 - /* - * PCI IRQ command line redirection. Yes, limits are hardcoded. - */ + /* PCI IRQ command line redirection. Yes, limits are hardcoded. */ if ((pin >= 16) && (pin <= 23)) { - if (pirq_entries[pin-16] != -1) { - if (!pirq_entries[pin-16]) { - apic_printk(APIC_VERBOSE, KERN_DEBUG - "disabling PIRQ%d\n", pin-16); + if (pirq_entries[pin - 16] != -1) { + if (!pirq_entries[pin - 16]) { + apic_pr_verbose("Disabling PIRQ%d\n", pin - 16); } else { int irq = pirq_entries[pin-16]; - apic_printk(APIC_VERBOSE, KERN_DEBUG - "using PIRQ%d -> IRQ %d\n", - pin-16, irq); + + apic_pr_verbose("Using PIRQ%d -> IRQ %d\n", pin - 16, irq); return irq; } } @@ -1133,10 +1056,9 @@ void mp_unmap_irq(int irq) if (!data || data->isa_irq) return; - mutex_lock(&ioapic_mutex); + guard(mutex)(&ioapic_mutex); if (--data->count == 0) irq_domain_free_irqs(irq, 1); - mutex_unlock(&ioapic_mutex); } /* @@ -1147,12 +1069,10 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) { int irq, i, best_ioapic = -1, best_idx = -1; - apic_printk(APIC_DEBUG, - "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", - bus, slot, pin); + apic_pr_debug("Querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", + bus, slot, pin); if (test_bit(bus, mp_bus_not_pci)) { - apic_printk(APIC_VERBOSE, - "PCI BIOS passed nonexistent PCI bus %d!\n", bus); + apic_pr_verbose("PCI BIOS passed nonexistent PCI bus %d!\n", bus); return -1; } @@ -1197,8 +1117,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) return -1; out: - return pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq, - IOAPIC_MAP_ALLOC); + return pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq, IOAPIC_MAP_ALLOC); } EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); @@ -1209,17 +1128,16 @@ static void __init setup_IO_APIC_irqs(void) unsigned int ioapic, pin; int idx; - apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); + apic_pr_verbose("Init IO_APIC IRQs\n"); for_each_ioapic_pin(ioapic, pin) { idx = find_irq_entry(ioapic, pin, mp_INT); - if (idx < 0) - apic_printk(APIC_VERBOSE, - KERN_DEBUG " apic %d pin %d not connected\n", - mpc_ioapic_id(ioapic), pin); - else - pin_2_irq(idx, ioapic, pin, - ioapic ? 0 : IOAPIC_MAP_ALLOC); + if (idx < 0) { + apic_pr_verbose("apic %d pin %d not connected\n", + mpc_ioapic_id(ioapic), pin); + } else { + pin_2_irq(idx, ioapic, pin, ioapic ? 0 : IOAPIC_MAP_ALLOC); + } } } @@ -1234,26 +1152,21 @@ static void io_apic_print_entries(unsigned int apic, unsigned int nr_entries) char buf[256]; int i; - printk(KERN_DEBUG "IOAPIC %d:\n", apic); + apic_dbg("IOAPIC %d:\n", apic); for (i = 0; i <= nr_entries; i++) { entry = ioapic_read_entry(apic, i); - snprintf(buf, sizeof(buf), - " pin%02x, %s, %s, %s, V(%02X), IRR(%1d), S(%1d)", - i, - entry.masked ? "disabled" : "enabled ", + snprintf(buf, sizeof(buf), " pin%02x, %s, %s, %s, V(%02X), IRR(%1d), S(%1d)", + i, entry.masked ? "disabled" : "enabled ", entry.is_level ? "level" : "edge ", entry.active_low ? "low " : "high", entry.vector, entry.irr, entry.delivery_status); if (entry.ir_format) { - printk(KERN_DEBUG "%s, remapped, I(%04X), Z(%X)\n", - buf, - (entry.ir_index_15 << 15) | entry.ir_index_0_14, - entry.ir_zero); + apic_dbg("%s, remapped, I(%04X), Z(%X)\n", buf, + (entry.ir_index_15 << 15) | entry.ir_index_0_14, entry.ir_zero); } else { - printk(KERN_DEBUG "%s, %s, D(%02X%02X), M(%1d)\n", buf, - entry.dest_mode_logical ? "logical " : "physical", - entry.virt_destid_8_14, entry.destid_0_7, - entry.delivery_mode); + apic_dbg("%s, %s, D(%02X%02X), M(%1d)\n", buf, + entry.dest_mode_logical ? "logical " : "physic al", + entry.virt_destid_8_14, entry.destid_0_7, entry.delivery_mode); } } } @@ -1264,30 +1177,25 @@ static void __init print_IO_APIC(int ioapic_idx) union IO_APIC_reg_01 reg_01; union IO_APIC_reg_02 reg_02; union IO_APIC_reg_03 reg_03; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic_idx, 0); - reg_01.raw = io_apic_read(ioapic_idx, 1); - if (reg_01.bits.version >= 0x10) - reg_02.raw = io_apic_read(ioapic_idx, 2); - if (reg_01.bits.version >= 0x20) - reg_03.raw = io_apic_read(ioapic_idx, 3); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - - printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx)); - printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); - printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); - printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); - printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS); - - printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); - printk(KERN_DEBUG "....... : max redirection entries: %02X\n", - reg_01.bits.entries); - - printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); - printk(KERN_DEBUG "....... : IO APIC version: %02X\n", - reg_01.bits.version); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) { + reg_00.raw = io_apic_read(ioapic_idx, 0); + reg_01.raw = io_apic_read(ioapic_idx, 1); + if (reg_01.bits.version >= 0x10) + reg_02.raw = io_apic_read(ioapic_idx, 2); + if (reg_01.bits.version >= 0x20) + reg_03.raw = io_apic_read(ioapic_idx, 3); + } + + apic_dbg("IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx)); + apic_dbg(".... register #00: %08X\n", reg_00.raw); + apic_dbg("....... : physical APIC id: %02X\n", reg_00.bits.ID); + apic_dbg("....... : Delivery Type: %X\n", reg_00.bits.delivery_type); + apic_dbg("....... : LTS : %X\n", reg_00.bits.LTS); + apic_dbg(".... register #01: %08X\n", *(int *)®_01); + apic_dbg("....... : max redirection entries: %02X\n", reg_01.bits.entries); + apic_dbg("....... : PRQ implemented: %X\n", reg_01.bits.PRQ); + apic_dbg("....... : IO APIC version: %02X\n", reg_01.bits.version); /* * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02, @@ -1295,8 +1203,8 @@ static void __init print_IO_APIC(int ioapic_idx) * value, so ignore it if reg_02 == reg_01. */ if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) { - printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); - printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); + apic_dbg(".... register #02: %08X\n", reg_02.raw); + apic_dbg("....... : arbitration: %02X\n", reg_02.bits.arbitration); } /* @@ -1306,11 +1214,11 @@ static void __init print_IO_APIC(int ioapic_idx) */ if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw && reg_03.raw != reg_01.raw) { - printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw); - printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT); + apic_dbg(".... register #03: %08X\n", reg_03.raw); + apic_dbg("....... : Boot DT : %X\n", reg_03.bits.boot_DT); } - printk(KERN_DEBUG ".... IRQ redirection table:\n"); + apic_dbg(".... IRQ redirection table:\n"); io_apic_print_entries(ioapic_idx, reg_01.bits.entries); } @@ -1319,11 +1227,11 @@ void __init print_IO_APICs(void) int ioapic_idx; unsigned int irq; - printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); - for_each_ioapic(ioapic_idx) - printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", - mpc_ioapic_id(ioapic_idx), - ioapics[ioapic_idx].nr_registers); + apic_dbg("number of MP IRQ sources: %d.\n", mp_irq_entries); + for_each_ioapic(ioapic_idx) { + apic_dbg("number of IO-APIC #%d registers: %d.\n", + mpc_ioapic_id(ioapic_idx), ioapics[ioapic_idx].nr_registers); + } /* * We are a bit conservative about what we expect. We have to @@ -1334,7 +1242,7 @@ void __init print_IO_APICs(void) for_each_ioapic(ioapic_idx) print_IO_APIC(ioapic_idx); - printk(KERN_DEBUG "IRQ to pin mappings:\n"); + apic_dbg("IRQ to pin mappings:\n"); for_each_active_irq(irq) { struct irq_pin_list *entry; struct irq_chip *chip; @@ -1349,7 +1257,7 @@ void __init print_IO_APICs(void) if (list_empty(&data->irq_2_pin)) continue; - printk(KERN_DEBUG "IRQ%d ", irq); + apic_dbg("IRQ%d ", irq); for_each_irq_pin(entry, data->irq_2_pin) pr_cont("-> %d:%d", entry->apic, entry->pin); pr_cont("\n"); @@ -1363,8 +1271,7 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; void __init enable_IO_APIC(void) { - int i8259_apic, i8259_pin; - int apic, pin; + int i8259_apic, i8259_pin, apic, pin; if (ioapic_is_disabled) nr_ioapics = 0; @@ -1376,19 +1283,21 @@ void __init enable_IO_APIC(void) /* See if any of the pins is in ExtINT mode */ struct IO_APIC_route_entry entry = ioapic_read_entry(apic, pin); - /* If the interrupt line is enabled and in ExtInt mode - * I have found the pin where the i8259 is connected. + /* + * If the interrupt line is enabled and in ExtInt mode I + * have found the pin where the i8259 is connected. */ - if (!entry.masked && - entry.delivery_mode == APIC_DELIVERY_MODE_EXTINT) { + if (!entry.masked && entry.delivery_mode == APIC_DELIVERY_MODE_EXTINT) { ioapic_i8259.apic = apic; ioapic_i8259.pin = pin; - goto found_i8259; + break; } } - found_i8259: - /* Look to see what if the MP table has reported the ExtINT */ - /* If we could not find the appropriate pin by looking at the ioapic + + /* + * Look to see what if the MP table has reported the ExtINT + * + * If we could not find the appropriate pin by looking at the ioapic * the i8259 probably is not connected the ioapic but give the * mptable a chance anyway. */ @@ -1396,29 +1305,24 @@ void __init enable_IO_APIC(void) i8259_apic = find_isa_irq_apic(0, mp_ExtINT); /* Trust the MP table if nothing is setup in the hardware */ if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) { - printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n"); + pr_warn("ExtINT not setup in hardware but reported by MP table\n"); ioapic_i8259.pin = i8259_pin; ioapic_i8259.apic = i8259_apic; } /* Complain if the MP table and the hardware disagree */ if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) && - (i8259_pin >= 0) && (ioapic_i8259.pin >= 0)) - { - printk(KERN_WARNING "ExtINT in hardware and MP table differ\n"); - } + (i8259_pin >= 0) && (ioapic_i8259.pin >= 0)) + pr_warn("ExtINT in hardware and MP table differ\n"); - /* - * Do not trust the IO-APIC being empty at bootup - */ + /* Do not trust the IO-APIC being empty at bootup */ clear_IO_APIC(); } void native_restore_boot_irq_mode(void) { /* - * If the i8259 is routed through an IOAPIC - * Put that IOAPIC in virtual wire mode - * so legacy interrupts can be delivered. + * If the i8259 is routed through an IOAPIC Put that IOAPIC in + * virtual wire mode so legacy interrupts can be delivered. */ if (ioapic_i8259.pin != -1) { struct IO_APIC_route_entry entry; @@ -1433,9 +1337,7 @@ void native_restore_boot_irq_mode(void) entry.destid_0_7 = apic_id & 0xFF; entry.virt_destid_8_14 = apic_id >> 8; - /* - * Add it to the IO-APIC irq-routing table: - */ + /* Add it to the IO-APIC irq-routing table */ ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry); } @@ -1464,7 +1366,6 @@ static void __init setup_ioapic_ids_from_mpc_nocheck(void) const u32 broadcast_id = 0xF; union IO_APIC_reg_00 reg_00; unsigned char old_id; - unsigned long flags; int ioapic_idx, i; /* @@ -1478,9 +1379,8 @@ static void __init setup_ioapic_ids_from_mpc_nocheck(void) */ for_each_ioapic(ioapic_idx) { /* Read the register 0 value */ - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic_idx, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) + reg_00.raw = io_apic_read(ioapic_idx, 0); old_id = mpc_ioapic_id(ioapic_idx); @@ -1508,47 +1408,42 @@ static void __init setup_ioapic_ids_from_mpc_nocheck(void) set_bit(i, phys_id_present_map); ioapics[ioapic_idx].mp_config.apicid = i; } else { - apic_printk(APIC_VERBOSE, "Setting %d in the phys_id_present_map\n", - mpc_ioapic_id(ioapic_idx)); + apic_pr_verbose("Setting %d in the phys_id_present_map\n", + mpc_ioapic_id(ioapic_idx)); set_bit(mpc_ioapic_id(ioapic_idx), phys_id_present_map); } /* - * We need to adjust the IRQ routing table - * if the ID changed. + * We need to adjust the IRQ routing table if the ID + * changed. */ - if (old_id != mpc_ioapic_id(ioapic_idx)) - for (i = 0; i < mp_irq_entries; i++) + if (old_id != mpc_ioapic_id(ioapic_idx)) { + for (i = 0; i < mp_irq_entries; i++) { if (mp_irqs[i].dstapic == old_id) - mp_irqs[i].dstapic - = mpc_ioapic_id(ioapic_idx); + mp_irqs[i].dstapic = mpc_ioapic_id(ioapic_idx); + } + } /* - * Update the ID register according to the right value - * from the MPC table if they are different. + * Update the ID register according to the right value from + * the MPC table if they are different. */ if (mpc_ioapic_id(ioapic_idx) == reg_00.bits.ID) continue; - apic_printk(APIC_VERBOSE, KERN_INFO - "...changing IO-APIC physical APIC ID to %d ...", - mpc_ioapic_id(ioapic_idx)); + apic_pr_verbose("...changing IO-APIC physical APIC ID to %d ...", + mpc_ioapic_id(ioapic_idx)); reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); - raw_spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic_idx, 0, reg_00.raw); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - - /* - * Sanity check - */ - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic_idx, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) { + io_apic_write(ioapic_idx, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic_idx, 0); + } + /* Sanity check */ if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) pr_cont("could not set ID!\n"); else - apic_printk(APIC_VERBOSE, " ok.\n"); + apic_pr_verbose(" ok.\n"); } } @@ -1593,8 +1488,7 @@ static void __init delay_with_tsc(void) do { rep_nop(); now = rdtsc(); - } while ((now - start) < 40000000000ULL / HZ && - time_before_eq(jiffies, end)); + } while ((now - start) < 40000000000ULL / HZ && time_before_eq(jiffies, end)); } static void __init delay_without_tsc(void) @@ -1655,36 +1549,29 @@ static int __init timer_irq_works(void) * so we 'resend' these IRQs via IPIs, to the same CPU. It's much * better to do it this way as thus we do not have to be aware of * 'pending' interrupts in the IRQ path, except at this point. - */ -/* - * Edge triggered needs to resend any interrupt - * that was delayed but this is now handled in the device - * independent code. - */ - -/* - * Starting up a edge-triggered IO-APIC interrupt is - * nasty - we need to make sure that we get the edge. - * If it is already asserted for some reason, we need - * return 1 to indicate that is was pending. * - * This is not complete - we should be able to fake - * an edge even if it isn't on the 8259A... + * + * Edge triggered needs to resend any interrupt that was delayed but this + * is now handled in the device independent code. + * + * Starting up a edge-triggered IO-APIC interrupt is nasty - we need to + * make sure that we get the edge. If it is already asserted for some + * reason, we need return 1 to indicate that is was pending. + * + * This is not complete - we should be able to fake an edge even if it + * isn't on the 8259A... */ static unsigned int startup_ioapic_irq(struct irq_data *data) { int was_pending = 0, irq = data->irq; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); if (irq < nr_legacy_irqs()) { legacy_pic->mask(irq); if (legacy_pic->irq_pending(irq)) was_pending = 1; } __unmask_ioapic(data->chip_data); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - return was_pending; } @@ -1694,9 +1581,8 @@ atomic_t irq_mis_count; static bool io_apic_level_ack_pending(struct mp_chip_data *data) { struct irq_pin_list *entry; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); for_each_irq_pin(entry, data->irq_2_pin) { struct IO_APIC_route_entry e; int pin; @@ -1704,13 +1590,9 @@ static bool io_apic_level_ack_pending(struct mp_chip_data *data) pin = entry->pin; e.w1 = io_apic_read(entry->apic, 0x10 + pin*2); /* Is the remote IRR bit set? */ - if (e.irr) { - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + if (e.irr) return true; - } } - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - return false; } @@ -1728,7 +1610,8 @@ static inline bool ioapic_prepare_move(struct irq_data *data) static inline void ioapic_finish_move(struct irq_data *data, bool moveit) { if (unlikely(moveit)) { - /* Only migrate the irq if the ack has been received. + /* + * Only migrate the irq if the ack has been received. * * On rare occasions the broadcast level triggered ack gets * delayed going to ioapics, and if we reprogram the @@ -1911,18 +1794,16 @@ static void ioapic_configure_entry(struct irq_data *irqd) __ioapic_write_entry(entry->apic, entry->pin, mpd->entry); } -static int ioapic_set_affinity(struct irq_data *irq_data, - const struct cpumask *mask, bool force) +static int ioapic_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) { struct irq_data *parent = irq_data->parent_data; - unsigned long flags; int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); - raw_spin_lock_irqsave(&ioapic_lock, flags); + + guard(raw_spinlock_irqsave)(&ioapic_lock); if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) ioapic_configure_entry(irq_data); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); return ret; } @@ -1941,9 +1822,8 @@ static int ioapic_set_affinity(struct irq_data *irq_data, * * Verify that the corresponding Remote-IRR bits are clear. */ -static int ioapic_irq_get_chip_state(struct irq_data *irqd, - enum irqchip_irq_state which, - bool *state) +static int ioapic_irq_get_chip_state(struct irq_data *irqd, enum irqchip_irq_state which, + bool *state) { struct mp_chip_data *mcd = irqd->chip_data; struct IO_APIC_route_entry rentry; @@ -1953,7 +1833,8 @@ static int ioapic_irq_get_chip_state(struct irq_data *irqd, return -EINVAL; *state = false; - raw_spin_lock(&ioapic_lock); + + guard(raw_spinlock)(&ioapic_lock); for_each_irq_pin(p, mcd->irq_2_pin) { rentry = __ioapic_read_entry(p->apic, p->pin); /* @@ -1967,7 +1848,6 @@ static int ioapic_irq_get_chip_state(struct irq_data *irqd, break; } } - raw_spin_unlock(&ioapic_lock); return 0; } @@ -2008,14 +1888,13 @@ static inline void init_IO_APIC_traps(void) cfg = irq_cfg(irq); if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { /* - * Hmm.. We don't have an entry for this, - * so default to an old-fashioned 8259 - * interrupt if we can.. + * Hmm.. We don't have an entry for this, so + * default to an old-fashioned 8259 interrupt if we + * can. Otherwise set the dummy interrupt chip. */ if (irq < nr_legacy_irqs()) legacy_pic->make_irq(irq); else - /* Strange. Oh, well.. */ irq_set_chip(irq, &no_irq_chip); } } @@ -2024,20 +1903,17 @@ static inline void init_IO_APIC_traps(void) /* * The local APIC irq-chip implementation: */ - static void mask_lapic_irq(struct irq_data *data) { - unsigned long v; + unsigned long v = apic_read(APIC_LVT0); - v = apic_read(APIC_LVT0); apic_write(APIC_LVT0, v | APIC_LVT_MASKED); } static void unmask_lapic_irq(struct irq_data *data) { - unsigned long v; + unsigned long v = apic_read(APIC_LVT0); - v = apic_read(APIC_LVT0); apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); } @@ -2056,8 +1932,7 @@ static struct irq_chip lapic_chip __read_mostly = { static void lapic_register_intr(int irq) { irq_clear_status_flags(irq, IRQ_LEVEL); - irq_set_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, - "edge"); + irq_set_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, "edge"); } /* @@ -2069,9 +1944,9 @@ static void lapic_register_intr(int irq) */ static inline void __init unlock_ExtINT_logic(void) { - int apic, pin, i; - struct IO_APIC_route_entry entry0, entry1; unsigned char save_control, save_freq_select; + struct IO_APIC_route_entry entry0, entry1; + int apic, pin, i; u32 apic_id; pin = find_isa_irq_pin(8, mp_INT); @@ -2131,10 +2006,10 @@ static int __init disable_timer_pin_setup(char *arg) } early_param("disable_timer_pin_1", disable_timer_pin_setup); -static int mp_alloc_timer_irq(int ioapic, int pin) +static int __init mp_alloc_timer_irq(int ioapic, int pin) { - int irq = -1; struct irq_domain *domain = mp_ioapic_irqdomain(ioapic); + int irq = -1; if (domain) { struct irq_alloc_info info; @@ -2142,21 +2017,36 @@ static int mp_alloc_timer_irq(int ioapic, int pin) ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 0, 0); info.devid = mpc_ioapic_id(ioapic); info.ioapic.pin = pin; - mutex_lock(&ioapic_mutex); + guard(mutex)(&ioapic_mutex); irq = alloc_isa_irq_from_domain(domain, 0, ioapic, pin, &info); - mutex_unlock(&ioapic_mutex); } return irq; } +static void __init replace_pin_at_irq_node(struct mp_chip_data *data, int node, + int oldapic, int oldpin, + int newapic, int newpin) +{ + struct irq_pin_list *entry; + + for_each_irq_pin(entry, data->irq_2_pin) { + if (entry->apic == oldapic && entry->pin == oldpin) { + entry->apic = newapic; + entry->pin = newpin; + return; + } + } + + /* Old apic/pin didn't exist, so just add a new one */ + add_pin_to_irq_node(data, node, newapic, newpin); +} + /* * This code may look a bit paranoid, but it's supposed to cooperate with * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ * is so screwy. Thanks to Brian Perkins for testing/hacking this beast * fanatically on his truly buggy board. - * - * FIXME: really need to revamp this for all platforms. */ static inline void __init check_timer(void) { @@ -2194,9 +2084,8 @@ static inline void __init check_timer(void) pin2 = ioapic_i8259.pin; apic2 = ioapic_i8259.apic; - apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X " - "apic1=%d pin1=%d apic2=%d pin2=%d\n", - cfg->vector, apic1, pin1, apic2, pin2); + pr_info("..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", + cfg->vector, apic1, pin1, apic2, pin2); /* * Some BIOS writers are clueless and report the ExtINTA @@ -2240,13 +2129,10 @@ static inline void __init check_timer(void) panic_if_irq_remap("timer doesn't work through Interrupt-remapped IO-APIC"); clear_IO_APIC_pin(apic1, pin1); if (!no_pin1) - apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: " - "8254 timer not connected to IO-APIC\n"); + pr_err("..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); - apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer " - "(IRQ0) through the 8259A ...\n"); - apic_printk(APIC_QUIET, KERN_INFO - "..... (found apic %d pin %d) ...\n", apic2, pin2); + pr_info("...trying to set up timer (IRQ0) through the 8259A ...\n"); + pr_info("..... (found apic %d pin %d) ...\n", apic2, pin2); /* * legacy devices should be connected to IO APIC #0 */ @@ -2255,7 +2141,7 @@ static inline void __init check_timer(void) irq_domain_activate_irq(irq_data, false); legacy_pic->unmask(0); if (timer_irq_works()) { - apic_printk(APIC_QUIET, KERN_INFO "....... works.\n"); + pr_info("....... works.\n"); goto out; } /* @@ -2263,26 +2149,24 @@ static inline void __init check_timer(void) */ legacy_pic->mask(0); clear_IO_APIC_pin(apic2, pin2); - apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n"); + pr_info("....... failed.\n"); } - apic_printk(APIC_QUIET, KERN_INFO - "...trying to set up timer as Virtual Wire IRQ...\n"); + pr_info("...trying to set up timer as Virtual Wire IRQ...\n"); lapic_register_intr(0); apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ legacy_pic->unmask(0); if (timer_irq_works()) { - apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); + pr_info("..... works.\n"); goto out; } legacy_pic->mask(0); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); - apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n"); + pr_info("..... failed.\n"); - apic_printk(APIC_QUIET, KERN_INFO - "...trying to set up timer as ExtINT IRQ...\n"); + pr_info("...trying to set up timer as ExtINT IRQ...\n"); legacy_pic->init(0); legacy_pic->make_irq(0); @@ -2292,14 +2176,15 @@ static inline void __init check_timer(void) unlock_ExtINT_logic(); if (timer_irq_works()) { - apic_printk(APIC_QUIET, KERN_INFO "..... works.\n"); + pr_info("..... works.\n"); goto out; } - apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); - if (apic_is_x2apic_enabled()) - apic_printk(APIC_QUIET, KERN_INFO - "Perhaps problem with the pre-enabled x2apic mode\n" - "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); + + pr_info("..... failed :\n"); + if (apic_is_x2apic_enabled()) { + pr_info("Perhaps problem with the pre-enabled x2apic mode\n" + "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); + } panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " "report. Then try booting with the 'noapic' option.\n"); out: @@ -2327,11 +2212,11 @@ out: static int mp_irqdomain_create(int ioapic) { - struct irq_domain *parent; + struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic); int hwirqs = mp_ioapic_pin_count(ioapic); struct ioapic *ip = &ioapics[ioapic]; struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg; - struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic); + struct irq_domain *parent; struct fwnode_handle *fn; struct irq_fwspec fwspec; @@ -2367,10 +2252,8 @@ static int mp_irqdomain_create(int ioapic) return -ENOMEM; } - if (cfg->type == IOAPIC_DOMAIN_LEGACY || - cfg->type == IOAPIC_DOMAIN_STRICT) - ioapic_dynirq_base = max(ioapic_dynirq_base, - gsi_cfg->gsi_end + 1); + if (cfg->type == IOAPIC_DOMAIN_LEGACY || cfg->type == IOAPIC_DOMAIN_STRICT) + ioapic_dynirq_base = max(ioapic_dynirq_base, gsi_cfg->gsi_end + 1); return 0; } @@ -2397,13 +2280,11 @@ void __init setup_IO_APIC(void) io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; - apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); + apic_pr_verbose("ENABLING IO-APIC IRQs\n"); for_each_ioapic(ioapic) BUG_ON(mp_irqdomain_create(ioapic)); - /* - * Set up IO-APIC IRQ routing. - */ + /* Set up IO-APIC IRQ routing. */ x86_init.mpparse.setup_ioapic_ids(); sync_Arb_IDs(); @@ -2417,16 +2298,14 @@ void __init setup_IO_APIC(void) static void resume_ioapic_id(int ioapic_idx) { - unsigned long flags; union IO_APIC_reg_00 reg_00; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); reg_00.raw = io_apic_read(ioapic_idx, 0); if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx)) { reg_00.bits.ID = mpc_ioapic_id(ioapic_idx); io_apic_write(ioapic_idx, 0, reg_00.raw); } - raw_spin_unlock_irqrestore(&ioapic_lock, flags); } static void ioapic_resume(void) @@ -2440,8 +2319,8 @@ static void ioapic_resume(void) } static struct syscore_ops ioapic_syscore_ops = { - .suspend = save_ioapic_entries, - .resume = ioapic_resume, + .suspend = save_ioapic_entries, + .resume = ioapic_resume, }; static int __init ioapic_init_ops(void) @@ -2456,15 +2335,13 @@ device_initcall(ioapic_init_ops); static int io_apic_get_redir_entries(int ioapic) { union IO_APIC_reg_01 reg_01; - unsigned long flags; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); reg_01.raw = io_apic_read(ioapic, 1); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - /* The register returns the maximum index redir index - * supported, which is one less than the total number of redir - * entries. + /* + * The register returns the maximum index redir index supported, + * which is one less than the total number of redir entries. */ return reg_01.bits.entries + 1; } @@ -2494,16 +2371,14 @@ static int io_apic_get_unique_id(int ioapic, int apic_id) static DECLARE_BITMAP(apic_id_map, MAX_LOCAL_APIC); const u32 broadcast_id = 0xF; union IO_APIC_reg_00 reg_00; - unsigned long flags; int i = 0; /* Initialize the ID map */ if (bitmap_empty(apic_id_map, MAX_LOCAL_APIC)) copy_phys_cpu_present_map(apic_id_map); - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(ioapic, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) + reg_00.raw = io_apic_read(ioapic, 0); if (apic_id >= broadcast_id) { pr_warn("IOAPIC[%d]: Invalid apic_id %d, trying %d\n", @@ -2530,21 +2405,19 @@ static int io_apic_get_unique_id(int ioapic, int apic_id) if (reg_00.bits.ID != apic_id) { reg_00.bits.ID = apic_id; - raw_spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, reg_00.raw); - reg_00.raw = io_apic_read(ioapic, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) { + io_apic_write(ioapic, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic, 0); + } /* Sanity check */ if (reg_00.bits.ID != apic_id) { - pr_err("IOAPIC[%d]: Unable to change apic_id!\n", - ioapic); + pr_err("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); return -1; } } - apic_printk(APIC_VERBOSE, KERN_INFO - "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + apic_pr_verbose("IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); return apic_id; } @@ -2560,7 +2433,6 @@ static u8 io_apic_unique_id(int idx, u8 id) { union IO_APIC_reg_00 reg_00; DECLARE_BITMAP(used, 256); - unsigned long flags; u8 new_id; int i; @@ -2576,26 +2448,23 @@ static u8 io_apic_unique_id(int idx, u8 id) * Read the current id from the ioapic and keep it if * available. */ - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_00.raw = io_apic_read(idx, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) + reg_00.raw = io_apic_read(idx, 0); + new_id = reg_00.bits.ID; if (!test_bit(new_id, used)) { - apic_printk(APIC_VERBOSE, KERN_INFO - "IOAPIC[%d]: Using reg apic_id %d instead of %d\n", - idx, new_id, id); + apic_pr_verbose("IOAPIC[%d]: Using reg apic_id %d instead of %d\n", + idx, new_id, id); return new_id; } - /* - * Get the next free id and write it to the ioapic. - */ + /* Get the next free id and write it to the ioapic. */ new_id = find_first_zero_bit(used, 256); reg_00.bits.ID = new_id; - raw_spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(idx, 0, reg_00.raw); - reg_00.raw = io_apic_read(idx, 0); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); + scoped_guard (raw_spinlock_irqsave, &ioapic_lock) { + io_apic_write(idx, 0, reg_00.raw); + reg_00.raw = io_apic_read(idx, 0); + } /* Sanity check */ BUG_ON(reg_00.bits.ID != new_id); @@ -2605,12 +2474,10 @@ static u8 io_apic_unique_id(int idx, u8 id) static int io_apic_get_version(int ioapic) { - union IO_APIC_reg_01 reg_01; - unsigned long flags; + union IO_APIC_reg_01 reg_01; - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); reg_01.raw = io_apic_read(ioapic, 1); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); return reg_01.bits.version; } @@ -2625,8 +2492,8 @@ static struct resource *ioapic_resources; static struct resource * __init ioapic_setup_resources(void) { - unsigned long n; struct resource *res; + unsigned long n; char *mem; int i; @@ -2686,9 +2553,7 @@ void __init io_apic_init_mappings(void) ioapic_phys = mpc_ioapic_addr(i); #ifdef CONFIG_X86_32 if (!ioapic_phys) { - printk(KERN_ERR - "WARNING: bogus zero IO-APIC " - "address found in MPTABLE, " + pr_err("WARNING: bogus zero IO-APIC address found in MPTABLE, " "disabling IO/APIC support!\n"); smp_found_config = 0; ioapic_is_disabled = true; @@ -2707,9 +2572,8 @@ fake_ioapic_page: ioapic_phys = __pa(ioapic_phys); } io_apic_set_fixmap(idx, ioapic_phys); - apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", - __fix_to_virt(idx) + (ioapic_phys & ~PAGE_MASK), - ioapic_phys); + apic_pr_verbose("mapped IOAPIC to %08lx (%08lx)\n", + __fix_to_virt(idx) + (ioapic_phys & ~PAGE_MASK), ioapic_phys); idx++; ioapic_res->start = ioapic_phys; @@ -2720,13 +2584,12 @@ fake_ioapic_page: void __init ioapic_insert_resources(void) { - int i; struct resource *r = ioapic_resources; + int i; if (!r) { if (nr_ioapics > 0) - printk(KERN_ERR - "IO APIC resources couldn't be allocated.\n"); + pr_err("IO APIC resources couldn't be allocated.\n"); return; } @@ -2746,11 +2609,12 @@ int mp_find_ioapic(u32 gsi) /* Find the IOAPIC that manages this GSI. */ for_each_ioapic(i) { struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i); + if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end) return i; } - printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); + pr_err("ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); return -1; } @@ -2789,12 +2653,10 @@ static int bad_ioapic_register(int idx) static int find_free_ioapic_entry(void) { - int idx; - - for (idx = 0; idx < MAX_IO_APICS; idx++) + for (int idx = 0; idx < MAX_IO_APICS; idx++) { if (ioapics[idx].nr_registers == 0) return idx; - + } return MAX_IO_APICS; } @@ -2805,8 +2667,7 @@ static int find_free_ioapic_entry(void) * @gsi_base: base of GSI associated with the IOAPIC * @cfg: configuration information for the IOAPIC */ -int mp_register_ioapic(int id, u32 address, u32 gsi_base, - struct ioapic_domain_cfg *cfg) +int mp_register_ioapic(int id, u32 address, u32 gsi_base, struct ioapic_domain_cfg *cfg) { bool hotplug = !!ioapic_initialized; struct mp_ioapic_gsi *gsi_cfg; @@ -2817,12 +2678,13 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base, pr_warn("Bogus (zero) I/O APIC address found, skipping!\n"); return -EINVAL; } - for_each_ioapic(ioapic) + + for_each_ioapic(ioapic) { if (ioapics[ioapic].mp_config.apicaddr == address) { - pr_warn("address 0x%x conflicts with IOAPIC%d\n", - address, ioapic); + pr_warn("address 0x%x conflicts with IOAPIC%d\n", address, ioapic); return -EEXIST; } + } idx = find_free_ioapic_entry(); if (idx >= MAX_IO_APICS) { @@ -2857,8 +2719,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base, (gsi_end >= gsi_cfg->gsi_base && gsi_end <= gsi_cfg->gsi_end)) { pr_warn("GSI range [%u-%u] for new IOAPIC conflicts with GSI[%u-%u]\n", - gsi_base, gsi_end, - gsi_cfg->gsi_base, gsi_cfg->gsi_end); + gsi_base, gsi_end, gsi_cfg->gsi_base, gsi_cfg->gsi_end); clear_fixmap(FIX_IO_APIC_BASE_0 + idx); return -ENOSPC; } @@ -2892,8 +2753,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base, ioapics[idx].nr_registers = entries; pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n", - idx, mpc_ioapic_id(idx), - mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), + idx, mpc_ioapic_id(idx), mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), gsi_cfg->gsi_base, gsi_cfg->gsi_end); return 0; @@ -2904,11 +2764,13 @@ int mp_unregister_ioapic(u32 gsi_base) int ioapic, pin; int found = 0; - for_each_ioapic(ioapic) + for_each_ioapic(ioapic) { if (ioapics[ioapic].gsi_config.gsi_base == gsi_base) { found = 1; break; } + } + if (!found) { pr_warn("can't find IOAPIC for GSI %d\n", gsi_base); return -ENODEV; @@ -2922,8 +2784,7 @@ int mp_unregister_ioapic(u32 gsi_base) if (irq >= 0) { data = irq_get_chip_data(irq); if (data && data->count) { - pr_warn("pin%d on IOAPIC%d is still in use.\n", - pin, ioapic); + pr_warn("pin%d on IOAPIC%d is still in use.\n", pin, ioapic); return -EBUSY; } } @@ -2958,8 +2819,7 @@ static void mp_irqdomain_get_attr(u32 gsi, struct mp_chip_data *data, if (info && info->ioapic.valid) { data->is_level = info->ioapic.is_level; data->active_low = info->ioapic.active_low; - } else if (__acpi_get_override_irq(gsi, &data->is_level, - &data->active_low) < 0) { + } else if (__acpi_get_override_irq(gsi, &data->is_level, &data->active_low) < 0) { /* PCI interrupts are always active low level triggered. */ data->is_level = true; data->active_low = true; @@ -3017,10 +2877,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, return -ENOMEM; ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); - if (ret < 0) { - kfree(data); - return ret; - } + if (ret < 0) + goto free_data; INIT_LIST_HEAD(&data->irq_2_pin); irq_data->hwirq = info->ioapic.pin; @@ -3029,7 +2887,10 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, irq_data->chip_data = data; mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info); - add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); + if (!add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin)) { + ret = -ENOMEM; + goto free_irqs; + } mp_preconfigure_entry(data); mp_register_handler(virq, data->is_level); @@ -3039,11 +2900,15 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, legacy_pic->mask(virq); local_irq_restore(flags); - apic_printk(APIC_VERBOSE, KERN_DEBUG - "IOAPIC[%d]: Preconfigured routing entry (%d-%d -> IRQ %d Level:%i ActiveLow:%i)\n", - ioapic, mpc_ioapic_id(ioapic), pin, virq, - data->is_level, data->active_low); + apic_pr_verbose("IOAPIC[%d]: Preconfigured routing entry (%d-%d -> IRQ %d Level:%i ActiveLow:%i)\n", + ioapic, mpc_ioapic_id(ioapic), pin, virq, data->is_level, data->active_low); return 0; + +free_irqs: + irq_domain_free_irqs_parent(domain, virq, nr_irqs); +free_data: + kfree(data); + return ret; } void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq, @@ -3056,22 +2921,17 @@ void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq, irq_data = irq_domain_get_irq_data(domain, virq); if (irq_data && irq_data->chip_data) { data = irq_data->chip_data; - __remove_pin_from_irq(data, mp_irqdomain_ioapic_idx(domain), - (int)irq_data->hwirq); + __remove_pin_from_irq(data, mp_irqdomain_ioapic_idx(domain), (int)irq_data->hwirq); WARN_ON(!list_empty(&data->irq_2_pin)); kfree(irq_data->chip_data); } irq_domain_free_irqs_top(domain, virq, nr_irqs); } -int mp_irqdomain_activate(struct irq_domain *domain, - struct irq_data *irq_data, bool reserve) +int mp_irqdomain_activate(struct irq_domain *domain, struct irq_data *irq_data, bool reserve) { - unsigned long flags; - - raw_spin_lock_irqsave(&ioapic_lock, flags); + guard(raw_spinlock_irqsave)(&ioapic_lock); ioapic_configure_entry(irq_data); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); return 0; } @@ -3079,8 +2939,7 @@ void mp_irqdomain_deactivate(struct irq_domain *domain, struct irq_data *irq_data) { /* It won't be called for IRQ with multiple IOAPIC pins associated */ - ioapic_mask_entry(mp_irqdomain_ioapic_idx(domain), - (int)irq_data->hwirq); + ioapic_mask_entry(mp_irqdomain_ioapic_idx(domain), (int)irq_data->hwirq); } int mp_irqdomain_ioapic_idx(struct irq_domain *domain) diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 557318145038..736f62812f5c 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -712,8 +712,8 @@ int __init arch_probe_nr_irqs(void) { int nr; - if (nr_irqs > (NR_VECTORS * nr_cpu_ids)) - nr_irqs = NR_VECTORS * nr_cpu_ids; + if (irq_get_nr_irqs() > NR_VECTORS * nr_cpu_ids) + irq_set_nr_irqs(NR_VECTORS * nr_cpu_ids); nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids; #if defined(CONFIG_PCI_MSI) @@ -725,8 +725,8 @@ int __init arch_probe_nr_irqs(void) else nr += gsi_top * 16; #endif - if (nr < nr_irqs) - nr_irqs = nr; + if (nr < irq_get_nr_irqs()) + irq_set_nr_irqs(nr); /* * We don't know if PIC is present at this point so we need to do diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 5857a0f5d514..4efdf5c2efc8 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -59,6 +59,8 @@ obj-$(CONFIG_ACRN_GUEST) += acrn.o obj-$(CONFIG_DEBUG_FS) += debugfs.o +obj-$(CONFIG_X86_BUS_LOCK_DETECT) += bus_lock.o + quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(src)/mkcapflags.sh $@ $^ diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 1e0fe5f8ab84..823f44f7bc94 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -924,6 +924,17 @@ static void init_amd_zen4(struct cpuinfo_x86 *c) { if (!cpu_has(c, X86_FEATURE_HYPERVISOR)) msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT); + + /* + * These Zen4 SoCs advertise support for virtualized VMLOAD/VMSAVE + * in some BIOS versions but they can lead to random host reboots. + */ + switch (c->x86_model) { + case 0x18 ... 0x1f: + case 0x60 ... 0x7f: + clear_cpu_cap(c, X86_FEATURE_V_VMSAVE_VMLOAD); + break; + } } static void init_amd_zen5(struct cpuinfo_x86 *c) @@ -1190,22 +1201,6 @@ unsigned long amd_get_dr_addr_mask(unsigned int dr) } EXPORT_SYMBOL_GPL(amd_get_dr_addr_mask); -u32 amd_get_highest_perf(void) -{ - struct cpuinfo_x86 *c = &boot_cpu_data; - - if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) || - (c->x86_model >= 0x70 && c->x86_model < 0x80))) - return 166; - - if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) || - (c->x86_model >= 0x40 && c->x86_model < 0x70))) - return 166; - - return 255; -} -EXPORT_SYMBOL_GPL(amd_get_highest_perf); - static void zenbleed_check_cpu(void *unused) { struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); @@ -1218,5 +1213,6 @@ void amd_check_microcode(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return; - on_each_cpu(zenbleed_check_cpu, NULL, 1); + if (cpu_feature_enabled(X86_FEATURE_ZEN2)) + on_each_cpu(zenbleed_check_cpu, NULL, 1); } diff --git a/arch/x86/kernel/cpu/aperfmperf.c b/arch/x86/kernel/cpu/aperfmperf.c index 0b69bfbf345d..f642de2ebdac 100644 --- a/arch/x86/kernel/cpu/aperfmperf.c +++ b/arch/x86/kernel/cpu/aperfmperf.c @@ -349,9 +349,89 @@ static DECLARE_WORK(disable_freq_invariance_work, DEFINE_PER_CPU(unsigned long, arch_freq_scale) = SCHED_CAPACITY_SCALE; EXPORT_PER_CPU_SYMBOL_GPL(arch_freq_scale); +static DEFINE_STATIC_KEY_FALSE(arch_hybrid_cap_scale_key); + +struct arch_hybrid_cpu_scale { + unsigned long capacity; + unsigned long freq_ratio; +}; + +static struct arch_hybrid_cpu_scale __percpu *arch_cpu_scale; + +/** + * arch_enable_hybrid_capacity_scale() - Enable hybrid CPU capacity scaling + * + * Allocate memory for per-CPU data used by hybrid CPU capacity scaling, + * initialize it and set the static key controlling its code paths. + * + * Must be called before arch_set_cpu_capacity(). + */ +bool arch_enable_hybrid_capacity_scale(void) +{ + int cpu; + + if (static_branch_unlikely(&arch_hybrid_cap_scale_key)) { + WARN_ONCE(1, "Hybrid CPU capacity scaling already enabled"); + return true; + } + + arch_cpu_scale = alloc_percpu(struct arch_hybrid_cpu_scale); + if (!arch_cpu_scale) + return false; + + for_each_possible_cpu(cpu) { + per_cpu_ptr(arch_cpu_scale, cpu)->capacity = SCHED_CAPACITY_SCALE; + per_cpu_ptr(arch_cpu_scale, cpu)->freq_ratio = arch_max_freq_ratio; + } + + static_branch_enable(&arch_hybrid_cap_scale_key); + + pr_info("Hybrid CPU capacity scaling enabled\n"); + + return true; +} + +/** + * arch_set_cpu_capacity() - Set scale-invariance parameters for a CPU + * @cpu: Target CPU. + * @cap: Capacity of @cpu at its maximum frequency, relative to @max_cap. + * @max_cap: System-wide maximum CPU capacity. + * @cap_freq: Frequency of @cpu corresponding to @cap. + * @base_freq: Frequency of @cpu at which MPERF counts. + * + * The units in which @cap and @max_cap are expressed do not matter, so long + * as they are consistent, because the former is effectively divided by the + * latter. Analogously for @cap_freq and @base_freq. + * + * After calling this function for all CPUs, call arch_rebuild_sched_domains() + * to let the scheduler know that capacity-aware scheduling can be used going + * forward. + */ +void arch_set_cpu_capacity(int cpu, unsigned long cap, unsigned long max_cap, + unsigned long cap_freq, unsigned long base_freq) +{ + if (static_branch_likely(&arch_hybrid_cap_scale_key)) { + WRITE_ONCE(per_cpu_ptr(arch_cpu_scale, cpu)->capacity, + div_u64(cap << SCHED_CAPACITY_SHIFT, max_cap)); + WRITE_ONCE(per_cpu_ptr(arch_cpu_scale, cpu)->freq_ratio, + div_u64(cap_freq << SCHED_CAPACITY_SHIFT, base_freq)); + } else { + WARN_ONCE(1, "Hybrid CPU capacity scaling not enabled"); + } +} + +unsigned long arch_scale_cpu_capacity(int cpu) +{ + if (static_branch_unlikely(&arch_hybrid_cap_scale_key)) + return READ_ONCE(per_cpu_ptr(arch_cpu_scale, cpu)->capacity); + + return SCHED_CAPACITY_SCALE; +} +EXPORT_SYMBOL_GPL(arch_scale_cpu_capacity); + static void scale_freq_tick(u64 acnt, u64 mcnt) { - u64 freq_scale; + u64 freq_scale, freq_ratio; if (!arch_scale_freq_invariant()) return; @@ -359,7 +439,12 @@ static void scale_freq_tick(u64 acnt, u64 mcnt) if (check_shl_overflow(acnt, 2*SCHED_CAPACITY_SHIFT, &acnt)) goto error; - if (check_mul_overflow(mcnt, arch_max_freq_ratio, &mcnt) || !mcnt) + if (static_branch_unlikely(&arch_hybrid_cap_scale_key)) + freq_ratio = READ_ONCE(this_cpu_ptr(arch_cpu_scale)->freq_ratio); + else + freq_ratio = arch_max_freq_ratio; + + if (check_mul_overflow(mcnt, freq_ratio, &mcnt) || !mcnt) goto error; freq_scale = div64_u64(acnt, mcnt); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 45675da354f3..47a01d4028f6 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -233,7 +233,8 @@ static void x86_amd_ssb_disable(void) #define pr_fmt(fmt) "MDS: " fmt /* Default mitigation for MDS-affected CPUs */ -static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL; +static enum mds_mitigations mds_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_MDS) ? MDS_MITIGATION_FULL : MDS_MITIGATION_OFF; static bool mds_nosmt __ro_after_init = false; static const char * const mds_strings[] = { @@ -293,7 +294,8 @@ enum taa_mitigations { }; /* Default mitigation for TAA-affected CPUs */ -static enum taa_mitigations taa_mitigation __ro_after_init = TAA_MITIGATION_VERW; +static enum taa_mitigations taa_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_TAA) ? TAA_MITIGATION_VERW : TAA_MITIGATION_OFF; static bool taa_nosmt __ro_after_init; static const char * const taa_strings[] = { @@ -391,7 +393,8 @@ enum mmio_mitigations { }; /* Default mitigation for Processor MMIO Stale Data vulnerabilities */ -static enum mmio_mitigations mmio_mitigation __ro_after_init = MMIO_MITIGATION_VERW; +static enum mmio_mitigations mmio_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_MMIO_STALE_DATA) ? MMIO_MITIGATION_VERW : MMIO_MITIGATION_OFF; static bool mmio_nosmt __ro_after_init = false; static const char * const mmio_strings[] = { @@ -605,7 +608,8 @@ enum srbds_mitigations { SRBDS_MITIGATION_HYPERVISOR, }; -static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL; +static enum srbds_mitigations srbds_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_SRBDS) ? SRBDS_MITIGATION_FULL : SRBDS_MITIGATION_OFF; static const char * const srbds_strings[] = { [SRBDS_MITIGATION_OFF] = "Vulnerable", @@ -731,11 +735,8 @@ enum gds_mitigations { GDS_MITIGATION_HYPERVISOR, }; -#if IS_ENABLED(CONFIG_MITIGATION_GDS_FORCE) -static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FORCE; -#else -static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL; -#endif +static enum gds_mitigations gds_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_GDS) ? GDS_MITIGATION_FULL : GDS_MITIGATION_OFF; static const char * const gds_strings[] = { [GDS_MITIGATION_OFF] = "Vulnerable", @@ -871,7 +872,8 @@ enum spectre_v1_mitigation { }; static enum spectre_v1_mitigation spectre_v1_mitigation __ro_after_init = - SPECTRE_V1_MITIGATION_AUTO; + IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V1) ? + SPECTRE_V1_MITIGATION_AUTO : SPECTRE_V1_MITIGATION_NONE; static const char * const spectre_v1_strings[] = { [SPECTRE_V1_MITIGATION_NONE] = "Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers", @@ -986,7 +988,7 @@ static const char * const retbleed_strings[] = { static enum retbleed_mitigation retbleed_mitigation __ro_after_init = RETBLEED_MITIGATION_NONE; static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init = - RETBLEED_CMD_AUTO; + IS_ENABLED(CONFIG_MITIGATION_RETBLEED) ? RETBLEED_CMD_AUTO : RETBLEED_CMD_OFF; static int __ro_after_init retbleed_nosmt = false; @@ -1113,8 +1115,25 @@ do_cmd_auto: case RETBLEED_MITIGATION_IBPB: setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); + + /* + * IBPB on entry already obviates the need for + * software-based untraining so clear those in case some + * other mitigation like SRSO has selected them. + */ + setup_clear_cpu_cap(X86_FEATURE_UNRET); + setup_clear_cpu_cap(X86_FEATURE_RETHUNK); + setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); mitigate_smt = true; + + /* + * There is no need for RSB filling: entry_ibpb() ensures + * all predictions, including the RSB, are invalidated, + * regardless of IBPB implementation. + */ + setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); + break; case RETBLEED_MITIGATION_STUFF: @@ -1447,17 +1466,18 @@ static void __init spec_v2_print_cond(const char *reason, bool secure) static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) { - enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO; + enum spectre_v2_mitigation_cmd cmd; char arg[20]; int ret, i; + cmd = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ? SPECTRE_V2_CMD_AUTO : SPECTRE_V2_CMD_NONE; if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") || cpu_mitigations_off()) return SPECTRE_V2_CMD_NONE; ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg)); if (ret < 0) - return SPECTRE_V2_CMD_AUTO; + return cmd; for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) { if (!match_option(arg, ret, mitigation_options[i].option)) @@ -1467,8 +1487,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) } if (i >= ARRAY_SIZE(mitigation_options)) { - pr_err("unknown option (%s). Switching to AUTO select\n", arg); - return SPECTRE_V2_CMD_AUTO; + pr_err("unknown option (%s). Switching to default mode\n", arg); + return cmd; } if ((cmd == SPECTRE_V2_CMD_RETPOLINE || @@ -2021,10 +2041,12 @@ static const struct { static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) { - enum ssb_mitigation_cmd cmd = SPEC_STORE_BYPASS_CMD_AUTO; + enum ssb_mitigation_cmd cmd; char arg[20]; int ret, i; + cmd = IS_ENABLED(CONFIG_MITIGATION_SSB) ? + SPEC_STORE_BYPASS_CMD_AUTO : SPEC_STORE_BYPASS_CMD_NONE; if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") || cpu_mitigations_off()) { return SPEC_STORE_BYPASS_CMD_NONE; @@ -2032,7 +2054,7 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable", arg, sizeof(arg)); if (ret < 0) - return SPEC_STORE_BYPASS_CMD_AUTO; + return cmd; for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) { if (!match_option(arg, ret, ssb_mitigation_options[i].option)) @@ -2043,8 +2065,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) } if (i >= ARRAY_SIZE(ssb_mitigation_options)) { - pr_err("unknown option (%s). Switching to AUTO select\n", arg); - return SPEC_STORE_BYPASS_CMD_AUTO; + pr_err("unknown option (%s). Switching to default mode\n", arg); + return cmd; } } @@ -2371,7 +2393,8 @@ EXPORT_SYMBOL_GPL(itlb_multihit_kvm_mitigation); #define pr_fmt(fmt) "L1TF: " fmt /* Default mitigation for L1TF-affected CPUs */ -enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH; +enum l1tf_mitigations l1tf_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_L1TF) ? L1TF_MITIGATION_FLUSH : L1TF_MITIGATION_OFF; #if IS_ENABLED(CONFIG_KVM_INTEL) EXPORT_SYMBOL_GPL(l1tf_mitigation); #endif @@ -2551,10 +2574,9 @@ static void __init srso_select_mitigation(void) { bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE); - if (cpu_mitigations_off()) - return; - - if (!boot_cpu_has_bug(X86_BUG_SRSO)) { + if (!boot_cpu_has_bug(X86_BUG_SRSO) || + cpu_mitigations_off() || + srso_cmd == SRSO_CMD_OFF) { if (boot_cpu_has(X86_FEATURE_SBPB)) x86_pred_cmd = PRED_CMD_SBPB; return; @@ -2585,11 +2607,6 @@ static void __init srso_select_mitigation(void) } switch (srso_cmd) { - case SRSO_CMD_OFF: - if (boot_cpu_has(X86_FEATURE_SBPB)) - x86_pred_cmd = PRED_CMD_SBPB; - return; - case SRSO_CMD_MICROCODE: if (has_microcode) { srso_mitigation = SRSO_MITIGATION_MICROCODE; @@ -2627,6 +2644,14 @@ static void __init srso_select_mitigation(void) if (has_microcode) { setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); srso_mitigation = SRSO_MITIGATION_IBPB; + + /* + * IBPB on entry already obviates the need for + * software-based untraining so clear those in case some + * other mitigation like Retbleed has selected them. + */ + setup_clear_cpu_cap(X86_FEATURE_UNRET); + setup_clear_cpu_cap(X86_FEATURE_RETHUNK); } } else { pr_err("WARNING: kernel not compiled with MITIGATION_IBPB_ENTRY.\n"); @@ -2638,11 +2663,20 @@ static void __init srso_select_mitigation(void) if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; + + /* + * There is no need for RSB filling: entry_ibpb() ensures + * all predictions, including the RSB, are invalidated, + * regardless of IBPB implementation. + */ + setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); } } else { pr_err("WARNING: kernel not compiled with MITIGATION_SRSO.\n"); } break; + default: + break; } out: diff --git a/arch/x86/kernel/cpu/bus_lock.c b/arch/x86/kernel/cpu/bus_lock.c new file mode 100644 index 000000000000..704e9241b964 --- /dev/null +++ b/arch/x86/kernel/cpu/bus_lock.c @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define pr_fmt(fmt) "x86/split lock detection: " fmt + +#include <linux/semaphore.h> +#include <linux/workqueue.h> +#include <linux/delay.h> +#include <linux/cpuhotplug.h> +#include <asm/cpu_device_id.h> +#include <asm/cmdline.h> +#include <asm/traps.h> +#include <asm/cpu.h> + +enum split_lock_detect_state { + sld_off = 0, + sld_warn, + sld_fatal, + sld_ratelimit, +}; + +/* + * Default to sld_off because most systems do not support split lock detection. + * sld_state_setup() will switch this to sld_warn on systems that support + * split lock/bus lock detect, unless there is a command line override. + */ +static enum split_lock_detect_state sld_state __ro_after_init = sld_off; +static u64 msr_test_ctrl_cache __ro_after_init; + +/* + * With a name like MSR_TEST_CTL it should go without saying, but don't touch + * MSR_TEST_CTL unless the CPU is one of the whitelisted models. Writing it + * on CPUs that do not support SLD can cause fireworks, even when writing '0'. + */ +static bool cpu_model_supports_sld __ro_after_init; + +static const struct { + const char *option; + enum split_lock_detect_state state; +} sld_options[] __initconst = { + { "off", sld_off }, + { "warn", sld_warn }, + { "fatal", sld_fatal }, + { "ratelimit:", sld_ratelimit }, +}; + +static struct ratelimit_state bld_ratelimit; + +static unsigned int sysctl_sld_mitigate = 1; +static DEFINE_SEMAPHORE(buslock_sem, 1); + +#ifdef CONFIG_PROC_SYSCTL +static struct ctl_table sld_sysctls[] = { + { + .procname = "split_lock_mitigate", + .data = &sysctl_sld_mitigate, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, +}; + +static int __init sld_mitigate_sysctl_init(void) +{ + register_sysctl_init("kernel", sld_sysctls); + return 0; +} + +late_initcall(sld_mitigate_sysctl_init); +#endif + +static inline bool match_option(const char *arg, int arglen, const char *opt) +{ + int len = strlen(opt), ratelimit; + + if (strncmp(arg, opt, len)) + return false; + + /* + * Min ratelimit is 1 bus lock/sec. + * Max ratelimit is 1000 bus locks/sec. + */ + if (sscanf(arg, "ratelimit:%d", &ratelimit) == 1 && + ratelimit > 0 && ratelimit <= 1000) { + ratelimit_state_init(&bld_ratelimit, HZ, ratelimit); + ratelimit_set_flags(&bld_ratelimit, RATELIMIT_MSG_ON_RELEASE); + return true; + } + + return len == arglen; +} + +static bool split_lock_verify_msr(bool on) +{ + u64 ctrl, tmp; + + if (rdmsrl_safe(MSR_TEST_CTRL, &ctrl)) + return false; + if (on) + ctrl |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT; + else + ctrl &= ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT; + if (wrmsrl_safe(MSR_TEST_CTRL, ctrl)) + return false; + rdmsrl(MSR_TEST_CTRL, tmp); + return ctrl == tmp; +} + +static void __init sld_state_setup(void) +{ + enum split_lock_detect_state state = sld_warn; + char arg[20]; + int i, ret; + + if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && + !boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) + return; + + ret = cmdline_find_option(boot_command_line, "split_lock_detect", + arg, sizeof(arg)); + if (ret >= 0) { + for (i = 0; i < ARRAY_SIZE(sld_options); i++) { + if (match_option(arg, ret, sld_options[i].option)) { + state = sld_options[i].state; + break; + } + } + } + sld_state = state; +} + +static void __init __split_lock_setup(void) +{ + if (!split_lock_verify_msr(false)) { + pr_info("MSR access failed: Disabled\n"); + return; + } + + rdmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache); + + if (!split_lock_verify_msr(true)) { + pr_info("MSR access failed: Disabled\n"); + return; + } + + /* Restore the MSR to its cached value. */ + wrmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache); + + setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT); +} + +/* + * MSR_TEST_CTRL is per core, but we treat it like a per CPU MSR. Locking + * is not implemented as one thread could undo the setting of the other + * thread immediately after dropping the lock anyway. + */ +static void sld_update_msr(bool on) +{ + u64 test_ctrl_val = msr_test_ctrl_cache; + + if (on) + test_ctrl_val |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT; + + wrmsrl(MSR_TEST_CTRL, test_ctrl_val); +} + +void split_lock_init(void) +{ + /* + * #DB for bus lock handles ratelimit and #AC for split lock is + * disabled. + */ + if (sld_state == sld_ratelimit) { + split_lock_verify_msr(false); + return; + } + + if (cpu_model_supports_sld) + split_lock_verify_msr(sld_state != sld_off); +} + +static void __split_lock_reenable_unlock(struct work_struct *work) +{ + sld_update_msr(true); + up(&buslock_sem); +} + +static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock); + +static void __split_lock_reenable(struct work_struct *work) +{ + sld_update_msr(true); +} +static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable); + +/* + * If a CPU goes offline with pending delayed work to re-enable split lock + * detection then the delayed work will be executed on some other CPU. That + * handles releasing the buslock_sem, but because it executes on a + * different CPU probably won't re-enable split lock detection. This is a + * problem on HT systems since the sibling CPU on the same core may then be + * left running with split lock detection disabled. + * + * Unconditionally re-enable detection here. + */ +static int splitlock_cpu_offline(unsigned int cpu) +{ + sld_update_msr(true); + + return 0; +} + +static void split_lock_warn(unsigned long ip) +{ + struct delayed_work *work; + int cpu; + + if (!current->reported_split_lock) + pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n", + current->comm, current->pid, ip); + current->reported_split_lock = 1; + + if (sysctl_sld_mitigate) { + /* + * misery factor #1: + * sleep 10ms before trying to execute split lock. + */ + if (msleep_interruptible(10) > 0) + return; + /* + * Misery factor #2: + * only allow one buslocked disabled core at a time. + */ + if (down_interruptible(&buslock_sem) == -EINTR) + return; + work = &sl_reenable_unlock; + } else { + work = &sl_reenable; + } + + cpu = get_cpu(); + schedule_delayed_work_on(cpu, work, 2); + + /* Disable split lock detection on this CPU to make progress */ + sld_update_msr(false); + put_cpu(); +} + +bool handle_guest_split_lock(unsigned long ip) +{ + if (sld_state == sld_warn) { + split_lock_warn(ip); + return true; + } + + pr_warn_once("#AC: %s/%d %s split_lock trap at address: 0x%lx\n", + current->comm, current->pid, + sld_state == sld_fatal ? "fatal" : "bogus", ip); + + current->thread.error_code = 0; + current->thread.trap_nr = X86_TRAP_AC; + force_sig_fault(SIGBUS, BUS_ADRALN, NULL); + return false; +} +EXPORT_SYMBOL_GPL(handle_guest_split_lock); + +void bus_lock_init(void) +{ + u64 val; + + if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) + return; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, val); + + if ((boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && + (sld_state == sld_warn || sld_state == sld_fatal)) || + sld_state == sld_off) { + /* + * Warn and fatal are handled by #AC for split lock if #AC for + * split lock is supported. + */ + val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT; + } else { + val |= DEBUGCTLMSR_BUS_LOCK_DETECT; + } + + wrmsrl(MSR_IA32_DEBUGCTLMSR, val); +} + +bool handle_user_split_lock(struct pt_regs *regs, long error_code) +{ + if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal) + return false; + split_lock_warn(regs->ip); + return true; +} + +void handle_bus_lock(struct pt_regs *regs) +{ + switch (sld_state) { + case sld_off: + break; + case sld_ratelimit: + /* Enforce no more than bld_ratelimit bus locks/sec. */ + while (!__ratelimit(&bld_ratelimit)) + msleep(20); + /* Warn on the bus lock. */ + fallthrough; + case sld_warn: + pr_warn_ratelimited("#DB: %s/%d took a bus_lock trap at address: 0x%lx\n", + current->comm, current->pid, regs->ip); + break; + case sld_fatal: + force_sig_fault(SIGBUS, BUS_ADRALN, NULL); + break; + } +} + +/* + * CPU models that are known to have the per-core split-lock detection + * feature even though they do not enumerate IA32_CORE_CAPABILITIES. + */ +static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = { + X86_MATCH_VFM(INTEL_ICELAKE_X, 0), + X86_MATCH_VFM(INTEL_ICELAKE_L, 0), + X86_MATCH_VFM(INTEL_ICELAKE_D, 0), + {} +}; + +static void __init split_lock_setup(struct cpuinfo_x86 *c) +{ + const struct x86_cpu_id *m; + u64 ia32_core_caps; + + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) + return; + + /* Check for CPUs that have support but do not enumerate it: */ + m = x86_match_cpu(split_lock_cpu_ids); + if (m) + goto supported; + + if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES)) + return; + + /* + * Not all bits in MSR_IA32_CORE_CAPS are architectural, but + * MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is. All CPUs that set + * it have split lock detection. + */ + rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps); + if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT) + goto supported; + + /* CPU is not in the model list and does not have the MSR bit: */ + return; + +supported: + cpu_model_supports_sld = true; + __split_lock_setup(); +} + +static void sld_state_show(void) +{ + if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) && + !boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) + return; + + switch (sld_state) { + case sld_off: + pr_info("disabled\n"); + break; + case sld_warn: + if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) { + pr_info("#AC: crashing the kernel on kernel split_locks and warning on user-space split_locks\n"); + if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + "x86/splitlock", NULL, splitlock_cpu_offline) < 0) + pr_warn("No splitlock CPU offline handler\n"); + } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) { + pr_info("#DB: warning on user-space bus_locks\n"); + } + break; + case sld_fatal: + if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) { + pr_info("#AC: crashing the kernel on kernel split_locks and sending SIGBUS on user-space split_locks\n"); + } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) { + pr_info("#DB: sending SIGBUS on user-space bus_locks%s\n", + boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ? + " from non-WB" : ""); + } + break; + case sld_ratelimit: + if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) + pr_info("#DB: setting system wide bus lock rate limit to %u/sec\n", bld_ratelimit.burst); + break; + } +} + +void __init sld_setup(struct cpuinfo_x86 *c) +{ + split_lock_setup(c); + sld_state_setup(); + sld_state_show(); +} diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d4e539d4e158..02637365d1a9 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -69,6 +69,7 @@ #include <asm/sev.h> #include <asm/tdx.h> #include <asm/posted_intr.h> +#include <asm/runtime-const.h> #include "cpu.h" @@ -1165,8 +1166,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { VULNWL_INTEL(INTEL_CORE_YONAH, NO_SSB), - VULNWL_INTEL(INTEL_ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT), - VULNWL_INTEL(INTEL_ATOM_AIRMONT_NP, NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT), + VULNWL_INTEL(INTEL_ATOM_AIRMONT_MID, NO_SSB | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | MSBDS_ONLY), + VULNWL_INTEL(INTEL_ATOM_AIRMONT_NP, NO_SSB | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT), VULNWL_INTEL(INTEL_ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), VULNWL_INTEL(INTEL_ATOM_GOLDMONT_D, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), @@ -1443,6 +1444,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) boot_cpu_has(X86_FEATURE_HYPERVISOR))) setup_force_cpu_bug(X86_BUG_BHI); + if (cpu_has(c, X86_FEATURE_AMD_IBPB) && !cpu_has(c, X86_FEATURE_AMD_IBPB_RET)) + setup_force_cpu_bug(X86_BUG_IBPB_NO_RET); + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) return; @@ -1510,6 +1514,11 @@ static void __init cpu_parse_early_param(void) if (cmdline_find_option_bool(boot_command_line, "nousershstk")) setup_clear_cpu_cap(X86_FEATURE_USER_SHSTK); + /* Minimize the gap between FRED is available and available but disabled. */ + arglen = cmdline_find_option(boot_command_line, "fred", arg, sizeof(arg)); + if (arglen != 2 || strncmp(arg, "on", 2)) + setup_clear_cpu_cap(X86_FEATURE_FRED); + arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg)); if (arglen <= 0) return; @@ -1832,6 +1841,8 @@ static void identify_cpu(struct cpuinfo_x86 *c) if (this_cpu->c_init) this_cpu->c_init(c); + bus_lock_init(); + /* Disable the PN if appropriate */ squash_the_stupid_serial_number(c); @@ -1897,9 +1908,7 @@ static void identify_cpu(struct cpuinfo_x86 *c) /* Init Machine Check Exception if available. */ mcheck_cpu_init(c); -#ifdef CONFIG_NUMA numa_add_cpu(smp_processor_id()); -#endif } /* @@ -2080,8 +2089,10 @@ void syscall_init(void) #ifdef CONFIG_STACKPROTECTOR DEFINE_PER_CPU(unsigned long, __stack_chk_guard); +#ifndef CONFIG_SMP EXPORT_PER_CPU_SYMBOL(__stack_chk_guard); #endif +#endif #endif /* CONFIG_X86_64 */ @@ -2171,7 +2182,7 @@ static inline void tss_setup_io_bitmap(struct tss_struct *tss) * Setup everything needed to handle exceptions from the IDT, including the IST * exceptions which use paranoid_entry(). */ -void cpu_init_exception_handling(void) +void cpu_init_exception_handling(bool boot_cpu) { struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw); int cpu = raw_smp_processor_id(); @@ -2190,10 +2201,23 @@ void cpu_init_exception_handling(void) /* GHCB needs to be setup to handle #VC. */ setup_ghcb(); + if (cpu_feature_enabled(X86_FEATURE_FRED)) { + /* The boot CPU has enabled FRED during early boot */ + if (!boot_cpu) + cpu_init_fred_exceptions(); + + cpu_init_fred_rsps(); + } else { + load_current_idt(); + } +} + +void __init cpu_init_replace_early_idt(void) +{ if (cpu_feature_enabled(X86_FEATURE_FRED)) cpu_init_fred_exceptions(); else - load_current_idt(); + idt_setup_early_pf(); } /* @@ -2368,6 +2392,15 @@ void __init arch_cpu_finalize_init(void) alternative_instructions(); if (IS_ENABLED(CONFIG_X86_64)) { + unsigned long USER_PTR_MAX = TASK_SIZE_MAX-1; + + /* + * Enable this when LAM is gated on LASS support + if (cpu_feature_enabled(X86_FEATURE_LAM)) + USER_PTR_MAX = (1ul << 63) - PAGE_SIZE - 1; + */ + runtime_const_init(ptr, USER_PTR_MAX); + /* * Make sure the first 2MB area is not mapped by huge pages * There are typically fixed size MTRRs in there and overlapping diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c index b7d9f530ae16..8bd84114c2d9 100644 --- a/arch/x86/kernel/cpu/cpuid-deps.c +++ b/arch/x86/kernel/cpu/cpuid-deps.c @@ -83,7 +83,6 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_AMX_TILE, X86_FEATURE_XFD }, { X86_FEATURE_SHSTK, X86_FEATURE_XSAVES }, { X86_FEATURE_FRED, X86_FEATURE_LKGS }, - { X86_FEATURE_FRED, X86_FEATURE_WRMSRNS }, {} }; diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c index 3baf3e435834..10719aba6276 100644 --- a/arch/x86/kernel/cpu/debugfs.c +++ b/arch/x86/kernel/cpu/debugfs.c @@ -22,6 +22,7 @@ static int cpu_debug_show(struct seq_file *m, void *p) seq_printf(m, "die_id: %u\n", c->topo.die_id); seq_printf(m, "cu_id: %u\n", c->topo.cu_id); seq_printf(m, "core_id: %u\n", c->topo.core_id); + seq_printf(m, "cpu_type: %s\n", get_topology_cpu_type_name(c)); seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id); seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id); seq_printf(m, "llc_id: %u\n", c->topo.llc_id); diff --git a/arch/x86/kernel/cpu/feat_ctl.c b/arch/x86/kernel/cpu/feat_ctl.c index 1640ae76548f..4a4118784c13 100644 --- a/arch/x86/kernel/cpu/feat_ctl.c +++ b/arch/x86/kernel/cpu/feat_ctl.c @@ -188,7 +188,7 @@ update_caps: update_sgx: if (!(msr & FEAT_CTL_SGX_ENABLED)) { if (enable_sgx_kvm || enable_sgx_driver) - pr_err_once("SGX disabled by BIOS.\n"); + pr_err_once("SGX disabled or unsupported by BIOS.\n"); clear_cpu_cap(c, X86_FEATURE_SGX); return; } diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 08b95a35b5cb..d1de300af173 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -7,13 +7,9 @@ #include <linux/smp.h> #include <linux/sched.h> #include <linux/sched/clock.h> -#include <linux/semaphore.h> #include <linux/thread_info.h> #include <linux/init.h> #include <linux/uaccess.h> -#include <linux/workqueue.h> -#include <linux/delay.h> -#include <linux/cpuhotplug.h> #include <asm/cpufeature.h> #include <asm/msr.h> @@ -24,8 +20,6 @@ #include <asm/hwcap2.h> #include <asm/elf.h> #include <asm/cpu_device_id.h> -#include <asm/cmdline.h> -#include <asm/traps.h> #include <asm/resctrl.h> #include <asm/numa.h> #include <asm/thermal.h> @@ -41,28 +35,6 @@ #include <asm/apic.h> #endif -enum split_lock_detect_state { - sld_off = 0, - sld_warn, - sld_fatal, - sld_ratelimit, -}; - -/* - * Default to sld_off because most systems do not support split lock detection. - * sld_state_setup() will switch this to sld_warn on systems that support - * split lock/bus lock detect, unless there is a command line override. - */ -static enum split_lock_detect_state sld_state __ro_after_init = sld_off; -static u64 msr_test_ctrl_cache __ro_after_init; - -/* - * With a name like MSR_TEST_CTL it should go without saying, but don't touch - * MSR_TEST_CTL unless the CPU is one of the whitelisted models. Writing it - * on CPUs that do not support SLD can cause fireworks, even when writing '0'. - */ -static bool cpu_model_supports_sld __ro_after_init; - /* * Processors which have self-snooping capability can handle conflicting * memory type across CPUs by snooping its own cache. However, there exists @@ -311,16 +283,18 @@ static void early_init_intel(struct cpuinfo_x86 *c) } /* - * There is a known erratum on Pentium III and Core Solo - * and Core Duo CPUs. - * " Page with PAT set to WC while associated MTRR is UC - * may consolidate to UC " - * Because of this erratum, it is better to stick with - * setting WC in MTRR rather than using PAT on these CPUs. + * PAT is broken on early family 6 CPUs, the last of which + * is "Yonah" where the erratum is named "AN7": + * + * Page with PAT (Page Attribute Table) Set to USWC + * (Uncacheable Speculative Write Combine) While + * Associated MTRR (Memory Type Range Register) Is UC + * (Uncacheable) May Consolidate to UC * - * Enable PAT WC only on P4, Core 2 or later CPUs. + * Disable PAT and fall back to MTRR on these CPUs. */ - if (c->x86 == 6 && c->x86_model < 15) + if (c->x86_vfm >= INTEL_PENTIUM_PRO && + c->x86_vfm <= INTEL_CORE_YONAH) clear_cpu_cap(c, X86_FEATURE_PAT); /* @@ -547,9 +521,6 @@ static void init_intel_misc_features(struct cpuinfo_x86 *c) wrmsrl(MSR_MISC_FEATURES_ENABLES, msr); } -static void split_lock_init(void); -static void bus_lock_init(void); - static void init_intel(struct cpuinfo_x86 *c) { early_init_intel(c); @@ -641,7 +612,6 @@ static void init_intel(struct cpuinfo_x86 *c) init_intel_misc_features(c); split_lock_init(); - bus_lock_init(); intel_init_thermal(c); } @@ -907,381 +877,6 @@ static const struct cpu_dev intel_cpu_dev = { cpu_dev_register(intel_cpu_dev); -#undef pr_fmt -#define pr_fmt(fmt) "x86/split lock detection: " fmt - -static const struct { - const char *option; - enum split_lock_detect_state state; -} sld_options[] __initconst = { - { "off", sld_off }, - { "warn", sld_warn }, - { "fatal", sld_fatal }, - { "ratelimit:", sld_ratelimit }, -}; - -static struct ratelimit_state bld_ratelimit; - -static unsigned int sysctl_sld_mitigate = 1; -static DEFINE_SEMAPHORE(buslock_sem, 1); - -#ifdef CONFIG_PROC_SYSCTL -static struct ctl_table sld_sysctls[] = { - { - .procname = "split_lock_mitigate", - .data = &sysctl_sld_mitigate, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = proc_douintvec_minmax, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, - }, -}; - -static int __init sld_mitigate_sysctl_init(void) -{ - register_sysctl_init("kernel", sld_sysctls); - return 0; -} - -late_initcall(sld_mitigate_sysctl_init); -#endif - -static inline bool match_option(const char *arg, int arglen, const char *opt) -{ - int len = strlen(opt), ratelimit; - - if (strncmp(arg, opt, len)) - return false; - - /* - * Min ratelimit is 1 bus lock/sec. - * Max ratelimit is 1000 bus locks/sec. - */ - if (sscanf(arg, "ratelimit:%d", &ratelimit) == 1 && - ratelimit > 0 && ratelimit <= 1000) { - ratelimit_state_init(&bld_ratelimit, HZ, ratelimit); - ratelimit_set_flags(&bld_ratelimit, RATELIMIT_MSG_ON_RELEASE); - return true; - } - - return len == arglen; -} - -static bool split_lock_verify_msr(bool on) -{ - u64 ctrl, tmp; - - if (rdmsrl_safe(MSR_TEST_CTRL, &ctrl)) - return false; - if (on) - ctrl |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT; - else - ctrl &= ~MSR_TEST_CTRL_SPLIT_LOCK_DETECT; - if (wrmsrl_safe(MSR_TEST_CTRL, ctrl)) - return false; - rdmsrl(MSR_TEST_CTRL, tmp); - return ctrl == tmp; -} - -static void __init sld_state_setup(void) -{ - enum split_lock_detect_state state = sld_warn; - char arg[20]; - int i, ret; - - if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && - !boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) - return; - - ret = cmdline_find_option(boot_command_line, "split_lock_detect", - arg, sizeof(arg)); - if (ret >= 0) { - for (i = 0; i < ARRAY_SIZE(sld_options); i++) { - if (match_option(arg, ret, sld_options[i].option)) { - state = sld_options[i].state; - break; - } - } - } - sld_state = state; -} - -static void __init __split_lock_setup(void) -{ - if (!split_lock_verify_msr(false)) { - pr_info("MSR access failed: Disabled\n"); - return; - } - - rdmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache); - - if (!split_lock_verify_msr(true)) { - pr_info("MSR access failed: Disabled\n"); - return; - } - - /* Restore the MSR to its cached value. */ - wrmsrl(MSR_TEST_CTRL, msr_test_ctrl_cache); - - setup_force_cpu_cap(X86_FEATURE_SPLIT_LOCK_DETECT); -} - -/* - * MSR_TEST_CTRL is per core, but we treat it like a per CPU MSR. Locking - * is not implemented as one thread could undo the setting of the other - * thread immediately after dropping the lock anyway. - */ -static void sld_update_msr(bool on) -{ - u64 test_ctrl_val = msr_test_ctrl_cache; - - if (on) - test_ctrl_val |= MSR_TEST_CTRL_SPLIT_LOCK_DETECT; - - wrmsrl(MSR_TEST_CTRL, test_ctrl_val); -} - -static void split_lock_init(void) -{ - /* - * #DB for bus lock handles ratelimit and #AC for split lock is - * disabled. - */ - if (sld_state == sld_ratelimit) { - split_lock_verify_msr(false); - return; - } - - if (cpu_model_supports_sld) - split_lock_verify_msr(sld_state != sld_off); -} - -static void __split_lock_reenable_unlock(struct work_struct *work) -{ - sld_update_msr(true); - up(&buslock_sem); -} - -static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock); - -static void __split_lock_reenable(struct work_struct *work) -{ - sld_update_msr(true); -} -static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable); - -/* - * If a CPU goes offline with pending delayed work to re-enable split lock - * detection then the delayed work will be executed on some other CPU. That - * handles releasing the buslock_sem, but because it executes on a - * different CPU probably won't re-enable split lock detection. This is a - * problem on HT systems since the sibling CPU on the same core may then be - * left running with split lock detection disabled. - * - * Unconditionally re-enable detection here. - */ -static int splitlock_cpu_offline(unsigned int cpu) -{ - sld_update_msr(true); - - return 0; -} - -static void split_lock_warn(unsigned long ip) -{ - struct delayed_work *work; - int cpu; - - if (!current->reported_split_lock) - pr_warn_ratelimited("#AC: %s/%d took a split_lock trap at address: 0x%lx\n", - current->comm, current->pid, ip); - current->reported_split_lock = 1; - - if (sysctl_sld_mitigate) { - /* - * misery factor #1: - * sleep 10ms before trying to execute split lock. - */ - if (msleep_interruptible(10) > 0) - return; - /* - * Misery factor #2: - * only allow one buslocked disabled core at a time. - */ - if (down_interruptible(&buslock_sem) == -EINTR) - return; - work = &sl_reenable_unlock; - } else { - work = &sl_reenable; - } - - cpu = get_cpu(); - schedule_delayed_work_on(cpu, work, 2); - - /* Disable split lock detection on this CPU to make progress */ - sld_update_msr(false); - put_cpu(); -} - -bool handle_guest_split_lock(unsigned long ip) -{ - if (sld_state == sld_warn) { - split_lock_warn(ip); - return true; - } - - pr_warn_once("#AC: %s/%d %s split_lock trap at address: 0x%lx\n", - current->comm, current->pid, - sld_state == sld_fatal ? "fatal" : "bogus", ip); - - current->thread.error_code = 0; - current->thread.trap_nr = X86_TRAP_AC; - force_sig_fault(SIGBUS, BUS_ADRALN, NULL); - return false; -} -EXPORT_SYMBOL_GPL(handle_guest_split_lock); - -static void bus_lock_init(void) -{ - u64 val; - - if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) - return; - - rdmsrl(MSR_IA32_DEBUGCTLMSR, val); - - if ((boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) && - (sld_state == sld_warn || sld_state == sld_fatal)) || - sld_state == sld_off) { - /* - * Warn and fatal are handled by #AC for split lock if #AC for - * split lock is supported. - */ - val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT; - } else { - val |= DEBUGCTLMSR_BUS_LOCK_DETECT; - } - - wrmsrl(MSR_IA32_DEBUGCTLMSR, val); -} - -bool handle_user_split_lock(struct pt_regs *regs, long error_code) -{ - if ((regs->flags & X86_EFLAGS_AC) || sld_state == sld_fatal) - return false; - split_lock_warn(regs->ip); - return true; -} - -void handle_bus_lock(struct pt_regs *regs) -{ - switch (sld_state) { - case sld_off: - break; - case sld_ratelimit: - /* Enforce no more than bld_ratelimit bus locks/sec. */ - while (!__ratelimit(&bld_ratelimit)) - msleep(20); - /* Warn on the bus lock. */ - fallthrough; - case sld_warn: - pr_warn_ratelimited("#DB: %s/%d took a bus_lock trap at address: 0x%lx\n", - current->comm, current->pid, regs->ip); - break; - case sld_fatal: - force_sig_fault(SIGBUS, BUS_ADRALN, NULL); - break; - } -} - -/* - * CPU models that are known to have the per-core split-lock detection - * feature even though they do not enumerate IA32_CORE_CAPABILITIES. - */ -static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = { - X86_MATCH_VFM(INTEL_ICELAKE_X, 0), - X86_MATCH_VFM(INTEL_ICELAKE_L, 0), - X86_MATCH_VFM(INTEL_ICELAKE_D, 0), - {} -}; - -static void __init split_lock_setup(struct cpuinfo_x86 *c) -{ - const struct x86_cpu_id *m; - u64 ia32_core_caps; - - if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) - return; - - /* Check for CPUs that have support but do not enumerate it: */ - m = x86_match_cpu(split_lock_cpu_ids); - if (m) - goto supported; - - if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES)) - return; - - /* - * Not all bits in MSR_IA32_CORE_CAPS are architectural, but - * MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is. All CPUs that set - * it have split lock detection. - */ - rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps); - if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT) - goto supported; - - /* CPU is not in the model list and does not have the MSR bit: */ - return; - -supported: - cpu_model_supports_sld = true; - __split_lock_setup(); -} - -static void sld_state_show(void) -{ - if (!boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) && - !boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) - return; - - switch (sld_state) { - case sld_off: - pr_info("disabled\n"); - break; - case sld_warn: - if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) { - pr_info("#AC: crashing the kernel on kernel split_locks and warning on user-space split_locks\n"); - if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, - "x86/splitlock", NULL, splitlock_cpu_offline) < 0) - pr_warn("No splitlock CPU offline handler\n"); - } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) { - pr_info("#DB: warning on user-space bus_locks\n"); - } - break; - case sld_fatal: - if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) { - pr_info("#AC: crashing the kernel on kernel split_locks and sending SIGBUS on user-space split_locks\n"); - } else if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) { - pr_info("#DB: sending SIGBUS on user-space bus_locks%s\n", - boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ? - " from non-WB" : ""); - } - break; - case sld_ratelimit: - if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) - pr_info("#DB: setting system wide bus lock rate limit to %u/sec\n", bld_ratelimit.burst); - break; - } -} - -void __init sld_setup(struct cpuinfo_x86 *c) -{ - split_lock_setup(c); - sld_state_setup(); - sld_state_show(); -} - #define X86_HYBRID_CPU_TYPE_ID_SHIFT 24 /** @@ -1297,3 +892,18 @@ u8 get_this_hybrid_cpu_type(void) return cpuid_eax(0x0000001a) >> X86_HYBRID_CPU_TYPE_ID_SHIFT; } + +/** + * get_this_hybrid_cpu_native_id() - Get the native id of this hybrid CPU + * + * Returns the uarch native ID [23:0] of a CPU in a hybrid processor. + * If the processor is not hybrid, returns 0. + */ +u32 get_this_hybrid_cpu_native_id(void) +{ + if (!cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) + return 0; + + return cpuid_eax(0x0000001a) & + (BIT_ULL(X86_HYBRID_CPU_TYPE_ID_SHIFT) - 1); +} diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index 9a0133ef7e20..6ca80fff1fea 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -778,29 +778,33 @@ bool amd_mce_usable_address(struct mce *m) static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc) { - struct mce m; + struct mce_hw_err err; + struct mce *m = &err.m; - mce_setup(&m); + mce_prep_record(&err); - m.status = status; - m.misc = misc; - m.bank = bank; - m.tsc = rdtsc(); + m->status = status; + m->misc = misc; + m->bank = bank; + m->tsc = rdtsc(); - if (m.status & MCI_STATUS_ADDRV) { - m.addr = addr; + if (m->status & MCI_STATUS_ADDRV) { + m->addr = addr; - smca_extract_err_addr(&m); + smca_extract_err_addr(m); } if (mce_flags.smca) { - rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m.ipid); + rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m->ipid); - if (m.status & MCI_STATUS_SYNDV) - rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m.synd); + if (m->status & MCI_STATUS_SYNDV) { + rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m->synd); + rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(bank), err.vendor.amd.synd1); + rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(bank), err.vendor.amd.synd2); + } } - mce_log(&m); + mce_log(&err); } DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error) diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c index 7f7309ff67d0..0a89947e47bc 100644 --- a/arch/x86/kernel/cpu/mce/apei.c +++ b/arch/x86/kernel/cpu/mce/apei.c @@ -28,7 +28,8 @@ void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err) { - struct mce m; + struct mce_hw_err err; + struct mce *m; int lsb; if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) @@ -44,30 +45,33 @@ void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err) else lsb = PAGE_SHIFT; - mce_setup(&m); - m.bank = -1; + mce_prep_record(&err); + m = &err.m; + m->bank = -1; /* Fake a memory read error with unknown channel */ - m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f; - m.misc = (MCI_MISC_ADDR_PHYS << 6) | lsb; + m->status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f; + m->misc = (MCI_MISC_ADDR_PHYS << 6) | lsb; if (severity >= GHES_SEV_RECOVERABLE) - m.status |= MCI_STATUS_UC; + m->status |= MCI_STATUS_UC; if (severity >= GHES_SEV_PANIC) { - m.status |= MCI_STATUS_PCC; - m.tsc = rdtsc(); + m->status |= MCI_STATUS_PCC; + m->tsc = rdtsc(); } - m.addr = mem_err->physical_addr; - mce_log(&m); + m->addr = mem_err->physical_addr; + mce_log(&err); } EXPORT_SYMBOL_GPL(apei_mce_report_mem_error); int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id) { const u64 *i_mce = ((const u64 *) (ctx_info + 1)); - unsigned int cpu; - struct mce m; + unsigned int cpu, num_regs; + bool apicid_found = false; + struct mce_hw_err err; + struct mce *m; if (!boot_cpu_has(X86_FEATURE_SMCA)) return -EINVAL; @@ -85,41 +89,86 @@ int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id) return -EINVAL; /* - * The register array size must be large enough to include all the - * SMCA registers which need to be extracted. - * * The number of registers in the register array is determined by * Register Array Size/8 as defined in UEFI spec v2.8, sec N.2.4.2.2. - * The register layout is fixed and currently the raw data in the - * register array includes 6 SMCA registers which the kernel can - * extract. + * Sanity-check registers array size. */ - if (ctx_info->reg_arr_size < 48) + num_regs = ctx_info->reg_arr_size >> 3; + if (!num_regs) return -EINVAL; - mce_setup(&m); - - m.extcpu = -1; - m.socketid = -1; - for_each_possible_cpu(cpu) { if (cpu_data(cpu).topo.initial_apicid == lapic_id) { - m.extcpu = cpu; - m.socketid = cpu_data(m.extcpu).topo.pkg_id; + apicid_found = true; break; } } - m.apicid = lapic_id; - m.bank = (ctx_info->msr_addr >> 4) & 0xFF; - m.status = *i_mce; - m.addr = *(i_mce + 1); - m.misc = *(i_mce + 2); - /* Skipping MCA_CONFIG */ - m.ipid = *(i_mce + 4); - m.synd = *(i_mce + 5); + if (!apicid_found) + return -EINVAL; + + m = &err.m; + memset(&err, 0, sizeof(struct mce_hw_err)); + mce_prep_record_common(m); + mce_prep_record_per_cpu(cpu, m); + + m->bank = (ctx_info->msr_addr >> 4) & 0xFF; + + /* + * The SMCA register layout is fixed and includes 16 registers. + * The end of the array may be variable, but the beginning is known. + * Cap the number of registers to expected max (15). + */ + if (num_regs > 15) + num_regs = 15; + + switch (num_regs) { + /* MCA_SYND2 */ + case 15: + err.vendor.amd.synd2 = *(i_mce + 14); + fallthrough; + /* MCA_SYND1 */ + case 14: + err.vendor.amd.synd1 = *(i_mce + 13); + fallthrough; + /* MCA_MISC4 */ + case 13: + /* MCA_MISC3 */ + case 12: + /* MCA_MISC2 */ + case 11: + /* MCA_MISC1 */ + case 10: + /* MCA_DEADDR */ + case 9: + /* MCA_DESTAT */ + case 8: + /* reserved */ + case 7: + /* MCA_SYND */ + case 6: + m->synd = *(i_mce + 5); + fallthrough; + /* MCA_IPID */ + case 5: + m->ipid = *(i_mce + 4); + fallthrough; + /* MCA_CONFIG */ + case 4: + /* MCA_MISC0 */ + case 3: + m->misc = *(i_mce + 2); + fallthrough; + /* MCA_ADDR */ + case 2: + m->addr = *(i_mce + 1); + fallthrough; + /* MCA_STATUS */ + case 1: + m->status = *i_mce; + } - mce_log(&m); + mce_log(&err); return 0; } diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index b85ec7a4ec9e..7fb5556a0b53 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -88,7 +88,7 @@ struct mca_config mca_cfg __read_mostly = { .monarch_timeout = -1 }; -static DEFINE_PER_CPU(struct mce, mces_seen); +static DEFINE_PER_CPU(struct mce_hw_err, hw_errs_seen); static unsigned long mce_need_notify; /* @@ -117,28 +117,41 @@ static struct irq_work mce_irq_work; */ BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain); -/* Do initial initialization of a struct mce */ -void mce_setup(struct mce *m) +void mce_prep_record_common(struct mce *m) { - memset(m, 0, sizeof(struct mce)); - m->cpu = m->extcpu = smp_processor_id(); + m->cpuid = cpuid_eax(1); + m->cpuvendor = boot_cpu_data.x86_vendor; + m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP); /* need the internal __ version to avoid deadlocks */ - m->time = __ktime_get_real_seconds(); - m->cpuvendor = boot_cpu_data.x86_vendor; - m->cpuid = cpuid_eax(1); - m->socketid = cpu_data(m->extcpu).topo.pkg_id; - m->apicid = cpu_data(m->extcpu).topo.initial_apicid; - m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP); - m->ppin = cpu_data(m->extcpu).ppin; - m->microcode = boot_cpu_data.microcode; + m->time = __ktime_get_real_seconds(); +} + +void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m) +{ + m->cpu = cpu; + m->extcpu = cpu; + m->apicid = cpu_data(cpu).topo.initial_apicid; + m->microcode = cpu_data(cpu).microcode; + m->ppin = topology_ppin(cpu); + m->socketid = topology_physical_package_id(cpu); +} + +/* Do initial initialization of struct mce_hw_err */ +void mce_prep_record(struct mce_hw_err *err) +{ + struct mce *m = &err->m; + + memset(err, 0, sizeof(struct mce_hw_err)); + mce_prep_record_common(m); + mce_prep_record_per_cpu(smp_processor_id(), m); } DEFINE_PER_CPU(struct mce, injectm); EXPORT_PER_CPU_SYMBOL_GPL(injectm); -void mce_log(struct mce *m) +void mce_log(struct mce_hw_err *err) { - if (!mce_gen_pool_add(m)) + if (!mce_gen_pool_add(err)) irq_work_queue(&mce_irq_work); } EXPORT_SYMBOL_GPL(mce_log); @@ -159,8 +172,10 @@ void mce_unregister_decode_chain(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); -static void __print_mce(struct mce *m) +static void __print_mce(struct mce_hw_err *err) { + struct mce *m = &err->m; + pr_emerg(HW_ERR "CPU %d: Machine Check%s: %Lx Bank %d: %016Lx\n", m->extcpu, (m->mcgstatus & MCG_STATUS_MCIP ? " Exception" : ""), @@ -187,6 +202,10 @@ static void __print_mce(struct mce *m) if (mce_flags.smca) { if (m->synd) pr_cont("SYND %llx ", m->synd); + if (err->vendor.amd.synd1) + pr_cont("SYND1 %llx ", err->vendor.amd.synd1); + if (err->vendor.amd.synd2) + pr_cont("SYND2 %llx ", err->vendor.amd.synd2); if (m->ipid) pr_cont("IPID %llx ", m->ipid); } @@ -202,9 +221,11 @@ static void __print_mce(struct mce *m) m->microcode); } -static void print_mce(struct mce *m) +static void print_mce(struct mce_hw_err *err) { - __print_mce(m); + struct mce *m = &err->m; + + __print_mce(err); if (m->cpuvendor != X86_VENDOR_AMD && m->cpuvendor != X86_VENDOR_HYGON) pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n"); @@ -239,7 +260,7 @@ static const char *mce_dump_aux_info(struct mce *m) return NULL; } -static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) +static noinstr void mce_panic(const char *msg, struct mce_hw_err *final, char *exp) { struct llist_node *pending; struct mce_evt_llist *l; @@ -270,20 +291,22 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) pending = mce_gen_pool_prepare_records(); /* First print corrected ones that are still unlogged */ llist_for_each_entry(l, pending, llnode) { - struct mce *m = &l->mce; + struct mce_hw_err *err = &l->err; + struct mce *m = &err->m; if (!(m->status & MCI_STATUS_UC)) { - print_mce(m); + print_mce(err); if (!apei_err) apei_err = apei_write_mce(m); } } /* Now print uncorrected but with the final one last */ llist_for_each_entry(l, pending, llnode) { - struct mce *m = &l->mce; + struct mce_hw_err *err = &l->err; + struct mce *m = &err->m; if (!(m->status & MCI_STATUS_UC)) continue; - if (!final || mce_cmp(m, final)) { - print_mce(m); + if (!final || mce_cmp(m, &final->m)) { + print_mce(err); if (!apei_err) apei_err = apei_write_mce(m); } @@ -291,12 +314,12 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) if (final) { print_mce(final); if (!apei_err) - apei_err = apei_write_mce(final); + apei_err = apei_write_mce(&final->m); } if (exp) pr_emerg(HW_ERR "Machine check: %s\n", exp); - memmsg = mce_dump_aux_info(final); + memmsg = mce_dump_aux_info(&final->m); if (memmsg) pr_emerg(HW_ERR "Machine check: %s\n", memmsg); @@ -311,9 +334,9 @@ static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) * panic. */ if (kexec_crash_loaded()) { - if (final && (final->status & MCI_STATUS_ADDRV)) { + if (final && (final->m.status & MCI_STATUS_ADDRV)) { struct page *p; - p = pfn_to_online_page(final->addr >> PAGE_SHIFT); + p = pfn_to_online_page(final->m.addr >> PAGE_SHIFT); if (p) SetPageHWPoison(p); } @@ -433,16 +456,18 @@ static noinstr void mce_wrmsrl(u32 msr, u64 v) * check into our "mce" struct so that we can use it later to assess * the severity of the problem as we read per-bank specific details. */ -static noinstr void mce_gather_info(struct mce *m, struct pt_regs *regs) +static noinstr void mce_gather_info(struct mce_hw_err *err, struct pt_regs *regs) { + struct mce *m; /* - * Enable instrumentation around mce_setup() which calls external + * Enable instrumentation around mce_prep_record() which calls external * facilities. */ instrumentation_begin(); - mce_setup(m); + mce_prep_record(err); instrumentation_end(); + m = &err->m; m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); if (regs) { /* @@ -562,13 +587,13 @@ EXPORT_SYMBOL_GPL(mce_is_correctable); static int mce_early_notifier(struct notifier_block *nb, unsigned long val, void *data) { - struct mce *m = (struct mce *)data; + struct mce_hw_err *err = to_mce_hw_err(data); - if (!m) + if (!err) return NOTIFY_DONE; /* Emit the trace record: */ - trace_mce_record(m); + trace_mce_record(err); set_bit(0, &mce_need_notify); @@ -612,13 +637,13 @@ static struct notifier_block mce_uc_nb = { static int mce_default_notifier(struct notifier_block *nb, unsigned long val, void *data) { - struct mce *m = (struct mce *)data; + struct mce_hw_err *err = to_mce_hw_err(data); - if (!m) + if (!err) return NOTIFY_DONE; - if (mca_cfg.print_all || !m->kflags) - __print_mce(m); + if (mca_cfg.print_all || !(err->m.kflags)) + __print_mce(err); return NOTIFY_DONE; } @@ -632,8 +657,10 @@ static struct notifier_block mce_default_nb = { /* * Read ADDR and MISC registers. */ -static noinstr void mce_read_aux(struct mce *m, int i) +static noinstr void mce_read_aux(struct mce_hw_err *err, int i) { + struct mce *m = &err->m; + if (m->status & MCI_STATUS_MISCV) m->misc = mce_rdmsrl(mca_msr_reg(i, MCA_MISC)); @@ -655,8 +682,11 @@ static noinstr void mce_read_aux(struct mce *m, int i) if (mce_flags.smca) { m->ipid = mce_rdmsrl(MSR_AMD64_SMCA_MCx_IPID(i)); - if (m->status & MCI_STATUS_SYNDV) + if (m->status & MCI_STATUS_SYNDV) { m->synd = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND(i)); + err->vendor.amd.synd1 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(i)); + err->vendor.amd.synd2 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(i)); + } } } @@ -680,26 +710,28 @@ DEFINE_PER_CPU(unsigned, mce_poll_count); void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) { struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array); - struct mce m; + struct mce_hw_err err; + struct mce *m; int i; this_cpu_inc(mce_poll_count); - mce_gather_info(&m, NULL); + mce_gather_info(&err, NULL); + m = &err.m; if (flags & MCP_TIMESTAMP) - m.tsc = rdtsc(); + m->tsc = rdtsc(); for (i = 0; i < this_cpu_read(mce_num_banks); i++) { if (!mce_banks[i].ctl || !test_bit(i, *b)) continue; - m.misc = 0; - m.addr = 0; - m.bank = i; + m->misc = 0; + m->addr = 0; + m->bank = i; barrier(); - m.status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS)); + m->status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS)); /* * Update storm tracking here, before checking for the @@ -709,17 +741,17 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) * storm status. */ if (!mca_cfg.cmci_disabled) - mce_track_storm(&m); + mce_track_storm(m); /* If this entry is not valid, ignore it */ - if (!(m.status & MCI_STATUS_VAL)) + if (!(m->status & MCI_STATUS_VAL)) continue; /* * If we are logging everything (at CPU online) or this * is a corrected error, then we must log it. */ - if ((flags & MCP_UC) || !(m.status & MCI_STATUS_UC)) + if ((flags & MCP_UC) || !(m->status & MCI_STATUS_UC)) goto log_it; /* @@ -729,20 +761,20 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) * everything else. */ if (!mca_cfg.ser) { - if (m.status & MCI_STATUS_UC) + if (m->status & MCI_STATUS_UC) continue; goto log_it; } /* Log "not enabled" (speculative) errors */ - if (!(m.status & MCI_STATUS_EN)) + if (!(m->status & MCI_STATUS_EN)) goto log_it; /* * Log UCNA (SDM: 15.6.3 "UCR Error Classification") * UC == 1 && PCC == 0 && S == 0 */ - if (!(m.status & MCI_STATUS_PCC) && !(m.status & MCI_STATUS_S)) + if (!(m->status & MCI_STATUS_PCC) && !(m->status & MCI_STATUS_S)) goto log_it; /* @@ -756,20 +788,20 @@ log_it: if (flags & MCP_DONTLOG) goto clear_it; - mce_read_aux(&m, i); - m.severity = mce_severity(&m, NULL, NULL, false); + mce_read_aux(&err, i); + m->severity = mce_severity(m, NULL, NULL, false); /* * Don't get the IP here because it's unlikely to * have anything to do with the actual error location. */ - if (mca_cfg.dont_log_ce && !mce_usable_address(&m)) + if (mca_cfg.dont_log_ce && !mce_usable_address(m)) goto clear_it; if (flags & MCP_QUEUE_LOG) - mce_gen_pool_add(&m); + mce_gen_pool_add(&err); else - mce_log(&m); + mce_log(&err); clear_it: /* @@ -893,9 +925,10 @@ static __always_inline void quirk_zen_ifu(int bank, struct mce *m, struct pt_reg * Do a quick check if any of the events requires a panic. * This decides if we keep the events around or clear them. */ -static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, +static __always_inline int mce_no_way_out(struct mce_hw_err *err, char **msg, unsigned long *validp, struct pt_regs *regs) { + struct mce *m = &err->m; char *tmp = *msg; int i; @@ -913,7 +946,7 @@ static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned lo m->bank = i; if (mce_severity(m, regs, &tmp, true) >= MCE_PANIC_SEVERITY) { - mce_read_aux(m, i); + mce_read_aux(err, i); *msg = tmp; return 1; } @@ -1004,10 +1037,11 @@ out: */ static void mce_reign(void) { - int cpu; + struct mce_hw_err *err = NULL; struct mce *m = NULL; int global_worst = 0; char *msg = NULL; + int cpu; /* * This CPU is the Monarch and the other CPUs have run @@ -1015,11 +1049,13 @@ static void mce_reign(void) * Grade the severity of the errors of all the CPUs. */ for_each_possible_cpu(cpu) { - struct mce *mtmp = &per_cpu(mces_seen, cpu); + struct mce_hw_err *etmp = &per_cpu(hw_errs_seen, cpu); + struct mce *mtmp = &etmp->m; if (mtmp->severity > global_worst) { global_worst = mtmp->severity; - m = &per_cpu(mces_seen, cpu); + err = &per_cpu(hw_errs_seen, cpu); + m = &err->m; } } @@ -1031,7 +1067,7 @@ static void mce_reign(void) if (m && global_worst >= MCE_PANIC_SEVERITY) { /* call mce_severity() to get "msg" for panic */ mce_severity(m, NULL, &msg, true); - mce_panic("Fatal machine check", m, msg); + mce_panic("Fatal machine check", err, msg); } /* @@ -1048,11 +1084,11 @@ static void mce_reign(void) mce_panic("Fatal machine check from unknown source", NULL, NULL); /* - * Now clear all the mces_seen so that they don't reappear on + * Now clear all the hw_errs_seen so that they don't reappear on * the next mce. */ for_each_possible_cpu(cpu) - memset(&per_cpu(mces_seen, cpu), 0, sizeof(struct mce)); + memset(&per_cpu(hw_errs_seen, cpu), 0, sizeof(struct mce_hw_err)); } static atomic_t global_nwo; @@ -1256,13 +1292,14 @@ static noinstr bool mce_check_crashing_cpu(void) } static __always_inline int -__mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final, - unsigned long *toclear, unsigned long *valid_banks, int no_way_out, - int *worst) +__mc_scan_banks(struct mce_hw_err *err, struct pt_regs *regs, + struct mce_hw_err *final, unsigned long *toclear, + unsigned long *valid_banks, int no_way_out, int *worst) { struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array); struct mca_config *cfg = &mca_cfg; int severity, i, taint = 0; + struct mce *m = &err->m; for (i = 0; i < this_cpu_read(mce_num_banks); i++) { arch___clear_bit(i, toclear); @@ -1307,7 +1344,7 @@ __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final, if (severity == MCE_NO_SEVERITY) continue; - mce_read_aux(m, i); + mce_read_aux(err, i); /* assuming valid severity level != 0 */ m->severity = severity; @@ -1317,17 +1354,17 @@ __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final, * done in #MC context, where instrumentation is disabled. */ instrumentation_begin(); - mce_log(m); + mce_log(err); instrumentation_end(); if (severity > *worst) { - *final = *m; + *final = *err; *worst = severity; } } /* mce_clear_state will clear *final, save locally for use later */ - *m = *final; + *err = *final; return taint; } @@ -1387,9 +1424,10 @@ static void kill_me_never(struct callback_head *cb) set_mce_nospec(pfn); } -static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *)) +static void queue_task_work(struct mce_hw_err *err, char *msg, void (*func)(struct callback_head *)) { int count = ++current->mce_count; + struct mce *m = &err->m; /* First call, save all the details */ if (count == 1) { @@ -1402,11 +1440,12 @@ static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callba /* Ten is likely overkill. Don't expect more than two faults before task_work() */ if (count > 10) - mce_panic("Too many consecutive machine checks while accessing user data", m, msg); + mce_panic("Too many consecutive machine checks while accessing user data", + err, msg); /* Second or later call, make sure page address matches the one from first call */ if (count > 1 && (current->mce_addr >> PAGE_SHIFT) != (m->addr >> PAGE_SHIFT)) - mce_panic("Consecutive machine checks to different user pages", m, msg); + mce_panic("Consecutive machine checks to different user pages", err, msg); /* Do not call task_work_add() more than once */ if (count > 1) @@ -1455,8 +1494,10 @@ noinstr void do_machine_check(struct pt_regs *regs) int worst = 0, order, no_way_out, kill_current_task, lmce, taint = 0; DECLARE_BITMAP(valid_banks, MAX_NR_BANKS) = { 0 }; DECLARE_BITMAP(toclear, MAX_NR_BANKS) = { 0 }; - struct mce m, *final; + struct mce_hw_err *final; + struct mce_hw_err err; char *msg = NULL; + struct mce *m; if (unlikely(mce_flags.p5)) return pentium_machine_check(regs); @@ -1494,13 +1535,14 @@ noinstr void do_machine_check(struct pt_regs *regs) this_cpu_inc(mce_exception_count); - mce_gather_info(&m, regs); - m.tsc = rdtsc(); + mce_gather_info(&err, regs); + m = &err.m; + m->tsc = rdtsc(); - final = this_cpu_ptr(&mces_seen); - *final = m; + final = this_cpu_ptr(&hw_errs_seen); + *final = err; - no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs); + no_way_out = mce_no_way_out(&err, &msg, valid_banks, regs); barrier(); @@ -1509,15 +1551,15 @@ noinstr void do_machine_check(struct pt_regs *regs) * Assume the worst for now, but if we find the * severity is MCE_AR_SEVERITY we have other options. */ - if (!(m.mcgstatus & MCG_STATUS_RIPV)) + if (!(m->mcgstatus & MCG_STATUS_RIPV)) kill_current_task = 1; /* * Check if this MCE is signaled to only this logical processor, * on Intel, Zhaoxin only. */ - if (m.cpuvendor == X86_VENDOR_INTEL || - m.cpuvendor == X86_VENDOR_ZHAOXIN) - lmce = m.mcgstatus & MCG_STATUS_LMCES; + if (m->cpuvendor == X86_VENDOR_INTEL || + m->cpuvendor == X86_VENDOR_ZHAOXIN) + lmce = m->mcgstatus & MCG_STATUS_LMCES; /* * Local machine check may already know that we have to panic. @@ -1528,12 +1570,12 @@ noinstr void do_machine_check(struct pt_regs *regs) */ if (lmce) { if (no_way_out) - mce_panic("Fatal local machine check", &m, msg); + mce_panic("Fatal local machine check", &err, msg); } else { order = mce_start(&no_way_out); } - taint = __mc_scan_banks(&m, regs, final, toclear, valid_banks, no_way_out, &worst); + taint = __mc_scan_banks(&err, regs, final, toclear, valid_banks, no_way_out, &worst); if (!no_way_out) mce_clear_state(toclear); @@ -1548,7 +1590,7 @@ noinstr void do_machine_check(struct pt_regs *regs) no_way_out = worst >= MCE_PANIC_SEVERITY; if (no_way_out) - mce_panic("Fatal machine check on current CPU", &m, msg); + mce_panic("Fatal machine check on current CPU", &err, msg); } } else { /* @@ -1560,8 +1602,8 @@ noinstr void do_machine_check(struct pt_regs *regs) * make sure we have the right "msg". */ if (worst >= MCE_PANIC_SEVERITY) { - mce_severity(&m, regs, &msg, true); - mce_panic("Local fatal machine check!", &m, msg); + mce_severity(m, regs, &msg, true); + mce_panic("Local fatal machine check!", &err, msg); } } @@ -1579,16 +1621,16 @@ noinstr void do_machine_check(struct pt_regs *regs) goto out; /* Fault was in user mode and we need to take some action */ - if ((m.cs & 3) == 3) { + if ((m->cs & 3) == 3) { /* If this triggers there is no way to recover. Die hard. */ BUG_ON(!on_thread_stack() || !user_mode(regs)); - if (!mce_usable_address(&m)) - queue_task_work(&m, msg, kill_me_now); + if (!mce_usable_address(m)) + queue_task_work(&err, msg, kill_me_now); else - queue_task_work(&m, msg, kill_me_maybe); + queue_task_work(&err, msg, kill_me_maybe); - } else if (m.mcgstatus & MCG_STATUS_SEAM_NR) { + } else if (m->mcgstatus & MCG_STATUS_SEAM_NR) { /* * Saved RIP on stack makes it look like the machine check * was taken in the kernel on the instruction following @@ -1600,8 +1642,8 @@ noinstr void do_machine_check(struct pt_regs *regs) * not occur there. Mark the page as poisoned so it won't * be added to free list when the guest is terminated. */ - if (mce_usable_address(&m)) { - struct page *p = pfn_to_online_page(m.addr >> PAGE_SHIFT); + if (mce_usable_address(m)) { + struct page *p = pfn_to_online_page(m->addr >> PAGE_SHIFT); if (p) SetPageHWPoison(p); @@ -1616,13 +1658,13 @@ noinstr void do_machine_check(struct pt_regs *regs) * corresponding exception handler which would do that is the * proper one. */ - if (m.kflags & MCE_IN_KERNEL_RECOV) { + if (m->kflags & MCE_IN_KERNEL_RECOV) { if (!fixup_exception(regs, X86_TRAP_MC, 0, 0)) - mce_panic("Failed kernel mode recovery", &m, msg); + mce_panic("Failed kernel mode recovery", &err, msg); } - if (m.kflags & MCE_IN_KERNEL_COPYIN) - queue_task_work(&m, msg, kill_me_never); + if (m->kflags & MCE_IN_KERNEL_COPYIN) + queue_task_work(&err, msg, kill_me_never); } out: diff --git a/arch/x86/kernel/cpu/mce/dev-mcelog.c b/arch/x86/kernel/cpu/mce/dev-mcelog.c index a05ac0716ecf..8d023239ce18 100644 --- a/arch/x86/kernel/cpu/mce/dev-mcelog.c +++ b/arch/x86/kernel/cpu/mce/dev-mcelog.c @@ -264,15 +264,8 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd, return put_user(sizeof(struct mce), p); case MCE_GET_LOG_LEN: return put_user(mcelog->len, p); - case MCE_GETCLEAR_FLAGS: { - unsigned flags; - - do { - flags = mcelog->flags; - } while (cmpxchg(&mcelog->flags, flags, 0) != flags); - - return put_user(flags, p); - } + case MCE_GETCLEAR_FLAGS: + return put_user(xchg(&mcelog->flags, 0), p); default: return -ENOTTY; } @@ -314,7 +307,7 @@ static ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, /* * Need to give user space some time to set everything up, - * so do it a jiffie or two later everywhere. + * so do it a jiffy or two later everywhere. */ schedule_timeout(2); @@ -331,7 +324,6 @@ static const struct file_operations mce_chrdev_ops = { .poll = mce_chrdev_poll, .unlocked_ioctl = mce_chrdev_ioctl, .compat_ioctl = compat_ptr_ioctl, - .llseek = no_llseek, }; static struct miscdevice mce_chrdev_device = { diff --git a/arch/x86/kernel/cpu/mce/genpool.c b/arch/x86/kernel/cpu/mce/genpool.c index 4284749ec803..d0be6dda0c14 100644 --- a/arch/x86/kernel/cpu/mce/genpool.c +++ b/arch/x86/kernel/cpu/mce/genpool.c @@ -31,15 +31,15 @@ static LLIST_HEAD(mce_event_llist); */ static bool is_duplicate_mce_record(struct mce_evt_llist *t, struct mce_evt_llist *l) { + struct mce_hw_err *err1, *err2; struct mce_evt_llist *node; - struct mce *m1, *m2; - m1 = &t->mce; + err1 = &t->err; llist_for_each_entry(node, &l->llnode, llnode) { - m2 = &node->mce; + err2 = &node->err; - if (!mce_cmp(m1, m2)) + if (!mce_cmp(&err1->m, &err2->m)) return true; } return false; @@ -73,8 +73,8 @@ struct llist_node *mce_gen_pool_prepare_records(void) void mce_gen_pool_process(struct work_struct *__unused) { - struct llist_node *head; struct mce_evt_llist *node, *tmp; + struct llist_node *head; struct mce *mce; head = llist_del_all(&mce_event_llist); @@ -83,7 +83,7 @@ void mce_gen_pool_process(struct work_struct *__unused) head = llist_reverse_order(head); llist_for_each_entry_safe(node, tmp, head, llnode) { - mce = &node->mce; + mce = &node->err.m; blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node)); } @@ -94,11 +94,11 @@ bool mce_gen_pool_empty(void) return llist_empty(&mce_event_llist); } -int mce_gen_pool_add(struct mce *mce) +int mce_gen_pool_add(struct mce_hw_err *err) { struct mce_evt_llist *node; - if (filter_mce(mce)) + if (filter_mce(&err->m)) return -EINVAL; if (!mce_evt_pool) @@ -110,7 +110,7 @@ int mce_gen_pool_add(struct mce *mce) return -ENOMEM; } - memcpy(&node->mce, mce, sizeof(*mce)); + memcpy(&node->err, err, sizeof(*err)); llist_add(&node->llnode, &mce_event_llist); return 0; diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c index 49ed3428785d..313fe682db33 100644 --- a/arch/x86/kernel/cpu/mce/inject.c +++ b/arch/x86/kernel/cpu/mce/inject.c @@ -502,8 +502,9 @@ static void prepare_msrs(void *info) static void do_inject(void) { - u64 mcg_status = 0; unsigned int cpu = i_mce.extcpu; + struct mce_hw_err err; + u64 mcg_status = 0; u8 b = i_mce.bank; i_mce.tsc = rdtsc_ordered(); @@ -517,7 +518,8 @@ static void do_inject(void) i_mce.status |= MCI_STATUS_SYNDV; if (inj_type == SW_INJ) { - mce_log(&i_mce); + err.m = i_mce; + mce_log(&err); return; } diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c index f6103e6bf69a..b3cd2c61b11d 100644 --- a/arch/x86/kernel/cpu/mce/intel.c +++ b/arch/x86/kernel/cpu/mce/intel.c @@ -94,7 +94,7 @@ static int cmci_supported(int *banks) if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6) return 0; rdmsrl(MSR_IA32_MCG_CAP, cap); - *banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff); + *banks = min_t(unsigned, MAX_NR_BANKS, cap & MCG_BANKCNT_MASK); return !!(cap & MCG_CMCI_P); } diff --git a/arch/x86/kernel/cpu/mce/internal.h b/arch/x86/kernel/cpu/mce/internal.h index 01f8f03969e6..84f810598231 100644 --- a/arch/x86/kernel/cpu/mce/internal.h +++ b/arch/x86/kernel/cpu/mce/internal.h @@ -26,12 +26,12 @@ extern struct blocking_notifier_head x86_mce_decoder_chain; struct mce_evt_llist { struct llist_node llnode; - struct mce mce; + struct mce_hw_err err; }; void mce_gen_pool_process(struct work_struct *__unused); bool mce_gen_pool_empty(void); -int mce_gen_pool_add(struct mce *mce); +int mce_gen_pool_add(struct mce_hw_err *err); int mce_gen_pool_init(void); struct llist_node *mce_gen_pool_prepare_records(void); @@ -261,6 +261,8 @@ enum mca_msr { /* Decide whether to add MCE record to MCE event pool or filter it out. */ extern bool filter_mce(struct mce *m); +void mce_prep_record_common(struct mce *m); +void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m); #ifdef CONFIG_X86_MCE_AMD extern bool amd_filter_mce(struct mce *m); diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index c0d56c02b8da..31a73715d755 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -89,6 +89,31 @@ static struct equiv_cpu_table { struct equiv_cpu_entry *entry; } equiv_table; +union zen_patch_rev { + struct { + __u32 rev : 8, + stepping : 4, + model : 4, + __reserved : 4, + ext_model : 4, + ext_fam : 8; + }; + __u32 ucode_rev; +}; + +union cpuid_1_eax { + struct { + __u32 stepping : 4, + model : 4, + family : 4, + __reserved0 : 4, + ext_model : 4, + ext_fam : 8, + __reserved1 : 4; + }; + __u32 full; +}; + /* * This points to the current valid container of microcode patches which we will * save from the initrd/builtin before jettisoning its contents. @mc is the @@ -96,7 +121,6 @@ static struct equiv_cpu_table { */ struct cont_desc { struct microcode_amd *mc; - u32 cpuid_1_eax; u32 psize; u8 *data; size_t size; @@ -109,10 +133,42 @@ struct cont_desc { static const char ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; +/* + * This is CPUID(1).EAX on the BSP. It is used in two ways: + * + * 1. To ignore the equivalence table on Zen1 and newer. + * + * 2. To match which patches to load because the patch revision ID + * already contains the f/m/s for which the microcode is destined + * for. + */ +static u32 bsp_cpuid_1_eax __ro_after_init; + +static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val) +{ + union zen_patch_rev p; + union cpuid_1_eax c; + + p.ucode_rev = val; + c.full = 0; + + c.stepping = p.stepping; + c.model = p.model; + c.ext_model = p.ext_model; + c.family = 0xf; + c.ext_fam = p.ext_fam; + + return c; +} + static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig) { unsigned int i; + /* Zen and newer do not need an equivalence table. */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) + return 0; + if (!et || !et->num_entries) return 0; @@ -159,6 +215,10 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size) if (!verify_container(buf, buf_size)) return false; + /* Zen and newer do not need an equivalence table. */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) + return true; + cont_type = hdr[1]; if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) { pr_debug("Wrong microcode container equivalence table type: %u.\n", @@ -222,8 +282,9 @@ __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize) * exceed the per-family maximum). @sh_psize is the size read from the section * header. */ -static unsigned int __verify_patch_size(u8 family, u32 sh_psize, size_t buf_size) +static unsigned int __verify_patch_size(u32 sh_psize, size_t buf_size) { + u8 family = x86_family(bsp_cpuid_1_eax); u32 max_size; if (family >= 0x15) @@ -258,9 +319,9 @@ static unsigned int __verify_patch_size(u8 family, u32 sh_psize, size_t buf_size * positive: patch is not for this family, skip it * 0: success */ -static int -verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size) +static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size) { + u8 family = x86_family(bsp_cpuid_1_eax); struct microcode_header_amd *mc_hdr; unsigned int ret; u32 sh_psize; @@ -286,7 +347,7 @@ verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size) return -1; } - ret = __verify_patch_size(family, sh_psize, buf_size); + ret = __verify_patch_size(sh_psize, buf_size); if (!ret) { pr_debug("Per-family patch size mismatch.\n"); return -1; @@ -308,6 +369,15 @@ verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size) return 0; } +static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id) +{ + /* Zen and newer do not need an equivalence table. */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) + return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax; + else + return eq_id == mc->hdr.processor_rev_id; +} + /* * This scans the ucode blob for the proper container as we can have multiple * containers glued together. Returns the equivalence ID from the equivalence @@ -336,7 +406,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) * doesn't contain a patch for the CPU, scan through the whole container * so that it can be skipped in case there are other containers appended. */ - eq_id = find_equiv_id(&table, desc->cpuid_1_eax); + eq_id = find_equiv_id(&table, bsp_cpuid_1_eax); buf += hdr[2] + CONTAINER_HDR_SZ; size -= hdr[2] + CONTAINER_HDR_SZ; @@ -350,7 +420,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) u32 patch_size; int ret; - ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size); + ret = verify_patch(buf, size, &patch_size); if (ret < 0) { /* * Patch verification failed, skip to the next container, if @@ -363,7 +433,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc) } mc = (struct microcode_amd *)(buf + SECTION_HDR_SIZE); - if (eq_id == mc->hdr.processor_rev_id) { + if (mc_patch_matches(mc, eq_id)) { desc->psize = patch_size; desc->mc = mc; } @@ -421,6 +491,7 @@ static int __apply_microcode_amd(struct microcode_amd *mc) /* verify patch application was successful */ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + if (rev != mc->hdr.patch_id) return -1; @@ -438,14 +509,12 @@ static int __apply_microcode_amd(struct microcode_amd *mc) * * Returns true if container found (sets @desc), false otherwise. */ -static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size) +static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size) { struct cont_desc desc = { 0 }; struct microcode_amd *mc; bool ret = false; - desc.cpuid_1_eax = cpuid_1_eax; - scan_containers(ucode, size, &desc); mc = desc.mc; @@ -463,9 +532,10 @@ static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, siz return !__apply_microcode_amd(mc); } -static bool get_builtin_microcode(struct cpio_data *cp, u8 family) +static bool get_builtin_microcode(struct cpio_data *cp) { char fw_name[36] = "amd-ucode/microcode_amd.bin"; + u8 family = x86_family(bsp_cpuid_1_eax); struct firmware fw; if (IS_ENABLED(CONFIG_X86_32)) @@ -484,11 +554,11 @@ static bool get_builtin_microcode(struct cpio_data *cp, u8 family) return false; } -static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret) +static void __init find_blobs_in_containers(struct cpio_data *ret) { struct cpio_data cp; - if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax))) + if (!get_builtin_microcode(&cp)) cp = find_microcode_in_initrd(ucode_path); *ret = cp; @@ -499,20 +569,22 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ struct cpio_data cp = { }; u32 dummy; + bsp_cpuid_1_eax = cpuid_1_eax; + native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy); /* Needed in load_microcode_amd() */ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax; - find_blobs_in_containers(cpuid_1_eax, &cp); + find_blobs_in_containers(&cp); if (!(cp.data && cp.size)) return; - if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size)) + if (early_apply_microcode(ed->old_rev, cp.data, cp.size)) native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); } -static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); +static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size); static int __init save_microcode_in_initrd(void) { @@ -525,17 +597,15 @@ static int __init save_microcode_in_initrd(void) if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) return 0; - find_blobs_in_containers(cpuid_1_eax, &cp); + find_blobs_in_containers(&cp); if (!(cp.data && cp.size)) return -EINVAL; - desc.cpuid_1_eax = cpuid_1_eax; - scan_containers(cp.data, cp.size, &desc); if (!desc.mc) return -EINVAL; - ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); + ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); if (ret > UCODE_UPDATED) return -EINVAL; @@ -543,26 +613,75 @@ static int __init save_microcode_in_initrd(void) } early_initcall(save_microcode_in_initrd); +static inline bool patch_cpus_equivalent(struct ucode_patch *p, + struct ucode_patch *n, + bool ignore_stepping) +{ + /* Zen and newer hardcode the f/m/s in the patch ID */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) { + union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id); + union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id); + + if (ignore_stepping) { + p_cid.stepping = 0; + n_cid.stepping = 0; + } + + return p_cid.full == n_cid.full; + } else { + return p->equiv_cpu == n->equiv_cpu; + } +} + /* * a small, trivial cache of per-family ucode patches */ -static struct ucode_patch *cache_find_patch(u16 equiv_cpu) +static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equiv_cpu) { struct ucode_patch *p; + struct ucode_patch n; + + n.equiv_cpu = equiv_cpu; + n.patch_id = uci->cpu_sig.rev; + + WARN_ON_ONCE(!n.patch_id); list_for_each_entry(p, µcode_cache, plist) - if (p->equiv_cpu == equiv_cpu) + if (patch_cpus_equivalent(p, &n, false)) return p; + return NULL; } +static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n) +{ + /* Zen and newer hardcode the f/m/s in the patch ID */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) { + union zen_patch_rev zp, zn; + + zp.ucode_rev = p->patch_id; + zn.ucode_rev = n->patch_id; + + if (zn.stepping != zp.stepping) + return -1; + + return zn.rev > zp.rev; + } else { + return n->patch_id > p->patch_id; + } +} + static void update_cache(struct ucode_patch *new_patch) { struct ucode_patch *p; + int ret; list_for_each_entry(p, µcode_cache, plist) { - if (p->equiv_cpu == new_patch->equiv_cpu) { - if (p->patch_id >= new_patch->patch_id) { + if (patch_cpus_equivalent(p, new_patch, true)) { + ret = patch_newer(p, new_patch); + if (ret < 0) + continue; + else if (!ret) { /* we already have the latest patch */ kfree(new_patch->data); kfree(new_patch); @@ -593,13 +712,22 @@ static void free_cache(void) static struct ucode_patch *find_patch(unsigned int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - u16 equiv_id; + u32 rev, dummy __always_unused; + u16 equiv_id = 0; - equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); - if (!equiv_id) - return NULL; + /* fetch rev if not populated yet: */ + if (!uci->cpu_sig.rev) { + rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + uci->cpu_sig.rev = rev; + } - return cache_find_patch(equiv_id); + if (x86_family(bsp_cpuid_1_eax) < 0x17) { + equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); + if (!equiv_id) + return NULL; + } + + return cache_find_patch(uci, equiv_id); } void reload_ucode_amd(unsigned int cpu) @@ -649,7 +777,7 @@ static enum ucode_state apply_microcode_amd(int cpu) struct ucode_cpu_info *uci; struct ucode_patch *p; enum ucode_state ret; - u32 rev, dummy __always_unused; + u32 rev; BUG_ON(raw_smp_processor_id() != cpu); @@ -659,11 +787,11 @@ static enum ucode_state apply_microcode_amd(int cpu) if (!p) return UCODE_NFOUND; + rev = uci->cpu_sig.rev; + mc_amd = p->data; uci->mc = p->data; - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); - /* need to apply patch? */ if (rev > mc_amd->hdr.patch_id) { ret = UCODE_OK; @@ -709,6 +837,10 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) hdr = (const u32 *)buf; equiv_tbl_len = hdr[2]; + /* Zen and newer do not need an equivalence table. */ + if (x86_family(bsp_cpuid_1_eax) >= 0x17) + goto out; + equiv_table.entry = vmalloc(equiv_tbl_len); if (!equiv_table.entry) { pr_err("failed to allocate equivalent CPU table\n"); @@ -718,12 +850,16 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) memcpy(equiv_table.entry, buf + CONTAINER_HDR_SZ, equiv_tbl_len); equiv_table.num_entries = equiv_tbl_len / sizeof(struct equiv_cpu_entry); +out: /* add header length */ return equiv_tbl_len + CONTAINER_HDR_SZ; } static void free_equiv_cpu_table(void) { + if (x86_family(bsp_cpuid_1_eax) >= 0x17) + return; + vfree(equiv_table.entry); memset(&equiv_table, 0, sizeof(equiv_table)); } @@ -749,7 +885,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, u16 proc_id; int ret; - ret = verify_patch(family, fw, leftover, patch_size); + ret = verify_patch(fw, leftover, patch_size); if (ret) return ret; @@ -774,7 +910,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, patch->patch_id = mc_hdr->patch_id; patch->equiv_cpu = proc_id; - pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n", + pr_debug("%s: Adding patch_id: 0x%08x, proc_id: 0x%04x\n", __func__, patch->patch_id, proc_id); /* ... and add to cache. */ @@ -818,21 +954,30 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, return UCODE_OK; } -static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) +static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size) { - struct cpuinfo_x86 *c; - unsigned int nid, cpu; - struct ucode_patch *p; enum ucode_state ret; /* free old equiv table */ free_equiv_cpu_table(); ret = __load_microcode_amd(family, data, size); - if (ret != UCODE_OK) { + if (ret != UCODE_OK) cleanup(); + + return ret; +} + +static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) +{ + struct cpuinfo_x86 *c; + unsigned int nid, cpu; + struct ucode_patch *p; + enum ucode_state ret; + + ret = _load_microcode_amd(family, data, size); + if (ret != UCODE_OK) return ret; - } for_each_node(nid) { cpu = cpumask_first(cpumask_of_node(nid)); diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 815fa67356a2..f3d534807d91 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -319,12 +319,6 @@ static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, return UCODE_OK; } - /* - * Writeback and invalidate caches before updating microcode to avoid - * internal issues depending on what the microcode is updating. - */ - native_wbinvd(); - /* write microcode via MSR 0x79 */ native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); @@ -574,14 +568,14 @@ static bool is_blacklisted(unsigned int cpu) /* * Late loading on model 79 with microcode revision less than 0x0b000021 * and LLC size per core bigger than 2.5MB may result in a system hang. - * This behavior is documented in item BDF90, #334165 (Intel Xeon + * This behavior is documented in item BDX90, #334165 (Intel Xeon * Processor E7-8800/4800 v4 Product Family). */ if (c->x86_vfm == INTEL_BROADWELL_X && c->x86_stepping == 0x01 && llc_size_per_core > 2621440 && c->microcode < 0x0b000021) { - pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); + pr_err_once("Erratum BDX90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode); pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); return true; } diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index e0fd57a8ba84..d18078834ded 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -16,7 +16,6 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/kexec.h> -#include <linux/i8253.h> #include <linux/random.h> #include <asm/processor.h> #include <asm/hypervisor.h> @@ -199,8 +198,8 @@ static void hv_machine_shutdown(void) * Call hv_cpu_die() on all the CPUs, otherwise later the hypervisor * corrupts the old VP Assist Pages and can crash the kexec kernel. */ - if (kexec_in_progress && hyperv_init_cpuhp > 0) - cpuhp_remove_state(hyperv_init_cpuhp); + if (kexec_in_progress) + cpuhp_remove_state(CPUHP_AP_HYPERV_ONLINE); /* The function calls stop_other_cpus(). */ native_machine_shutdown(); @@ -424,6 +423,7 @@ static void __init ms_hyperv_init_platform(void) ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { x86_platform.calibrate_tsc = hv_get_tsc_khz; x86_platform.calibrate_cpu = hv_get_tsc_khz; + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); } if (ms_hyperv.priv_high & HV_ISOLATION) { @@ -449,9 +449,23 @@ static void __init ms_hyperv_init_platform(void) ms_hyperv.hints &= ~HV_X64_APIC_ACCESS_RECOMMENDED; if (!ms_hyperv.paravisor_present) { - /* To be supported: more work is required. */ + /* + * Mark the Hyper-V TSC page feature as disabled + * in a TDX VM without paravisor so that the + * Invariant TSC, which is a better clocksource + * anyway, is used instead. + */ ms_hyperv.features &= ~HV_MSR_REFERENCE_TSC_AVAILABLE; + /* + * The Invariant TSC is expected to be available + * in a TDX VM without paravisor, but if not, + * print a warning message. The slower Hyper-V MSR-based + * Ref Counter should end up being the clocksource. + */ + if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) + pr_warn("Hyper-V: Invariant TSC is unavailable\n"); + /* HV_MSR_CRASH_CTL is unsupported. */ ms_hyperv.misc_features &= ~HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE; @@ -522,16 +536,6 @@ static void __init ms_hyperv_init_platform(void) if (efi_enabled(EFI_BOOT)) x86_platform.get_nmi_reason = hv_get_nmi_reason; - /* - * Hyper-V VMs have a PIT emulation quirk such that zeroing the - * counter register during PIT shutdown restarts the PIT. So it - * continues to interrupt @18.2 HZ. Setting i8253_clear_counter - * to false tells pit_shutdown() not to zero the counter so that - * the PIT really is shutdown. Generation 2 VMs don't have a PIT, - * and setting this value has no effect. - */ - i8253_clear_counter_on_shutdown = false; - #if IS_ENABLED(CONFIG_HYPERV) if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) || ms_hyperv.paravisor_present) diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c index 2a2fc14955cd..989d368be04f 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.c +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c @@ -55,6 +55,12 @@ #include "mtrr.h" +static_assert(X86_MEMTYPE_UC == MTRR_TYPE_UNCACHABLE); +static_assert(X86_MEMTYPE_WC == MTRR_TYPE_WRCOMB); +static_assert(X86_MEMTYPE_WT == MTRR_TYPE_WRTHROUGH); +static_assert(X86_MEMTYPE_WP == MTRR_TYPE_WRPROT); +static_assert(X86_MEMTYPE_WB == MTRR_TYPE_WRBACK); + /* arch_phys_wc_add returns an MTRR register index plus this offset. */ #define MTRR_TO_PHYS_WC_OFFSET 1000 diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index e65fae63660e..41ed01f46bd9 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -41,11 +41,11 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: yes\n", - boot_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", - boot_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", - boot_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", - boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", - boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", + str_yes_no(boot_cpu_has_bug(X86_BUG_FDIV)), + str_yes_no(boot_cpu_has_bug(X86_BUG_F00F)), + str_yes_no(boot_cpu_has_bug(X86_BUG_COMA)), + str_yes_no(boot_cpu_has(X86_FEATURE_FPU)), + str_yes_no(boot_cpu_has(X86_FEATURE_FPU)), c->cpuid_level); } #else diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c index 1930fce9dfe9..b681c2e07dbf 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -119,6 +119,14 @@ struct rdt_hw_resource rdt_resources_all[] = { }, }; +u32 resctrl_arch_system_num_rmid_idx(void) +{ + struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3].r_resctrl; + + /* RMID are independent numbers for x86. num_rmid_idx == num_rmid */ + return r->num_rmid; +} + /* * cache_alloc_hsw_probe() - Have to probe for Intel haswell server CPUs * as they do not have CPUID enumeration support for Cache allocation. @@ -199,7 +207,7 @@ static inline bool rdt_get_mb_table(struct rdt_resource *r) return false; } -static bool __get_mem_config_intel(struct rdt_resource *r) +static __init bool __get_mem_config_intel(struct rdt_resource *r) { struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); union cpuid_0x10_3_eax eax; @@ -233,7 +241,7 @@ static bool __get_mem_config_intel(struct rdt_resource *r) return true; } -static bool __rdt_get_mem_config_amd(struct rdt_resource *r) +static __init bool __rdt_get_mem_config_amd(struct rdt_resource *r) { struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); u32 eax, ebx, ecx, edx, subleaf; diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c index 50fa1fe9a073..200d89a64027 100644 --- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c +++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c @@ -29,10 +29,10 @@ * hardware. The allocated bandwidth percentage is rounded to the next * control step available on the hardware. */ -static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) +static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r) { - unsigned long bw; int ret; + u32 bw; /* * Only linear delay values is supported for current Intel SKUs. @@ -42,16 +42,21 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) return false; } - ret = kstrtoul(buf, 10, &bw); + ret = kstrtou32(buf, 10, &bw); if (ret) { - rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf); + rdt_last_cmd_printf("Invalid MB value %s\n", buf); return false; } - if ((bw < r->membw.min_bw || bw > r->default_ctrl) && - !is_mba_sc(r)) { - rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw, - r->membw.min_bw, r->default_ctrl); + /* Nothing else to do if software controller is enabled. */ + if (is_mba_sc(r)) { + *data = bw; + return true; + } + + if (bw < r->membw.min_bw || bw > r->default_ctrl) { + rdt_last_cmd_printf("MB value %u out of range [%d,%d]\n", + bw, r->membw.min_bw, r->default_ctrl); return false; } @@ -65,7 +70,7 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct resctrl_staged_config *cfg; u32 closid = data->rdtgrp->closid; struct rdt_resource *r = s->res; - unsigned long bw_val; + u32 bw_val; cfg = &d->staged_config[s->conf_type]; if (cfg->have_new_ctrl) { diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index 851b561850e0..5fcb3d635d91 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -1158,11 +1158,12 @@ static __init int snc_get_config(void) ret = cpus_per_l3 / cpus_per_node; - /* sanity check: Only valid results are 1, 2, 3, 4 */ + /* sanity check: Only valid results are 1, 2, 3, 4, 6 */ switch (ret) { case 1: break; case 2 ... 4: + case 6: pr_info("Sub-NUMA Cluster mode detected with %d nodes per L3 cache\n", ret); rdt_resources_all[RDT_RESOURCE_L3].r_resctrl.mon_scope = RESCTRL_L3_NODE; break; diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c index e69489d48625..972e6b6b0481 100644 --- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c @@ -1567,7 +1567,6 @@ static int pseudo_lock_dev_mmap(struct file *filp, struct vm_area_struct *vma) static const struct file_operations pseudo_lock_dev_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, .read = NULL, .write = NULL, .open = pseudo_lock_dev_open, diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index d7163b764c62..d906a1cd8491 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -1596,7 +1596,7 @@ static void mondata_config_read(struct rdt_mon_domain *d, struct mon_config_info static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid) { - struct mon_config_info mon_info = {0}; + struct mon_config_info mon_info; struct rdt_mon_domain *dom; bool sep = false; diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index c84c30188fdf..16f3ca30626a 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -24,34 +24,36 @@ struct cpuid_bit { * levels are different and there is a separate entry for each. */ static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 }, - { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, - { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 }, - { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 }, - { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 }, - { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 }, - { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 }, - { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 }, - { X86_FEATURE_CQM_MBM_LOCAL, CPUID_EDX, 2, 0x0000000f, 1 }, - { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 }, - { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 }, - { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 }, - { X86_FEATURE_CDP_L2, CPUID_ECX, 2, 0x00000010, 2 }, - { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 }, - { X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 }, - { X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 }, - { X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 }, - { X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 }, - { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, - { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, - { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, - { X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, - { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, - { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 }, - { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 }, - { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 }, - { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 }, + { X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 }, + { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, + { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 }, + { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 }, + { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 }, + { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 }, + { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 }, + { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 }, + { X86_FEATURE_CQM_MBM_LOCAL, CPUID_EDX, 2, 0x0000000f, 1 }, + { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 }, + { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 }, + { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 }, + { X86_FEATURE_CDP_L2, CPUID_ECX, 2, 0x00000010, 2 }, + { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 }, + { X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 }, + { X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 }, + { X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 }, + { X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 }, + { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, + { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, + { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, + { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, + { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, + { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 }, + { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 }, + { X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 }, + { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 }, + { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 }, { X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 }, + { X86_FEATURE_AMD_HETEROGENEOUS_CORES, CPUID_EAX, 30, 0x80000026, 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 27892e57c4ef..eb5848d1851a 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -475,24 +475,25 @@ struct sgx_epc_page *__sgx_alloc_epc_page(void) { struct sgx_epc_page *page; int nid_of_current = numa_node_id(); - int nid = nid_of_current; + int nid_start, nid; - if (node_isset(nid_of_current, sgx_numa_mask)) { - page = __sgx_alloc_epc_page_from_node(nid_of_current); - if (page) - return page; - } - - /* Fall back to the non-local NUMA nodes: */ - while (true) { - nid = next_node_in(nid, sgx_numa_mask); - if (nid == nid_of_current) - break; + /* + * Try local node first. If it doesn't have an EPC section, + * fall back to the non-local NUMA nodes. + */ + if (node_isset(nid_of_current, sgx_numa_mask)) + nid_start = nid_of_current; + else + nid_start = next_node_in(nid_of_current, sgx_numa_mask); + nid = nid_start; + do { page = __sgx_alloc_epc_page_from_node(nid); if (page) return page; - } + + nid = next_node_in(nid, sgx_numa_mask); + } while (nid != nid_start); return ERR_PTR(-ENOMEM); } @@ -732,7 +733,7 @@ out: return 0; } -/** +/* * A section metric is concatenated in a way that @low bits 12-31 define the * bits 12-31 of the metric and @high bits 0-19 define the bits 32-51 of the * metric. @@ -847,6 +848,13 @@ static bool __init sgx_page_cache_init(void) return false; } + for_each_online_node(nid) { + if (!node_isset(nid, sgx_numa_mask) && + node_state(nid, N_MEMORY) && node_state(nid, N_CPU)) + pr_info("node%d has both CPUs and memory but doesn't have an EPC section\n", + nid); + } + return true; } @@ -893,19 +901,15 @@ static struct miscdevice sgx_dev_provision = { int sgx_set_attribute(unsigned long *allowed_attributes, unsigned int attribute_fd) { - struct fd f = fdget(attribute_fd); + CLASS(fd, f)(attribute_fd); - if (!f.file) + if (fd_empty(f)) return -EINVAL; - if (f.file->f_op != &sgx_provision_fops) { - fdput(f); + if (fd_file(f)->f_op != &sgx_provision_fops) return -EINVAL; - } *allowed_attributes |= SGX_ATTR_PROVISIONKEY; - - fdput(f); return 0; } EXPORT_SYMBOL_GPL(sgx_set_attribute); diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index 7d476fa697ca..03b3c9c3a45e 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -182,6 +182,9 @@ static void parse_topology_amd(struct topo_scan *tscan) if (cpu_feature_enabled(X86_FEATURE_TOPOEXT)) has_topoext = cpu_parse_topology_ext(tscan); + if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) + tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); + if (!has_topoext && !parse_8000_0008(tscan)) return; diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c index 9a6069e7133c..8277c64f88db 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c @@ -3,6 +3,7 @@ #include <xen/xen.h> +#include <asm/intel-family.h> #include <asm/apic.h> #include <asm/processor.h> #include <asm/smp.h> @@ -27,6 +28,36 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom, } } +enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c) +{ + if (c->x86_vendor == X86_VENDOR_INTEL) { + switch (c->topo.intel_type) { + case INTEL_CPU_TYPE_ATOM: return TOPO_CPU_TYPE_EFFICIENCY; + case INTEL_CPU_TYPE_CORE: return TOPO_CPU_TYPE_PERFORMANCE; + } + } + if (c->x86_vendor == X86_VENDOR_AMD) { + switch (c->topo.amd_type) { + case 0: return TOPO_CPU_TYPE_PERFORMANCE; + case 1: return TOPO_CPU_TYPE_EFFICIENCY; + } + } + + return TOPO_CPU_TYPE_UNKNOWN; +} + +const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c) +{ + switch (get_topology_cpu_type(c)) { + case TOPO_CPU_TYPE_PERFORMANCE: + return "performance"; + case TOPO_CPU_TYPE_EFFICIENCY: + return "efficiency"; + default: + return "unknown"; + } +} + static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c) { struct { @@ -87,6 +118,7 @@ static void parse_topology(struct topo_scan *tscan, bool early) .cu_id = 0xff, .llc_id = BAD_APICID, .l2c_id = BAD_APICID, + .cpu_type = TOPO_CPU_TYPE_UNKNOWN, }; struct cpuinfo_x86 *c = tscan->c; struct { @@ -132,6 +164,8 @@ static void parse_topology(struct topo_scan *tscan, bool early) case X86_VENDOR_INTEL: if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan)) parse_legacy(tscan); + if (c->cpuid_level >= 0x1a) + c->topo.cpu_type = cpuid_eax(0x1a); break; case X86_VENDOR_HYGON: if (IS_ENABLED(CONFIG_CPU_SUP_HYGON)) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 64280879c68c..59d23cdf4ed0 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -305,7 +305,7 @@ void __init x86_flattree_get_config(void) map_len = size; } - early_init_dt_verify(dt); + early_init_dt_verify(dt, __pa(dt)); } unflatten_and_copy_device_tree(); diff --git a/arch/x86/kernel/eisa.c b/arch/x86/kernel/eisa.c index 53935b4d62e3..9535a6507db7 100644 --- a/arch/x86/kernel/eisa.c +++ b/arch/x86/kernel/eisa.c @@ -11,15 +11,15 @@ static __init int eisa_bus_probe(void) { - void __iomem *p; + u32 *p; if ((xen_pv_domain() && !xen_initial_domain()) || cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) return 0; - p = ioremap(0x0FFFD9, 4); - if (p && readl(p) == 'E' + ('I' << 8) + ('S' << 16) + ('A' << 24)) + p = memremap(0x0FFFD9, 4, MEMREMAP_WB); + if (p && *p == 'E' + ('I' << 8) + ('S' << 16) + ('A' << 24)) EISA_bus = 1; - iounmap(p); + memunmap(p); return 0; } subsys_initcall(eisa_bus_probe); diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 247f2225aa9f..1065ab995305 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -64,6 +64,16 @@ setfx: } /* + * Update the value of PKRU register that was already pushed onto the signal frame. + */ +static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru) +{ + if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE))) + return 0; + return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); +} + +/* * Signal frame handlers. */ static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf) @@ -156,10 +166,17 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame, return !err; } -static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf) +static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru) { - if (use_xsave()) - return xsave_to_user_sigframe(buf); + int err = 0; + + if (use_xsave()) { + err = xsave_to_user_sigframe(buf); + if (!err) + err = update_pkru_in_sigframe(buf, pkru); + return err; + } + if (use_fxsr()) return fxsave_to_user_sigframe((struct fxregs_state __user *) buf); else @@ -185,7 +202,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf) * For [f]xsave state, update the SW reserved fields in the [f]xsave frame * indicating the absence/presence of the extended state to the user. */ -bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) +bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size, u32 pkru) { struct task_struct *tsk = current; struct fpstate *fpstate = tsk->thread.fpu.fpstate; @@ -228,7 +245,7 @@ retry: fpregs_restore_userregs(); pagefault_disable(); - ret = copy_fpregs_to_sigframe(buf_fx); + ret = copy_fpregs_to_sigframe(buf_fx, pkru); pagefault_enable(); fpregs_unlock(); diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index c5a026fee5e0..22abb5ee0cf2 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -13,6 +13,7 @@ #include <linux/seq_file.h> #include <linux/proc_fs.h> #include <linux/vmalloc.h> +#include <linux/coredump.h> #include <asm/fpu/api.h> #include <asm/fpu/regset.h> @@ -23,6 +24,8 @@ #include <asm/prctl.h> #include <asm/elf.h> +#include <uapi/asm/elf.h> + #include "context.h" #include "internal.h" #include "legacy.h" @@ -788,6 +791,9 @@ void __init fpu__init_system_xstate(unsigned int legacy_size) goto out_disable; } + fpu_kernel_cfg.independent_features = fpu_kernel_cfg.max_features & + XFEATURE_MASK_INDEPENDENT; + /* * Clear XSAVE features that are disabled in the normal CPUID. */ @@ -993,6 +999,19 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr) } EXPORT_SYMBOL_GPL(get_xsave_addr); +/* + * Given an xstate feature nr, calculate where in the xsave buffer the state is. + * The xsave buffer should be in standard format, not compacted (e.g. user mode + * signal frames). + */ +void __user *get_xsave_addr_user(struct xregs_state __user *xsave, int xfeature_nr) +{ + if (WARN_ON_ONCE(!xfeature_enabled(xfeature_nr))) + return NULL; + + return (void __user *)xsave + xstate_offsets[xfeature_nr]; +} + #ifdef CONFIG_ARCH_HAS_PKEYS /* @@ -1838,3 +1857,89 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns, return 0; } #endif /* CONFIG_PROC_PID_ARCH_STATUS */ + +#ifdef CONFIG_COREDUMP +static const char owner_name[] = "LINUX"; + +/* + * Dump type, size, offset and flag values for every xfeature that is present. + */ +static int dump_xsave_layout_desc(struct coredump_params *cprm) +{ + int num_records = 0; + int i; + + for_each_extended_xfeature(i, fpu_user_cfg.max_features) { + struct x86_xfeat_component xc = { + .type = i, + .size = xstate_sizes[i], + .offset = xstate_offsets[i], + /* reserved for future use */ + .flags = 0, + }; + + if (!dump_emit(cprm, &xc, sizeof(xc))) + return 0; + + num_records++; + } + return num_records; +} + +static u32 get_xsave_desc_size(void) +{ + u32 cnt = 0; + u32 i; + + for_each_extended_xfeature(i, fpu_user_cfg.max_features) + cnt++; + + return cnt * (sizeof(struct x86_xfeat_component)); +} + +int elf_coredump_extra_notes_write(struct coredump_params *cprm) +{ + int num_records = 0; + struct elf_note en; + + if (!fpu_user_cfg.max_features) + return 0; + + en.n_namesz = sizeof(owner_name); + en.n_descsz = get_xsave_desc_size(); + en.n_type = NT_X86_XSAVE_LAYOUT; + + if (!dump_emit(cprm, &en, sizeof(en))) + return 1; + if (!dump_emit(cprm, owner_name, en.n_namesz)) + return 1; + if (!dump_align(cprm, 4)) + return 1; + + num_records = dump_xsave_layout_desc(cprm); + if (!num_records) + return 1; + + /* Total size should be equal to the number of records */ + if ((sizeof(struct x86_xfeat_component) * num_records) != en.n_descsz) + return 1; + + return 0; +} + +int elf_coredump_extra_notes_size(void) +{ + int size; + + if (!fpu_user_cfg.max_features) + return 0; + + /* .note header */ + size = sizeof(struct elf_note); + /* Name plus alignment to 4 bytes */ + size += roundup(sizeof(owner_name), 4); + size += get_xsave_desc_size(); + + return size; +} +#endif /* CONFIG_COREDUMP */ diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h index 2ee0b9c53dcc..0b86a5002c84 100644 --- a/arch/x86/kernel/fpu/xstate.h +++ b/arch/x86/kernel/fpu/xstate.h @@ -54,6 +54,8 @@ extern int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void extern void fpu__init_cpu_xstate(void); extern void fpu__init_system_xstate(unsigned int legacy_size); +extern void __user *get_xsave_addr_user(struct xregs_state __user *xsave, int xfeature_nr); + static inline u64 xfeatures_mask_supervisor(void) { return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED; @@ -62,9 +64,9 @@ static inline u64 xfeatures_mask_supervisor(void) static inline u64 xfeatures_mask_independent(void) { if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) - return XFEATURE_MASK_INDEPENDENT & ~XFEATURE_MASK_LBR; + return fpu_kernel_cfg.independent_features & ~XFEATURE_MASK_LBR; - return XFEATURE_MASK_INDEPENDENT; + return fpu_kernel_cfg.independent_features; } /* XSAVE/XRSTOR wrapper functions */ diff --git a/arch/x86/kernel/fred.c b/arch/x86/kernel/fred.c index 4bcd8791ad96..8d32c3f48abc 100644 --- a/arch/x86/kernel/fred.c +++ b/arch/x86/kernel/fred.c @@ -21,17 +21,53 @@ #define FRED_STKLVL(vector, lvl) ((lvl) << (2 * (vector))) +DEFINE_PER_CPU(unsigned long, fred_rsp0); +EXPORT_PER_CPU_SYMBOL(fred_rsp0); + void cpu_init_fred_exceptions(void) { /* When FRED is enabled by default, remove this log message */ pr_info("Initialize FRED on CPU%d\n", smp_processor_id()); + /* + * If a kernel event is delivered before a CPU goes to user level for + * the first time, its SS is NULL thus NULL is pushed into the SS field + * of the FRED stack frame. But before ERETS is executed, the CPU may + * context switch to another task and go to user level. Then when the + * CPU comes back to kernel mode, SS is changed to __KERNEL_DS. Later + * when ERETS is executed to return from the kernel event handler, a #GP + * fault is generated because SS doesn't match the SS saved in the FRED + * stack frame. + * + * Initialize SS to __KERNEL_DS when enabling FRED to avoid such #GPs. + */ + loadsegment(ss, __KERNEL_DS); + wrmsrl(MSR_IA32_FRED_CONFIG, /* Reserve for CALL emulation */ FRED_CONFIG_REDZONE | FRED_CONFIG_INT_STKLVL(0) | FRED_CONFIG_ENTRYPOINT(asm_fred_entrypoint_user)); + wrmsrl(MSR_IA32_FRED_STKLVLS, 0); + wrmsrl(MSR_IA32_FRED_RSP0, 0); + wrmsrl(MSR_IA32_FRED_RSP1, 0); + wrmsrl(MSR_IA32_FRED_RSP2, 0); + wrmsrl(MSR_IA32_FRED_RSP3, 0); + + /* Enable FRED */ + cr4_set_bits(X86_CR4_FRED); + /* Any further IDT use is a bug */ + idt_invalidate(); + + /* Use int $0x80 for 32-bit system calls in FRED mode */ + setup_clear_cpu_cap(X86_FEATURE_SYSENTER32); + setup_clear_cpu_cap(X86_FEATURE_SYSCALL32); +} + +/* Must be called after setup_cpu_entry_areas() */ +void cpu_init_fred_rsps(void) +{ /* * The purpose of separate stacks for NMI, #DB and #MC *in the kernel* * (remember that user space faults are always taken on stack level 0) @@ -47,13 +83,4 @@ void cpu_init_fred_exceptions(void) wrmsrl(MSR_IA32_FRED_RSP1, __this_cpu_ist_top_va(DB)); wrmsrl(MSR_IA32_FRED_RSP2, __this_cpu_ist_top_va(NMI)); wrmsrl(MSR_IA32_FRED_RSP3, __this_cpu_ist_top_va(DF)); - - /* Enable FRED */ - cr4_set_bits(X86_CR4_FRED); - /* Any further IDT use is a bug */ - idt_invalidate(); - - /* Use int $0x80 for 32-bit system calls in FRED mode */ - setup_clear_cpu_cap(X86_FEATURE_SYSENTER32); - setup_clear_cpu_cap(X86_FEATURE_SYSCALL32); } diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 8da0e66ca22d..adb09f78edb2 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -647,7 +647,7 @@ void prepare_ftrace_return(unsigned long ip, unsigned long *parent, void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - struct pt_regs *regs = &fregs->regs; + struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs; unsigned long *stack = (unsigned long *)kernel_stack_pointer(regs); prepare_ftrace_return(ip, (unsigned long *)stack, 0); diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index a817ed0724d1..4b9d4557fc94 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -559,10 +559,11 @@ void early_setup_idt(void) */ void __head startup_64_setup_gdt_idt(void) { + struct desc_struct *gdt = (void *)(__force unsigned long)init_per_cpu_var(gdt_page.gdt); void *handler = NULL; struct desc_ptr startup_gdt_descr = { - .address = (unsigned long)&RIP_REL_REF(init_per_cpu_var(gdt_page.gdt)), + .address = (unsigned long)&RIP_REL_REF(*gdt), .size = GDT_SIZE - 1, }; diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 330922b328bf..56163e2124cf 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -32,13 +32,6 @@ * We are not able to switch in one step to the final KERNEL ADDRESS SPACE * because we need identity-mapped pages. */ -#define l4_index(x) (((x) >> 39) & 511) -#define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) - -L4_PAGE_OFFSET = l4_index(__PAGE_OFFSET_BASE_L4) -L4_START_KERNEL = l4_index(__START_KERNEL_map) - -L3_START_KERNEL = pud_index(__START_KERNEL_map) __HEAD .code64 @@ -84,6 +77,7 @@ SYM_CODE_START_NOALIGN(startup_64) lretq .Lon_kernel_cs: + ANNOTATE_NOENDBR UNWIND_HINT_END_OF_STACK #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -577,9 +571,6 @@ SYM_CODE_START_NOALIGN(vc_no_ghcb) SYM_CODE_END(vc_no_ghcb) #endif -#define SYM_DATA_START_PAGE_ALIGNED(name) \ - SYM_START(name, SYM_L_GLOBAL, .balign PAGE_SIZE) - #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION /* * Each PGD needs to be 8k long and 8k aligned. We do not @@ -601,14 +592,6 @@ SYM_CODE_END(vc_no_ghcb) #define PTI_USER_PGD_FILL 0 #endif -/* Automate the creation of 1 to 1 mapping pmd entries */ -#define PMDS(START, PERM, COUNT) \ - i = 0 ; \ - .rept (COUNT) ; \ - .quad (START) + (i << PMD_SHIFT) + (PERM) ; \ - i = i + 1 ; \ - .endr - __INITDATA .balign 4 @@ -708,8 +691,6 @@ SYM_DATA_START_PAGE_ALIGNED(level1_fixmap_pgt) .endr SYM_DATA_END(level1_fixmap_pgt) -#undef PMDS - .data .align 16 diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 2b7999a1a50a..80e262bb627f 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -8,6 +8,7 @@ #include <linux/timex.h> #include <linux/i8253.h> +#include <asm/hypervisor.h> #include <asm/apic.h> #include <asm/hpet.h> #include <asm/time.h> @@ -39,9 +40,15 @@ static bool __init use_pit(void) bool __init pit_timer_init(void) { - if (!use_pit()) + if (!use_pit()) { + /* + * Don't just ignore the PIT. Ensure it's stopped, because + * VMMs otherwise steal CPU time just to pointlessly waggle + * the (masked) IRQ. + */ + clockevent_i8253_disable(); return false; - + } clockevent_i8253_init(true); global_clock_event = &i8253_clockevent; return true; diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c index df337860612d..cd8ed1edbf9e 100644 --- a/arch/x86/kernel/jailhouse.c +++ b/arch/x86/kernel/jailhouse.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/reboot.h> #include <linux/serial_8250.h> +#include <linux/acpi.h> #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/acpi.h> diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c index 15af7e98e161..2be55ec3f392 100644 --- a/arch/x86/kernel/kprobes/ftrace.c +++ b/arch/x86/kernel/kprobes/ftrace.c @@ -9,6 +9,7 @@ #include <linux/hardirq.h> #include <linux/preempt.h> #include <linux/ftrace.h> +#include <asm/text-patching.h> #include "common.h" @@ -36,23 +37,25 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, if (kprobe_running()) { kprobes_inc_nmissed_count(p); } else { - unsigned long orig_ip = regs->ip; + unsigned long orig_ip = instruction_pointer(regs); + /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ - regs->ip = ip + sizeof(kprobe_opcode_t); + instruction_pointer_set(regs, ip + INT3_INSN_SIZE); __this_cpu_write(current_kprobe, p); kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (!p->pre_handler || !p->pre_handler(p, regs)) { - /* - * Emulate singlestep (and also recover regs->ip) - * as if there is a 5byte nop - */ - regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE; if (unlikely(p->post_handler)) { + /* + * Emulate singlestep (and also recover regs->ip) + * as if there is a 5byte nop + */ + instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE); kcb->kprobe_status = KPROBE_HIT_SSDONE; p->post_handler(p, regs, 0); } - regs->ip = orig_ip; + /* Recover IP address */ + instruction_pointer_set(regs, orig_ip); } /* * If pre_handler returns !0, it changes regs->ip. We have to diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 263f8aed4e2c..21e9e4845354 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -37,6 +37,7 @@ #include <asm/apic.h> #include <asm/apicdef.h> #include <asm/hypervisor.h> +#include <asm/mtrr.h> #include <asm/tlb.h> #include <asm/cpuidle_haltpoll.h> #include <asm/ptrace.h> @@ -980,6 +981,9 @@ static void __init kvm_init_platform(void) } kvmclock_init(); x86_platform.apic_post_init = kvm_apic_init; + + /* Set WB as the default cache mode for SEV-SNP and TDX */ + mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK); } #if defined(CONFIG_AMD_MEM_ENCRYPT) diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index cc0f7f70b17b..9c9ac606893e 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -28,6 +28,7 @@ #include <asm/setup.h> #include <asm/set_memory.h> #include <asm/cpu.h> +#include <asm/efi.h> #ifdef CONFIG_ACPI /* @@ -87,6 +88,8 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p) { #ifdef CONFIG_EFI unsigned long mstart, mend; + void *kaddr; + int ret; if (!efi_enabled(EFI_BOOT)) return 0; @@ -102,6 +105,30 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p) if (!mstart) return 0; + ret = kernel_ident_mapping_init(info, level4p, mstart, mend); + if (ret) + return ret; + + kaddr = memremap(mstart, mend - mstart, MEMREMAP_WB); + if (!kaddr) { + pr_err("Could not map UEFI system table\n"); + return -ENOMEM; + } + + mstart = efi_config_table; + + if (efi_enabled(EFI_64BIT)) { + efi_system_table_64_t *stbl = (efi_system_table_64_t *)kaddr; + + mend = mstart + sizeof(efi_config_table_64_t) * stbl->nr_tables; + } else { + efi_system_table_32_t *stbl = (efi_system_table_32_t *)kaddr; + + mend = mstart + sizeof(efi_config_table_32_t) * stbl->nr_tables; + } + + memunmap(kaddr); + return kernel_ident_mapping_init(info, level4p, mstart, mend); #endif return 0; diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index c94dec6a1834..1f54eedc3015 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -9,6 +9,7 @@ #include <linux/pci.h> #include <linux/dmi.h> #include <linux/range.h> +#include <linux/acpi.h> #include <asm/pci-direct.h> #include <linux/sort.h> diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index e89171b0347a..4a1b1b28abf9 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -68,7 +68,7 @@ static void __init mpc_oem_bus_info(struct mpc_bus *m, char *str) { memcpy(str, m->bustype, 6); str[6] = 0; - apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str); + apic_pr_verbose("Bus #%d is %s\n", m->busid, str); } static void __init MP_bus_info(struct mpc_bus *m) @@ -417,7 +417,7 @@ static unsigned long __init get_mpc_size(unsigned long physptr) mpc = early_memremap(physptr, PAGE_SIZE); size = mpc->length; early_memunmap(mpc, PAGE_SIZE); - apic_printk(APIC_VERBOSE, " mpc: %lx-%lx\n", physptr, physptr + size); + apic_pr_verbose(" mpc: %lx-%lx\n", physptr, physptr + size); return size; } @@ -560,8 +560,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) struct mpf_intel *mpf; int ret = 0; - apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n", - base, base + length - 1); + apic_pr_verbose("Scan for SMP in [mem %#010lx-%#010lx]\n", base, base + length - 1); BUILD_BUG_ON(sizeof(*mpf) != 16); while (length > 0) { @@ -683,13 +682,13 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) { int i; - apic_printk(APIC_VERBOSE, "OLD "); + apic_pr_verbose("OLD "); print_mp_irq_info(m); i = get_MP_intsrc_index(m); if (i > 0) { memcpy(m, &mp_irqs[i], sizeof(*m)); - apic_printk(APIC_VERBOSE, "NEW "); + apic_pr_verbose("NEW "); print_mp_irq_info(&mp_irqs[i]); return; } @@ -772,7 +771,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc, continue; if (nr_m_spare > 0) { - apic_printk(APIC_VERBOSE, "*NEW* found\n"); + apic_pr_verbose("*NEW* found\n"); nr_m_spare--; memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i])); m_spare[nr_m_spare] = NULL; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 6d3d20e3e43a..226472332a70 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -798,6 +798,32 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr) #define LAM_U57_BITS 6 +static void enable_lam_func(void *__mm) +{ + struct mm_struct *mm = __mm; + unsigned long lam; + + if (this_cpu_read(cpu_tlbstate.loaded_mm) == mm) { + lam = mm_lam_cr3_mask(mm); + write_cr3(__read_cr3() | lam); + cpu_tlbstate_update_lam(lam, mm_untag_mask(mm)); + } +} + +static void mm_enable_lam(struct mm_struct *mm) +{ + mm->context.lam_cr3_mask = X86_CR3_LAM_U57; + mm->context.untag_mask = ~GENMASK(62, 57); + + /* + * Even though the process must still be single-threaded at this + * point, kernel threads may be using the mm. IPI those kernel + * threads if they exist. + */ + on_each_cpu_mask(mm_cpumask(mm), enable_lam_func, mm, true); + set_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags); +} + static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits) { if (!cpu_feature_enabled(X86_FEATURE_LAM)) @@ -814,25 +840,21 @@ static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits) if (mmap_write_lock_killable(mm)) return -EINTR; + /* + * MM_CONTEXT_LOCK_LAM is set on clone. Prevent LAM from + * being enabled unless the process is single threaded: + */ if (test_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags)) { mmap_write_unlock(mm); return -EBUSY; } - if (!nr_bits) { - mmap_write_unlock(mm); - return -EINVAL; - } else if (nr_bits <= LAM_U57_BITS) { - mm->context.lam_cr3_mask = X86_CR3_LAM_U57; - mm->context.untag_mask = ~GENMASK(62, 57); - } else { + if (!nr_bits || nr_bits > LAM_U57_BITS) { mmap_write_unlock(mm); return -EINVAL; } - write_cr3(__read_cr3() | mm->context.lam_cr3_mask); - set_tlbstate_lam_mode(mm); - set_bit(MM_CONTEXT_LOCK_LAM, &mm->context.flags); + mm_enable_lam(mm); mmap_write_unlock(mm); diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 0e0a4cf6b5eb..615922838c51 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -530,7 +530,7 @@ static inline void kb_wait(void) static inline void nmi_shootdown_cpus_on_restart(void); -#if IS_ENABLED(CONFIG_KVM_INTEL) || IS_ENABLED(CONFIG_KVM_AMD) +#if IS_ENABLED(CONFIG_KVM_X86) /* RCU-protected callback to disable virtualization prior to reboot. */ static cpu_emergency_virt_cb __rcu *cpu_emergency_virt_callback; @@ -600,7 +600,7 @@ static void emergency_reboot_disable_virtualization(void) } #else static void emergency_reboot_disable_virtualization(void) { } -#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */ +#endif /* CONFIG_KVM_X86 */ void __attribute__((weak)) mach_reboot_fixups(void) { diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 042c9a0334e9..e9e88c342f75 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -170,6 +170,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped) wbinvd .Lsme_off: + /* Save the preserve_context to %r11 as swap_pages clobbers %rcx. */ movq %rcx, %r11 call swap_pages @@ -258,7 +259,7 @@ SYM_CODE_END(virtual_mapped) /* Do the copies */ SYM_CODE_START_LOCAL_NOALIGN(swap_pages) UNWIND_HINT_END_OF_STACK - movq %rdi, %rcx /* Put the page_list in %rcx */ + movq %rdi, %rcx /* Put the indirection_page in %rcx */ xorl %edi, %edi xorl %esi, %esi jmp 1f @@ -289,18 +290,21 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages) movq %rcx, %rsi /* For ever source page do a copy */ andq $0xfffffffffffff000, %rsi - movq %rdi, %rdx - movq %rsi, %rax + movq %rdi, %rdx /* Save destination page to %rdx */ + movq %rsi, %rax /* Save source page to %rax */ + /* copy source page to swap page */ movq %r10, %rdi movl $512, %ecx rep ; movsq + /* copy destination page to source page */ movq %rax, %rdi movq %rdx, %rsi movl $512, %ecx rep ; movsq + /* copy swap page to destination page */ movq %rdx, %rdi movq %r10, %rsi movl $512, %ecx diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 6129dc2ba784..f1fea506e20f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1039,7 +1039,12 @@ void __init setup_arch(char **cmdline_p) init_mem_mapping(); - idt_setup_early_pf(); + /* + * init_mem_mapping() relies on the early IDT page fault handling. + * Now either enable FRED or install the real page fault handler + * for 64-bit in the IDT. + */ + cpu_init_replace_early_idt(); /* * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 31b6f5dddfc2..5f441039b572 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -61,6 +61,24 @@ static inline int is_x32_frame(struct ksignal *ksig) } /* + * Enable all pkeys temporarily, so as to ensure that both the current + * execution stack as well as the alternate signal stack are writeable. + * The application can use any of the available pkeys to protect the + * alternate signal stack, and we don't know which one it is, so enable + * all. The PKRU register will be reset to init_pkru later in the flow, + * in fpu__clear_user_states(), and it is the application's responsibility + * to enable the appropriate pkey as the first step in the signal handler + * so that the handler does not segfault. + */ +static inline u32 sig_prepare_pkru(void) +{ + u32 orig_pkru = read_pkru(); + + write_pkru(0); + return orig_pkru; +} + +/* * Set up a signal frame. */ @@ -84,6 +102,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size, unsigned long math_size = 0; unsigned long sp = regs->sp; unsigned long buf_fx = 0; + u32 pkru; /* redzone */ if (!ia32_frame) @@ -138,9 +157,17 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size, return (void __user *)-1L; } + /* Update PKRU to enable access to the alternate signal stack. */ + pkru = sig_prepare_pkru(); /* save i387 and extended state */ - if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size)) + if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru)) { + /* + * Restore PKRU to the original, user-defined value; disable + * extra pkeys enabled for the alternate signal stack, if any. + */ + write_pkru(pkru); return (void __user *)-1L; + } return (void __user *)sp; } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 8a94053c5444..ee9453891901 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -260,13 +260,13 @@ SYSCALL_DEFINE0(rt_sigreturn) set_current_blocked(&set); - if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags)) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; - if (restore_signal_shadow_stack()) + if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags)) goto badframe; - if (restore_altstack(&frame->uc.uc_stack)) + if (restore_signal_shadow_stack()) goto badframe; return regs->ax; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0c35207320cb..b5a8f0891135 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -60,6 +60,7 @@ #include <linux/stackprotector.h> #include <linux/cpuhotplug.h> #include <linux/mc146818rtc.h> +#include <linux/acpi.h> #include <asm/acpi.h> #include <asm/cacheinfo.h> @@ -246,7 +247,7 @@ static void notrace start_secondary(void *unused) __flush_tlb_all(); } - cpu_init_exception_handling(); + cpu_init_exception_handling(false); /* * Load the microcode before reaching the AP alive synchronization @@ -496,8 +497,9 @@ static int x86_cluster_flags(void) static int x86_die_flags(void) { - if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) - return x86_sched_itmt_flags(); + if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU) || + cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) + return x86_sched_itmt_flags(); return 0; } diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 01d7cd85ef97..87f8c9a71c49 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -121,7 +121,7 @@ static inline unsigned long stack_guard_placement(vm_flags_t vm_flags) } unsigned long -arch_get_unmapped_area_vmflags(struct file *filp, unsigned long addr, unsigned long len, +arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) { struct mm_struct *mm = current->mm; @@ -158,7 +158,7 @@ arch_get_unmapped_area_vmflags(struct file *filp, unsigned long addr, unsigned l } unsigned long -arch_get_unmapped_area_topdown_vmflags(struct file *filp, unsigned long addr0, +arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) { @@ -228,20 +228,5 @@ bottomup: * can happen with large stack limits and large mmap() * allocations. */ - return arch_get_unmapped_area(filp, addr0, len, pgoff, flags); -} - -unsigned long -arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - return arch_get_unmapped_area_vmflags(filp, addr, len, pgoff, flags, 0); -} - -unsigned long -arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) -{ - return arch_get_unmapped_area_topdown_vmflags(filp, addr, len, pgoff, flags, 0); + return arch_get_unmapped_area(filp, addr0, len, pgoff, flags, 0); } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 4fa0b17e5043..2dbadf347b5f 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -42,6 +42,7 @@ #include <linux/hardirq.h> #include <linux/atomic.h> #include <linux/iommu.h> +#include <linux/ubsan.h> #include <asm/stacktrace.h> #include <asm/processor.h> @@ -91,6 +92,47 @@ __always_inline int is_valid_bugaddr(unsigned long addr) return *(unsigned short *)addr == INSN_UD2; } +/* + * Check for UD1 or UD2, accounting for Address Size Override Prefixes. + * If it's a UD1, get the ModRM byte to pass along to UBSan. + */ +__always_inline int decode_bug(unsigned long addr, u32 *imm) +{ + u8 v; + + if (addr < TASK_SIZE_MAX) + return BUG_NONE; + + v = *(u8 *)(addr++); + if (v == INSN_ASOP) + v = *(u8 *)(addr++); + if (v != OPCODE_ESCAPE) + return BUG_NONE; + + v = *(u8 *)(addr++); + if (v == SECOND_BYTE_OPCODE_UD2) + return BUG_UD2; + + if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1) + return BUG_NONE; + + /* Retrieve the immediate (type value) for the UBSAN UD1 */ + v = *(u8 *)(addr++); + if (X86_MODRM_RM(v) == 4) + addr++; + + *imm = 0; + if (X86_MODRM_MOD(v) == 1) + *imm = *(u8 *)addr; + else if (X86_MODRM_MOD(v) == 2) + *imm = *(u32 *)addr; + else + WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v)); + + return BUG_UD1; +} + + static nokprobe_inline int do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, struct pt_regs *regs, long error_code) @@ -216,14 +258,11 @@ static inline void handle_invalid_op(struct pt_regs *regs) static noinstr bool handle_bug(struct pt_regs *regs) { bool handled = false; + int ud_type; + u32 imm; - /* - * Normally @regs are unpoisoned by irqentry_enter(), but handle_bug() - * is a rare case that uses @regs without passing them to - * irqentry_enter(). - */ - kmsan_unpoison_entry_regs(regs); - if (!is_valid_bugaddr(regs->ip)) + ud_type = decode_bug(regs->ip, &imm); + if (ud_type == BUG_NONE) return handled; /* @@ -231,15 +270,25 @@ static noinstr bool handle_bug(struct pt_regs *regs) */ instrumentation_begin(); /* + * Normally @regs are unpoisoned by irqentry_enter(), but handle_bug() + * is a rare case that uses @regs without passing them to + * irqentry_enter(). + */ + kmsan_unpoison_entry_regs(regs); + /* * Since we're emulating a CALL with exceptions, restore the interrupt * state to what it was at the exception site. */ if (regs->flags & X86_EFLAGS_IF) raw_local_irq_enable(); - if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || - handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { - regs->ip += LEN_UD2; - handled = true; + if (ud_type == BUG_UD2) { + if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || + handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { + regs->ip += LEN_UD2; + handled = true; + } + } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { + pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip); } if (regs->flags & X86_EFLAGS_IF) raw_local_irq_disable(); @@ -1402,34 +1451,8 @@ DEFINE_IDTENTRY_SW(iret_error) } #endif -/* Do not enable FRED by default yet. */ -static bool enable_fred __ro_after_init = false; - -#ifdef CONFIG_X86_FRED -static int __init fred_setup(char *str) -{ - if (!str) - return -EINVAL; - - if (!cpu_feature_enabled(X86_FEATURE_FRED)) - return 0; - - if (!strcmp(str, "on")) - enable_fred = true; - else if (!strcmp(str, "off")) - enable_fred = false; - else - pr_warn("invalid FRED option: 'fred=%s'\n", str); - return 0; -} -early_param("fred", fred_setup); -#endif - void __init trap_init(void) { - if (cpu_feature_enabled(X86_FEATURE_FRED) && !enable_fred) - setup_clear_cpu_cap(X86_FEATURE_FRED); - /* Init cpu_entry_area before IST entries are set up */ setup_cpu_entry_areas(); @@ -1437,7 +1460,7 @@ void __init trap_init(void) sev_es_init_vc_handling(); /* Initialize TSS before setting up traps so ISTs work */ - cpu_init_exception_handling(); + cpu_init_exception_handling(true); /* Setup traps as cpu_init() might #GP */ if (!cpu_feature_enabled(X86_FEATURE_FRED)) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index d4462fb26299..67aeaba4ba9c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -28,6 +28,7 @@ #include <asm/apic.h> #include <asm/cpu_device_id.h> #include <asm/i8259.h> +#include <asm/topology.h> #include <asm/uv/uv.h> unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ @@ -173,10 +174,11 @@ static void __set_cyc2ns_scale(unsigned long khz, int cpu, unsigned long long ts c2n = per_cpu_ptr(&cyc2ns, cpu); - raw_write_seqcount_latch(&c2n->seq); + write_seqcount_latch_begin(&c2n->seq); c2n->data[0] = data; - raw_write_seqcount_latch(&c2n->seq); + write_seqcount_latch(&c2n->seq); c2n->data[1] = data; + write_seqcount_latch_end(&c2n->seq); } static void set_cyc2ns_scale(unsigned long khz, int cpu, unsigned long long tsc_now) @@ -1253,15 +1255,12 @@ static void __init check_system_tsc_reliable(void) * - TSC which does not stop in C-States * - the TSC_ADJUST register which allows to detect even minimal * modifications - * - not more than two sockets. As the number of sockets cannot be - * evaluated at the early boot stage where this has to be - * invoked, check the number of online memory nodes as a - * fallback solution which is an reasonable estimate. + * - not more than four packages */ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && boot_cpu_has(X86_FEATURE_TSC_ADJUST) && - nr_online_nodes <= 4) + topology_max_packages() <= 4) tsc_disable_clocksource_watchdog(); } @@ -1290,7 +1289,7 @@ int unsynchronized_tsc(void) */ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { /* assume multi socket systems are not synchronized: */ - if (num_possible_cpus() > 1) + if (topology_max_packages() > 1) return 1; } diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index d00c28aaa5be..d4705a348a80 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -723,7 +723,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, state->sp = task->thread.sp + sizeof(*frame); state->bp = READ_ONCE_NOCHECK(frame->bp); state->ip = READ_ONCE_NOCHECK(frame->ret_addr); - state->signal = (void *)state->ip == ret_from_fork; + state->signal = (void *)state->ip == ret_from_fork_asm; } if (get_stack_info((unsigned long *)state->sp, state->task, diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 6e73403e874f..68efd8cd8bf1 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -193,29 +193,6 @@ SECTIONS ORC_UNWIND_TABLE - . = ALIGN(PAGE_SIZE); - __vvar_page = .; - - .vvar : AT(ADDR(.vvar) - LOAD_OFFSET) { - /* work around gold bug 13023 */ - __vvar_beginning_hack = .; - - /* Place all vvars at the offsets in asm/vvar.h. */ -#define EMIT_VVAR(name, offset) \ - . = __vvar_beginning_hack + offset; \ - *(.vvar_ ## name) -#include <asm/vvar.h> -#undef EMIT_VVAR - - /* - * Pad the rest of the page with zeros. Otherwise the loader - * can leave garbage here. - */ - . = __vvar_beginning_hack + PAGE_SIZE; - } :data - - . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); - /* Init code and data - will be freed after init */ . = ALIGN(PAGE_SIZE); .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) { @@ -357,8 +334,8 @@ SECTIONS PERCPU_SECTION(INTERNODE_CACHE_BYTES) #endif - RUNTIME_CONST(shift, d_hash_shift) - RUNTIME_CONST(ptr, dentry_hashtable) + RUNTIME_CONST_VARIABLES + RUNTIME_CONST(ptr, USER_PTR_MAX) . = ALIGN(PAGE_SIZE); @@ -491,6 +468,9 @@ SECTIONS . = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE), "kernel image bigger than KERNEL_IMAGE_SIZE"); +/* needed for Clang - see arch/x86/entry/entry.S */ +PROVIDE(__ref_stack_chk_guard = __stack_chk_guard); + #ifdef CONFIG_X86_64 /* * Per-cpu symbols which need to be offset from __per_cpu_load @@ -528,3 +508,22 @@ INIT_PER_CPU(irq_stack_backing_store); #endif #endif /* CONFIG_X86_64 */ + +/* + * The symbols below are referenced using relative relocations in the + * respective ELF notes. This produces build time constants that the + * linker will never mark as relocatable. (Using just ABSOLUTE() is not + * sufficient for that). + */ +#ifdef CONFIG_XEN +#ifdef CONFIG_XEN_PV +xen_elfnote_entry_value = + ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen); +#endif +xen_elfnote_hypercall_page_value = + ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page); +#endif +#ifdef CONFIG_PVH +xen_elfnote_phys32_entry_value = + ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET); +#endif diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 82b128d3f309..0a2bbd674a6d 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -8,6 +8,7 @@ #include <linux/ioport.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/acpi.h> #include <asm/bios_ebda.h> diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 472a1537b7a9..f09f13c01c6b 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -17,9 +17,8 @@ menuconfig VIRTUALIZATION if VIRTUALIZATION -config KVM - tristate "Kernel-based Virtual Machine (KVM) support" - depends on HIGH_RES_TIMERS +config KVM_X86 + def_tristate KVM if KVM_INTEL || KVM_AMD depends on X86_LOCAL_APIC select KVM_COMMON select KVM_GENERIC_MMU_NOTIFIER @@ -45,7 +44,11 @@ config KVM select HAVE_KVM_PM_NOTIFIER if PM select KVM_GENERIC_HARDWARE_ENABLING select KVM_GENERIC_PRE_FAULT_MEMORY + select KVM_GENERIC_PRIVATE_MEM if KVM_SW_PROTECTED_VM select KVM_WERROR if WERROR + +config KVM + tristate "Kernel-based Virtual Machine (KVM) support" help Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent @@ -78,7 +81,6 @@ config KVM_SW_PROTECTED_VM bool "Enable support for KVM software-protected VMs" depends on EXPERT depends on KVM && X86_64 - select KVM_GENERIC_PRIVATE_MEM help Enable support for KVM software-protected VMs. Currently, software- protected VMs are purely a development and testing vehicle for @@ -144,8 +146,10 @@ config KVM_AMD_SEV select HAVE_KVM_ARCH_GMEM_PREPARE select HAVE_KVM_ARCH_GMEM_INVALIDATE help - Provides support for launching Encrypted VMs (SEV) and Encrypted VMs - with Encrypted State (SEV-ES) on AMD processors. + Provides support for launching encrypted VMs which use Secure + Encrypted Virtualization (SEV), Secure Encrypted Virtualization with + Encrypted State (SEV-ES), and Secure Encrypted Virtualization with + Secure Nested Paging (SEV-SNP) technologies on AMD processors. config KVM_SMM bool "System Management Mode emulation" diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index 5494669a055a..f9dddb8cb466 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -32,7 +32,7 @@ kvm-intel-y += vmx/vmx_onhyperv.o vmx/hyperv_evmcs.o kvm-amd-y += svm/svm_onhyperv.o endif -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM_X86) += kvm.o obj-$(CONFIG_KVM_INTEL) += kvm-intel.o obj-$(CONFIG_KVM_AMD) += kvm-amd.o diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 2617be544480..41786b834b16 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -705,7 +705,7 @@ void kvm_set_cpu_caps(void) kvm_cpu_cap_init_kvm_defined(CPUID_7_1_EDX, F(AVX_VNNI_INT8) | F(AVX_NE_CONVERT) | F(PREFETCHITI) | - F(AMX_COMPLEX) + F(AMX_COMPLEX) | F(AVX10) ); kvm_cpu_cap_init_kvm_defined(CPUID_7_2_EDX, @@ -721,6 +721,10 @@ void kvm_set_cpu_caps(void) SF(SGX1) | SF(SGX2) | SF(SGX_EDECCSSA) ); + kvm_cpu_cap_init_kvm_defined(CPUID_24_0_EBX, + F(AVX10_128) | F(AVX10_256) | F(AVX10_512) + ); + kvm_cpu_cap_mask(CPUID_8000_0001_ECX, F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ | F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) | @@ -949,7 +953,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) switch (function) { case 0: /* Limited to the highest leaf implemented in KVM. */ - entry->eax = min(entry->eax, 0x1fU); + entry->eax = min(entry->eax, 0x24U); break; case 1: cpuid_entry_override(entry, CPUID_1_EDX); @@ -1174,6 +1178,28 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) break; } break; + case 0x24: { + u8 avx10_version; + + if (!kvm_cpu_cap_has(X86_FEATURE_AVX10)) { + entry->eax = entry->ebx = entry->ecx = entry->edx = 0; + break; + } + + /* + * The AVX10 version is encoded in EBX[7:0]. Note, the version + * is guaranteed to be >=1 if AVX10 is supported. Note #2, the + * version needs to be captured before overriding EBX features! + */ + avx10_version = min_t(u8, entry->ebx & 0xff, 1); + cpuid_entry_override(entry, CPUID_24_0_EBX); + entry->ebx |= avx10_version; + + entry->eax = 0; + entry->ecx = 0; + entry->edx = 0; + break; + } case KVM_CPUID_SIGNATURE: { const u32 *sigptr = (const u32 *)KVM_SIGNATURE; entry->eax = KVM_CPUID_FEATURES; diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index 3d7eb11d0e45..63f66c51975a 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); * Read pending interrupt(from non-APIC source) * vector and intack. */ -static int kvm_cpu_get_extint(struct kvm_vcpu *v) +int kvm_cpu_get_extint(struct kvm_vcpu *v) { if (!kvm_cpu_has_extint(v)) { WARN_ON(!lapic_in_kernel(v)); @@ -131,6 +131,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) } else return kvm_pic_read_irq(v->kvm); /* PIC */ } +EXPORT_SYMBOL_GPL(kvm_cpu_get_extint); /* * Read pending interrupt vector and intack. @@ -141,9 +142,12 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) if (vector != -1) return vector; /* PIC */ - return kvm_get_apic_interrupt(v); /* APIC */ + vector = kvm_apic_has_interrupt(v); /* APIC */ + if (vector != -1) + kvm_apic_ack_interrupt(v, vector); + + return vector; } -EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt); void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu) { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 5bb481aefcbc..95c6beb8ce27 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1944,7 +1944,7 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic) u64 ns = 0; ktime_t expire; struct kvm_vcpu *vcpu = apic->vcpu; - unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz; + u32 this_tsc_khz = vcpu->arch.virtual_tsc_khz; unsigned long flags; ktime_t now; @@ -2453,6 +2453,43 @@ void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); +#define X2APIC_ICR_RESERVED_BITS (GENMASK_ULL(31, 20) | GENMASK_ULL(17, 16) | BIT(13)) + +int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data) +{ + if (data & X2APIC_ICR_RESERVED_BITS) + return 1; + + /* + * The BUSY bit is reserved on both Intel and AMD in x2APIC mode, but + * only AMD requires it to be zero, Intel essentially just ignores the + * bit. And if IPI virtualization (Intel) or x2AVIC (AMD) is enabled, + * the CPU performs the reserved bits checks, i.e. the underlying CPU + * behavior will "win". Arbitrarily clear the BUSY bit, as there is no + * sane way to provide consistent behavior with respect to hardware. + */ + data &= ~APIC_ICR_BUSY; + + kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32)); + if (kvm_x86_ops.x2apic_icr_is_split) { + kvm_lapic_set_reg(apic, APIC_ICR, data); + kvm_lapic_set_reg(apic, APIC_ICR2, data >> 32); + } else { + kvm_lapic_set_reg64(apic, APIC_ICR, data); + } + trace_kvm_apic_write(APIC_ICR, data); + return 0; +} + +static u64 kvm_x2apic_icr_read(struct kvm_lapic *apic) +{ + if (kvm_x86_ops.x2apic_icr_is_split) + return (u64)kvm_lapic_get_reg(apic, APIC_ICR) | + (u64)kvm_lapic_get_reg(apic, APIC_ICR2) << 32; + + return kvm_lapic_get_reg64(apic, APIC_ICR); +} + /* emulate APIC access in a trap manner */ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) { @@ -2470,7 +2507,7 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) * maybe-unecessary write, and both are in the noise anyways. */ if (apic_x2apic_mode(apic) && offset == APIC_ICR) - kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR)); + WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_x2apic_icr_read(apic))); else kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset)); } @@ -2592,19 +2629,26 @@ void kvm_apic_update_apicv(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; - if (apic->apicv_active) { - /* irr_pending is always true when apicv is activated. */ - apic->irr_pending = true; + /* + * When APICv is enabled, KVM must always search the IRR for a pending + * IRQ, as other vCPUs and devices can set IRR bits even if the vCPU + * isn't running. If APICv is disabled, KVM _should_ search the IRR + * for a pending IRQ. But KVM currently doesn't ensure *all* hardware, + * e.g. CPUs and IOMMUs, has seen the change in state, i.e. searching + * the IRR at this time could race with IRQ delivery from hardware that + * still sees APICv as being enabled. + * + * FIXME: Ensure other vCPUs and devices observe the change in APICv + * state prior to updating KVM's metadata caches, so that KVM + * can safely search the IRR and set irr_pending accordingly. + */ + apic->irr_pending = true; + + if (apic->apicv_active) apic->isr_count = 1; - } else { - /* - * Don't clear irr_pending, searching the IRR can race with - * updates from the CPU as APICv is still active from hardware's - * perspective. The flag will be cleared as appropriate when - * KVM injects the interrupt. - */ + else apic->isr_count = count_vectors(apic->regs + APIC_ISR); - } + apic->highest_isr_cache = -1; } @@ -2922,14 +2966,13 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu) } } -int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) +void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector) { - int vector = kvm_apic_has_interrupt(vcpu); struct kvm_lapic *apic = vcpu->arch.apic; u32 ppr; - if (vector == -1) - return -1; + if (WARN_ON_ONCE(vector < 0 || !apic)) + return; /* * We get here even with APIC virtualization enabled, if doing @@ -2957,8 +3000,8 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) __apic_update_ppr(apic, &ppr); } - return vector; } +EXPORT_SYMBOL_GPL(kvm_apic_ack_interrupt); static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s, bool set) @@ -2990,18 +3033,22 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu, /* * In x2APIC mode, the LDR is fixed and based on the id. And - * ICR is internally a single 64-bit register, but needs to be - * split to ICR+ICR2 in userspace for backwards compatibility. + * if the ICR is _not_ split, ICR is internally a single 64-bit + * register, but needs to be split to ICR+ICR2 in userspace for + * backwards compatibility. */ - if (set) { + if (set) *ldr = kvm_apic_calc_x2apic_ldr(x2apic_id); - icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | - (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; - __kvm_lapic_set_reg64(s->regs, APIC_ICR, icr); - } else { - icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR); - __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32); + if (!kvm_x86_ops.x2apic_icr_is_split) { + if (set) { + icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) | + (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32; + __kvm_lapic_set_reg64(s->regs, APIC_ICR, icr); + } else { + icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR); + __kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32); + } } } @@ -3194,22 +3241,12 @@ int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) return 0; } -int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data) -{ - data &= ~APIC_ICR_BUSY; - - kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32)); - kvm_lapic_set_reg64(apic, APIC_ICR, data); - trace_kvm_apic_write(APIC_ICR, data); - return 0; -} - static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data) { u32 low; if (reg == APIC_ICR) { - *data = kvm_lapic_get_reg64(apic, APIC_ICR); + *data = kvm_x2apic_icr_read(apic); return 0; } diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 7ef8ae73e82d..1b8ef9856422 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -88,15 +88,14 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu); void kvm_free_lapic(struct kvm_vcpu *vcpu); int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu); +void kvm_apic_ack_interrupt(struct kvm_vcpu *vcpu, int vector); int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu); -int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu); int kvm_apic_accept_events(struct kvm_vcpu *vcpu); void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event); u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu); void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8); void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu); void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value); -u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); void kvm_recalculate_apic_map(struct kvm *kvm); void kvm_apic_set_version(struct kvm_vcpu *vcpu); void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 4341e0e28571..9dc5dd43ae7f 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -223,8 +223,6 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, bool kvm_mmu_may_ignore_guest_pat(void); -int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu); - int kvm_mmu_post_init_vm(struct kvm *kvm); void kvm_mmu_pre_destroy_vm(struct kvm *kvm); diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 928cf84778b0..8e853a5fc867 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -614,32 +614,6 @@ static u64 mmu_spte_get_lockless(u64 *sptep) return __get_spte_lockless(sptep); } -/* Returns the Accessed status of the PTE and resets it at the same time. */ -static bool mmu_spte_age(u64 *sptep) -{ - u64 spte = mmu_spte_get_lockless(sptep); - - if (!is_accessed_spte(spte)) - return false; - - if (spte_ad_enabled(spte)) { - clear_bit((ffs(shadow_accessed_mask) - 1), - (unsigned long *)sptep); - } else { - /* - * Capture the dirty status of the page, so that it doesn't get - * lost when the SPTE is marked for access tracking. - */ - if (is_writable_pte(spte)) - kvm_set_pfn_dirty(spte_to_pfn(spte)); - - spte = mark_spte_for_access_track(spte); - mmu_spte_update_no_track(sptep, spte); - } - - return true; -} - static inline bool is_tdp_mmu_active(struct kvm_vcpu *vcpu) { return tdp_mmu_enabled && vcpu->arch.mmu->root_role.direct; @@ -938,6 +912,7 @@ static struct kvm_memory_slot *gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu * in this rmap chain. Otherwise, (rmap_head->val & ~1) points to a struct * pte_list_desc containing more mappings. */ +#define KVM_RMAP_MANY BIT(0) /* * Returns the number of pointers in the rmap chain, not counting the new one. @@ -950,16 +925,16 @@ static int pte_list_add(struct kvm_mmu_memory_cache *cache, u64 *spte, if (!rmap_head->val) { rmap_head->val = (unsigned long)spte; - } else if (!(rmap_head->val & 1)) { + } else if (!(rmap_head->val & KVM_RMAP_MANY)) { desc = kvm_mmu_memory_cache_alloc(cache); desc->sptes[0] = (u64 *)rmap_head->val; desc->sptes[1] = spte; desc->spte_count = 2; desc->tail_count = 0; - rmap_head->val = (unsigned long)desc | 1; + rmap_head->val = (unsigned long)desc | KVM_RMAP_MANY; ++count; } else { - desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); count = desc->tail_count + desc->spte_count; /* @@ -968,10 +943,10 @@ static int pte_list_add(struct kvm_mmu_memory_cache *cache, u64 *spte, */ if (desc->spte_count == PTE_LIST_EXT) { desc = kvm_mmu_memory_cache_alloc(cache); - desc->more = (struct pte_list_desc *)(rmap_head->val & ~1ul); + desc->more = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); desc->spte_count = 0; desc->tail_count = count; - rmap_head->val = (unsigned long)desc | 1; + rmap_head->val = (unsigned long)desc | KVM_RMAP_MANY; } desc->sptes[desc->spte_count++] = spte; } @@ -982,7 +957,7 @@ static void pte_list_desc_remove_entry(struct kvm *kvm, struct kvm_rmap_head *rmap_head, struct pte_list_desc *desc, int i) { - struct pte_list_desc *head_desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + struct pte_list_desc *head_desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); int j = head_desc->spte_count - 1; /* @@ -1011,7 +986,7 @@ static void pte_list_desc_remove_entry(struct kvm *kvm, if (!head_desc->more) rmap_head->val = 0; else - rmap_head->val = (unsigned long)head_desc->more | 1; + rmap_head->val = (unsigned long)head_desc->more | KVM_RMAP_MANY; mmu_free_pte_list_desc(head_desc); } @@ -1024,13 +999,13 @@ static void pte_list_remove(struct kvm *kvm, u64 *spte, if (KVM_BUG_ON_DATA_CORRUPTION(!rmap_head->val, kvm)) return; - if (!(rmap_head->val & 1)) { + if (!(rmap_head->val & KVM_RMAP_MANY)) { if (KVM_BUG_ON_DATA_CORRUPTION((u64 *)rmap_head->val != spte, kvm)) return; rmap_head->val = 0; } else { - desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); while (desc) { for (i = 0; i < desc->spte_count; ++i) { if (desc->sptes[i] == spte) { @@ -1063,12 +1038,12 @@ static bool kvm_zap_all_rmap_sptes(struct kvm *kvm, if (!rmap_head->val) return false; - if (!(rmap_head->val & 1)) { + if (!(rmap_head->val & KVM_RMAP_MANY)) { mmu_spte_clear_track_bits(kvm, (u64 *)rmap_head->val); goto out; } - desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); for (; desc; desc = next) { for (i = 0; i < desc->spte_count; i++) @@ -1088,10 +1063,10 @@ unsigned int pte_list_count(struct kvm_rmap_head *rmap_head) if (!rmap_head->val) return 0; - else if (!(rmap_head->val & 1)) + else if (!(rmap_head->val & KVM_RMAP_MANY)) return 1; - desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); return desc->tail_count + desc->spte_count; } @@ -1153,13 +1128,13 @@ static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head, if (!rmap_head->val) return NULL; - if (!(rmap_head->val & 1)) { + if (!(rmap_head->val & KVM_RMAP_MANY)) { iter->desc = NULL; sptep = (u64 *)rmap_head->val; goto out; } - iter->desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); + iter->desc = (struct pte_list_desc *)(rmap_head->val & ~KVM_RMAP_MANY); iter->pos = 0; sptep = iter->desc->sptes[iter->pos]; out: @@ -1307,15 +1282,6 @@ static bool __rmap_clear_dirty(struct kvm *kvm, struct kvm_rmap_head *rmap_head, return flush; } -/** - * kvm_mmu_write_protect_pt_masked - write protect selected PT level pages - * @kvm: kvm instance - * @slot: slot to protect - * @gfn_offset: start of the BITS_PER_LONG pages we care about - * @mask: indicates which pages we should protect - * - * Used when we do not need to care about huge page mappings. - */ static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask) @@ -1339,16 +1305,6 @@ static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, } } -/** - * kvm_mmu_clear_dirty_pt_masked - clear MMU D-bit for PT level pages, or write - * protect the page if the D-bit isn't supported. - * @kvm: kvm instance - * @slot: slot to clear D-bit - * @gfn_offset: start of the BITS_PER_LONG pages we care about - * @mask: indicates which pages we should clear D-bit - * - * Used for PML to re-log the dirty GPAs after userspace querying dirty_bitmap. - */ static void kvm_mmu_clear_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask) @@ -1372,24 +1328,16 @@ static void kvm_mmu_clear_dirty_pt_masked(struct kvm *kvm, } } -/** - * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected - * PT level pages. - * - * It calls kvm_mmu_write_protect_pt_masked to write protect selected pages to - * enable dirty logging for them. - * - * We need to care about huge page mappings: e.g. during dirty logging we may - * have such mappings. - */ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask) { /* - * Huge pages are NOT write protected when we start dirty logging in - * initially-all-set mode; must write protect them here so that they - * are split to 4K on the first write. + * If the slot was assumed to be "initially all dirty", write-protect + * huge pages to ensure they are split to 4KiB on the first write (KVM + * dirty logs at 4KiB granularity). If eager page splitting is enabled, + * immediately try to split huge pages, e.g. so that vCPUs don't get + * saddled with the cost of splitting. * * The gfn_offset is guaranteed to be aligned to 64, but the base_gfn * of memslot has no such restriction, so the range can cross two large @@ -1411,7 +1359,16 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, PG_LEVEL_2M); } - /* Now handle 4K PTEs. */ + /* + * (Re)Enable dirty logging for all 4KiB SPTEs that map the GFNs in + * mask. If PML is enabled and the GFN doesn't need to be write- + * protected for other reasons, e.g. shadow paging, clear the Dirty bit. + * Otherwise clear the Writable bit. + * + * Note that kvm_mmu_clear_dirty_pt_masked() is called whenever PML is + * enabled but it chooses between clearing the Dirty bit and Writeable + * bit based on the context. + */ if (kvm_x86_ops.cpu_dirty_log_size) kvm_mmu_clear_dirty_pt_masked(kvm, slot, gfn_offset, mask); else @@ -1453,16 +1410,10 @@ static bool kvm_vcpu_write_protect_gfn(struct kvm_vcpu *vcpu, u64 gfn) return kvm_mmu_slot_gfn_write_protect(vcpu->kvm, slot, gfn, PG_LEVEL_4K); } -static bool __kvm_zap_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head, - const struct kvm_memory_slot *slot) -{ - return kvm_zap_all_rmap_sptes(kvm, rmap_head); -} - static bool kvm_zap_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head, - struct kvm_memory_slot *slot, gfn_t gfn, int level) + const struct kvm_memory_slot *slot) { - return __kvm_zap_rmap(kvm, rmap_head, slot); + return kvm_zap_all_rmap_sptes(kvm, rmap_head); } struct slot_rmap_walk_iterator { @@ -1513,7 +1464,7 @@ static bool slot_rmap_walk_okay(struct slot_rmap_walk_iterator *iterator) static void slot_rmap_walk_next(struct slot_rmap_walk_iterator *iterator) { while (++iterator->rmap <= iterator->end_rmap) { - iterator->gfn += (1UL << KVM_HPAGE_GFN_SHIFT(iterator->level)); + iterator->gfn += KVM_PAGES_PER_HPAGE(iterator->level); if (iterator->rmap->val) return; @@ -1534,31 +1485,92 @@ static void slot_rmap_walk_next(struct slot_rmap_walk_iterator *iterator) slot_rmap_walk_okay(_iter_); \ slot_rmap_walk_next(_iter_)) -typedef bool (*rmap_handler_t)(struct kvm *kvm, struct kvm_rmap_head *rmap_head, - struct kvm_memory_slot *slot, gfn_t gfn, - int level); +/* The return value indicates if tlb flush on all vcpus is needed. */ +typedef bool (*slot_rmaps_handler) (struct kvm *kvm, + struct kvm_rmap_head *rmap_head, + const struct kvm_memory_slot *slot); -static __always_inline bool kvm_handle_gfn_range(struct kvm *kvm, - struct kvm_gfn_range *range, - rmap_handler_t handler) +static __always_inline bool __walk_slot_rmaps(struct kvm *kvm, + const struct kvm_memory_slot *slot, + slot_rmaps_handler fn, + int start_level, int end_level, + gfn_t start_gfn, gfn_t end_gfn, + bool can_yield, bool flush_on_yield, + bool flush) { struct slot_rmap_walk_iterator iterator; - bool ret = false; - for_each_slot_rmap_range(range->slot, PG_LEVEL_4K, KVM_MAX_HUGEPAGE_LEVEL, - range->start, range->end - 1, &iterator) - ret |= handler(kvm, iterator.rmap, range->slot, iterator.gfn, - iterator.level); + lockdep_assert_held_write(&kvm->mmu_lock); - return ret; + for_each_slot_rmap_range(slot, start_level, end_level, start_gfn, + end_gfn, &iterator) { + if (iterator.rmap) + flush |= fn(kvm, iterator.rmap, slot); + + if (!can_yield) + continue; + + if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) { + if (flush && flush_on_yield) { + kvm_flush_remote_tlbs_range(kvm, start_gfn, + iterator.gfn - start_gfn + 1); + flush = false; + } + cond_resched_rwlock_write(&kvm->mmu_lock); + } + } + + return flush; +} + +static __always_inline bool walk_slot_rmaps(struct kvm *kvm, + const struct kvm_memory_slot *slot, + slot_rmaps_handler fn, + int start_level, int end_level, + bool flush_on_yield) +{ + return __walk_slot_rmaps(kvm, slot, fn, start_level, end_level, + slot->base_gfn, slot->base_gfn + slot->npages - 1, + true, flush_on_yield, false); +} + +static __always_inline bool walk_slot_rmaps_4k(struct kvm *kvm, + const struct kvm_memory_slot *slot, + slot_rmaps_handler fn, + bool flush_on_yield) +{ + return walk_slot_rmaps(kvm, slot, fn, PG_LEVEL_4K, PG_LEVEL_4K, flush_on_yield); +} + +static bool __kvm_rmap_zap_gfn_range(struct kvm *kvm, + const struct kvm_memory_slot *slot, + gfn_t start, gfn_t end, bool can_yield, + bool flush) +{ + return __walk_slot_rmaps(kvm, slot, kvm_zap_rmap, + PG_LEVEL_4K, KVM_MAX_HUGEPAGE_LEVEL, + start, end - 1, can_yield, true, flush); } bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) { bool flush = false; + /* + * To prevent races with vCPUs faulting in a gfn using stale data, + * zapping a gfn range must be protected by mmu_invalidate_in_progress + * (and mmu_invalidate_seq). The only exception is memslot deletion; + * in that case, SRCU synchronization ensures that SPTEs are zapped + * after all vCPUs have unlocked SRCU, guaranteeing that vCPUs see the + * invalid slot. + */ + lockdep_assert_once(kvm->mmu_invalidate_in_progress || + lockdep_is_held(&kvm->slots_lock)); + if (kvm_memslots_have_rmaps(kvm)) - flush = kvm_handle_gfn_range(kvm, range, kvm_zap_rmap); + flush = __kvm_rmap_zap_gfn_range(kvm, range->slot, + range->start, range->end, + range->may_block, flush); if (tdp_mmu_enabled) flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); @@ -1570,31 +1582,6 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) return flush; } -static bool kvm_age_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head, - struct kvm_memory_slot *slot, gfn_t gfn, int level) -{ - u64 *sptep; - struct rmap_iterator iter; - int young = 0; - - for_each_rmap_spte(rmap_head, &iter, sptep) - young |= mmu_spte_age(sptep); - - return young; -} - -static bool kvm_test_age_rmap(struct kvm *kvm, struct kvm_rmap_head *rmap_head, - struct kvm_memory_slot *slot, gfn_t gfn, int level) -{ - u64 *sptep; - struct rmap_iterator iter; - - for_each_rmap_spte(rmap_head, &iter, sptep) - if (is_accessed_spte(*sptep)) - return true; - return false; -} - #define RMAP_RECYCLE_THRESHOLD 1000 static void __rmap_add(struct kvm *kvm, @@ -1629,12 +1616,52 @@ static void rmap_add(struct kvm_vcpu *vcpu, const struct kvm_memory_slot *slot, __rmap_add(vcpu->kvm, cache, slot, spte, gfn, access); } +static bool kvm_rmap_age_gfn_range(struct kvm *kvm, + struct kvm_gfn_range *range, bool test_only) +{ + struct slot_rmap_walk_iterator iterator; + struct rmap_iterator iter; + bool young = false; + u64 *sptep; + + for_each_slot_rmap_range(range->slot, PG_LEVEL_4K, KVM_MAX_HUGEPAGE_LEVEL, + range->start, range->end - 1, &iterator) { + for_each_rmap_spte(iterator.rmap, &iter, sptep) { + u64 spte = *sptep; + + if (!is_accessed_spte(spte)) + continue; + + if (test_only) + return true; + + if (spte_ad_enabled(spte)) { + clear_bit((ffs(shadow_accessed_mask) - 1), + (unsigned long *)sptep); + } else { + /* + * Capture the dirty status of the page, so that + * it doesn't get lost when the SPTE is marked + * for access tracking. + */ + if (is_writable_pte(spte)) + kvm_set_pfn_dirty(spte_to_pfn(spte)); + + spte = mark_spte_for_access_track(spte); + mmu_spte_update_no_track(sptep, spte); + } + young = true; + } + } + return young; +} + bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) { bool young = false; if (kvm_memslots_have_rmaps(kvm)) - young = kvm_handle_gfn_range(kvm, range, kvm_age_rmap); + young = kvm_rmap_age_gfn_range(kvm, range, false); if (tdp_mmu_enabled) young |= kvm_tdp_mmu_age_gfn_range(kvm, range); @@ -1647,7 +1674,7 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) bool young = false; if (kvm_memslots_have_rmaps(kvm)) - young = kvm_handle_gfn_range(kvm, range, kvm_test_age_rmap); + young = kvm_rmap_age_gfn_range(kvm, range, true); if (tdp_mmu_enabled) young |= kvm_tdp_mmu_test_age_gfn(kvm, range); @@ -2713,36 +2740,49 @@ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long goal_nr_mmu_pages) write_unlock(&kvm->mmu_lock); } -int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn) +bool __kvm_mmu_unprotect_gfn_and_retry(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + bool always_retry) { - struct kvm_mmu_page *sp; + struct kvm *kvm = vcpu->kvm; LIST_HEAD(invalid_list); - int r; + struct kvm_mmu_page *sp; + gpa_t gpa = cr2_or_gpa; + bool r = false; + + /* + * Bail early if there aren't any write-protected shadow pages to avoid + * unnecessarily taking mmu_lock lock, e.g. if the gfn is write-tracked + * by a third party. Reading indirect_shadow_pages without holding + * mmu_lock is safe, as this is purely an optimization, i.e. a false + * positive is benign, and a false negative will simply result in KVM + * skipping the unprotect+retry path, which is also an optimization. + */ + if (!READ_ONCE(kvm->arch.indirect_shadow_pages)) + goto out; + + if (!vcpu->arch.mmu->root_role.direct) { + gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL); + if (gpa == INVALID_GPA) + goto out; + } - r = 0; write_lock(&kvm->mmu_lock); - for_each_gfn_valid_sp_with_gptes(kvm, sp, gfn) { - r = 1; + for_each_gfn_valid_sp_with_gptes(kvm, sp, gpa_to_gfn(gpa)) kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list); - } + + /* + * Snapshot the result before zapping, as zapping will remove all list + * entries, i.e. checking the list later would yield a false negative. + */ + r = !list_empty(&invalid_list); kvm_mmu_commit_zap_page(kvm, &invalid_list); write_unlock(&kvm->mmu_lock); - return r; -} - -static int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) -{ - gpa_t gpa; - int r; - - if (vcpu->arch.mmu->root_role.direct) - return 0; - - gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); - - r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT); - +out: + if (r || always_retry) { + vcpu->arch.last_retry_eip = kvm_rip_read(vcpu); + vcpu->arch.last_retry_addr = cr2_or_gpa; + } return r; } @@ -2914,10 +2954,8 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot, trace_kvm_mmu_set_spte(level, gfn, sptep); } - if (wrprot) { - if (write_fault) - ret = RET_PF_EMULATE; - } + if (wrprot && write_fault) + ret = RET_PF_WRITE_PROTECTED; if (flush) kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, level); @@ -4549,7 +4587,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault return RET_PF_RETRY; if (page_fault_handle_page_track(vcpu, fault)) - return RET_PF_EMULATE; + return RET_PF_WRITE_PROTECTED; r = fast_page_fault(vcpu, fault); if (r != RET_PF_INVALID) @@ -4618,8 +4656,6 @@ int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code, if (!flags) { trace_kvm_page_fault(vcpu, fault_address, error_code); - if (kvm_event_needs_reinjection(vcpu)) - kvm_mmu_unprotect_page_virt(vcpu, fault_address); r = kvm_mmu_page_fault(vcpu, fault_address, error_code, insn, insn_len); } else if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) { @@ -4642,7 +4678,7 @@ static int kvm_tdp_mmu_page_fault(struct kvm_vcpu *vcpu, int r; if (page_fault_handle_page_track(vcpu, fault)) - return RET_PF_EMULATE; + return RET_PF_WRITE_PROTECTED; r = fast_page_fault(vcpu, fault); if (r != RET_PF_INVALID) @@ -4674,16 +4710,14 @@ out_unlock: bool kvm_mmu_may_ignore_guest_pat(void) { /* - * When EPT is enabled (shadow_memtype_mask is non-zero), the CPU does - * not support self-snoop (or is affected by an erratum), and the VM + * When EPT is enabled (shadow_memtype_mask is non-zero), and the VM * has non-coherent DMA (DMA doesn't snoop CPU caches), KVM's ABI is to * honor the memtype from the guest's PAT so that guest accesses to * memory that is DMA'd aren't cached against the guest's wishes. As a * result, KVM _may_ ignore guest PAT, whereas without non-coherent DMA, - * KVM _always_ ignores or honors guest PAT, i.e. doesn't toggle SPTE - * bits in response to non-coherent device (un)registration. + * KVM _always_ ignores guest PAT (when EPT is enabled). */ - return !static_cpu_has(X86_FEATURE_SELFSNOOP) && shadow_memtype_mask; + return shadow_memtype_mask; } int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) @@ -4721,6 +4755,7 @@ static int kvm_tdp_map_page(struct kvm_vcpu *vcpu, gpa_t gpa, u64 error_code, switch (r) { case RET_PF_FIXED: case RET_PF_SPURIOUS: + case RET_PF_WRITE_PROTECTED: return 0; case RET_PF_EMULATE: @@ -4750,7 +4785,9 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, * reload is efficient when called repeatedly, so we can do it on * every iteration. */ - kvm_mmu_reload(vcpu); + r = kvm_mmu_reload(vcpu); + if (r) + return r; if (kvm_arch_has_private_mem(vcpu->kvm) && kvm_mem_is_private(vcpu->kvm, gpa_to_gfn(range->gpa))) @@ -5963,6 +6000,106 @@ void kvm_mmu_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new, write_unlock(&vcpu->kvm->mmu_lock); } +static bool is_write_to_guest_page_table(u64 error_code) +{ + const u64 mask = PFERR_GUEST_PAGE_MASK | PFERR_WRITE_MASK | PFERR_PRESENT_MASK; + + return (error_code & mask) == mask; +} + +static int kvm_mmu_write_protect_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + u64 error_code, int *emulation_type) +{ + bool direct = vcpu->arch.mmu->root_role.direct; + + /* + * Do not try to unprotect and retry if the vCPU re-faulted on the same + * RIP with the same address that was previously unprotected, as doing + * so will likely put the vCPU into an infinite. E.g. if the vCPU uses + * a non-page-table modifying instruction on the PDE that points to the + * instruction, then unprotecting the gfn will unmap the instruction's + * code, i.e. make it impossible for the instruction to ever complete. + */ + if (vcpu->arch.last_retry_eip == kvm_rip_read(vcpu) && + vcpu->arch.last_retry_addr == cr2_or_gpa) + return RET_PF_EMULATE; + + /* + * Reset the unprotect+retry values that guard against infinite loops. + * The values will be refreshed if KVM explicitly unprotects a gfn and + * retries, in all other cases it's safe to retry in the future even if + * the next page fault happens on the same RIP+address. + */ + vcpu->arch.last_retry_eip = 0; + vcpu->arch.last_retry_addr = 0; + + /* + * It should be impossible to reach this point with an MMIO cache hit, + * as RET_PF_WRITE_PROTECTED is returned if and only if there's a valid, + * writable memslot, and creating a memslot should invalidate the MMIO + * cache by way of changing the memslot generation. WARN and disallow + * retry if MMIO is detected, as retrying MMIO emulation is pointless + * and could put the vCPU into an infinite loop because the processor + * will keep faulting on the non-existent MMIO address. + */ + if (WARN_ON_ONCE(mmio_info_in_cache(vcpu, cr2_or_gpa, direct))) + return RET_PF_EMULATE; + + /* + * Before emulating the instruction, check to see if the access was due + * to a read-only violation while the CPU was walking non-nested NPT + * page tables, i.e. for a direct MMU, for _guest_ page tables in L1. + * If L1 is sharing (a subset of) its page tables with L2, e.g. by + * having nCR3 share lower level page tables with hCR3, then when KVM + * (L0) write-protects the nested NPTs, i.e. npt12 entries, KVM is also + * unknowingly write-protecting L1's guest page tables, which KVM isn't + * shadowing. + * + * Because the CPU (by default) walks NPT page tables using a write + * access (to ensure the CPU can do A/D updates), page walks in L1 can + * trigger write faults for the above case even when L1 isn't modifying + * PTEs. As a result, KVM will unnecessarily emulate (or at least, try + * to emulate) an excessive number of L1 instructions; because L1's MMU + * isn't shadowed by KVM, there is no need to write-protect L1's gPTEs + * and thus no need to emulate in order to guarantee forward progress. + * + * Try to unprotect the gfn, i.e. zap any shadow pages, so that L1 can + * proceed without triggering emulation. If one or more shadow pages + * was zapped, skip emulation and resume L1 to let it natively execute + * the instruction. If no shadow pages were zapped, then the write- + * fault is due to something else entirely, i.e. KVM needs to emulate, + * as resuming the guest will put it into an infinite loop. + * + * Note, this code also applies to Intel CPUs, even though it is *very* + * unlikely that an L1 will share its page tables (IA32/PAE/paging64 + * format) with L2's page tables (EPT format). + * + * For indirect MMUs, i.e. if KVM is shadowing the current MMU, try to + * unprotect the gfn and retry if an event is awaiting reinjection. If + * KVM emulates multiple instructions before completing event injection, + * the event could be delayed beyond what is architecturally allowed, + * e.g. KVM could inject an IRQ after the TPR has been raised. + */ + if (((direct && is_write_to_guest_page_table(error_code)) || + (!direct && kvm_event_needs_reinjection(vcpu))) && + kvm_mmu_unprotect_gfn_and_retry(vcpu, cr2_or_gpa)) + return RET_PF_RETRY; + + /* + * The gfn is write-protected, but if KVM detects its emulating an + * instruction that is unlikely to be used to modify page tables, or if + * emulation fails, KVM can try to unprotect the gfn and let the CPU + * re-execute the instruction that caused the page fault. Do not allow + * retrying an instruction from a nested guest as KVM is only explicitly + * shadowing L1's page tables, i.e. unprotecting something for L1 isn't + * going to magically fix whatever issue caused L2 to fail. + */ + if (!is_guest_mode(vcpu)) + *emulation_type |= EMULTYPE_ALLOW_RETRY_PF; + + return RET_PF_EMULATE; +} + int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code, void *insn, int insn_len) { @@ -6008,6 +6145,10 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err if (r < 0) return r; + if (r == RET_PF_WRITE_PROTECTED) + r = kvm_mmu_write_protect_fault(vcpu, cr2_or_gpa, error_code, + &emulation_type); + if (r == RET_PF_FIXED) vcpu->stat.pf_fixed++; else if (r == RET_PF_EMULATE) @@ -6018,32 +6159,6 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err if (r != RET_PF_EMULATE) return 1; - /* - * Before emulating the instruction, check if the error code - * was due to a RO violation while translating the guest page. - * This can occur when using nested virtualization with nested - * paging in both guests. If true, we simply unprotect the page - * and resume the guest. - */ - if (vcpu->arch.mmu->root_role.direct && - (error_code & PFERR_NESTED_GUEST_PAGE) == PFERR_NESTED_GUEST_PAGE) { - kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(cr2_or_gpa)); - return 1; - } - - /* - * vcpu->arch.mmu.page_fault returned RET_PF_EMULATE, but we can still - * optimistically try to just unprotect the page and let the processor - * re-execute the instruction that caused the page fault. Do not allow - * retrying MMIO emulation, as it's not only pointless but could also - * cause us to enter an infinite loop because the processor will keep - * faulting on the non-existent MMIO address. Retrying an instruction - * from a nested guest is also pointless and dangerous as we are only - * explicitly shadowing L1's page tables, i.e. unprotecting something - * for L1 isn't going to magically fix whatever issue cause L2 to fail. - */ - if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu)) - emulation_type |= EMULTYPE_ALLOW_RETRY_PF; emulate: return x86_emulate_instruction(vcpu, cr2_or_gpa, emulation_type, insn, insn_len); @@ -6202,59 +6317,6 @@ void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level, } EXPORT_SYMBOL_GPL(kvm_configure_mmu); -/* The return value indicates if tlb flush on all vcpus is needed. */ -typedef bool (*slot_rmaps_handler) (struct kvm *kvm, - struct kvm_rmap_head *rmap_head, - const struct kvm_memory_slot *slot); - -static __always_inline bool __walk_slot_rmaps(struct kvm *kvm, - const struct kvm_memory_slot *slot, - slot_rmaps_handler fn, - int start_level, int end_level, - gfn_t start_gfn, gfn_t end_gfn, - bool flush_on_yield, bool flush) -{ - struct slot_rmap_walk_iterator iterator; - - lockdep_assert_held_write(&kvm->mmu_lock); - - for_each_slot_rmap_range(slot, start_level, end_level, start_gfn, - end_gfn, &iterator) { - if (iterator.rmap) - flush |= fn(kvm, iterator.rmap, slot); - - if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) { - if (flush && flush_on_yield) { - kvm_flush_remote_tlbs_range(kvm, start_gfn, - iterator.gfn - start_gfn + 1); - flush = false; - } - cond_resched_rwlock_write(&kvm->mmu_lock); - } - } - - return flush; -} - -static __always_inline bool walk_slot_rmaps(struct kvm *kvm, - const struct kvm_memory_slot *slot, - slot_rmaps_handler fn, - int start_level, int end_level, - bool flush_on_yield) -{ - return __walk_slot_rmaps(kvm, slot, fn, start_level, end_level, - slot->base_gfn, slot->base_gfn + slot->npages - 1, - flush_on_yield, false); -} - -static __always_inline bool walk_slot_rmaps_4k(struct kvm *kvm, - const struct kvm_memory_slot *slot, - slot_rmaps_handler fn, - bool flush_on_yield) -{ - return walk_slot_rmaps(kvm, slot, fn, PG_LEVEL_4K, PG_LEVEL_4K, flush_on_yield); -} - static void free_mmu_pages(struct kvm_mmu *mmu) { if (!tdp_enabled && mmu->pae_root) @@ -6528,9 +6590,8 @@ static bool kvm_rmap_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_e if (WARN_ON_ONCE(start >= end)) continue; - flush = __walk_slot_rmaps(kvm, memslot, __kvm_zap_rmap, - PG_LEVEL_4K, KVM_MAX_HUGEPAGE_LEVEL, - start, end - 1, true, flush); + flush = __kvm_rmap_zap_gfn_range(kvm, memslot, start, + end, true, flush); } } @@ -6818,7 +6879,7 @@ static void kvm_shadow_mmu_try_split_huge_pages(struct kvm *kvm, */ for (level = KVM_MAX_HUGEPAGE_LEVEL; level > target_level; level--) __walk_slot_rmaps(kvm, slot, shadow_mmu_try_split_huge_pages, - level, level, start, end - 1, true, false); + level, level, start, end - 1, true, true, false); } /* Must be called with the mmu_lock held in write-mode. */ @@ -6997,10 +7058,70 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm) kvm_mmu_zap_all(kvm); } +static void kvm_mmu_zap_memslot_pages_and_flush(struct kvm *kvm, + struct kvm_memory_slot *slot, + bool flush) +{ + LIST_HEAD(invalid_list); + unsigned long i; + + if (list_empty(&kvm->arch.active_mmu_pages)) + goto out_flush; + + /* + * Since accounting information is stored in struct kvm_arch_memory_slot, + * all MMU pages that are shadowing guest PTEs must be zapped before the + * memslot is deleted, as freeing such pages after the memslot is freed + * will result in use-after-free, e.g. in unaccount_shadowed(). + */ + for (i = 0; i < slot->npages; i++) { + struct kvm_mmu_page *sp; + gfn_t gfn = slot->base_gfn + i; + + for_each_gfn_valid_sp_with_gptes(kvm, sp, gfn) + kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list); + + if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) { + kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush); + flush = false; + cond_resched_rwlock_write(&kvm->mmu_lock); + } + } + +out_flush: + kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush); +} + +static void kvm_mmu_zap_memslot(struct kvm *kvm, + struct kvm_memory_slot *slot) +{ + struct kvm_gfn_range range = { + .slot = slot, + .start = slot->base_gfn, + .end = slot->base_gfn + slot->npages, + .may_block = true, + }; + bool flush; + + write_lock(&kvm->mmu_lock); + flush = kvm_unmap_gfn_range(kvm, &range); + kvm_mmu_zap_memslot_pages_and_flush(kvm, slot, flush); + write_unlock(&kvm->mmu_lock); +} + +static inline bool kvm_memslot_flush_zap_all(struct kvm *kvm) +{ + return kvm->arch.vm_type == KVM_X86_DEFAULT_VM && + kvm_check_has_quirk(kvm, KVM_X86_QUIRK_SLOT_ZAP_ALL); +} + void kvm_arch_flush_shadow_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) { - kvm_mmu_zap_all_fast(kvm); + if (kvm_memslot_flush_zap_all(kvm)) + kvm_mmu_zap_all_fast(kvm); + else + kvm_mmu_zap_memslot(kvm, slot); } void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen) diff --git a/arch/x86/kvm/mmu/mmu_internal.h b/arch/x86/kvm/mmu/mmu_internal.h index 1721d97743e9..c98827840e07 100644 --- a/arch/x86/kvm/mmu/mmu_internal.h +++ b/arch/x86/kvm/mmu/mmu_internal.h @@ -258,6 +258,8 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault); * RET_PF_CONTINUE: So far, so good, keep handling the page fault. * RET_PF_RETRY: let CPU fault again on the address. * RET_PF_EMULATE: mmio page fault, emulate the instruction directly. + * RET_PF_WRITE_PROTECTED: the gfn is write-protected, either unprotected the + * gfn and retry, or emulate the instruction directly. * RET_PF_INVALID: the spte is invalid, let the real page fault path update it. * RET_PF_FIXED: The faulting entry has been fixed. * RET_PF_SPURIOUS: The faulting entry was already fixed, e.g. by another vCPU. @@ -274,6 +276,7 @@ enum { RET_PF_CONTINUE = 0, RET_PF_RETRY, RET_PF_EMULATE, + RET_PF_WRITE_PROTECTED, RET_PF_INVALID, RET_PF_FIXED, RET_PF_SPURIOUS, @@ -349,8 +352,6 @@ int kvm_mmu_max_mapping_level(struct kvm *kvm, void kvm_mmu_hugepage_adjust(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault); void disallowed_hugepage_adjust(struct kvm_page_fault *fault, u64 spte, int cur_level); -void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc); - void track_possible_nx_huge_page(struct kvm *kvm, struct kvm_mmu_page *sp); void untrack_possible_nx_huge_page(struct kvm *kvm, struct kvm_mmu_page *sp); diff --git a/arch/x86/kvm/mmu/mmutrace.h b/arch/x86/kvm/mmu/mmutrace.h index 195d98bc8de8..f35a830ce469 100644 --- a/arch/x86/kvm/mmu/mmutrace.h +++ b/arch/x86/kvm/mmu/mmutrace.h @@ -57,6 +57,7 @@ TRACE_DEFINE_ENUM(RET_PF_CONTINUE); TRACE_DEFINE_ENUM(RET_PF_RETRY); TRACE_DEFINE_ENUM(RET_PF_EMULATE); +TRACE_DEFINE_ENUM(RET_PF_WRITE_PROTECTED); TRACE_DEFINE_ENUM(RET_PF_INVALID); TRACE_DEFINE_ENUM(RET_PF_FIXED); TRACE_DEFINE_ENUM(RET_PF_SPURIOUS); diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 69941cebb3a8..ae7d39ff2d07 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -646,10 +646,10 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault, * really care if it changes underneath us after this point). */ if (FNAME(gpte_changed)(vcpu, gw, top_level)) - goto out_gpte_changed; + return RET_PF_RETRY; if (WARN_ON_ONCE(!VALID_PAGE(vcpu->arch.mmu->root.hpa))) - goto out_gpte_changed; + return RET_PF_RETRY; /* * Load a new root and retry the faulting instruction in the extremely @@ -659,7 +659,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault, */ if (unlikely(kvm_mmu_is_dummy_root(vcpu->arch.mmu->root.hpa))) { kvm_make_request(KVM_REQ_MMU_FREE_OBSOLETE_ROOTS, vcpu); - goto out_gpte_changed; + return RET_PF_RETRY; } for_each_shadow_entry(vcpu, fault->addr, it) { @@ -674,34 +674,38 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault, sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn, false, access); - if (sp != ERR_PTR(-EEXIST)) { - /* - * We must synchronize the pagetable before linking it - * because the guest doesn't need to flush tlb when - * the gpte is changed from non-present to present. - * Otherwise, the guest may use the wrong mapping. - * - * For PG_LEVEL_4K, kvm_mmu_get_page() has already - * synchronized it transiently via kvm_sync_page(). - * - * For higher level pagetable, we synchronize it via - * the slower mmu_sync_children(). If it needs to - * break, some progress has been made; return - * RET_PF_RETRY and retry on the next #PF. - * KVM_REQ_MMU_SYNC is not necessary but it - * expedites the process. - */ - if (sp->unsync_children && - mmu_sync_children(vcpu, sp, false)) - return RET_PF_RETRY; - } + /* + * Synchronize the new page before linking it, as the CPU (KVM) + * is architecturally disallowed from inserting non-present + * entries into the TLB, i.e. the guest isn't required to flush + * the TLB when changing the gPTE from non-present to present. + * + * For PG_LEVEL_4K, kvm_mmu_find_shadow_page() has already + * synchronized the page via kvm_sync_page(). + * + * For higher level pages, which cannot be unsync themselves + * but can have unsync children, synchronize via the slower + * mmu_sync_children(). If KVM needs to drop mmu_lock due to + * contention or to reschedule, instruct the caller to retry + * the #PF (mmu_sync_children() ensures forward progress will + * be made). + */ + if (sp != ERR_PTR(-EEXIST) && sp->unsync_children && + mmu_sync_children(vcpu, sp, false)) + return RET_PF_RETRY; /* - * Verify that the gpte in the page we've just write - * protected is still there. + * Verify that the gpte in the page, which is now either + * write-protected or unsync, wasn't modified between the fault + * and acquiring mmu_lock. This needs to be done even when + * reusing an existing shadow page to ensure the information + * gathered by the walker matches the information stored in the + * shadow page (which could have been modified by a different + * vCPU even if the page was already linked). Holding mmu_lock + * prevents the shadow page from changing after this point. */ if (FNAME(gpte_changed)(vcpu, gw, it.level - 1)) - goto out_gpte_changed; + return RET_PF_RETRY; if (sp != ERR_PTR(-EEXIST)) link_shadow_page(vcpu, it.sptep, sp); @@ -755,9 +759,6 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault, FNAME(pte_prefetch)(vcpu, gw, it.sptep); return ret; - -out_gpte_changed: - return RET_PF_RETRY; } /* @@ -805,7 +806,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault if (page_fault_handle_page_track(vcpu, fault)) { shadow_page_table_clear_flood(vcpu, fault->addr); - return RET_PF_EMULATE; + return RET_PF_WRITE_PROTECTED; } r = mmu_topup_memory_caches(vcpu, true); diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c index d4527965e48c..8f7eb3ad88fc 100644 --- a/arch/x86/kvm/mmu/spte.c +++ b/arch/x86/kvm/mmu/spte.c @@ -391,9 +391,9 @@ void kvm_mmu_set_mmio_spte_mask(u64 mmio_value, u64 mmio_mask, u64 access_mask) mmio_value = 0; /* - * The masked MMIO value must obviously match itself and a removed SPTE - * must not get a false positive. Removed SPTEs and MMIO SPTEs should - * never collide as MMIO must set some RWX bits, and removed SPTEs must + * The masked MMIO value must obviously match itself and a frozen SPTE + * must not get a false positive. Frozen SPTEs and MMIO SPTEs should + * never collide as MMIO must set some RWX bits, and frozen SPTEs must * not set any RWX bits. */ if (WARN_ON((mmio_value & mmio_mask) != mmio_value) || diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h index ef793c459b05..2cb816ea2430 100644 --- a/arch/x86/kvm/mmu/spte.h +++ b/arch/x86/kvm/mmu/spte.h @@ -214,7 +214,7 @@ extern u64 __read_mostly shadow_nonpresent_or_rsvd_mask; */ #define FROZEN_SPTE (SHADOW_NONPRESENT_VALUE | 0x5a0ULL) -/* Removed SPTEs must not be misconstrued as shadow present PTEs. */ +/* Frozen SPTEs must not be misconstrued as shadow present PTEs. */ static_assert(!(FROZEN_SPTE & SPTE_MMU_PRESENT_MASK)); static inline bool is_frozen_spte(u64 spte) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index c7dc49ee7388..3b996c1fdaab 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -359,10 +359,10 @@ static void handle_removed_pt(struct kvm *kvm, tdp_ptep_t pt, bool shared) /* * Set the SPTE to a nonpresent value that other * threads will not overwrite. If the SPTE was - * already marked as removed then another thread + * already marked as frozen then another thread * handling a page fault could overwrite it, so * set the SPTE until it is set from some other - * value to the removed SPTE value. + * value to the frozen SPTE value. */ for (;;) { old_spte = kvm_tdp_mmu_write_spte_atomic(sptep, FROZEN_SPTE); @@ -536,8 +536,8 @@ static inline int __must_check __tdp_mmu_set_spte_atomic(struct tdp_iter *iter, u64 *sptep = rcu_dereference(iter->sptep); /* - * The caller is responsible for ensuring the old SPTE is not a REMOVED - * SPTE. KVM should never attempt to zap or manipulate a REMOVED SPTE, + * The caller is responsible for ensuring the old SPTE is not a FROZEN + * SPTE. KVM should never attempt to zap or manipulate a FROZEN SPTE, * and pre-checking before inserting a new SPTE is advantageous as it * avoids unnecessary work. */ @@ -1046,10 +1046,8 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, * protected, emulation is needed. If the emulation was skipped, * the vCPU would have the same fault again. */ - if (wrprot) { - if (fault->write) - ret = RET_PF_EMULATE; - } + if (wrprot && fault->write) + ret = RET_PF_WRITE_PROTECTED; /* If a MMIO SPTE is installed, the MMIO will need to be emulated. */ if (unlikely(is_mmio_spte(vcpu->kvm, new_spte))) { diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index 2f4e155080ba..0d17d6b70639 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -17,6 +17,7 @@ enum kvm_only_cpuid_leafs { CPUID_8000_0007_EDX, CPUID_8000_0022_EAX, CPUID_7_2_EDX, + CPUID_24_0_EBX, NR_KVM_CPU_CAPS, NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, @@ -46,6 +47,7 @@ enum kvm_only_cpuid_leafs { #define X86_FEATURE_AVX_NE_CONVERT KVM_X86_FEATURE(CPUID_7_1_EDX, 5) #define X86_FEATURE_AMX_COMPLEX KVM_X86_FEATURE(CPUID_7_1_EDX, 8) #define X86_FEATURE_PREFETCHITI KVM_X86_FEATURE(CPUID_7_1_EDX, 14) +#define X86_FEATURE_AVX10 KVM_X86_FEATURE(CPUID_7_1_EDX, 19) /* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */ #define X86_FEATURE_INTEL_PSFD KVM_X86_FEATURE(CPUID_7_2_EDX, 0) @@ -55,6 +57,11 @@ enum kvm_only_cpuid_leafs { #define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4) #define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5) +/* Intel-defined sub-features, CPUID level 0x00000024:0 (EBX) */ +#define X86_FEATURE_AVX10_128 KVM_X86_FEATURE(CPUID_24_0_EBX, 16) +#define X86_FEATURE_AVX10_256 KVM_X86_FEATURE(CPUID_24_0_EBX, 17) +#define X86_FEATURE_AVX10_512 KVM_X86_FEATURE(CPUID_24_0_EBX, 18) + /* CPUID level 0x80000007 (EDX). */ #define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, 8) @@ -90,6 +97,7 @@ static const struct cpuid_reg reverse_cpuid[] = { [CPUID_8000_0021_EAX] = {0x80000021, 0, CPUID_EAX}, [CPUID_8000_0022_EAX] = {0x80000022, 0, CPUID_EAX}, [CPUID_7_2_EDX] = { 7, 2, CPUID_EDX}, + [CPUID_24_0_EBX] = { 0x24, 0, CPUID_EBX}, }; /* diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c index 00e3c27d2a87..85241c0c7f56 100644 --- a/arch/x86/kvm/smm.c +++ b/arch/x86/kvm/smm.c @@ -624,17 +624,31 @@ int emulator_leave_smm(struct x86_emulate_ctxt *ctxt) #endif /* - * Give leave_smm() a chance to make ISA-specific changes to the vCPU - * state (e.g. enter guest mode) before loading state from the SMM - * state-save area. + * FIXME: When resuming L2 (a.k.a. guest mode), the transition to guest + * mode should happen _after_ loading state from SMRAM. However, KVM + * piggybacks the nested VM-Enter flows (which is wrong for many other + * reasons), and so nSVM/nVMX would clobber state that is loaded from + * SMRAM and from the VMCS/VMCB. */ if (kvm_x86_call(leave_smm)(vcpu, &smram)) return X86EMUL_UNHANDLEABLE; #ifdef CONFIG_X86_64 if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) - return rsm_load_state_64(ctxt, &smram.smram64); + ret = rsm_load_state_64(ctxt, &smram.smram64); else #endif - return rsm_load_state_32(ctxt, &smram.smram32); + ret = rsm_load_state_32(ctxt, &smram.smram32); + + /* + * If RSM fails and triggers shutdown, architecturally the shutdown + * occurs *before* the transition to guest mode. But due to KVM's + * flawed handling of RSM to L2 (see above), the vCPU may already be + * in_guest_mode(). Force the vCPU out of guest mode before delivering + * the shutdown, so that L1 enters shutdown instead of seeing a VM-Exit + * that architecturally shouldn't be possible. + */ + if (ret != X86EMUL_CONTINUE && is_guest_mode(vcpu)) + kvm_leave_nested(vcpu); + return ret; } diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 6f704c1037e5..cf84103ce38b 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -63,8 +63,12 @@ static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index) u64 pdpte; int ret; + /* + * Note, nCR3 is "assumed" to be 32-byte aligned, i.e. the CPU ignores + * nCR3[4:0] when loading PDPTEs from memory. + */ ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(cr3), &pdpte, - offset_in_page(cr3) + index * 8, 8); + (cr3 & GENMASK(11, 5)) + index * 8, 8); if (ret) return 0; return pdpte; @@ -1693,8 +1697,8 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, return -EINVAL; ret = -ENOMEM; - ctl = kzalloc(sizeof(*ctl), GFP_KERNEL_ACCOUNT); - save = kzalloc(sizeof(*save), GFP_KERNEL_ACCOUNT); + ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); + save = kzalloc(sizeof(*save), GFP_KERNEL); if (!ctl || !save) goto out_free; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 714c517dd4b7..92d4711fd1e4 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -450,8 +450,11 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp, goto e_free; /* This needs to happen after SEV/SNP firmware initialization. */ - if (vm_type == KVM_X86_SNP_VM && snp_guest_req_init(kvm)) - goto e_free; + if (vm_type == KVM_X86_SNP_VM) { + ret = snp_guest_req_init(kvm); + if (ret) + goto e_free; + } INIT_LIST_HEAD(&sev->regions_list); INIT_LIST_HEAD(&sev->mirror_vms); @@ -530,17 +533,12 @@ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error) static int __sev_issue_cmd(int fd, int id, void *data, int *error) { - struct fd f; - int ret; + CLASS(fd, f)(fd); - f = fdget(fd); - if (!f.file) + if (fd_empty(f)) return -EBADF; - ret = sev_issue_cmd_external_user(f.file, id, data, error); - - fdput(f); - return ret; + return sev_issue_cmd_external_user(fd_file(f), id, data, error); } static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error) @@ -2073,23 +2071,21 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd) { struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info; struct kvm_sev_info *src_sev, *cg_cleanup_sev; - struct fd f = fdget(source_fd); + CLASS(fd, f)(source_fd); struct kvm *source_kvm; bool charged = false; int ret; - if (!f.file) + if (fd_empty(f)) return -EBADF; - if (!file_is_kvm(f.file)) { - ret = -EBADF; - goto out_fput; - } + if (!file_is_kvm(fd_file(f))) + return -EBADF; - source_kvm = f.file->private_data; + source_kvm = fd_file(f)->private_data; ret = sev_lock_two_vms(kvm, source_kvm); if (ret) - goto out_fput; + return ret; if (kvm->arch.vm_type != source_kvm->arch.vm_type || sev_guest(kvm) || !sev_guest(source_kvm)) { @@ -2136,8 +2132,6 @@ out_dst_cgroup: cg_cleanup_sev->misc_cg = NULL; out_unlock: sev_unlock_two_vms(kvm, source_kvm); -out_fput: - fdput(f); return ret; } @@ -2212,10 +2206,6 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) if (sev->snp_context) return -EINVAL; - sev->snp_context = snp_context_create(kvm, argp); - if (!sev->snp_context) - return -ENOTTY; - if (params.flags) return -EINVAL; @@ -2230,6 +2220,10 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) if (params.policy & SNP_POLICY_MASK_SINGLE_SOCKET) return -EINVAL; + sev->snp_context = snp_context_create(kvm, argp); + if (!sev->snp_context) + return -ENOTTY; + start.gctx_paddr = __psp_pa(sev->snp_context); start.policy = params.policy; memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw)); @@ -2798,23 +2792,21 @@ failed: int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd) { - struct fd f = fdget(source_fd); + CLASS(fd, f)(source_fd); struct kvm *source_kvm; struct kvm_sev_info *source_sev, *mirror_sev; int ret; - if (!f.file) + if (fd_empty(f)) return -EBADF; - if (!file_is_kvm(f.file)) { - ret = -EBADF; - goto e_source_fput; - } + if (!file_is_kvm(fd_file(f))) + return -EBADF; - source_kvm = f.file->private_data; + source_kvm = fd_file(f)->private_data; ret = sev_lock_two_vms(kvm, source_kvm); if (ret) - goto e_source_fput; + return ret; /* * Mirrors of mirrors should work, but let's not get silly. Also @@ -2857,8 +2849,6 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd) e_unlock: sev_unlock_two_vms(kvm, source_kvm); -e_source_fput: - fdput(f); return ret; } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d6f252555ab3..9df3e1e5ae81 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -573,7 +573,7 @@ static void __svm_write_tsc_multiplier(u64 multiplier) static __always_inline struct sev_es_save_area *sev_es_host_save_area(struct svm_cpu_data *sd) { - return page_address(sd->save_area) + 0x400; + return &sd->save_area->host_sev_es_save; } static inline void kvm_cpu_svm_disable(void) @@ -592,14 +592,14 @@ static inline void kvm_cpu_svm_disable(void) } } -static void svm_emergency_disable(void) +static void svm_emergency_disable_virtualization_cpu(void) { kvm_rebooting = true; kvm_cpu_svm_disable(); } -static void svm_hardware_disable(void) +static void svm_disable_virtualization_cpu(void) { /* Make sure we clean up behind us */ if (tsc_scaling) @@ -610,7 +610,7 @@ static void svm_hardware_disable(void) amd_pmu_disable_virt(); } -static int svm_hardware_enable(void) +static int svm_enable_virtualization_cpu(void) { struct svm_cpu_data *sd; @@ -696,7 +696,7 @@ static void svm_cpu_uninit(int cpu) return; kfree(sd->sev_vmcbs); - __free_page(sd->save_area); + __free_page(__sme_pa_to_page(sd->save_area_pa)); sd->save_area_pa = 0; sd->save_area = NULL; } @@ -704,23 +704,24 @@ static void svm_cpu_uninit(int cpu) static int svm_cpu_init(int cpu) { struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu); + struct page *save_area_page; int ret = -ENOMEM; memset(sd, 0, sizeof(struct svm_cpu_data)); - sd->save_area = snp_safe_alloc_page_node(cpu_to_node(cpu), GFP_KERNEL); - if (!sd->save_area) + save_area_page = snp_safe_alloc_page_node(cpu_to_node(cpu), GFP_KERNEL); + if (!save_area_page) return ret; ret = sev_cpu_init(sd); if (ret) goto free_save_area; - sd->save_area_pa = __sme_page_pa(sd->save_area); + sd->save_area = page_address(save_area_page); + sd->save_area_pa = __sme_page_pa(save_area_page); return 0; free_save_area: - __free_page(sd->save_area); - sd->save_area = NULL; + __free_page(save_area_page); return ret; } @@ -1124,8 +1125,7 @@ static void svm_hardware_unsetup(void) for_each_possible_cpu(cpu) svm_cpu_uninit(cpu); - __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), - get_order(IOPM_SIZE)); + __free_pages(__sme_pa_to_page(iopm_base), get_order(IOPM_SIZE)); iopm_base = 0; } @@ -1301,7 +1301,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu) if (!kvm_hlt_in_guest(vcpu->kvm)) svm_set_intercept(svm, INTERCEPT_HLT); - control->iopm_base_pa = __sme_set(iopm_base); + control->iopm_base_pa = iopm_base; control->msrpm_base_pa = __sme_set(__pa(svm->msrpm)); control->int_ctl = V_INTR_MASKING_MASK; @@ -1503,7 +1503,7 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu) sev_free_vcpu(vcpu); - __free_page(pfn_to_page(__sme_clr(svm->vmcb01.pa) >> PAGE_SHIFT)); + __free_page(__sme_pa_to_page(svm->vmcb01.pa)); __free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE)); } @@ -1533,7 +1533,7 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) * TSC_AUX is always virtualized for SEV-ES guests when the feature is * available. The user return MSR support is not required in this case * because TSC_AUX is restored on #VMEXIT from the host save area - * (which has been initialized in svm_hardware_enable()). + * (which has been initialized in svm_enable_virtualization_cpu()). */ if (likely(tsc_aux_uret_slot >= 0) && (!boot_cpu_has(X86_FEATURE_V_TSC_AUX) || !sev_es_guest(vcpu->kvm))) @@ -2825,17 +2825,17 @@ static int efer_trap(struct kvm_vcpu *vcpu) return kvm_complete_insn_gp(vcpu, ret); } -static int svm_get_msr_feature(struct kvm_msr_entry *msr) +static int svm_get_feature_msr(u32 msr, u64 *data) { - msr->data = 0; + *data = 0; - switch (msr->index) { + switch (msr) { case MSR_AMD64_DE_CFG: if (cpu_feature_enabled(X86_FEATURE_LFENCE_RDTSC)) - msr->data |= MSR_AMD64_DE_CFG_LFENCE_SERIALIZE; + *data |= MSR_AMD64_DE_CFG_LFENCE_SERIALIZE; break; default: - return KVM_MSR_RET_INVALID; + return KVM_MSR_RET_UNSUPPORTED; } return 0; @@ -2876,6 +2876,12 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_CSTAR: msr_info->data = svm->vmcb01.ptr->save.cstar; break; + case MSR_GS_BASE: + msr_info->data = svm->vmcb01.ptr->save.gs.base; + break; + case MSR_FS_BASE: + msr_info->data = svm->vmcb01.ptr->save.fs.base; + break; case MSR_KERNEL_GS_BASE: msr_info->data = svm->vmcb01.ptr->save.kernel_gs_base; break; @@ -3101,6 +3107,12 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) case MSR_CSTAR: svm->vmcb01.ptr->save.cstar = data; break; + case MSR_GS_BASE: + svm->vmcb01.ptr->save.gs.base = data; + break; + case MSR_FS_BASE: + svm->vmcb01.ptr->save.fs.base = data; + break; case MSR_KERNEL_GS_BASE: svm->vmcb01.ptr->save.kernel_gs_base = data; break; @@ -3132,7 +3144,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) * feature is available. The user return MSR support is not * required in this case because TSC_AUX is restored on #VMEXIT * from the host save area (which has been initialized in - * svm_hardware_enable()). + * svm_enable_virtualization_cpu()). */ if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && sev_es_guest(vcpu->kvm)) break; @@ -3179,18 +3191,21 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) kvm_pr_unimpl_wrmsr(vcpu, ecx, data); break; case MSR_AMD64_DE_CFG: { - struct kvm_msr_entry msr_entry; + u64 supported_de_cfg; - msr_entry.index = msr->index; - if (svm_get_msr_feature(&msr_entry)) + if (svm_get_feature_msr(ecx, &supported_de_cfg)) return 1; - /* Check the supported bits */ - if (data & ~msr_entry.data) + if (data & ~supported_de_cfg) return 1; - /* Don't allow the guest to change a bit, #GP */ - if (!msr->host_initiated && (data ^ msr_entry.data)) + /* + * Don't let the guest change the host-programmed value. The + * MSR is very model specific, i.e. contains multiple bits that + * are completely unknown to KVM, and the one bit known to KVM + * is simply a reflection of hardware capabilities. + */ + if (!msr->host_initiated && data != svm->msr_decfg) return 1; svm->msr_decfg = data; @@ -4144,12 +4159,21 @@ static int svm_vcpu_pre_run(struct kvm_vcpu *vcpu) static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu) { + struct vcpu_svm *svm = to_svm(vcpu); + if (is_guest_mode(vcpu)) return EXIT_FASTPATH_NONE; - if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR && - to_svm(vcpu)->vmcb->control.exit_info_1) + switch (svm->vmcb->control.exit_code) { + case SVM_EXIT_MSR: + if (!svm->vmcb->control.exit_info_1) + break; return handle_fastpath_set_msr_irqoff(vcpu); + case SVM_EXIT_HLT: + return handle_fastpath_hlt(vcpu); + default: + break; + } return EXIT_FASTPATH_NONE; } @@ -4980,8 +5004,9 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .check_processor_compatibility = svm_check_processor_compat, .hardware_unsetup = svm_hardware_unsetup, - .hardware_enable = svm_hardware_enable, - .hardware_disable = svm_hardware_disable, + .enable_virtualization_cpu = svm_enable_virtualization_cpu, + .disable_virtualization_cpu = svm_disable_virtualization_cpu, + .emergency_disable_virtualization_cpu = svm_emergency_disable_virtualization_cpu, .has_emulated_msr = svm_has_emulated_msr, .vcpu_create = svm_vcpu_create, @@ -4999,7 +5024,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .vcpu_unblocking = avic_vcpu_unblocking, .update_exception_bitmap = svm_update_exception_bitmap, - .get_msr_feature = svm_get_msr_feature, + .get_feature_msr = svm_get_feature_msr, .get_msr = svm_get_msr, .set_msr = svm_set_msr, .get_segment_base = svm_get_segment_base, @@ -5050,6 +5075,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .enable_nmi_window = svm_enable_nmi_window, .enable_irq_window = svm_enable_irq_window, .update_cr8_intercept = svm_update_cr8_intercept, + + .x2apic_icr_is_split = true, .set_virtual_apic_mode = avic_refresh_virtual_apic_mode, .refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl, .apicv_post_state_restore = avic_apicv_post_state_restore, @@ -5224,6 +5251,9 @@ static __init void svm_set_cpu_caps(void) /* CPUID 0x8000001F (SME/SEV features) */ sev_set_cpu_caps(); + + /* Don't advertise Bus Lock Detect to guest if SVM support is absent */ + kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT); } static __init int svm_hardware_setup(void) @@ -5251,7 +5281,7 @@ static __init int svm_hardware_setup(void) iopm_va = page_address(iopm_pages); memset(iopm_va, 0xff, PAGE_SIZE * (1 << order)); - iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT; + iopm_base = __sme_page_pa(iopm_pages); init_msrpm_offsets(); @@ -5410,8 +5440,6 @@ static struct kvm_x86_init_ops svm_init_ops __initdata = { static void __svm_exit(void) { kvm_x86_vendor_exit(); - - cpu_emergency_unregister_virt_callback(svm_emergency_disable); } static int __init svm_init(void) @@ -5427,8 +5455,6 @@ static int __init svm_init(void) if (r) return r; - cpu_emergency_register_virt_callback(svm_emergency_disable); - /* * Common KVM initialization _must_ come last, after this, /dev/kvm is * exposed to userspace! diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 76107c7d0595..43fa6a16eb19 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -25,7 +25,21 @@ #include "cpuid.h" #include "kvm_cache_regs.h" -#define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT) +/* + * Helpers to convert to/from physical addresses for pages whose address is + * consumed directly by hardware. Even though it's a physical address, SVM + * often restricts the address to the natural width, hence 'unsigned long' + * instead of 'hpa_t'. + */ +static inline unsigned long __sme_page_pa(struct page *page) +{ + return __sme_set(page_to_pfn(page) << PAGE_SHIFT); +} + +static inline struct page *__sme_pa_to_page(unsigned long pa) +{ + return pfn_to_page(__sme_clr(pa) >> PAGE_SHIFT); +} #define IOPM_SIZE PAGE_SIZE * 3 #define MSRPM_SIZE PAGE_SIZE * 2 @@ -321,7 +335,7 @@ struct svm_cpu_data { u32 next_asid; u32 min_asid; - struct page *save_area; + struct vmcb *save_area; unsigned long save_area_pa; struct vmcb *current_vmcb; diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index a0c8eb37d3e1..2ed80aea3bb1 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -209,10 +209,8 @@ SYM_FUNC_START(__svm_vcpu_run) 7: vmload %_ASM_AX 8: -#ifdef CONFIG_MITIGATION_RETPOLINE /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ - FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE -#endif + FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT /* Clobbers RAX, RCX, RDX. */ RESTORE_HOST_SPEC_CTRL @@ -348,10 +346,8 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) 2: cli -#ifdef CONFIG_MITIGATION_RETPOLINE /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ - FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE -#endif + FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT /* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */ RESTORE_HOST_SPEC_CTRL diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h index 41a4533f9989..cb6588238f46 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -54,9 +54,7 @@ struct nested_vmx_msrs { }; struct vmcs_config { - int size; - u32 basic_cap; - u32 revision_id; + u64 basic; u32 pin_based_exec_ctrl; u32 cpu_based_exec_ctrl; u32 cpu_based_2nd_exec_ctrl; @@ -76,7 +74,7 @@ extern struct vmx_capability vmx_capability __ro_after_init; static inline bool cpu_has_vmx_basic_inout(void) { - return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT); + return vmcs_config.basic & VMX_BASIC_INOUT; } static inline bool cpu_has_virtual_nmis(void) @@ -225,7 +223,7 @@ static inline bool cpu_has_vmx_vmfunc(void) static inline bool cpu_has_vmx_shadow_vmcs(void) { /* check if the cpu supports writing r/o exit information fields */ - if (!(vmcs_config.misc & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS)) + if (!(vmcs_config.misc & VMX_MISC_VMWRITE_SHADOW_RO_FIELDS)) return false; return vmcs_config.cpu_based_2nd_exec_ctrl & @@ -367,7 +365,7 @@ static inline bool cpu_has_vmx_invvpid_global(void) static inline bool cpu_has_vmx_intel_pt(void) { - return (vmcs_config.misc & MSR_IA32_VMX_MISC_INTEL_PT) && + return (vmcs_config.misc & VMX_MISC_INTEL_PT) && (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) && (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL); } diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c index 0bf35ebe8a1b..7668e2fb8043 100644 --- a/arch/x86/kvm/vmx/main.c +++ b/arch/x86/kvm/vmx/main.c @@ -23,8 +23,10 @@ struct kvm_x86_ops vt_x86_ops __initdata = { .hardware_unsetup = vmx_hardware_unsetup, - .hardware_enable = vmx_hardware_enable, - .hardware_disable = vmx_hardware_disable, + .enable_virtualization_cpu = vmx_enable_virtualization_cpu, + .disable_virtualization_cpu = vmx_disable_virtualization_cpu, + .emergency_disable_virtualization_cpu = vmx_emergency_disable_virtualization_cpu, + .has_emulated_msr = vmx_has_emulated_msr, .vm_size = sizeof(struct kvm_vmx), @@ -41,7 +43,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { .vcpu_put = vmx_vcpu_put, .update_exception_bitmap = vmx_update_exception_bitmap, - .get_msr_feature = vmx_get_msr_feature, + .get_feature_msr = vmx_get_feature_msr, .get_msr = vmx_get_msr, .set_msr = vmx_set_msr, .get_segment_base = vmx_get_segment_base, @@ -89,6 +91,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = { .enable_nmi_window = vmx_enable_nmi_window, .enable_irq_window = vmx_enable_irq_window, .update_cr8_intercept = vmx_update_cr8_intercept, + + .x2apic_icr_is_split = false, .set_virtual_apic_mode = vmx_set_virtual_apic_mode, .set_apic_access_page_addr = vmx_set_apic_access_page_addr, .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl, diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 2392a7ef254d..931a7361c30f 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -981,7 +981,7 @@ static u32 nested_vmx_load_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count) __func__, i, e.index, e.reserved); goto fail; } - if (kvm_set_msr(vcpu, e.index, e.value)) { + if (kvm_set_msr_with_filter(vcpu, e.index, e.value)) { pr_debug_ratelimited( "%s cannot write MSR (%u, 0x%x, 0x%llx)\n", __func__, i, e.index, e.value); @@ -1017,7 +1017,7 @@ static bool nested_vmx_get_vmexit_msr_value(struct kvm_vcpu *vcpu, } } - if (kvm_get_msr(vcpu, msr_index, data)) { + if (kvm_get_msr_with_filter(vcpu, msr_index, data)) { pr_debug_ratelimited("%s cannot read MSR (0x%x)\n", __func__, msr_index); return false; @@ -1112,9 +1112,9 @@ static void prepare_vmx_msr_autostore_list(struct kvm_vcpu *vcpu, /* * Emulated VMEntry does not fail here. Instead a less * accurate value will be returned by - * nested_vmx_get_vmexit_msr_value() using kvm_get_msr() - * instead of reading the value from the vmcs02 VMExit - * MSR-store area. + * nested_vmx_get_vmexit_msr_value() by reading KVM's + * internal MSR state instead of reading the value from + * the vmcs02 VMExit MSR-store area. */ pr_warn_ratelimited( "Not enough msr entries in msr_autostore. Can't add msr %x\n", @@ -1197,11 +1197,14 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu, kvm_hv_nested_transtion_tlb_flush(vcpu, enable_ept); /* - * If vmcs12 doesn't use VPID, L1 expects linear and combined mappings - * for *all* contexts to be flushed on VM-Enter/VM-Exit, i.e. it's a - * full TLB flush from the guest's perspective. This is required even - * if VPID is disabled in the host as KVM may need to synchronize the - * MMU in response to the guest TLB flush. + * If VPID is disabled, then guest TLB accesses use VPID=0, i.e. the + * same VPID as the host, and so architecturally, linear and combined + * mappings for VPID=0 must be flushed at VM-Enter and VM-Exit. KVM + * emulates L2 sharing L1's VPID=0 by using vpid01 while running L2, + * and so KVM must also emulate TLB flush of VPID=0, i.e. vpid01. This + * is required if VPID is disabled in KVM, as a TLB flush (there are no + * VPIDs) still occurs from L1's perspective, and KVM may need to + * synchronize the MMU in response to the guest TLB flush. * * Note, using TLB_FLUSH_GUEST is correct even if nested EPT is in use. * EPT is a special snowflake, as guest-physical mappings aren't @@ -1251,21 +1254,32 @@ static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask) static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data) { - const u64 feature_and_reserved = - /* feature (except bit 48; see below) */ - BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) | - /* reserved */ - BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56); + const u64 feature_bits = VMX_BASIC_DUAL_MONITOR_TREATMENT | + VMX_BASIC_INOUT | + VMX_BASIC_TRUE_CTLS; + + const u64 reserved_bits = GENMASK_ULL(63, 56) | + GENMASK_ULL(47, 45) | + BIT_ULL(31); + u64 vmx_basic = vmcs_config.nested.basic; - if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved)) + BUILD_BUG_ON(feature_bits & reserved_bits); + + /* + * Except for 32BIT_PHYS_ADDR_ONLY, which is an anti-feature bit (has + * inverted polarity), the incoming value must not set feature bits or + * reserved bits that aren't allowed/supported by KVM. Fields, i.e. + * multi-bit values, are explicitly checked below. + */ + if (!is_bitwise_subset(vmx_basic, data, feature_bits | reserved_bits)) return -EINVAL; /* * KVM does not emulate a version of VMX that constrains physical * addresses of VMX structures (e.g. VMCS) to 32-bits. */ - if (data & BIT_ULL(48)) + if (data & VMX_BASIC_32BIT_PHYS_ADDR_ONLY) return -EINVAL; if (vmx_basic_vmcs_revision_id(vmx_basic) != @@ -1334,16 +1348,29 @@ vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data) static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data) { - const u64 feature_and_reserved_bits = - /* feature */ - BIT_ULL(5) | GENMASK_ULL(8, 6) | BIT_ULL(14) | BIT_ULL(15) | - BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) | - /* reserved */ - GENMASK_ULL(13, 9) | BIT_ULL(31); + const u64 feature_bits = VMX_MISC_SAVE_EFER_LMA | + VMX_MISC_ACTIVITY_HLT | + VMX_MISC_ACTIVITY_SHUTDOWN | + VMX_MISC_ACTIVITY_WAIT_SIPI | + VMX_MISC_INTEL_PT | + VMX_MISC_RDMSR_IN_SMM | + VMX_MISC_VMWRITE_SHADOW_RO_FIELDS | + VMX_MISC_VMXOFF_BLOCK_SMI | + VMX_MISC_ZERO_LEN_INS; + + const u64 reserved_bits = BIT_ULL(31) | GENMASK_ULL(13, 9); + u64 vmx_misc = vmx_control_msr(vmcs_config.nested.misc_low, vmcs_config.nested.misc_high); - if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits)) + BUILD_BUG_ON(feature_bits & reserved_bits); + + /* + * The incoming value must not set feature bits or reserved bits that + * aren't allowed/supported by KVM. Fields, i.e. multi-bit values, are + * explicitly checked below. + */ + if (!is_bitwise_subset(vmx_misc, data, feature_bits | reserved_bits)) return -EINVAL; if ((vmx->nested.msrs.pinbased_ctls_high & @@ -2291,6 +2318,17 @@ static void prepare_vmcs02_early_rare(struct vcpu_vmx *vmx, vmcs_write64(VMCS_LINK_POINTER, INVALID_GPA); + /* + * If VPID is disabled, then guest TLB accesses use VPID=0, i.e. the + * same VPID as the host. Emulate this behavior by using vpid01 for L2 + * if VPID is disabled in vmcs12. Note, if VPID is disabled, VM-Enter + * and VM-Exit are architecturally required to flush VPID=0, but *only* + * VPID=0. I.e. using vpid02 would be ok (so long as KVM emulates the + * required flushes), but doing so would cause KVM to over-flush. E.g. + * if L1 runs L2 X with VPID12=1, then runs L2 Y with VPID12 disabled, + * and then runs L2 X again, then KVM can and should retain TLB entries + * for VPID12=1. + */ if (enable_vpid) { if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02); @@ -2317,10 +2355,12 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0 /* Posted interrupts setting is only taken from vmcs12. */ vmx->nested.pi_pending = false; - if (nested_cpu_has_posted_intr(vmcs12)) + if (nested_cpu_has_posted_intr(vmcs12)) { vmx->nested.posted_intr_nv = vmcs12->posted_intr_nv; - else + } else { + vmx->nested.posted_intr_nv = -1; exec_control &= ~PIN_BASED_POSTED_INTR; + } pin_controls_set(vmx, exec_control); /* @@ -2470,6 +2510,7 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) if (!hv_evmcs || !(hv_evmcs->hv_clean_fields & HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2)) { + vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector); vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector); vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector); @@ -2507,7 +2548,7 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base); vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base); - vmx->segment_cache.bitmask = 0; + vmx_segment_cache_clear(vmx); } if (!hv_evmcs || !(hv_evmcs->hv_clean_fields & @@ -4284,11 +4325,52 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) } if (kvm_cpu_has_interrupt(vcpu) && !vmx_interrupt_blocked(vcpu)) { + int irq; + if (block_nested_events) return -EBUSY; if (!nested_exit_on_intr(vcpu)) goto no_vmexit; - nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0); + + if (!nested_exit_intr_ack_set(vcpu)) { + nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0); + return 0; + } + + irq = kvm_cpu_get_extint(vcpu); + if (irq != -1) { + nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, + INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | irq, 0); + return 0; + } + + irq = kvm_apic_has_interrupt(vcpu); + if (WARN_ON_ONCE(irq < 0)) + goto no_vmexit; + + /* + * If the IRQ is L2's PI notification vector, process posted + * interrupts for L2 instead of injecting VM-Exit, as the + * detection/morphing architecturally occurs when the IRQ is + * delivered to the CPU. Note, only interrupts that are routed + * through the local APIC trigger posted interrupt processing, + * and enabling posted interrupts requires ACK-on-exit. + */ + if (irq == vmx->nested.posted_intr_nv) { + vmx->nested.pi_pending = true; + kvm_apic_clear_irr(vcpu, irq); + goto no_vmexit; + } + + nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, + INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | irq, 0); + + /* + * ACK the interrupt _after_ emulating VM-Exit, as the IRQ must + * be marked as in-service in vmcs01.GUEST_INTERRUPT_STATUS.SVI + * if APICv is active. + */ + kvm_apic_ack_interrupt(vcpu, irq); return 0; } @@ -4806,7 +4888,7 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu) goto vmabort; } - if (kvm_set_msr(vcpu, h.index, h.value)) { + if (kvm_set_msr_with_filter(vcpu, h.index, h.value)) { pr_debug_ratelimited( "%s WRMSR failed (%u, 0x%x, 0x%llx)\n", __func__, j, h.index, h.value); @@ -4969,14 +5051,6 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; if (likely(!vmx->fail)) { - if ((u16)vm_exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT && - nested_exit_intr_ack_set(vcpu)) { - int irq = kvm_cpu_get_interrupt(vcpu); - WARN_ON(irq < 0); - vmcs12->vm_exit_intr_info = irq | - INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR; - } - if (vm_exit_reason != -1) trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason, vmcs12->exit_qualification, @@ -5890,6 +5964,12 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) return nested_vmx_fail(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); + /* + * Always flush the effective vpid02, i.e. never flush the current VPID + * and never explicitly flush vpid01. INVVPID targets a VPID, not a + * VMCS, and so whether or not the current vmcs12 has VPID enabled is + * irrelevant (and there may not be a loaded vmcs12). + */ vpid02 = nested_get_vpid02(vcpu); switch (type) { case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: @@ -7051,7 +7131,7 @@ static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf, { msrs->misc_low = (u32)vmcs_conf->misc & VMX_MISC_SAVE_EFER_LMA; msrs->misc_low |= - MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS | + VMX_MISC_VMWRITE_SHADOW_RO_FIELDS | VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE | VMX_MISC_ACTIVITY_HLT | VMX_MISC_ACTIVITY_WAIT_SIPI; @@ -7066,12 +7146,10 @@ static void nested_vmx_setup_basic(struct nested_vmx_msrs *msrs) * guest, and the VMCS structure we give it - not about the * VMX support of the underlying hardware. */ - msrs->basic = - VMCS12_REVISION | - VMX_BASIC_TRUE_CTLS | - ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) | - (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT); + msrs->basic = vmx_basic_encode_vmcs_info(VMCS12_REVISION, VMCS12_SIZE, + X86_MEMTYPE_WB); + msrs->basic |= VMX_BASIC_TRUE_CTLS; if (cpu_has_vmx_basic_inout()) msrs->basic |= VMX_BASIC_INOUT; } diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index cce4e2aa30fb..2c296b6abb8c 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -39,11 +39,17 @@ bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port, static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) { + lockdep_assert_once(lockdep_is_held(&vcpu->mutex) || + !refcount_read(&vcpu->kvm->users_count)); + return to_vmx(vcpu)->nested.cached_vmcs12; } static inline struct vmcs12 *get_shadow_vmcs12(struct kvm_vcpu *vcpu) { + lockdep_assert_once(lockdep_is_held(&vcpu->mutex) || + !refcount_read(&vcpu->kvm->users_count)); + return to_vmx(vcpu)->nested.cached_shadow_vmcs12; } @@ -109,7 +115,7 @@ static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu) static inline bool nested_cpu_has_vmwrite_any_field(struct kvm_vcpu *vcpu) { return to_vmx(vcpu)->nested.msrs.misc_low & - MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS; + VMX_MISC_VMWRITE_SHADOW_RO_FIELDS; } static inline bool nested_cpu_has_zero_length_injection(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index 6fef01e0536e..a3c3d2a51f47 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -274,7 +274,7 @@ static int handle_encls_ecreate(struct kvm_vcpu *vcpu) * simultaneously set SGX_ATTR_PROVISIONKEY to bypass the check to * enforce restriction of access to the PROVISIONKEY. */ - contents = (struct sgx_secs *)__get_free_page(GFP_KERNEL_ACCOUNT); + contents = (struct sgx_secs *)__get_free_page(GFP_KERNEL); if (!contents) return -ENOMEM; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index f18c2d8c7476..d28618e9277e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -217,9 +217,11 @@ module_param(ple_window_shrink, uint, 0444); static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX; module_param(ple_window_max, uint, 0444); -/* Default is SYSTEM mode, 1 for host-guest mode */ +/* Default is SYSTEM mode, 1 for host-guest mode (which is BROKEN) */ int __read_mostly pt_mode = PT_MODE_SYSTEM; +#ifdef CONFIG_BROKEN module_param(pt_mode, int, S_IRUGO); +#endif struct x86_pmu_lbr __ro_after_init vmx_lbr_caps; @@ -525,10 +527,6 @@ static const struct kvm_vmx_segment_field { VMX_SEGMENT_FIELD(LDTR), }; -static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx) -{ - vmx->segment_cache.bitmask = 0; -} static unsigned long host_idt_base; @@ -755,7 +753,7 @@ fault: return -EIO; } -static void vmx_emergency_disable(void) +void vmx_emergency_disable_virtualization_cpu(void) { int cpu = raw_smp_processor_id(); struct loaded_vmcs *v; @@ -1998,15 +1996,15 @@ static inline bool is_vmx_feature_control_msr_valid(struct vcpu_vmx *vmx, return !(msr->data & ~valid_bits); } -int vmx_get_msr_feature(struct kvm_msr_entry *msr) +int vmx_get_feature_msr(u32 msr, u64 *data) { - switch (msr->index) { + switch (msr) { case KVM_FIRST_EMULATED_VMX_MSR ... KVM_LAST_EMULATED_VMX_MSR: if (!nested) return 1; - return vmx_get_vmx_msr(&vmcs_config.nested, msr->index, &msr->data); + return vmx_get_vmx_msr(&vmcs_config.nested, msr, data); default: - return KVM_MSR_RET_INVALID; + return KVM_MSR_RET_UNSUPPORTED; } } @@ -2605,13 +2603,13 @@ static u64 adjust_vmx_controls64(u64 ctl_opt, u32 msr) static int setup_vmcs_config(struct vmcs_config *vmcs_conf, struct vmx_capability *vmx_cap) { - u32 vmx_msr_low, vmx_msr_high; u32 _pin_based_exec_control = 0; u32 _cpu_based_exec_control = 0; u32 _cpu_based_2nd_exec_control = 0; u64 _cpu_based_3rd_exec_control = 0; u32 _vmexit_control = 0; u32 _vmentry_control = 0; + u64 basic_msr; u64 misc_msr; int i; @@ -2734,29 +2732,29 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf, _vmexit_control &= ~x_ctrl; } - rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high); + rdmsrl(MSR_IA32_VMX_BASIC, basic_msr); /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ - if ((vmx_msr_high & 0x1fff) > PAGE_SIZE) + if (vmx_basic_vmcs_size(basic_msr) > PAGE_SIZE) return -EIO; #ifdef CONFIG_X86_64 - /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ - if (vmx_msr_high & (1u<<16)) + /* + * KVM expects to be able to shove all legal physical addresses into + * VMCS fields for 64-bit kernels, and per the SDM, "This bit is always + * 0 for processors that support Intel 64 architecture". + */ + if (basic_msr & VMX_BASIC_32BIT_PHYS_ADDR_ONLY) return -EIO; #endif /* Require Write-Back (WB) memory type for VMCS accesses. */ - if (((vmx_msr_high >> 18) & 15) != 6) + if (vmx_basic_vmcs_mem_type(basic_msr) != X86_MEMTYPE_WB) return -EIO; rdmsrl(MSR_IA32_VMX_MISC, misc_msr); - vmcs_conf->size = vmx_msr_high & 0x1fff; - vmcs_conf->basic_cap = vmx_msr_high & ~0x1fff; - - vmcs_conf->revision_id = vmx_msr_low; - + vmcs_conf->basic = basic_msr; vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control; vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control; vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control; @@ -2844,7 +2842,7 @@ fault: return -EFAULT; } -int vmx_hardware_enable(void) +int vmx_enable_virtualization_cpu(void) { int cpu = raw_smp_processor_id(); u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); @@ -2881,7 +2879,7 @@ static void vmclear_local_loaded_vmcss(void) __loaded_vmcs_clear(v); } -void vmx_hardware_disable(void) +void vmx_disable_virtualization_cpu(void) { vmclear_local_loaded_vmcss(); @@ -2903,13 +2901,13 @@ struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags) if (!pages) return NULL; vmcs = page_address(pages); - memset(vmcs, 0, vmcs_config.size); + memset(vmcs, 0, vmx_basic_vmcs_size(vmcs_config.basic)); /* KVM supports Enlightened VMCS v1 only */ if (kvm_is_using_evmcs()) vmcs->hdr.revision_id = KVM_EVMCS_VERSION; else - vmcs->hdr.revision_id = vmcs_config.revision_id; + vmcs->hdr.revision_id = vmx_basic_vmcs_revision_id(vmcs_config.basic); if (shadow) vmcs->hdr.shadow_vmcs = 1; @@ -3002,7 +3000,7 @@ static __init int alloc_kvm_area(void) * physical CPU. */ if (kvm_is_using_evmcs()) - vmcs->hdr.revision_id = vmcs_config.revision_id; + vmcs->hdr.revision_id = vmx_basic_vmcs_revision_id(vmcs_config.basic); per_cpu(vmxarea, cpu) = vmcs; } @@ -3220,7 +3218,7 @@ void vmx_flush_tlb_all(struct kvm_vcpu *vcpu) static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu) { - if (is_guest_mode(vcpu)) + if (is_guest_mode(vcpu) && nested_cpu_has_vpid(get_vmcs12(vcpu))) return nested_get_vpid02(vcpu); return to_vmx(vcpu)->vpid; } @@ -4219,6 +4217,13 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu, { struct vcpu_vmx *vmx = to_vmx(vcpu); + /* + * DO NOT query the vCPU's vmcs12, as vmcs12 is dynamically allocated + * and freed, and must not be accessed outside of vcpu->mutex. The + * vCPU's cached PI NV is valid if and only if posted interrupts + * enabled in its vmcs12, i.e. checking the vector also checks that + * L1 has enabled posted interrupts for L2. + */ if (is_guest_mode(vcpu) && vector == vmx->nested.posted_intr_nv) { /* @@ -4885,9 +4890,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) vmx->hv_deadline_tsc = -1; kvm_set_cr8(vcpu, 0); - vmx_segment_cache_clear(vmx); - kvm_register_mark_available(vcpu, VCPU_EXREG_SEGMENTS); - seg_setup(VCPU_SREG_CS); vmcs_write16(GUEST_CS_SELECTOR, 0xf000); vmcs_writel(GUEST_CS_BASE, 0xffff0000ul); @@ -4914,6 +4916,9 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) vmcs_writel(GUEST_IDTR_BASE, 0); vmcs_write32(GUEST_IDTR_LIMIT, 0xffff); + vmx_segment_cache_clear(vmx); + kvm_register_mark_available(vcpu, VCPU_EXREG_SEGMENTS); + vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE); vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0); vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, 0); @@ -5804,8 +5809,9 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) error_code |= (exit_qualification & EPT_VIOLATION_RWX_MASK) ? PFERR_PRESENT_MASK : 0; - error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) != 0 ? - PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; + if (error_code & EPT_VIOLATION_GVA_IS_VALID) + error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) ? + PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK; /* * Check that the GPA doesn't exceed physical memory limits, as that is @@ -7265,6 +7271,8 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu, return handle_fastpath_set_msr_irqoff(vcpu); case EXIT_REASON_PREEMPTION_TIMER: return handle_fastpath_preemption_timer(vcpu, force_immediate_exit); + case EXIT_REASON_HLT: + return handle_fastpath_hlt(vcpu); default: return EXIT_FASTPATH_NONE; } @@ -7659,13 +7667,11 @@ u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) /* * Force WB and ignore guest PAT if the VM does NOT have a non-coherent - * device attached and the CPU doesn't support self-snoop. Letting the - * guest control memory types on Intel CPUs without self-snoop may - * result in unexpected behavior, and so KVM's (historical) ABI is to - * trust the guest to behave only as a last resort. + * device attached. Letting the guest control memory types on Intel + * CPUs may result in unexpected behavior, and so KVM's ABI is to trust + * the guest to behave only as a last resort. */ - if (!static_cpu_has(X86_FEATURE_SELFSNOOP) && - !kvm_arch_has_noncoherent_dma(vcpu->kvm)) + if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IPAT_BIT; return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT); @@ -7967,6 +7973,7 @@ static __init void vmx_set_cpu_caps(void) kvm_cpu_cap_clear(X86_FEATURE_SGX_LC); kvm_cpu_cap_clear(X86_FEATURE_SGX1); kvm_cpu_cap_clear(X86_FEATURE_SGX2); + kvm_cpu_cap_clear(X86_FEATURE_SGX_EDECCSSA); } if (vmx_umip_emulated()) @@ -8517,7 +8524,7 @@ __init int vmx_hardware_setup(void) u64 use_timer_freq = 5000ULL * 1000 * 1000; cpu_preemption_timer_multi = - vmcs_config.misc & VMX_MISC_PREEMPTION_TIMER_RATE_MASK; + vmx_misc_preemption_timer_rate(vmcs_config.misc); if (tsc_khz) use_timer_freq = (u64)tsc_khz * 1000; @@ -8584,8 +8591,6 @@ static void __vmx_exit(void) { allow_smaller_maxphyaddr = false; - cpu_emergency_unregister_virt_callback(vmx_emergency_disable); - vmx_cleanup_l1d_flush(); } @@ -8632,8 +8637,6 @@ static int __init vmx_init(void) pi_init_cpu(cpu); } - cpu_emergency_register_virt_callback(vmx_emergency_disable); - vmx_check_vmcs12_offsets(); /* diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 42498fa63abb..2325f773a20b 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -17,10 +17,6 @@ #include "run_flags.h" #include "../mmu.h" -#define MSR_TYPE_R 1 -#define MSR_TYPE_W 2 -#define MSR_TYPE_RW 3 - #define X2APIC_MSR(r) (APIC_BASE_MSR + ((r) >> 4)) #ifdef CONFIG_X86_64 @@ -756,4 +752,9 @@ static inline bool vmx_can_use_ipiv(struct kvm_vcpu *vcpu) return lapic_in_kernel(vcpu) && enable_ipiv; } +static inline void vmx_segment_cache_clear(struct vcpu_vmx *vmx) +{ + vmx->segment_cache.bitmask = 0; +} + #endif /* __KVM_X86_VMX_H */ diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.h b/arch/x86/kvm/vmx/vmx_onhyperv.h index eb48153bfd73..bba24ed99ee6 100644 --- a/arch/x86/kvm/vmx/vmx_onhyperv.h +++ b/arch/x86/kvm/vmx/vmx_onhyperv.h @@ -104,6 +104,14 @@ static inline void evmcs_load(u64 phys_addr) struct hv_vp_assist_page *vp_ap = hv_get_vp_assist_page(smp_processor_id()); + /* + * When enabling eVMCS, KVM verifies that every CPU has a valid hv_vp_assist_page() + * and aborts enabling the feature otherwise. CPU onlining path is also checked in + * vmx_hardware_enable(). + */ + if (KVM_BUG_ON(!vp_ap, kvm_get_running_vcpu()->kvm)) + return; + if (current_evmcs->hv_enlightenments_control.nested_flush_hypercall) vp_ap->nested_control.features.directhypercall = 1; vp_ap->current_nested_vmcs = phys_addr; diff --git a/arch/x86/kvm/vmx/vmx_ops.h b/arch/x86/kvm/vmx/vmx_ops.h index 8060e5fc6dbd..93e020dc88f6 100644 --- a/arch/x86/kvm/vmx/vmx_ops.h +++ b/arch/x86/kvm/vmx/vmx_ops.h @@ -47,7 +47,7 @@ static __always_inline void vmcs_check16(unsigned long field) BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001, "16-bit accessor invalid for 64-bit high field"); BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000, - "16-bit accessor invalid for 32-bit high field"); + "16-bit accessor invalid for 32-bit field"); BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000, "16-bit accessor invalid for natural width field"); } diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h index ce3221cd1d01..a55981c5216e 100644 --- a/arch/x86/kvm/vmx/x86_ops.h +++ b/arch/x86/kvm/vmx/x86_ops.h @@ -13,8 +13,9 @@ extern struct kvm_x86_init_ops vt_init_ops __initdata; void vmx_hardware_unsetup(void); int vmx_check_processor_compat(void); -int vmx_hardware_enable(void); -void vmx_hardware_disable(void); +int vmx_enable_virtualization_cpu(void); +void vmx_disable_virtualization_cpu(void); +void vmx_emergency_disable_virtualization_cpu(void); int vmx_vm_init(struct kvm *kvm); void vmx_vm_destroy(struct kvm *kvm); int vmx_vcpu_precreate(struct kvm *kvm); @@ -56,7 +57,7 @@ bool vmx_has_emulated_msr(struct kvm *kvm, u32 index); void vmx_msr_filter_changed(struct kvm_vcpu *vcpu); void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu); void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu); -int vmx_get_msr_feature(struct kvm_msr_entry *msr); +int vmx_get_feature_msr(u32 msr, u64 *data); int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info); u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg); void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 70219e406987..83fe0a78146f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -305,24 +305,237 @@ const struct kvm_stats_header kvm_vcpu_stats_header = { static struct kmem_cache *x86_emulator_cache; /* - * When called, it means the previous get/set msr reached an invalid msr. - * Return true if we want to ignore/silent this failed msr access. + * The three MSR lists(msrs_to_save, emulated_msrs, msr_based_features) track + * the set of MSRs that KVM exposes to userspace through KVM_GET_MSRS, + * KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. msrs_to_save holds MSRs that + * require host support, i.e. should be probed via RDMSR. emulated_msrs holds + * MSRs that KVM emulates without strictly requiring host support. + * msr_based_features holds MSRs that enumerate features, i.e. are effectively + * CPUID leafs. Note, msr_based_features isn't mutually exclusive with + * msrs_to_save and emulated_msrs. + */ + +static const u32 msrs_to_save_base[] = { + MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, + MSR_STAR, +#ifdef CONFIG_X86_64 + MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, +#endif + MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, + MSR_IA32_FEAT_CTL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, + MSR_IA32_SPEC_CTRL, MSR_IA32_TSX_CTRL, + MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_STATUS, MSR_IA32_RTIT_CR3_MATCH, + MSR_IA32_RTIT_OUTPUT_BASE, MSR_IA32_RTIT_OUTPUT_MASK, + MSR_IA32_RTIT_ADDR0_A, MSR_IA32_RTIT_ADDR0_B, + MSR_IA32_RTIT_ADDR1_A, MSR_IA32_RTIT_ADDR1_B, + MSR_IA32_RTIT_ADDR2_A, MSR_IA32_RTIT_ADDR2_B, + MSR_IA32_RTIT_ADDR3_A, MSR_IA32_RTIT_ADDR3_B, + MSR_IA32_UMWAIT_CONTROL, + + MSR_IA32_XFD, MSR_IA32_XFD_ERR, +}; + +static const u32 msrs_to_save_pmu[] = { + MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1, + MSR_ARCH_PERFMON_FIXED_CTR0 + 2, + MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, + MSR_CORE_PERF_GLOBAL_CTRL, + MSR_IA32_PEBS_ENABLE, MSR_IA32_DS_AREA, MSR_PEBS_DATA_CFG, + + /* This part of MSRs should match KVM_MAX_NR_INTEL_GP_COUNTERS. */ + MSR_ARCH_PERFMON_PERFCTR0, MSR_ARCH_PERFMON_PERFCTR1, + MSR_ARCH_PERFMON_PERFCTR0 + 2, MSR_ARCH_PERFMON_PERFCTR0 + 3, + MSR_ARCH_PERFMON_PERFCTR0 + 4, MSR_ARCH_PERFMON_PERFCTR0 + 5, + MSR_ARCH_PERFMON_PERFCTR0 + 6, MSR_ARCH_PERFMON_PERFCTR0 + 7, + MSR_ARCH_PERFMON_EVENTSEL0, MSR_ARCH_PERFMON_EVENTSEL1, + MSR_ARCH_PERFMON_EVENTSEL0 + 2, MSR_ARCH_PERFMON_EVENTSEL0 + 3, + MSR_ARCH_PERFMON_EVENTSEL0 + 4, MSR_ARCH_PERFMON_EVENTSEL0 + 5, + MSR_ARCH_PERFMON_EVENTSEL0 + 6, MSR_ARCH_PERFMON_EVENTSEL0 + 7, + + MSR_K7_EVNTSEL0, MSR_K7_EVNTSEL1, MSR_K7_EVNTSEL2, MSR_K7_EVNTSEL3, + MSR_K7_PERFCTR0, MSR_K7_PERFCTR1, MSR_K7_PERFCTR2, MSR_K7_PERFCTR3, + + /* This part of MSRs should match KVM_MAX_NR_AMD_GP_COUNTERS. */ + MSR_F15H_PERF_CTL0, MSR_F15H_PERF_CTL1, MSR_F15H_PERF_CTL2, + MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5, + MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2, + MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5, + + MSR_AMD64_PERF_CNTR_GLOBAL_CTL, + MSR_AMD64_PERF_CNTR_GLOBAL_STATUS, + MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, +}; + +static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_base) + + ARRAY_SIZE(msrs_to_save_pmu)]; +static unsigned num_msrs_to_save; + +static const u32 emulated_msrs_all[] = { + MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, + MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, + +#ifdef CONFIG_KVM_HYPERV + HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, + HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC, + HV_X64_MSR_TSC_FREQUENCY, HV_X64_MSR_APIC_FREQUENCY, + HV_X64_MSR_CRASH_P0, HV_X64_MSR_CRASH_P1, HV_X64_MSR_CRASH_P2, + HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL, + HV_X64_MSR_RESET, + HV_X64_MSR_VP_INDEX, + HV_X64_MSR_VP_RUNTIME, + HV_X64_MSR_SCONTROL, + HV_X64_MSR_STIMER0_CONFIG, + HV_X64_MSR_VP_ASSIST_PAGE, + HV_X64_MSR_REENLIGHTENMENT_CONTROL, HV_X64_MSR_TSC_EMULATION_CONTROL, + HV_X64_MSR_TSC_EMULATION_STATUS, HV_X64_MSR_TSC_INVARIANT_CONTROL, + HV_X64_MSR_SYNDBG_OPTIONS, + HV_X64_MSR_SYNDBG_CONTROL, HV_X64_MSR_SYNDBG_STATUS, + HV_X64_MSR_SYNDBG_SEND_BUFFER, HV_X64_MSR_SYNDBG_RECV_BUFFER, + HV_X64_MSR_SYNDBG_PENDING_BUFFER, +#endif + + MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME, + MSR_KVM_PV_EOI_EN, MSR_KVM_ASYNC_PF_INT, MSR_KVM_ASYNC_PF_ACK, + + MSR_IA32_TSC_ADJUST, + MSR_IA32_TSC_DEADLINE, + MSR_IA32_ARCH_CAPABILITIES, + MSR_IA32_PERF_CAPABILITIES, + MSR_IA32_MISC_ENABLE, + MSR_IA32_MCG_STATUS, + MSR_IA32_MCG_CTL, + MSR_IA32_MCG_EXT_CTL, + MSR_IA32_SMBASE, + MSR_SMI_COUNT, + MSR_PLATFORM_INFO, + MSR_MISC_FEATURES_ENABLES, + MSR_AMD64_VIRT_SPEC_CTRL, + MSR_AMD64_TSC_RATIO, + MSR_IA32_POWER_CTL, + MSR_IA32_UCODE_REV, + + /* + * KVM always supports the "true" VMX control MSRs, even if the host + * does not. The VMX MSRs as a whole are considered "emulated" as KVM + * doesn't strictly require them to exist in the host (ignoring that + * KVM would refuse to load in the first place if the core set of MSRs + * aren't supported). + */ + MSR_IA32_VMX_BASIC, + MSR_IA32_VMX_TRUE_PINBASED_CTLS, + MSR_IA32_VMX_TRUE_PROCBASED_CTLS, + MSR_IA32_VMX_TRUE_EXIT_CTLS, + MSR_IA32_VMX_TRUE_ENTRY_CTLS, + MSR_IA32_VMX_MISC, + MSR_IA32_VMX_CR0_FIXED0, + MSR_IA32_VMX_CR4_FIXED0, + MSR_IA32_VMX_VMCS_ENUM, + MSR_IA32_VMX_PROCBASED_CTLS2, + MSR_IA32_VMX_EPT_VPID_CAP, + MSR_IA32_VMX_VMFUNC, + + MSR_K7_HWCR, + MSR_KVM_POLL_CONTROL, +}; + +static u32 emulated_msrs[ARRAY_SIZE(emulated_msrs_all)]; +static unsigned num_emulated_msrs; + +/* + * List of MSRs that control the existence of MSR-based features, i.e. MSRs + * that are effectively CPUID leafs. VMX MSRs are also included in the set of + * feature MSRs, but are handled separately to allow expedited lookups. + */ +static const u32 msr_based_features_all_except_vmx[] = { + MSR_AMD64_DE_CFG, + MSR_IA32_UCODE_REV, + MSR_IA32_ARCH_CAPABILITIES, + MSR_IA32_PERF_CAPABILITIES, +}; + +static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all_except_vmx) + + (KVM_LAST_EMULATED_VMX_MSR - KVM_FIRST_EMULATED_VMX_MSR + 1)]; +static unsigned int num_msr_based_features; + +/* + * All feature MSRs except uCode revID, which tracks the currently loaded uCode + * patch, are immutable once the vCPU model is defined. */ -static bool kvm_msr_ignored_check(u32 msr, u64 data, bool write) +static bool kvm_is_immutable_feature_msr(u32 msr) { - const char *op = write ? "wrmsr" : "rdmsr"; + int i; - if (ignore_msrs) { - if (report_ignored_msrs) - kvm_pr_unimpl("ignored %s: 0x%x data 0x%llx\n", - op, msr, data); - /* Mask the error */ + if (msr >= KVM_FIRST_EMULATED_VMX_MSR && msr <= KVM_LAST_EMULATED_VMX_MSR) return true; - } else { + + for (i = 0; i < ARRAY_SIZE(msr_based_features_all_except_vmx); i++) { + if (msr == msr_based_features_all_except_vmx[i]) + return msr != MSR_IA32_UCODE_REV; + } + + return false; +} + +static bool kvm_is_advertised_msr(u32 msr_index) +{ + unsigned int i; + + for (i = 0; i < num_msrs_to_save; i++) { + if (msrs_to_save[i] == msr_index) + return true; + } + + for (i = 0; i < num_emulated_msrs; i++) { + if (emulated_msrs[i] == msr_index) + return true; + } + + return false; +} + +typedef int (*msr_access_t)(struct kvm_vcpu *vcpu, u32 index, u64 *data, + bool host_initiated); + +static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr, + u64 *data, bool host_initiated, + enum kvm_msr_access rw, + msr_access_t msr_access_fn) +{ + const char *op = rw == MSR_TYPE_W ? "wrmsr" : "rdmsr"; + int ret; + + BUILD_BUG_ON(rw != MSR_TYPE_R && rw != MSR_TYPE_W); + + /* + * Zero the data on read failures to avoid leaking stack data to the + * guest and/or userspace, e.g. if the failure is ignored below. + */ + ret = msr_access_fn(vcpu, msr, data, host_initiated); + if (ret && rw == MSR_TYPE_R) + *data = 0; + + if (ret != KVM_MSR_RET_UNSUPPORTED) + return ret; + + /* + * Userspace is allowed to read MSRs, and write '0' to MSRs, that KVM + * advertises to userspace, even if an MSR isn't fully supported. + * Simply check that @data is '0', which covers both the write '0' case + * and all reads (in which case @data is zeroed on failure; see above). + */ + if (host_initiated && !*data && kvm_is_advertised_msr(msr)) + return 0; + + if (!ignore_msrs) { kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n", - op, msr, data); - return false; + op, msr, *data); + return ret; } + + if (report_ignored_msrs) + kvm_pr_unimpl("ignored %s: 0x%x data 0x%llx\n", op, msr, *data); + + return 0; } static struct kmem_cache *kvm_alloc_emulator_cache(void) @@ -355,7 +568,7 @@ static void kvm_on_user_return(struct user_return_notifier *urn) /* * Disabling irqs at this point since the following code could be - * interrupted and executed through kvm_arch_hardware_disable() + * interrupted and executed through kvm_arch_disable_virtualization_cpu() */ local_irq_save(flags); if (msrs->registered) { @@ -413,8 +626,7 @@ EXPORT_SYMBOL_GPL(kvm_find_user_return_msr); static void kvm_user_return_msr_cpu_online(void) { - unsigned int cpu = smp_processor_id(); - struct kvm_user_return_msrs *msrs = per_cpu_ptr(user_return_msrs, cpu); + struct kvm_user_return_msrs *msrs = this_cpu_ptr(user_return_msrs); u64 value; int i; @@ -621,12 +833,6 @@ static void kvm_queue_exception_vmexit(struct kvm_vcpu *vcpu, unsigned int vecto ex->payload = payload; } -/* Forcibly leave the nested mode in cases like a vCPU reset */ -static void kvm_leave_nested(struct kvm_vcpu *vcpu) -{ - kvm_x86_ops.nested_ops->leave_nested(vcpu); -} - static void kvm_multiple_exception(struct kvm_vcpu *vcpu, unsigned nr, bool has_error, u32 error_code, bool has_payload, unsigned long payload, bool reinject) @@ -1412,178 +1618,6 @@ int kvm_emulate_rdpmc(struct kvm_vcpu *vcpu) EXPORT_SYMBOL_GPL(kvm_emulate_rdpmc); /* - * The three MSR lists(msrs_to_save, emulated_msrs, msr_based_features) track - * the set of MSRs that KVM exposes to userspace through KVM_GET_MSRS, - * KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. msrs_to_save holds MSRs that - * require host support, i.e. should be probed via RDMSR. emulated_msrs holds - * MSRs that KVM emulates without strictly requiring host support. - * msr_based_features holds MSRs that enumerate features, i.e. are effectively - * CPUID leafs. Note, msr_based_features isn't mutually exclusive with - * msrs_to_save and emulated_msrs. - */ - -static const u32 msrs_to_save_base[] = { - MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, - MSR_STAR, -#ifdef CONFIG_X86_64 - MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, -#endif - MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, - MSR_IA32_FEAT_CTL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, - MSR_IA32_SPEC_CTRL, MSR_IA32_TSX_CTRL, - MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_STATUS, MSR_IA32_RTIT_CR3_MATCH, - MSR_IA32_RTIT_OUTPUT_BASE, MSR_IA32_RTIT_OUTPUT_MASK, - MSR_IA32_RTIT_ADDR0_A, MSR_IA32_RTIT_ADDR0_B, - MSR_IA32_RTIT_ADDR1_A, MSR_IA32_RTIT_ADDR1_B, - MSR_IA32_RTIT_ADDR2_A, MSR_IA32_RTIT_ADDR2_B, - MSR_IA32_RTIT_ADDR3_A, MSR_IA32_RTIT_ADDR3_B, - MSR_IA32_UMWAIT_CONTROL, - - MSR_IA32_XFD, MSR_IA32_XFD_ERR, -}; - -static const u32 msrs_to_save_pmu[] = { - MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1, - MSR_ARCH_PERFMON_FIXED_CTR0 + 2, - MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, - MSR_CORE_PERF_GLOBAL_CTRL, - MSR_IA32_PEBS_ENABLE, MSR_IA32_DS_AREA, MSR_PEBS_DATA_CFG, - - /* This part of MSRs should match KVM_MAX_NR_INTEL_GP_COUNTERS. */ - MSR_ARCH_PERFMON_PERFCTR0, MSR_ARCH_PERFMON_PERFCTR1, - MSR_ARCH_PERFMON_PERFCTR0 + 2, MSR_ARCH_PERFMON_PERFCTR0 + 3, - MSR_ARCH_PERFMON_PERFCTR0 + 4, MSR_ARCH_PERFMON_PERFCTR0 + 5, - MSR_ARCH_PERFMON_PERFCTR0 + 6, MSR_ARCH_PERFMON_PERFCTR0 + 7, - MSR_ARCH_PERFMON_EVENTSEL0, MSR_ARCH_PERFMON_EVENTSEL1, - MSR_ARCH_PERFMON_EVENTSEL0 + 2, MSR_ARCH_PERFMON_EVENTSEL0 + 3, - MSR_ARCH_PERFMON_EVENTSEL0 + 4, MSR_ARCH_PERFMON_EVENTSEL0 + 5, - MSR_ARCH_PERFMON_EVENTSEL0 + 6, MSR_ARCH_PERFMON_EVENTSEL0 + 7, - - MSR_K7_EVNTSEL0, MSR_K7_EVNTSEL1, MSR_K7_EVNTSEL2, MSR_K7_EVNTSEL3, - MSR_K7_PERFCTR0, MSR_K7_PERFCTR1, MSR_K7_PERFCTR2, MSR_K7_PERFCTR3, - - /* This part of MSRs should match KVM_MAX_NR_AMD_GP_COUNTERS. */ - MSR_F15H_PERF_CTL0, MSR_F15H_PERF_CTL1, MSR_F15H_PERF_CTL2, - MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5, - MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2, - MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5, - - MSR_AMD64_PERF_CNTR_GLOBAL_CTL, - MSR_AMD64_PERF_CNTR_GLOBAL_STATUS, - MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, -}; - -static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_base) + - ARRAY_SIZE(msrs_to_save_pmu)]; -static unsigned num_msrs_to_save; - -static const u32 emulated_msrs_all[] = { - MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, - MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, - -#ifdef CONFIG_KVM_HYPERV - HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, - HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC, - HV_X64_MSR_TSC_FREQUENCY, HV_X64_MSR_APIC_FREQUENCY, - HV_X64_MSR_CRASH_P0, HV_X64_MSR_CRASH_P1, HV_X64_MSR_CRASH_P2, - HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL, - HV_X64_MSR_RESET, - HV_X64_MSR_VP_INDEX, - HV_X64_MSR_VP_RUNTIME, - HV_X64_MSR_SCONTROL, - HV_X64_MSR_STIMER0_CONFIG, - HV_X64_MSR_VP_ASSIST_PAGE, - HV_X64_MSR_REENLIGHTENMENT_CONTROL, HV_X64_MSR_TSC_EMULATION_CONTROL, - HV_X64_MSR_TSC_EMULATION_STATUS, HV_X64_MSR_TSC_INVARIANT_CONTROL, - HV_X64_MSR_SYNDBG_OPTIONS, - HV_X64_MSR_SYNDBG_CONTROL, HV_X64_MSR_SYNDBG_STATUS, - HV_X64_MSR_SYNDBG_SEND_BUFFER, HV_X64_MSR_SYNDBG_RECV_BUFFER, - HV_X64_MSR_SYNDBG_PENDING_BUFFER, -#endif - - MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME, - MSR_KVM_PV_EOI_EN, MSR_KVM_ASYNC_PF_INT, MSR_KVM_ASYNC_PF_ACK, - - MSR_IA32_TSC_ADJUST, - MSR_IA32_TSC_DEADLINE, - MSR_IA32_ARCH_CAPABILITIES, - MSR_IA32_PERF_CAPABILITIES, - MSR_IA32_MISC_ENABLE, - MSR_IA32_MCG_STATUS, - MSR_IA32_MCG_CTL, - MSR_IA32_MCG_EXT_CTL, - MSR_IA32_SMBASE, - MSR_SMI_COUNT, - MSR_PLATFORM_INFO, - MSR_MISC_FEATURES_ENABLES, - MSR_AMD64_VIRT_SPEC_CTRL, - MSR_AMD64_TSC_RATIO, - MSR_IA32_POWER_CTL, - MSR_IA32_UCODE_REV, - - /* - * KVM always supports the "true" VMX control MSRs, even if the host - * does not. The VMX MSRs as a whole are considered "emulated" as KVM - * doesn't strictly require them to exist in the host (ignoring that - * KVM would refuse to load in the first place if the core set of MSRs - * aren't supported). - */ - MSR_IA32_VMX_BASIC, - MSR_IA32_VMX_TRUE_PINBASED_CTLS, - MSR_IA32_VMX_TRUE_PROCBASED_CTLS, - MSR_IA32_VMX_TRUE_EXIT_CTLS, - MSR_IA32_VMX_TRUE_ENTRY_CTLS, - MSR_IA32_VMX_MISC, - MSR_IA32_VMX_CR0_FIXED0, - MSR_IA32_VMX_CR4_FIXED0, - MSR_IA32_VMX_VMCS_ENUM, - MSR_IA32_VMX_PROCBASED_CTLS2, - MSR_IA32_VMX_EPT_VPID_CAP, - MSR_IA32_VMX_VMFUNC, - - MSR_K7_HWCR, - MSR_KVM_POLL_CONTROL, -}; - -static u32 emulated_msrs[ARRAY_SIZE(emulated_msrs_all)]; -static unsigned num_emulated_msrs; - -/* - * List of MSRs that control the existence of MSR-based features, i.e. MSRs - * that are effectively CPUID leafs. VMX MSRs are also included in the set of - * feature MSRs, but are handled separately to allow expedited lookups. - */ -static const u32 msr_based_features_all_except_vmx[] = { - MSR_AMD64_DE_CFG, - MSR_IA32_UCODE_REV, - MSR_IA32_ARCH_CAPABILITIES, - MSR_IA32_PERF_CAPABILITIES, -}; - -static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all_except_vmx) + - (KVM_LAST_EMULATED_VMX_MSR - KVM_FIRST_EMULATED_VMX_MSR + 1)]; -static unsigned int num_msr_based_features; - -/* - * All feature MSRs except uCode revID, which tracks the currently loaded uCode - * patch, are immutable once the vCPU model is defined. - */ -static bool kvm_is_immutable_feature_msr(u32 msr) -{ - int i; - - if (msr >= KVM_FIRST_EMULATED_VMX_MSR && msr <= KVM_LAST_EMULATED_VMX_MSR) - return true; - - for (i = 0; i < ARRAY_SIZE(msr_based_features_all_except_vmx); i++) { - if (msr == msr_based_features_all_except_vmx[i]) - return msr != MSR_IA32_UCODE_REV; - } - - return false; -} - -/* * Some IA32_ARCH_CAPABILITIES bits have dependencies on MSRs that KVM * does not yet virtualize. These include: * 10 - MISC_PACKAGE_CTRLS @@ -1660,40 +1694,31 @@ static u64 kvm_get_arch_capabilities(void) return data; } -static int kvm_get_msr_feature(struct kvm_msr_entry *msr) +static int kvm_get_feature_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, + bool host_initiated) { - switch (msr->index) { + WARN_ON_ONCE(!host_initiated); + + switch (index) { case MSR_IA32_ARCH_CAPABILITIES: - msr->data = kvm_get_arch_capabilities(); + *data = kvm_get_arch_capabilities(); break; case MSR_IA32_PERF_CAPABILITIES: - msr->data = kvm_caps.supported_perf_cap; + *data = kvm_caps.supported_perf_cap; break; case MSR_IA32_UCODE_REV: - rdmsrl_safe(msr->index, &msr->data); + rdmsrl_safe(index, data); break; default: - return kvm_x86_call(get_msr_feature)(msr); + return kvm_x86_call(get_feature_msr)(index, data); } return 0; } -static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data) +static int do_get_feature_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) { - struct kvm_msr_entry msr; - int r; - - /* Unconditionally clear the output for simplicity */ - msr.data = 0; - msr.index = index; - r = kvm_get_msr_feature(&msr); - - if (r == KVM_MSR_RET_INVALID && kvm_msr_ignored_check(index, 0, false)) - r = 0; - - *data = msr.data; - - return r; + return kvm_do_msr_access(vcpu, index, data, true, MSR_TYPE_R, + kvm_get_feature_msr); } static bool __kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer) @@ -1880,16 +1905,17 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data, return kvm_x86_call(set_msr)(vcpu, &msr); } +static int _kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, + bool host_initiated) +{ + return __kvm_set_msr(vcpu, index, *data, host_initiated); +} + static int kvm_set_msr_ignored_check(struct kvm_vcpu *vcpu, u32 index, u64 data, bool host_initiated) { - int ret = __kvm_set_msr(vcpu, index, data, host_initiated); - - if (ret == KVM_MSR_RET_INVALID) - if (kvm_msr_ignored_check(index, data, true)) - ret = 0; - - return ret; + return kvm_do_msr_access(vcpu, index, &data, host_initiated, MSR_TYPE_W, + _kvm_set_msr); } /* @@ -1928,31 +1954,25 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu, u32 index, u64 *data, bool host_initiated) { - int ret = __kvm_get_msr(vcpu, index, data, host_initiated); - - if (ret == KVM_MSR_RET_INVALID) { - /* Unconditionally clear *data for simplicity */ - *data = 0; - if (kvm_msr_ignored_check(index, 0, false)) - ret = 0; - } - - return ret; + return kvm_do_msr_access(vcpu, index, data, host_initiated, MSR_TYPE_R, + __kvm_get_msr); } -static int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data) +int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data) { if (!kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_READ)) return KVM_MSR_RET_FILTERED; return kvm_get_msr_ignored_check(vcpu, index, data, false); } +EXPORT_SYMBOL_GPL(kvm_get_msr_with_filter); -static int kvm_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 data) +int kvm_set_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 data) { if (!kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_WRITE)) return KVM_MSR_RET_FILTERED; return kvm_set_msr_ignored_check(vcpu, index, data, false); } +EXPORT_SYMBOL_GPL(kvm_set_msr_with_filter); int kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data) { @@ -1999,7 +2019,7 @@ static int complete_fast_rdmsr(struct kvm_vcpu *vcpu) static u64 kvm_msr_reason(int r) { switch (r) { - case KVM_MSR_RET_INVALID: + case KVM_MSR_RET_UNSUPPORTED: return KVM_MSR_EXIT_REASON_UNKNOWN; case KVM_MSR_RET_FILTERED: return KVM_MSR_EXIT_REASON_FILTER; @@ -2162,31 +2182,34 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu) { u32 msr = kvm_rcx_read(vcpu); u64 data; - fastpath_t ret = EXIT_FASTPATH_NONE; + fastpath_t ret; + bool handled; kvm_vcpu_srcu_read_lock(vcpu); switch (msr) { case APIC_BASE_MSR + (APIC_ICR >> 4): data = kvm_read_edx_eax(vcpu); - if (!handle_fastpath_set_x2apic_icr_irqoff(vcpu, data)) { - kvm_skip_emulated_instruction(vcpu); - ret = EXIT_FASTPATH_EXIT_HANDLED; - } + handled = !handle_fastpath_set_x2apic_icr_irqoff(vcpu, data); break; case MSR_IA32_TSC_DEADLINE: data = kvm_read_edx_eax(vcpu); - if (!handle_fastpath_set_tscdeadline(vcpu, data)) { - kvm_skip_emulated_instruction(vcpu); - ret = EXIT_FASTPATH_REENTER_GUEST; - } + handled = !handle_fastpath_set_tscdeadline(vcpu, data); break; default: + handled = false; break; } - if (ret != EXIT_FASTPATH_NONE) + if (handled) { + if (!kvm_skip_emulated_instruction(vcpu)) + ret = EXIT_FASTPATH_EXIT_USERSPACE; + else + ret = EXIT_FASTPATH_REENTER_GUEST; trace_kvm_msr_write(msr, data); + } else { + ret = EXIT_FASTPATH_NONE; + } kvm_vcpu_srcu_read_unlock(vcpu); @@ -3746,18 +3769,6 @@ static void record_steal_time(struct kvm_vcpu *vcpu) mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa)); } -static bool kvm_is_msr_to_save(u32 msr_index) -{ - unsigned int i; - - for (i = 0; i < num_msrs_to_save; i++) { - if (msrs_to_save[i] == msr_index) - return true; - } - - return false; -} - int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { u32 msr = msr_info->index; @@ -4139,15 +4150,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (kvm_pmu_is_valid_msr(vcpu, msr)) return kvm_pmu_set_msr(vcpu, msr_info); - /* - * Userspace is allowed to write '0' to MSRs that KVM reports - * as to-be-saved, even if an MSRs isn't fully supported. - */ - if (msr_info->host_initiated && !data && - kvm_is_msr_to_save(msr)) - break; - - return KVM_MSR_RET_INVALID; + return KVM_MSR_RET_UNSUPPORTED; } return 0; } @@ -4498,17 +4501,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) return kvm_pmu_get_msr(vcpu, msr_info); - /* - * Userspace is allowed to read MSRs that KVM reports as - * to-be-saved, even if an MSR isn't fully supported. - */ - if (msr_info->host_initiated && - kvm_is_msr_to_save(msr_info->index)) { - msr_info->data = 0; - break; - } - - return KVM_MSR_RET_INVALID; + return KVM_MSR_RET_UNSUPPORTED; } return 0; } @@ -4656,7 +4649,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ASYNC_PF_INT: case KVM_CAP_GET_TSC_KHZ: case KVM_CAP_KVMCLOCK_CTRL: - case KVM_CAP_READONLY_MEM: case KVM_CAP_IOAPIC_POLARITY_IGNORED: case KVM_CAP_TSC_DEADLINE_TIMER: case KVM_CAP_DISABLE_QUIRKS: @@ -4815,6 +4807,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_VM_TYPES: r = kvm_caps.supported_vm_types; break; + case KVM_CAP_READONLY_MEM: + r = kvm ? kvm_arch_has_readonly_mem(kvm) : 1; + break; default: break; } @@ -4944,7 +4939,7 @@ long kvm_arch_dev_ioctl(struct file *filp, break; } case KVM_GET_MSRS: - r = msr_io(NULL, argp, do_get_msr_feature, 1); + r = msr_io(NULL, argp, do_get_feature_msr, 1); break; #ifdef CONFIG_KVM_HYPERV case KVM_GET_SUPPORTED_HV_CPUID: @@ -6040,7 +6035,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, if (copy_from_user(&events, argp, sizeof(struct kvm_vcpu_events))) break; + kvm_vcpu_srcu_read_lock(vcpu); r = kvm_vcpu_ioctl_x86_set_vcpu_events(vcpu, &events); + kvm_vcpu_srcu_read_unlock(vcpu); break; } case KVM_GET_DEBUGREGS: { @@ -7379,11 +7376,9 @@ out: static void kvm_probe_feature_msr(u32 msr_index) { - struct kvm_msr_entry msr = { - .index = msr_index, - }; + u64 data; - if (kvm_get_msr_feature(&msr)) + if (kvm_get_feature_msr(NULL, msr_index, &data, true)) return; msr_based_features[num_msr_based_features++] = msr_index; @@ -8861,60 +8856,13 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type) return 1; } -static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, - int emulation_type) +static bool kvm_unprotect_and_retry_on_failure(struct kvm_vcpu *vcpu, + gpa_t cr2_or_gpa, + int emulation_type) { - gpa_t gpa = cr2_or_gpa; - kvm_pfn_t pfn; - if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF)) return false; - if (WARN_ON_ONCE(is_guest_mode(vcpu)) || - WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF))) - return false; - - if (!vcpu->arch.mmu->root_role.direct) { - /* - * Write permission should be allowed since only - * write access need to be emulated. - */ - gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL); - - /* - * If the mapping is invalid in guest, let cpu retry - * it to generate fault. - */ - if (gpa == INVALID_GPA) - return true; - } - - /* - * Do not retry the unhandleable instruction if it faults on the - * readonly host memory, otherwise it will goto a infinite loop: - * retry instruction -> write #PF -> emulation fail -> retry - * instruction -> ... - */ - pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa)); - - /* - * If the instruction failed on the error pfn, it can not be fixed, - * report the error to userspace. - */ - if (is_error_noslot_pfn(pfn)) - return false; - - kvm_release_pfn_clean(pfn); - - /* - * If emulation may have been triggered by a write to a shadowed page - * table, unprotect the gfn (zap any relevant SPTEs) and re-enter the - * guest to let the CPU re-execute the instruction in the hope that the - * CPU can cleanly execute the instruction that KVM failed to emulate. - */ - if (vcpu->kvm->arch.indirect_shadow_pages) - kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa)); - /* * If the failed instruction faulted on an access to page tables that * are used to translate any part of the instruction, KVM can't resolve @@ -8925,54 +8873,24 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, * then zap the SPTE to unprotect the gfn, and then do it all over * again. Report the error to userspace. */ - return !(emulation_type & EMULTYPE_WRITE_PF_TO_SP); -} - -static bool retry_instruction(struct x86_emulate_ctxt *ctxt, - gpa_t cr2_or_gpa, int emulation_type) -{ - struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - unsigned long last_retry_eip, last_retry_addr, gpa = cr2_or_gpa; - - last_retry_eip = vcpu->arch.last_retry_eip; - last_retry_addr = vcpu->arch.last_retry_addr; + if (emulation_type & EMULTYPE_WRITE_PF_TO_SP) + return false; /* - * If the emulation is caused by #PF and it is non-page_table - * writing instruction, it means the VM-EXIT is caused by shadow - * page protected, we can zap the shadow page and retry this - * instruction directly. - * - * Note: if the guest uses a non-page-table modifying instruction - * on the PDE that points to the instruction, then we will unmap - * the instruction and go to an infinite loop. So, we cache the - * last retried eip and the last fault address, if we meet the eip - * and the address again, we can break out of the potential infinite - * loop. + * If emulation may have been triggered by a write to a shadowed page + * table, unprotect the gfn (zap any relevant SPTEs) and re-enter the + * guest to let the CPU re-execute the instruction in the hope that the + * CPU can cleanly execute the instruction that KVM failed to emulate. */ - vcpu->arch.last_retry_eip = vcpu->arch.last_retry_addr = 0; - - if (!(emulation_type & EMULTYPE_ALLOW_RETRY_PF)) - return false; - - if (WARN_ON_ONCE(is_guest_mode(vcpu)) || - WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF))) - return false; - - if (x86_page_table_writing_insn(ctxt)) - return false; - - if (ctxt->eip == last_retry_eip && last_retry_addr == cr2_or_gpa) - return false; - - vcpu->arch.last_retry_eip = ctxt->eip; - vcpu->arch.last_retry_addr = cr2_or_gpa; - - if (!vcpu->arch.mmu->root_role.direct) - gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL); - - kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa)); + __kvm_mmu_unprotect_gfn_and_retry(vcpu, cr2_or_gpa, true); + /* + * Retry even if _this_ vCPU didn't unprotect the gfn, as it's possible + * all SPTEs were already zapped by a different task. The alternative + * is to report the error to userspace and likely terminate the guest, + * and the last_retry_{eip,addr} checks will prevent retrying the page + * fault indefinitely, i.e. there's nothing to lose by retrying. + */ return true; } @@ -9172,6 +9090,11 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt; bool writeback = true; + if ((emulation_type & EMULTYPE_ALLOW_RETRY_PF) && + (WARN_ON_ONCE(is_guest_mode(vcpu)) || + WARN_ON_ONCE(!(emulation_type & EMULTYPE_PF)))) + emulation_type &= ~EMULTYPE_ALLOW_RETRY_PF; + r = kvm_check_emulate_insn(vcpu, emulation_type, insn, insn_len); if (r != X86EMUL_CONTINUE) { if (r == X86EMUL_RETRY_INSTR || r == X86EMUL_PROPAGATE_FAULT) @@ -9202,8 +9125,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, kvm_queue_exception(vcpu, UD_VECTOR); return 1; } - if (reexecute_instruction(vcpu, cr2_or_gpa, - emulation_type)) + if (kvm_unprotect_and_retry_on_failure(vcpu, cr2_or_gpa, + emulation_type)) return 1; if (ctxt->have_exception && @@ -9250,7 +9173,15 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, return 1; } - if (retry_instruction(ctxt, cr2_or_gpa, emulation_type)) + /* + * If emulation was caused by a write-protection #PF on a non-page_table + * writing instruction, try to unprotect the gfn, i.e. zap shadow pages, + * and retry the instruction, as the vCPU is likely no longer using the + * gfn as a page table. + */ + if ((emulation_type & EMULTYPE_ALLOW_RETRY_PF) && + !x86_page_table_writing_insn(ctxt) && + kvm_mmu_unprotect_gfn_and_retry(vcpu, cr2_or_gpa)) return 1; /* this is needed for vmware backdoor interface to work since it @@ -9281,7 +9212,8 @@ restart: return 1; if (r == EMULATION_FAILED) { - if (reexecute_instruction(vcpu, cr2_or_gpa, emulation_type)) + if (kvm_unprotect_and_retry_on_failure(vcpu, cr2_or_gpa, + emulation_type)) return 1; return handle_emulation_failure(vcpu, emulation_type); @@ -9749,7 +9681,7 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops) guard(mutex)(&vendor_module_lock); - if (kvm_x86_ops.hardware_enable) { + if (kvm_x86_ops.enable_virtualization_cpu) { pr_err("already loaded vendor module '%s'\n", kvm_x86_ops.name); return -EEXIST; } @@ -9876,7 +9808,7 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops) return 0; out_unwind_ops: - kvm_x86_ops.hardware_enable = NULL; + kvm_x86_ops.enable_virtualization_cpu = NULL; kvm_x86_call(hardware_unsetup)(); out_mmu_exit: kvm_mmu_vendor_module_exit(); @@ -9917,56 +9849,11 @@ void kvm_x86_vendor_exit(void) WARN_ON(static_branch_unlikely(&kvm_xen_enabled.key)); #endif mutex_lock(&vendor_module_lock); - kvm_x86_ops.hardware_enable = NULL; + kvm_x86_ops.enable_virtualization_cpu = NULL; mutex_unlock(&vendor_module_lock); } EXPORT_SYMBOL_GPL(kvm_x86_vendor_exit); -static int __kvm_emulate_halt(struct kvm_vcpu *vcpu, int state, int reason) -{ - /* - * The vCPU has halted, e.g. executed HLT. Update the run state if the - * local APIC is in-kernel, the run loop will detect the non-runnable - * state and halt the vCPU. Exit to userspace if the local APIC is - * managed by userspace, in which case userspace is responsible for - * handling wake events. - */ - ++vcpu->stat.halt_exits; - if (lapic_in_kernel(vcpu)) { - vcpu->arch.mp_state = state; - return 1; - } else { - vcpu->run->exit_reason = reason; - return 0; - } -} - -int kvm_emulate_halt_noskip(struct kvm_vcpu *vcpu) -{ - return __kvm_emulate_halt(vcpu, KVM_MP_STATE_HALTED, KVM_EXIT_HLT); -} -EXPORT_SYMBOL_GPL(kvm_emulate_halt_noskip); - -int kvm_emulate_halt(struct kvm_vcpu *vcpu) -{ - int ret = kvm_skip_emulated_instruction(vcpu); - /* - * TODO: we might be squashing a GUESTDBG_SINGLESTEP-triggered - * KVM_EXIT_DEBUG here. - */ - return kvm_emulate_halt_noskip(vcpu) && ret; -} -EXPORT_SYMBOL_GPL(kvm_emulate_halt); - -int kvm_emulate_ap_reset_hold(struct kvm_vcpu *vcpu) -{ - int ret = kvm_skip_emulated_instruction(vcpu); - - return __kvm_emulate_halt(vcpu, KVM_MP_STATE_AP_RESET_HOLD, - KVM_EXIT_AP_RESET_HOLD) && ret; -} -EXPORT_SYMBOL_GPL(kvm_emulate_ap_reset_hold); - #ifdef CONFIG_X86_64 static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr, unsigned long clock_type) @@ -11203,6 +11090,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) if (vcpu->arch.apic_attention) kvm_lapic_sync_from_vapic(vcpu); + if (unlikely(exit_fastpath == EXIT_FASTPATH_EXIT_USERSPACE)) + return 0; + r = kvm_x86_call(handle_exit)(vcpu, exit_fastpath); return r; @@ -11216,6 +11106,67 @@ out: return r; } +static bool kvm_vcpu_running(struct kvm_vcpu *vcpu) +{ + return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE && + !vcpu->arch.apf.halted); +} + +static bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) +{ + if (!list_empty_careful(&vcpu->async_pf.done)) + return true; + + if (kvm_apic_has_pending_init_or_sipi(vcpu) && + kvm_apic_init_sipi_allowed(vcpu)) + return true; + + if (vcpu->arch.pv.pv_unhalted) + return true; + + if (kvm_is_exception_pending(vcpu)) + return true; + + if (kvm_test_request(KVM_REQ_NMI, vcpu) || + (vcpu->arch.nmi_pending && + kvm_x86_call(nmi_allowed)(vcpu, false))) + return true; + +#ifdef CONFIG_KVM_SMM + if (kvm_test_request(KVM_REQ_SMI, vcpu) || + (vcpu->arch.smi_pending && + kvm_x86_call(smi_allowed)(vcpu, false))) + return true; +#endif + + if (kvm_test_request(KVM_REQ_PMI, vcpu)) + return true; + + if (kvm_test_request(KVM_REQ_UPDATE_PROTECTED_GUEST_STATE, vcpu)) + return true; + + if (kvm_arch_interrupt_allowed(vcpu) && kvm_cpu_has_interrupt(vcpu)) + return true; + + if (kvm_hv_has_stimer_pending(vcpu)) + return true; + + if (is_guest_mode(vcpu) && + kvm_x86_ops.nested_ops->has_events && + kvm_x86_ops.nested_ops->has_events(vcpu, false)) + return true; + + if (kvm_xen_has_pending_events(vcpu)) + return true; + + return false; +} + +int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) +{ + return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu); +} + /* Called within kvm->srcu read side. */ static inline int vcpu_block(struct kvm_vcpu *vcpu) { @@ -11287,12 +11238,6 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu) return 1; } -static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu) -{ - return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE && - !vcpu->arch.apf.halted); -} - /* Called within kvm->srcu read side. */ static int vcpu_run(struct kvm_vcpu *vcpu) { @@ -11344,6 +11289,98 @@ static int vcpu_run(struct kvm_vcpu *vcpu) return r; } +static int __kvm_emulate_halt(struct kvm_vcpu *vcpu, int state, int reason) +{ + /* + * The vCPU has halted, e.g. executed HLT. Update the run state if the + * local APIC is in-kernel, the run loop will detect the non-runnable + * state and halt the vCPU. Exit to userspace if the local APIC is + * managed by userspace, in which case userspace is responsible for + * handling wake events. + */ + ++vcpu->stat.halt_exits; + if (lapic_in_kernel(vcpu)) { + if (kvm_vcpu_has_events(vcpu)) + vcpu->arch.pv.pv_unhalted = false; + else + vcpu->arch.mp_state = state; + return 1; + } else { + vcpu->run->exit_reason = reason; + return 0; + } +} + +int kvm_emulate_halt_noskip(struct kvm_vcpu *vcpu) +{ + return __kvm_emulate_halt(vcpu, KVM_MP_STATE_HALTED, KVM_EXIT_HLT); +} +EXPORT_SYMBOL_GPL(kvm_emulate_halt_noskip); + +int kvm_emulate_halt(struct kvm_vcpu *vcpu) +{ + int ret = kvm_skip_emulated_instruction(vcpu); + /* + * TODO: we might be squashing a GUESTDBG_SINGLESTEP-triggered + * KVM_EXIT_DEBUG here. + */ + return kvm_emulate_halt_noskip(vcpu) && ret; +} +EXPORT_SYMBOL_GPL(kvm_emulate_halt); + +fastpath_t handle_fastpath_hlt(struct kvm_vcpu *vcpu) +{ + int ret; + + kvm_vcpu_srcu_read_lock(vcpu); + ret = kvm_emulate_halt(vcpu); + kvm_vcpu_srcu_read_unlock(vcpu); + + if (!ret) + return EXIT_FASTPATH_EXIT_USERSPACE; + + if (kvm_vcpu_running(vcpu)) + return EXIT_FASTPATH_REENTER_GUEST; + + return EXIT_FASTPATH_EXIT_HANDLED; +} +EXPORT_SYMBOL_GPL(handle_fastpath_hlt); + +int kvm_emulate_ap_reset_hold(struct kvm_vcpu *vcpu) +{ + int ret = kvm_skip_emulated_instruction(vcpu); + + return __kvm_emulate_halt(vcpu, KVM_MP_STATE_AP_RESET_HOLD, + KVM_EXIT_AP_RESET_HOLD) && ret; +} +EXPORT_SYMBOL_GPL(kvm_emulate_ap_reset_hold); + +bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu) +{ + return kvm_vcpu_apicv_active(vcpu) && + kvm_x86_call(dy_apicv_has_pending_interrupt)(vcpu); +} + +bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.preempted_in_kernel; +} + +bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu) +{ + if (READ_ONCE(vcpu->arch.pv.pv_unhalted)) + return true; + + if (kvm_test_request(KVM_REQ_NMI, vcpu) || +#ifdef CONFIG_KVM_SMM + kvm_test_request(KVM_REQ_SMI, vcpu) || +#endif + kvm_test_request(KVM_REQ_EVENT, vcpu)) + return true; + + return kvm_arch_dy_has_pending_interrupt(vcpu); +} + static inline int complete_emulated_io(struct kvm_vcpu *vcpu) { return kvm_emulate_instruction(vcpu, EMULTYPE_NO_DECODE); @@ -12260,8 +12297,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu); vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu); - vcpu->arch.pat = MSR_IA32_CR_PAT_DEFAULT; - kvm_async_pf_hash_reset(vcpu); vcpu->arch.perf_capabilities = kvm_caps.supported_perf_cap; @@ -12427,6 +12462,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) if (!init_event) { vcpu->arch.smbase = 0x30000; + vcpu->arch.pat = MSR_IA32_CR_PAT_DEFAULT; + vcpu->arch.msr_misc_features_enables = 0; vcpu->arch.ia32_misc_enable_msr = MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL | MSR_IA32_MISC_ENABLE_BTS_UNAVAIL; @@ -12512,7 +12549,17 @@ void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector) } EXPORT_SYMBOL_GPL(kvm_vcpu_deliver_sipi_vector); -int kvm_arch_hardware_enable(void) +void kvm_arch_enable_virtualization(void) +{ + cpu_emergency_register_virt_callback(kvm_x86_ops.emergency_disable_virtualization_cpu); +} + +void kvm_arch_disable_virtualization(void) +{ + cpu_emergency_unregister_virt_callback(kvm_x86_ops.emergency_disable_virtualization_cpu); +} + +int kvm_arch_enable_virtualization_cpu(void) { struct kvm *kvm; struct kvm_vcpu *vcpu; @@ -12528,7 +12575,7 @@ int kvm_arch_hardware_enable(void) if (ret) return ret; - ret = kvm_x86_call(hardware_enable)(); + ret = kvm_x86_call(enable_virtualization_cpu)(); if (ret != 0) return ret; @@ -12608,9 +12655,9 @@ int kvm_arch_hardware_enable(void) return 0; } -void kvm_arch_hardware_disable(void) +void kvm_arch_disable_virtualization_cpu(void) { - kvm_x86_call(hardware_disable)(); + kvm_x86_call(disable_virtualization_cpu)(); drop_user_return_notifiers(); } @@ -13158,87 +13205,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, kvm_arch_free_memslot(kvm, old); } -static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) -{ - if (!list_empty_careful(&vcpu->async_pf.done)) - return true; - - if (kvm_apic_has_pending_init_or_sipi(vcpu) && - kvm_apic_init_sipi_allowed(vcpu)) - return true; - - if (vcpu->arch.pv.pv_unhalted) - return true; - - if (kvm_is_exception_pending(vcpu)) - return true; - - if (kvm_test_request(KVM_REQ_NMI, vcpu) || - (vcpu->arch.nmi_pending && - kvm_x86_call(nmi_allowed)(vcpu, false))) - return true; - -#ifdef CONFIG_KVM_SMM - if (kvm_test_request(KVM_REQ_SMI, vcpu) || - (vcpu->arch.smi_pending && - kvm_x86_call(smi_allowed)(vcpu, false))) - return true; -#endif - - if (kvm_test_request(KVM_REQ_PMI, vcpu)) - return true; - - if (kvm_test_request(KVM_REQ_UPDATE_PROTECTED_GUEST_STATE, vcpu)) - return true; - - if (kvm_arch_interrupt_allowed(vcpu) && kvm_cpu_has_interrupt(vcpu)) - return true; - - if (kvm_hv_has_stimer_pending(vcpu)) - return true; - - if (is_guest_mode(vcpu) && - kvm_x86_ops.nested_ops->has_events && - kvm_x86_ops.nested_ops->has_events(vcpu, false)) - return true; - - if (kvm_xen_has_pending_events(vcpu)) - return true; - - return false; -} - -int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) -{ - return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu); -} - -bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu) -{ - return kvm_vcpu_apicv_active(vcpu) && - kvm_x86_call(dy_apicv_has_pending_interrupt)(vcpu); -} - -bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu) -{ - return vcpu->arch.preempted_in_kernel; -} - -bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu) -{ - if (READ_ONCE(vcpu->arch.pv.pv_unhalted)) - return true; - - if (kvm_test_request(KVM_REQ_NMI, vcpu) || -#ifdef CONFIG_KVM_SMM - kvm_test_request(KVM_REQ_SMI, vcpu) || -#endif - kvm_test_request(KVM_REQ_EVENT, vcpu)) - return true; - - return kvm_arch_dy_has_pending_interrupt(vcpu); -} - bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu) { if (vcpu->arch.guest_state_protected) diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 50596f6f8320..a84c48ef5278 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -103,11 +103,18 @@ static inline unsigned int __shrink_ple_window(unsigned int val, return max(val, min); } -#define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL +#define MSR_IA32_CR_PAT_DEFAULT \ + PAT_VALUE(WB, WT, UC_MINUS, UC, WB, WT, UC_MINUS, UC) void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu); int kvm_check_nested_events(struct kvm_vcpu *vcpu); +/* Forcibly leave the nested mode in cases like a vCPU reset */ +static inline void kvm_leave_nested(struct kvm_vcpu *vcpu) +{ + kvm_x86_ops.nested_ops->leave_nested(vcpu); +} + static inline bool kvm_vcpu_has_run(struct kvm_vcpu *vcpu) { return vcpu->arch.last_vmentry_cpu != -1; @@ -334,6 +341,7 @@ int x86_decode_emulated_instruction(struct kvm_vcpu *vcpu, int emulation_type, int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, int emulation_type, void *insn, int insn_len); fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu); +fastpath_t handle_fastpath_hlt(struct kvm_vcpu *vcpu); extern struct kvm_caps kvm_caps; extern struct kvm_host_values kvm_host; @@ -504,13 +512,26 @@ int kvm_handle_memory_failure(struct kvm_vcpu *vcpu, int r, int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva); bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type); +enum kvm_msr_access { + MSR_TYPE_R = BIT(0), + MSR_TYPE_W = BIT(1), + MSR_TYPE_RW = MSR_TYPE_R | MSR_TYPE_W, +}; + /* * Internal error codes that are used to indicate that MSR emulation encountered - * an error that should result in #GP in the guest, unless userspace - * handles it. + * an error that should result in #GP in the guest, unless userspace handles it. + * Note, '1', '0', and negative numbers are off limits, as they are used by KVM + * as part of KVM's lightly documented internal KVM_RUN return codes. + * + * UNSUPPORTED - The MSR isn't supported, either because it is completely + * unknown to KVM, or because the MSR should not exist according + * to the vCPU model. + * + * FILTERED - Access to the MSR is denied by a userspace MSR filter. */ -#define KVM_MSR_RET_INVALID 2 /* in-kernel MSR emulation #GP condition */ -#define KVM_MSR_RET_FILTERED 3 /* #GP due to userspace MSR filter */ +#define KVM_MSR_RET_UNSUPPORTED 2 +#define KVM_MSR_RET_FILTERED 3 #define __cr4_reserved_bits(__cpu_has, __c) \ ({ \ diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 622fe24da910..a909b817b9c0 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -263,13 +263,6 @@ static void kvm_xen_stop_timer(struct kvm_vcpu *vcpu) atomic_set(&vcpu->arch.xen.timer_pending, 0); } -static void kvm_xen_init_timer(struct kvm_vcpu *vcpu) -{ - hrtimer_init(&vcpu->arch.xen.timer, CLOCK_MONOTONIC, - HRTIMER_MODE_ABS_HARD); - vcpu->arch.xen.timer.function = xen_timer_callback; -} - static void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, bool atomic) { struct kvm_vcpu_xen *vx = &v->arch.xen; @@ -1070,9 +1063,6 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) break; } - if (!vcpu->arch.xen.timer.function) - kvm_xen_init_timer(vcpu); - /* Stop the timer (if it's running) before changing the vector */ kvm_xen_stop_timer(vcpu); vcpu->arch.xen.timer_virq = data->u.timer.port; @@ -2235,6 +2225,8 @@ void kvm_xen_init_vcpu(struct kvm_vcpu *vcpu) vcpu->arch.xen.poll_evtchn = 0; timer_setup(&vcpu->arch.xen.poll_timer, cancel_evtchn_poll, 0); + hrtimer_init(&vcpu->arch.xen.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD); + vcpu->arch.xen.timer.function = xen_timer_callback; kvm_gpc_init(&vcpu->arch.xen.runstate_cache, vcpu->kvm); kvm_gpc_init(&vcpu->arch.xen.runstate2_cache, vcpu->kvm); diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S index 90afb488b396..b2eff07d65e4 100644 --- a/arch/x86/lib/atomic64_cx8_32.S +++ b/arch/x86/lib/atomic64_cx8_32.S @@ -16,6 +16,11 @@ cmpxchg8b (\reg) .endm +.macro read64_nonatomic reg + movl (\reg), %eax + movl 4(\reg), %edx +.endm + SYM_FUNC_START(atomic64_read_cx8) read64 %ecx RET @@ -51,7 +56,7 @@ SYM_FUNC_START(atomic64_\func\()_return_cx8) movl %edx, %edi movl %ecx, %ebp - read64 %ecx + read64_nonatomic %ecx 1: movl %eax, %ebx movl %edx, %ecx @@ -79,7 +84,7 @@ addsub_return sub sub sbb SYM_FUNC_START(atomic64_\func\()_return_cx8) pushl %ebx - read64 %esi + read64_nonatomic %esi 1: movl %eax, %ebx movl %edx, %ecx diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index d066aecf8aeb..4357ec2a0bfc 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -39,8 +39,13 @@ .macro check_range size:req .if IS_ENABLED(CONFIG_X86_64) - mov %rax, %rdx - sar $63, %rdx + movq $0x0123456789abcdef,%rdx + 1: + .pushsection runtime_ptr_USER_PTR_MAX,"a" + .long 1b - 8 - . + .popsection + cmp %rax, %rdx + sbb %rdx, %rdx or %rdx, %rax .else cmp $TASK_SIZE_MAX-\size+1, %eax diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 5952ab41c60f..6ffb931b9fb1 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c @@ -13,7 +13,7 @@ #endif #include <asm/inat.h> /*__ignore_sync_check__ */ #include <asm/insn.h> /* __ignore_sync_check__ */ -#include <asm/unaligned.h> /* __ignore_sync_check__ */ +#include <linux/unaligned.h> /* __ignore_sync_check__ */ #include <linux/errno.h> #include <linux/kconfig.h> diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 8d3a00e5c528..690fbf48e853 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o obj-$(CONFIG_AMD_NUMA) += amdtopology.o obj-$(CONFIG_ACPI_NUMA) += srat.o -obj-$(CONFIG_NUMA_EMU) += numa_emulation.o obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o diff --git a/arch/x86/mm/amdtopology.c b/arch/x86/mm/amdtopology.c index 9332b36a1091..628833afee37 100644 --- a/arch/x86/mm/amdtopology.c +++ b/arch/x86/mm/amdtopology.c @@ -12,6 +12,7 @@ #include <linux/string.h> #include <linux/nodemask.h> #include <linux/memblock.h> +#include <linux/numa_memblks.h> #include <asm/io.h> #include <linux/pci_ids.h> diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c index e91500a80963..575f863f3c75 100644 --- a/arch/x86/mm/cpu_entry_area.c +++ b/arch/x86/mm/cpu_entry_area.c @@ -164,7 +164,7 @@ static void __init percpu_setup_exception_stacks(unsigned int cpu) } } #else -static inline void percpu_setup_exception_stacks(unsigned int cpu) +static void __init percpu_setup_exception_stacks(unsigned int cpu) { struct cpu_entry_area *cea = get_cpu_entry_area(cpu); diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c index c45127265f2f..437e96fb4977 100644 --- a/arch/x86/mm/ident_map.c +++ b/arch/x86/mm/ident_map.c @@ -99,18 +99,31 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, for (; addr < end; addr = next) { pud_t *pud = pud_page + pud_index(addr); pmd_t *pmd; + bool use_gbpage; next = (addr & PUD_MASK) + PUD_SIZE; if (next > end) next = end; - if (info->direct_gbpages) { - pud_t pudval; + /* if this is already a gbpage, this portion is already mapped */ + if (pud_leaf(*pud)) + continue; + + /* Is using a gbpage allowed? */ + use_gbpage = info->direct_gbpages; - if (pud_present(*pud)) - continue; + /* Don't use gbpage if it maps more than the requested region. */ + /* at the begining: */ + use_gbpage &= ((addr & ~PUD_MASK) == 0); + /* ... or at the end: */ + use_gbpage &= ((next & ~PUD_MASK) == 0); + + /* Never overwrite existing mappings */ + use_gbpage &= !pud_present(*pud); + + if (use_gbpage) { + pud_t pudval; - addr &= PUD_MASK; pudval = __pud((addr - info->offset) | info->page_flag); set_pud(pud, pudval); continue; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index eb503f53c319..101725c149c4 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -263,28 +263,33 @@ static void __init probe_page_size_mask(void) } /* - * INVLPG may not properly flush Global entries - * on these CPUs when PCIDs are enabled. + * INVLPG may not properly flush Global entries on + * these CPUs. New microcode fixes the issue. */ static const struct x86_cpu_id invlpg_miss_ids[] = { - X86_MATCH_VFM(INTEL_ALDERLAKE, 0), - X86_MATCH_VFM(INTEL_ALDERLAKE_L, 0), - X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0), - X86_MATCH_VFM(INTEL_RAPTORLAKE, 0), - X86_MATCH_VFM(INTEL_RAPTORLAKE_P, 0), - X86_MATCH_VFM(INTEL_RAPTORLAKE_S, 0), + X86_MATCH_VFM(INTEL_ALDERLAKE, 0x2e), + X86_MATCH_VFM(INTEL_ALDERLAKE_L, 0x42c), + X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0x11), + X86_MATCH_VFM(INTEL_RAPTORLAKE, 0x118), + X86_MATCH_VFM(INTEL_RAPTORLAKE_P, 0x4117), + X86_MATCH_VFM(INTEL_RAPTORLAKE_S, 0x2e), {} }; static void setup_pcid(void) { + const struct x86_cpu_id *invlpg_miss_match; + if (!IS_ENABLED(CONFIG_X86_64)) return; if (!boot_cpu_has(X86_FEATURE_PCID)) return; - if (x86_match_cpu(invlpg_miss_ids)) { + invlpg_miss_match = x86_match_cpu(invlpg_miss_ids); + + if (invlpg_miss_match && + boot_cpu_data.microcode < invlpg_miss_match->driver_data) { pr_info("Incomplete global flushes, disabling PCID"); setup_clear_cpu_cap(X86_FEATURE_PCID); return; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d8dbeac8b206..ff253648706f 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -958,8 +958,12 @@ static void update_end_of_memory_vars(u64 start, u64 size) int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, struct mhp_params *params) { + unsigned long end = ((start_pfn + nr_pages) << PAGE_SHIFT) - 1; int ret; + if (WARN_ON_ONCE(end > PHYSMEM_END)) + return -ERANGE; + ret = __add_pages(nid, start_pfn, nr_pages, params); WARN_ON_ONCE(ret); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index aa7d279321ea..8d29163568a7 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/ioport.h> +#include <linux/ioremap.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/mmiotrace.h> @@ -457,7 +458,7 @@ void iounmap(volatile void __iomem *addr) { struct vm_struct *p, *o; - if ((void __force *)addr <= high_memory) + if (WARN_ON_ONCE(!is_ioremap_addr((void __force *)addr))) return; /* @@ -655,7 +656,8 @@ static bool memremap_is_setup_data(resource_size_t phys_addr, paddr_next = data->next; len = data->len; - if ((phys_addr > paddr) && (phys_addr < (paddr + len))) { + if ((phys_addr > paddr) && + (phys_addr < (paddr + sizeof(struct setup_data) + len))) { memunmap(data); return true; } @@ -717,7 +719,8 @@ static bool __init early_memremap_is_setup_data(resource_size_t phys_addr, paddr_next = data->next; len = data->len; - if ((phys_addr > paddr) && (phys_addr < (paddr + len))) { + if ((phys_addr > paddr) && + (phys_addr < (paddr + sizeof(struct setup_data) + len))) { early_memunmap(data, sizeof(*data)); return true; } diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c index 37db264866b6..e17e6e27b7ec 100644 --- a/arch/x86/mm/kaslr.c +++ b/arch/x86/mm/kaslr.c @@ -22,7 +22,7 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/random.h> +#include <linux/prandom.h> #include <linux/memblock.h> #include <linux/pgtable.h> @@ -47,13 +47,24 @@ static const unsigned long vaddr_end = CPU_ENTRY_AREA_BASE; */ static __initdata struct kaslr_memory_region { unsigned long *base; + unsigned long *end; unsigned long size_tb; } kaslr_regions[] = { - { &page_offset_base, 0 }, - { &vmalloc_base, 0 }, - { &vmemmap_base, 0 }, + { + .base = &page_offset_base, + .end = &physmem_end, + }, + { + .base = &vmalloc_base, + }, + { + .base = &vmemmap_base, + }, }; +/* The end of the possible address space for physical memory */ +unsigned long physmem_end __ro_after_init; + /* Get size in bytes used by the memory region */ static inline unsigned long get_padding(struct kaslr_memory_region *region) { @@ -82,6 +93,8 @@ void __init kernel_randomize_memory(void) BUILD_BUG_ON(vaddr_end != CPU_ENTRY_AREA_BASE); BUILD_BUG_ON(vaddr_end > __START_KERNEL_map); + /* Preset the end of the possible address space for physical memory */ + physmem_end = ((1ULL << MAX_PHYSMEM_BITS) - 1); if (!kaslr_memory_enabled()) return; @@ -128,11 +141,18 @@ void __init kernel_randomize_memory(void) vaddr += entropy; *kaslr_regions[i].base = vaddr; + /* Calculate the end of the region */ + vaddr += get_padding(&kaslr_regions[i]); /* - * Jump the region and add a minimum padding based on - * randomization alignment. + * KASLR trims the maximum possible size of the + * direct-map. Update the physmem_end boundary. + * No rounding required as the region starts + * PUD aligned and size is in units of TB. */ - vaddr += get_padding(&kaslr_regions[i]); + if (kaslr_regions[i].end) + *kaslr_regions[i].end = __pa_nodebug(vaddr - 1); + + /* Add a minimum padding based on randomization alignment. */ vaddr = round_up(vaddr + 1, PUD_SIZE); remain_entropy -= entropy; } diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c index 86a476a426c2..774f9677458f 100644 --- a/arch/x86/mm/mem_encrypt_amd.c +++ b/arch/x86/mm/mem_encrypt_amd.c @@ -311,59 +311,82 @@ static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool en return 0; } -static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) +int prepare_pte_enc(struct pte_enc_desc *d) { - pgprot_t old_prot, new_prot; - unsigned long pfn, pa, size; - pte_t new_pte; + pgprot_t old_prot; - pfn = pg_level_to_pfn(level, kpte, &old_prot); - if (!pfn) - return; + d->pfn = pg_level_to_pfn(d->pte_level, d->kpte, &old_prot); + if (!d->pfn) + return 1; - new_prot = old_prot; - if (enc) - pgprot_val(new_prot) |= _PAGE_ENC; + d->new_pgprot = old_prot; + if (d->encrypt) + pgprot_val(d->new_pgprot) |= _PAGE_ENC; else - pgprot_val(new_prot) &= ~_PAGE_ENC; + pgprot_val(d->new_pgprot) &= ~_PAGE_ENC; /* If prot is same then do nothing. */ - if (pgprot_val(old_prot) == pgprot_val(new_prot)) - return; + if (pgprot_val(old_prot) == pgprot_val(d->new_pgprot)) + return 1; - pa = pfn << PAGE_SHIFT; - size = page_level_size(level); + d->pa = d->pfn << PAGE_SHIFT; + d->size = page_level_size(d->pte_level); /* - * We are going to perform in-place en-/decryption and change the - * physical page attribute from C=1 to C=0 or vice versa. Flush the - * caches to ensure that data gets accessed with the correct C-bit. + * In-place en-/decryption and physical page attribute change + * from C=1 to C=0 or vice versa will be performed. Flush the + * caches to ensure that data gets accessed with the correct + * C-bit. */ - clflush_cache_range(__va(pa), size); + if (d->va) + clflush_cache_range(d->va, d->size); + else + clflush_cache_range(__va(d->pa), d->size); + + return 0; +} + +void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) +{ + pte_t new_pte; + + /* Change the page encryption mask. */ + new_pte = pfn_pte(pfn, new_prot); + set_pte_atomic(kpte, new_pte); +} + +static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) +{ + struct pte_enc_desc d = { + .kpte = kpte, + .pte_level = level, + .encrypt = enc + }; + + if (prepare_pte_enc(&d)) + return; /* Encrypt/decrypt the contents in-place */ if (enc) { - sme_early_encrypt(pa, size); + sme_early_encrypt(d.pa, d.size); } else { - sme_early_decrypt(pa, size); + sme_early_decrypt(d.pa, d.size); /* * ON SNP, the page state in the RMP table must happen * before the page table updates. */ - early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1); + early_snp_set_memory_shared((unsigned long)__va(d.pa), d.pa, 1); } - /* Change the page encryption mask. */ - new_pte = pfn_pte(pfn, new_prot); - set_pte_atomic(kpte, new_pte); + set_pte_enc_mask(kpte, d.pfn, d.new_pgprot); /* * If page is set encrypted in the page table, then update the RMP table to * add this page as private. */ if (enc) - early_snp_set_memory_private((unsigned long)__va(pa), pa, 1); + early_snp_set_memory_private((unsigned long)__va(d.pa), d.pa, 1); } static int __init early_set_memory_enc_dec(unsigned long vaddr, @@ -467,6 +490,8 @@ void __init sme_early_init(void) x86_platform.guest.enc_status_change_finish = amd_enc_status_change_finish; x86_platform.guest.enc_tlb_flush_required = amd_enc_tlb_flush_required; x86_platform.guest.enc_cache_flush_required = amd_enc_cache_flush_required; + x86_platform.guest.enc_kexec_begin = snp_kexec_begin; + x86_platform.guest.enc_kexec_finish = snp_kexec_finish; /* * AMD-SEV-ES intercepts the RDMSR to read the X2APIC ID in the diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index ac33b2263a43..e6c7686f443a 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c @@ -495,10 +495,10 @@ void __head sme_enable(struct boot_params *bp) unsigned int eax, ebx, ecx, edx; unsigned long feature_mask; unsigned long me_mask; - bool snp; + bool snp_en; u64 msr; - snp = snp_init(bp); + snp_en = snp_init(bp); /* Check for the SME/SEV support leaf */ eax = 0x80000000; @@ -531,8 +531,11 @@ void __head sme_enable(struct boot_params *bp) RIP_REL_REF(sev_status) = msr = __rdmsr(MSR_AMD64_SEV); feature_mask = (msr & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT; - /* The SEV-SNP CC blob should never be present unless SEV-SNP is enabled. */ - if (snp && !(msr & MSR_AMD64_SEV_SNP_ENABLED)) + /* + * Any discrepancies between the presence of a CC blob and SNP + * enablement abort the guest. + */ + if (snp_en ^ !!(msr & MSR_AMD64_SEV_SNP_ENABLED)) snp_abort(); /* Check if memory encryption is enabled */ diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index a2cabb1c81e1..b8a6ffffb451 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -163,11 +163,6 @@ unsigned long get_mmap_base(int is_legacy) return is_legacy ? mm->mmap_legacy_base : mm->mmap_base; } -const char *arch_vma_name(struct vm_area_struct *vma) -{ - return NULL; -} - /** * mmap_address_hint_valid - Validate the address hint of mmap * @addr: Address hint diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 6ce10e3c6228..64e5cdb2460a 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -13,6 +13,7 @@ #include <linux/sched.h> #include <linux/topology.h> #include <linux/sort.h> +#include <linux/numa_memblks.h> #include <asm/e820/api.h> #include <asm/proto.h> @@ -22,16 +23,6 @@ #include "numa_internal.h" int numa_off; -nodemask_t numa_nodes_parsed __initdata; - -struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; -EXPORT_SYMBOL(node_data); - -static struct numa_meminfo numa_meminfo __initdata_or_meminfo; -static struct numa_meminfo numa_reserved_meminfo __initdata_or_meminfo; - -static int numa_distance_cnt; -static u8 *numa_distance; static __init int numa_setup(char *opt) { @@ -124,456 +115,27 @@ void __init setup_node_to_cpumask_map(void) pr_debug("Node to cpumask map for %u nodes\n", nr_node_ids); } -static int __init numa_add_memblk_to(int nid, u64 start, u64 end, - struct numa_meminfo *mi) -{ - /* ignore zero length blks */ - if (start == end) - return 0; - - /* whine about and ignore invalid blks */ - if (start > end || nid < 0 || nid >= MAX_NUMNODES) { - pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n", - nid, start, end - 1); - return 0; - } - - if (mi->nr_blks >= NR_NODE_MEMBLKS) { - pr_err("too many memblk ranges\n"); - return -EINVAL; - } - - mi->blk[mi->nr_blks].start = start; - mi->blk[mi->nr_blks].end = end; - mi->blk[mi->nr_blks].nid = nid; - mi->nr_blks++; - return 0; -} - -/** - * numa_remove_memblk_from - Remove one numa_memblk from a numa_meminfo - * @idx: Index of memblk to remove - * @mi: numa_meminfo to remove memblk from - * - * Remove @idx'th numa_memblk from @mi by shifting @mi->blk[] and - * decrementing @mi->nr_blks. - */ -void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi) -{ - mi->nr_blks--; - memmove(&mi->blk[idx], &mi->blk[idx + 1], - (mi->nr_blks - idx) * sizeof(mi->blk[0])); -} - -/** - * numa_move_tail_memblk - Move a numa_memblk from one numa_meminfo to another - * @dst: numa_meminfo to append block to - * @idx: Index of memblk to remove - * @src: numa_meminfo to remove memblk from - */ -static void __init numa_move_tail_memblk(struct numa_meminfo *dst, int idx, - struct numa_meminfo *src) -{ - dst->blk[dst->nr_blks++] = src->blk[idx]; - numa_remove_memblk_from(idx, src); -} - -/** - * numa_add_memblk - Add one numa_memblk to numa_meminfo - * @nid: NUMA node ID of the new memblk - * @start: Start address of the new memblk - * @end: End address of the new memblk - * - * Add a new memblk to the default numa_meminfo. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -int __init numa_add_memblk(int nid, u64 start, u64 end) -{ - return numa_add_memblk_to(nid, start, end, &numa_meminfo); -} - -/* Allocate NODE_DATA for a node on the local memory */ -static void __init alloc_node_data(int nid) +static int __init numa_register_nodes(void) { - const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE); - u64 nd_pa; - void *nd; - int tnid; - - /* - * Allocate node data. Try node-local memory and then any node. - * Never allocate in DMA zone. - */ - nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); - if (!nd_pa) { - pr_err("Cannot find %zu bytes in any node (initial node: %d)\n", - nd_size, nid); - return; - } - nd = __va(nd_pa); - - /* report and initialize */ - printk(KERN_INFO "NODE_DATA(%d) allocated [mem %#010Lx-%#010Lx]\n", nid, - nd_pa, nd_pa + nd_size - 1); - tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); - if (tnid != nid) - printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nid, tnid); - - node_data[nid] = nd; - memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); - - node_set_online(nid); -} - -/** - * numa_cleanup_meminfo - Cleanup a numa_meminfo - * @mi: numa_meminfo to clean up - * - * Sanitize @mi by merging and removing unnecessary memblks. Also check for - * conflicts and clear unused memblks. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -int __init numa_cleanup_meminfo(struct numa_meminfo *mi) -{ - const u64 low = 0; - const u64 high = PFN_PHYS(max_pfn); - int i, j, k; - - /* first, trim all entries */ - for (i = 0; i < mi->nr_blks; i++) { - struct numa_memblk *bi = &mi->blk[i]; - - /* move / save reserved memory ranges */ - if (!memblock_overlaps_region(&memblock.memory, - bi->start, bi->end - bi->start)) { - numa_move_tail_memblk(&numa_reserved_meminfo, i--, mi); - continue; - } - - /* make sure all non-reserved blocks are inside the limits */ - bi->start = max(bi->start, low); - - /* preserve info for non-RAM areas above 'max_pfn': */ - if (bi->end > high) { - numa_add_memblk_to(bi->nid, high, bi->end, - &numa_reserved_meminfo); - bi->end = high; - } - - /* and there's no empty block */ - if (bi->start >= bi->end) - numa_remove_memblk_from(i--, mi); - } - - /* merge neighboring / overlapping entries */ - for (i = 0; i < mi->nr_blks; i++) { - struct numa_memblk *bi = &mi->blk[i]; - - for (j = i + 1; j < mi->nr_blks; j++) { - struct numa_memblk *bj = &mi->blk[j]; - u64 start, end; - - /* - * See whether there are overlapping blocks. Whine - * about but allow overlaps of the same nid. They - * will be merged below. - */ - if (bi->end > bj->start && bi->start < bj->end) { - if (bi->nid != bj->nid) { - pr_err("node %d [mem %#010Lx-%#010Lx] overlaps with node %d [mem %#010Lx-%#010Lx]\n", - bi->nid, bi->start, bi->end - 1, - bj->nid, bj->start, bj->end - 1); - return -EINVAL; - } - pr_warn("Warning: node %d [mem %#010Lx-%#010Lx] overlaps with itself [mem %#010Lx-%#010Lx]\n", - bi->nid, bi->start, bi->end - 1, - bj->start, bj->end - 1); - } - - /* - * Join together blocks on the same node, holes - * between which don't overlap with memory on other - * nodes. - */ - if (bi->nid != bj->nid) - continue; - start = min(bi->start, bj->start); - end = max(bi->end, bj->end); - for (k = 0; k < mi->nr_blks; k++) { - struct numa_memblk *bk = &mi->blk[k]; - - if (bi->nid == bk->nid) - continue; - if (start < bk->end && end > bk->start) - break; - } - if (k < mi->nr_blks) - continue; - printk(KERN_INFO "NUMA: Node %d [mem %#010Lx-%#010Lx] + [mem %#010Lx-%#010Lx] -> [mem %#010Lx-%#010Lx]\n", - bi->nid, bi->start, bi->end - 1, bj->start, - bj->end - 1, start, end - 1); - bi->start = start; - bi->end = end; - numa_remove_memblk_from(j--, mi); - } - } - - /* clear unused ones */ - for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) { - mi->blk[i].start = mi->blk[i].end = 0; - mi->blk[i].nid = NUMA_NO_NODE; - } - - return 0; -} - -/* - * Set nodes, which have memory in @mi, in *@nodemask. - */ -static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask, - const struct numa_meminfo *mi) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mi->blk); i++) - if (mi->blk[i].start != mi->blk[i].end && - mi->blk[i].nid != NUMA_NO_NODE) - node_set(mi->blk[i].nid, *nodemask); -} - -/** - * numa_reset_distance - Reset NUMA distance table - * - * The current table is freed. The next numa_set_distance() call will - * create a new one. - */ -void __init numa_reset_distance(void) -{ - size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]); - - /* numa_distance could be 1LU marking allocation failure, test cnt */ - if (numa_distance_cnt) - memblock_free(numa_distance, size); - numa_distance_cnt = 0; - numa_distance = NULL; /* enable table creation */ -} - -static int __init numa_alloc_distance(void) -{ - nodemask_t nodes_parsed; - size_t size; - int i, j, cnt = 0; - u64 phys; - - /* size the new table and allocate it */ - nodes_parsed = numa_nodes_parsed; - numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo); - - for_each_node_mask(i, nodes_parsed) - cnt = i; - cnt++; - size = cnt * cnt * sizeof(numa_distance[0]); - - phys = memblock_phys_alloc_range(size, PAGE_SIZE, 0, - PFN_PHYS(max_pfn_mapped)); - if (!phys) { - pr_warn("Warning: can't allocate distance table!\n"); - /* don't retry until explicitly reset */ - numa_distance = (void *)1LU; - return -ENOMEM; - } - - numa_distance = __va(phys); - numa_distance_cnt = cnt; - - /* fill with the default distances */ - for (i = 0; i < cnt; i++) - for (j = 0; j < cnt; j++) - numa_distance[i * cnt + j] = i == j ? - LOCAL_DISTANCE : REMOTE_DISTANCE; - printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt); - - return 0; -} - -/** - * numa_set_distance - Set NUMA distance from one NUMA to another - * @from: the 'from' node to set distance - * @to: the 'to' node to set distance - * @distance: NUMA distance - * - * Set the distance from node @from to @to to @distance. If distance table - * doesn't exist, one which is large enough to accommodate all the currently - * known nodes will be created. - * - * If such table cannot be allocated, a warning is printed and further - * calls are ignored until the distance table is reset with - * numa_reset_distance(). - * - * If @from or @to is higher than the highest known node or lower than zero - * at the time of table creation or @distance doesn't make sense, the call - * is ignored. - * This is to allow simplification of specific NUMA config implementations. - */ -void __init numa_set_distance(int from, int to, int distance) -{ - if (!numa_distance && numa_alloc_distance() < 0) - return; - - if (from >= numa_distance_cnt || to >= numa_distance_cnt || - from < 0 || to < 0) { - pr_warn_once("Warning: node ids are out of bound, from=%d to=%d distance=%d\n", - from, to, distance); - return; - } - - if ((u8)distance != distance || - (from == to && distance != LOCAL_DISTANCE)) { - pr_warn_once("Warning: invalid distance parameter, from=%d to=%d distance=%d\n", - from, to, distance); - return; - } - - numa_distance[from * numa_distance_cnt + to] = distance; -} - -int __node_distance(int from, int to) -{ - if (from >= numa_distance_cnt || to >= numa_distance_cnt) - return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE; - return numa_distance[from * numa_distance_cnt + to]; -} -EXPORT_SYMBOL(__node_distance); - -/* - * Mark all currently memblock-reserved physical memory (which covers the - * kernel's own memory ranges) as hot-unswappable. - */ -static void __init numa_clear_kernel_node_hotplug(void) -{ - nodemask_t reserved_nodemask = NODE_MASK_NONE; - struct memblock_region *mb_region; - int i; - - /* - * We have to do some preprocessing of memblock regions, to - * make them suitable for reservation. - * - * At this time, all memory regions reserved by memblock are - * used by the kernel, but those regions are not split up - * along node boundaries yet, and don't necessarily have their - * node ID set yet either. - * - * So iterate over all memory known to the x86 architecture, - * and use those ranges to set the nid in memblock.reserved. - * This will split up the memblock regions along node - * boundaries and will set the node IDs as well. - */ - for (i = 0; i < numa_meminfo.nr_blks; i++) { - struct numa_memblk *mb = numa_meminfo.blk + i; - int ret; - - ret = memblock_set_node(mb->start, mb->end - mb->start, &memblock.reserved, mb->nid); - WARN_ON_ONCE(ret); - } - - /* - * Now go over all reserved memblock regions, to construct a - * node mask of all kernel reserved memory areas. - * - * [ Note, when booting with mem=nn[kMG] or in a kdump kernel, - * numa_meminfo might not include all memblock.reserved - * memory ranges, because quirks such as trim_snb_memory() - * reserve specific pages for Sandy Bridge graphics. ] - */ - for_each_reserved_mem_region(mb_region) { - int nid = memblock_get_region_node(mb_region); - - if (nid != NUMA_NO_NODE) - node_set(nid, reserved_nodemask); - } - - /* - * Finally, clear the MEMBLOCK_HOTPLUG flag for all memory - * belonging to the reserved node mask. - * - * Note that this will include memory regions that reside - * on nodes that contain kernel memory - entire nodes - * become hot-unpluggable: - */ - for (i = 0; i < numa_meminfo.nr_blks; i++) { - struct numa_memblk *mb = numa_meminfo.blk + i; - - if (!node_isset(mb->nid, reserved_nodemask)) - continue; - - memblock_clear_hotplug(mb->start, mb->end - mb->start); - } -} - -static int __init numa_register_memblks(struct numa_meminfo *mi) -{ - int i, nid; - - /* Account for nodes with cpus and no memory */ - node_possible_map = numa_nodes_parsed; - numa_nodemask_from_meminfo(&node_possible_map, mi); - if (WARN_ON(nodes_empty(node_possible_map))) - return -EINVAL; - - for (i = 0; i < mi->nr_blks; i++) { - struct numa_memblk *mb = &mi->blk[i]; - memblock_set_node(mb->start, mb->end - mb->start, - &memblock.memory, mb->nid); - } - - /* - * At very early time, the kernel have to use some memory such as - * loading the kernel image. We cannot prevent this anyway. So any - * node the kernel resides in should be un-hotpluggable. - * - * And when we come here, alloc node data won't fail. - */ - numa_clear_kernel_node_hotplug(); - - /* - * If sections array is gonna be used for pfn -> nid mapping, check - * whether its granularity is fine enough. - */ - if (IS_ENABLED(NODE_NOT_IN_PAGE_FLAGS)) { - unsigned long pfn_align = node_map_pfn_alignment(); - - if (pfn_align && pfn_align < PAGES_PER_SECTION) { - pr_warn("Node alignment %LuMB < min %LuMB, rejecting NUMA config\n", - PFN_PHYS(pfn_align) >> 20, - PFN_PHYS(PAGES_PER_SECTION) >> 20); - return -EINVAL; - } - } + int nid; if (!memblock_validate_numa_coverage(SZ_1M)) return -EINVAL; /* Finally register nodes. */ for_each_node_mask(nid, node_possible_map) { - u64 start = PFN_PHYS(max_pfn); - u64 end = 0; - - for (i = 0; i < mi->nr_blks; i++) { - if (nid != mi->blk[i].nid) - continue; - start = min(mi->blk[i].start, start); - end = max(mi->blk[i].end, end); - } + unsigned long start_pfn, end_pfn; - if (start >= end) + /* + * Note, get_pfn_range_for_nid() depends on + * memblock_set_node() having already happened + */ + get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); + if (start_pfn >= end_pfn) continue; alloc_node_data(nid); + node_set_online(nid); } /* Dump memblock with node info and return. */ @@ -609,39 +171,11 @@ static int __init numa_init(int (*init_func)(void)) for (i = 0; i < MAX_LOCAL_APIC; i++) set_apicid_to_node(i, NUMA_NO_NODE); - nodes_clear(numa_nodes_parsed); - nodes_clear(node_possible_map); - nodes_clear(node_online_map); - memset(&numa_meminfo, 0, sizeof(numa_meminfo)); - WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.memory, - NUMA_NO_NODE)); - WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.reserved, - NUMA_NO_NODE)); - /* In case that parsing SRAT failed. */ - WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX)); - numa_reset_distance(); - - ret = init_func(); - if (ret < 0) - return ret; - - /* - * We reset memblock back to the top-down direction - * here because if we configured ACPI_NUMA, we have - * parsed SRAT in init_func(). It is ok to have the - * reset here even if we did't configure ACPI_NUMA - * or acpi numa init fails and fallbacks to dummy - * numa init. - */ - memblock_set_bottom_up(false); - - ret = numa_cleanup_meminfo(&numa_meminfo); + ret = numa_memblks_init(init_func, /* memblock_force_top_down */ true); if (ret < 0) return ret; - numa_emulation(&numa_meminfo, numa_distance_cnt); - - ret = numa_register_memblks(&numa_meminfo); + ret = numa_register_nodes(); if (ret < 0) return ret; @@ -782,12 +316,12 @@ void __init init_cpu_to_node(void) #ifndef CONFIG_DEBUG_PER_CPU_MAPS # ifndef CONFIG_NUMA_EMU -void numa_add_cpu(int cpu) +void numa_add_cpu(unsigned int cpu) { cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } -void numa_remove_cpu(int cpu) +void numa_remove_cpu(unsigned int cpu) { cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } @@ -825,7 +359,7 @@ int early_cpu_to_node(int cpu) return per_cpu(x86_cpu_to_node_map, cpu); } -void debug_cpumask_set_cpu(int cpu, int node, bool enable) +void debug_cpumask_set_cpu(unsigned int cpu, int node, bool enable) { struct cpumask *mask; @@ -857,12 +391,12 @@ static void numa_set_cpumask(int cpu, bool enable) debug_cpumask_set_cpu(cpu, early_cpu_to_node(cpu), enable); } -void numa_add_cpu(int cpu) +void numa_add_cpu(unsigned int cpu) { numa_set_cpumask(cpu, true); } -void numa_remove_cpu(int cpu) +void numa_remove_cpu(unsigned int cpu) { numa_set_cpumask(cpu, false); } @@ -893,113 +427,29 @@ EXPORT_SYMBOL(cpumask_of_node); #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ -#ifdef CONFIG_NUMA_KEEP_MEMINFO -static int meminfo_to_nid(struct numa_meminfo *mi, u64 start) +#ifdef CONFIG_NUMA_EMU +void __init numa_emu_update_cpu_to_node(int *emu_nid_to_phys, + unsigned int nr_emu_nids) { - int i; - - for (i = 0; i < mi->nr_blks; i++) - if (mi->blk[i].start <= start && mi->blk[i].end > start) - return mi->blk[i].nid; - return NUMA_NO_NODE; -} - -int phys_to_target_node(phys_addr_t start) -{ - int nid = meminfo_to_nid(&numa_meminfo, start); + int i, j; /* - * Prefer online nodes, but if reserved memory might be - * hot-added continue the search with reserved ranges. + * Transform __apicid_to_node table to use emulated nids by + * reverse-mapping phys_nid. The maps should always exist but fall + * back to zero just in case. */ - if (nid != NUMA_NO_NODE) - return nid; - - return meminfo_to_nid(&numa_reserved_meminfo, start); -} -EXPORT_SYMBOL_GPL(phys_to_target_node); - -int memory_add_physaddr_to_nid(u64 start) -{ - int nid = meminfo_to_nid(&numa_meminfo, start); - - if (nid == NUMA_NO_NODE) - nid = numa_meminfo.blk[0].nid; - return nid; -} -EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); - -#endif - -static int __init cmp_memblk(const void *a, const void *b) -{ - const struct numa_memblk *ma = *(const struct numa_memblk **)a; - const struct numa_memblk *mb = *(const struct numa_memblk **)b; - - return (ma->start > mb->start) - (ma->start < mb->start); + for (i = 0; i < ARRAY_SIZE(__apicid_to_node); i++) { + if (__apicid_to_node[i] == NUMA_NO_NODE) + continue; + for (j = 0; j < nr_emu_nids; j++) + if (__apicid_to_node[i] == emu_nid_to_phys[j]) + break; + __apicid_to_node[i] = j < nr_emu_nids ? j : 0; + } } -static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata; - -/** - * numa_fill_memblks - Fill gaps in numa_meminfo memblks - * @start: address to begin fill - * @end: address to end fill - * - * Find and extend numa_meminfo memblks to cover the physical - * address range @start-@end - * - * RETURNS: - * 0 : Success - * NUMA_NO_MEMBLK : No memblks exist in address range @start-@end - */ - -int __init numa_fill_memblks(u64 start, u64 end) +u64 __init numa_emu_dma_end(void) { - struct numa_memblk **blk = &numa_memblk_list[0]; - struct numa_meminfo *mi = &numa_meminfo; - int count = 0; - u64 prev_end; - - /* - * Create a list of pointers to numa_meminfo memblks that - * overlap start, end. The list is used to make in-place - * changes that fill out the numa_meminfo memblks. - */ - for (int i = 0; i < mi->nr_blks; i++) { - struct numa_memblk *bi = &mi->blk[i]; - - if (memblock_addrs_overlap(start, end - start, bi->start, - bi->end - bi->start)) { - blk[count] = &mi->blk[i]; - count++; - } - } - if (!count) - return NUMA_NO_MEMBLK; - - /* Sort the list of pointers in memblk->start order */ - sort(&blk[0], count, sizeof(blk[0]), cmp_memblk, NULL); - - /* Make sure the first/last memblks include start/end */ - blk[0]->start = min(blk[0]->start, start); - blk[count - 1]->end = max(blk[count - 1]->end, end); - - /* - * Fill any gaps by tracking the previous memblks - * end address and backfilling to it if needed. - */ - prev_end = blk[0]->end; - for (int i = 1; i < count; i++) { - struct numa_memblk *curr = blk[i]; - - if (prev_end >= curr->start) { - if (prev_end < curr->end) - prev_end = curr->end; - } else { - curr->start = prev_end; - prev_end = curr->end; - } - } - return 0; + return PFN_PHYS(MAX_DMA32_PFN); } +#endif /* CONFIG_NUMA_EMU */ diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c deleted file mode 100644 index 9a9305367fdd..000000000000 --- a/arch/x86/mm/numa_emulation.c +++ /dev/null @@ -1,585 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NUMA emulation - */ -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/topology.h> -#include <linux/memblock.h> -#include <asm/dma.h> - -#include "numa_internal.h" - -static int emu_nid_to_phys[MAX_NUMNODES]; -static char *emu_cmdline __initdata; - -int __init numa_emu_cmdline(char *str) -{ - emu_cmdline = str; - return 0; -} - -static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi) -{ - int i; - - for (i = 0; i < mi->nr_blks; i++) - if (mi->blk[i].nid == nid) - return i; - return -ENOENT; -} - -static u64 __init mem_hole_size(u64 start, u64 end) -{ - unsigned long start_pfn = PFN_UP(start); - unsigned long end_pfn = PFN_DOWN(end); - - if (start_pfn < end_pfn) - return PFN_PHYS(absent_pages_in_range(start_pfn, end_pfn)); - return 0; -} - -/* - * Sets up nid to range from @start to @end. The return value is -errno if - * something went wrong, 0 otherwise. - */ -static int __init emu_setup_memblk(struct numa_meminfo *ei, - struct numa_meminfo *pi, - int nid, int phys_blk, u64 size) -{ - struct numa_memblk *eb = &ei->blk[ei->nr_blks]; - struct numa_memblk *pb = &pi->blk[phys_blk]; - - if (ei->nr_blks >= NR_NODE_MEMBLKS) { - pr_err("NUMA: Too many emulated memblks, failing emulation\n"); - return -EINVAL; - } - - ei->nr_blks++; - eb->start = pb->start; - eb->end = pb->start + size; - eb->nid = nid; - - if (emu_nid_to_phys[nid] == NUMA_NO_NODE) - emu_nid_to_phys[nid] = pb->nid; - - pb->start += size; - if (pb->start >= pb->end) { - WARN_ON_ONCE(pb->start > pb->end); - numa_remove_memblk_from(phys_blk, pi); - } - - printk(KERN_INFO "Faking node %d at [mem %#018Lx-%#018Lx] (%LuMB)\n", - nid, eb->start, eb->end - 1, (eb->end - eb->start) >> 20); - return 0; -} - -/* - * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr - * to max_addr. - * - * Returns zero on success or negative on error. - */ -static int __init split_nodes_interleave(struct numa_meminfo *ei, - struct numa_meminfo *pi, - u64 addr, u64 max_addr, int nr_nodes) -{ - nodemask_t physnode_mask = numa_nodes_parsed; - u64 size; - int big; - int nid = 0; - int i, ret; - - if (nr_nodes <= 0) - return -1; - if (nr_nodes > MAX_NUMNODES) { - pr_info("numa=fake=%d too large, reducing to %d\n", - nr_nodes, MAX_NUMNODES); - nr_nodes = MAX_NUMNODES; - } - - /* - * Calculate target node size. x86_32 freaks on __udivdi3() so do - * the division in ulong number of pages and convert back. - */ - size = max_addr - addr - mem_hole_size(addr, max_addr); - size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes); - - /* - * Calculate the number of big nodes that can be allocated as a result - * of consolidating the remainder. - */ - big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * nr_nodes) / - FAKE_NODE_MIN_SIZE; - - size &= FAKE_NODE_MIN_HASH_MASK; - if (!size) { - pr_err("Not enough memory for each node. " - "NUMA emulation disabled.\n"); - return -1; - } - - /* - * Continue to fill physical nodes with fake nodes until there is no - * memory left on any of them. - */ - while (!nodes_empty(physnode_mask)) { - for_each_node_mask(i, physnode_mask) { - u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN); - u64 start, limit, end; - int phys_blk; - - phys_blk = emu_find_memblk_by_nid(i, pi); - if (phys_blk < 0) { - node_clear(i, physnode_mask); - continue; - } - start = pi->blk[phys_blk].start; - limit = pi->blk[phys_blk].end; - end = start + size; - - if (nid < big) - end += FAKE_NODE_MIN_SIZE; - - /* - * Continue to add memory to this fake node if its - * non-reserved memory is less than the per-node size. - */ - while (end - start - mem_hole_size(start, end) < size) { - end += FAKE_NODE_MIN_SIZE; - if (end > limit) { - end = limit; - break; - } - } - - /* - * If there won't be at least FAKE_NODE_MIN_SIZE of - * non-reserved memory in ZONE_DMA32 for the next node, - * this one must extend to the boundary. - */ - if (end < dma32_end && dma32_end - end - - mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) - end = dma32_end; - - /* - * If there won't be enough non-reserved memory for the - * next node, this one must extend to the end of the - * physical node. - */ - if (limit - end - mem_hole_size(end, limit) < size) - end = limit; - - ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes, - phys_blk, - min(end, limit) - start); - if (ret < 0) - return ret; - } - } - return 0; -} - -/* - * Returns the end address of a node so that there is at least `size' amount of - * non-reserved memory or `max_addr' is reached. - */ -static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size) -{ - u64 end = start + size; - - while (end - start - mem_hole_size(start, end) < size) { - end += FAKE_NODE_MIN_SIZE; - if (end > max_addr) { - end = max_addr; - break; - } - } - return end; -} - -static u64 uniform_size(u64 max_addr, u64 base, u64 hole, int nr_nodes) -{ - unsigned long max_pfn = PHYS_PFN(max_addr); - unsigned long base_pfn = PHYS_PFN(base); - unsigned long hole_pfns = PHYS_PFN(hole); - - return PFN_PHYS((max_pfn - base_pfn - hole_pfns) / nr_nodes); -} - -/* - * Sets up fake nodes of `size' interleaved over physical nodes ranging from - * `addr' to `max_addr'. - * - * Returns zero on success or negative on error. - */ -static int __init split_nodes_size_interleave_uniform(struct numa_meminfo *ei, - struct numa_meminfo *pi, - u64 addr, u64 max_addr, u64 size, - int nr_nodes, struct numa_memblk *pblk, - int nid) -{ - nodemask_t physnode_mask = numa_nodes_parsed; - int i, ret, uniform = 0; - u64 min_size; - - if ((!size && !nr_nodes) || (nr_nodes && !pblk)) - return -1; - - /* - * In the 'uniform' case split the passed in physical node by - * nr_nodes, in the non-uniform case, ignore the passed in - * physical block and try to create nodes of at least size - * @size. - * - * In the uniform case, split the nodes strictly by physical - * capacity, i.e. ignore holes. In the non-uniform case account - * for holes and treat @size as a minimum floor. - */ - if (!nr_nodes) - nr_nodes = MAX_NUMNODES; - else { - nodes_clear(physnode_mask); - node_set(pblk->nid, physnode_mask); - uniform = 1; - } - - if (uniform) { - min_size = uniform_size(max_addr, addr, 0, nr_nodes); - size = min_size; - } else { - /* - * The limit on emulated nodes is MAX_NUMNODES, so the - * size per node is increased accordingly if the - * requested size is too small. This creates a uniform - * distribution of node sizes across the entire machine - * (but not necessarily over physical nodes). - */ - min_size = uniform_size(max_addr, addr, - mem_hole_size(addr, max_addr), nr_nodes); - } - min_size = ALIGN(max(min_size, FAKE_NODE_MIN_SIZE), FAKE_NODE_MIN_SIZE); - if (size < min_size) { - pr_err("Fake node size %LuMB too small, increasing to %LuMB\n", - size >> 20, min_size >> 20); - size = min_size; - } - size = ALIGN_DOWN(size, FAKE_NODE_MIN_SIZE); - - /* - * Fill physical nodes with fake nodes of size until there is no memory - * left on any of them. - */ - while (!nodes_empty(physnode_mask)) { - for_each_node_mask(i, physnode_mask) { - u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN); - u64 start, limit, end; - int phys_blk; - - phys_blk = emu_find_memblk_by_nid(i, pi); - if (phys_blk < 0) { - node_clear(i, physnode_mask); - continue; - } - - start = pi->blk[phys_blk].start; - limit = pi->blk[phys_blk].end; - - if (uniform) - end = start + size; - else - end = find_end_of_node(start, limit, size); - /* - * If there won't be at least FAKE_NODE_MIN_SIZE of - * non-reserved memory in ZONE_DMA32 for the next node, - * this one must extend to the boundary. - */ - if (end < dma32_end && dma32_end - end - - mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) - end = dma32_end; - - /* - * If there won't be enough non-reserved memory for the - * next node, this one must extend to the end of the - * physical node. - */ - if ((limit - end - mem_hole_size(end, limit) < size) - && !uniform) - end = limit; - - ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES, - phys_blk, - min(end, limit) - start); - if (ret < 0) - return ret; - } - } - return nid; -} - -static int __init split_nodes_size_interleave(struct numa_meminfo *ei, - struct numa_meminfo *pi, - u64 addr, u64 max_addr, u64 size) -{ - return split_nodes_size_interleave_uniform(ei, pi, addr, max_addr, size, - 0, NULL, 0); -} - -static int __init setup_emu2phys_nid(int *dfl_phys_nid) -{ - int i, max_emu_nid = 0; - - *dfl_phys_nid = NUMA_NO_NODE; - for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++) { - if (emu_nid_to_phys[i] != NUMA_NO_NODE) { - max_emu_nid = i; - if (*dfl_phys_nid == NUMA_NO_NODE) - *dfl_phys_nid = emu_nid_to_phys[i]; - } - } - - return max_emu_nid; -} - -/** - * numa_emulation - Emulate NUMA nodes - * @numa_meminfo: NUMA configuration to massage - * @numa_dist_cnt: The size of the physical NUMA distance table - * - * Emulate NUMA nodes according to the numa=fake kernel parameter. - * @numa_meminfo contains the physical memory configuration and is modified - * to reflect the emulated configuration on success. @numa_dist_cnt is - * used to determine the size of the physical distance table. - * - * On success, the following modifications are made. - * - * - @numa_meminfo is updated to reflect the emulated nodes. - * - * - __apicid_to_node[] is updated such that APIC IDs are mapped to the - * emulated nodes. - * - * - NUMA distance table is rebuilt to represent distances between emulated - * nodes. The distances are determined considering how emulated nodes - * are mapped to physical nodes and match the actual distances. - * - * - emu_nid_to_phys[] reflects how emulated nodes are mapped to physical - * nodes. This is used by numa_add_cpu() and numa_remove_cpu(). - * - * If emulation is not enabled or fails, emu_nid_to_phys[] is filled with - * identity mapping and no other modification is made. - */ -void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) -{ - static struct numa_meminfo ei __initdata; - static struct numa_meminfo pi __initdata; - const u64 max_addr = PFN_PHYS(max_pfn); - u8 *phys_dist = NULL; - size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]); - int max_emu_nid, dfl_phys_nid; - int i, j, ret; - - if (!emu_cmdline) - goto no_emu; - - memset(&ei, 0, sizeof(ei)); - pi = *numa_meminfo; - - for (i = 0; i < MAX_NUMNODES; i++) - emu_nid_to_phys[i] = NUMA_NO_NODE; - - /* - * If the numa=fake command-line contains a 'M' or 'G', it represents - * the fixed node size. Otherwise, if it is just a single number N, - * split the system RAM into N fake nodes. - */ - if (strchr(emu_cmdline, 'U')) { - nodemask_t physnode_mask = numa_nodes_parsed; - unsigned long n; - int nid = 0; - - n = simple_strtoul(emu_cmdline, &emu_cmdline, 0); - ret = -1; - for_each_node_mask(i, physnode_mask) { - /* - * The reason we pass in blk[0] is due to - * numa_remove_memblk_from() called by - * emu_setup_memblk() will delete entry 0 - * and then move everything else up in the pi.blk - * array. Therefore we should always be looking - * at blk[0]. - */ - ret = split_nodes_size_interleave_uniform(&ei, &pi, - pi.blk[0].start, pi.blk[0].end, 0, - n, &pi.blk[0], nid); - if (ret < 0) - break; - if (ret < n) { - pr_info("%s: phys: %d only got %d of %ld nodes, failing\n", - __func__, i, ret, n); - ret = -1; - break; - } - nid = ret; - } - } else if (strchr(emu_cmdline, 'M') || strchr(emu_cmdline, 'G')) { - u64 size; - - size = memparse(emu_cmdline, &emu_cmdline); - ret = split_nodes_size_interleave(&ei, &pi, 0, max_addr, size); - } else { - unsigned long n; - - n = simple_strtoul(emu_cmdline, &emu_cmdline, 0); - ret = split_nodes_interleave(&ei, &pi, 0, max_addr, n); - } - if (*emu_cmdline == ':') - emu_cmdline++; - - if (ret < 0) - goto no_emu; - - if (numa_cleanup_meminfo(&ei) < 0) { - pr_warn("NUMA: Warning: constructed meminfo invalid, disabling emulation\n"); - goto no_emu; - } - - /* copy the physical distance table */ - if (numa_dist_cnt) { - u64 phys; - - phys = memblock_phys_alloc_range(phys_size, PAGE_SIZE, 0, - PFN_PHYS(max_pfn_mapped)); - if (!phys) { - pr_warn("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n"); - goto no_emu; - } - phys_dist = __va(phys); - - for (i = 0; i < numa_dist_cnt; i++) - for (j = 0; j < numa_dist_cnt; j++) - phys_dist[i * numa_dist_cnt + j] = - node_distance(i, j); - } - - /* - * Determine the max emulated nid and the default phys nid to use - * for unmapped nodes. - */ - max_emu_nid = setup_emu2phys_nid(&dfl_phys_nid); - - /* commit */ - *numa_meminfo = ei; - - /* Make sure numa_nodes_parsed only contains emulated nodes */ - nodes_clear(numa_nodes_parsed); - for (i = 0; i < ARRAY_SIZE(ei.blk); i++) - if (ei.blk[i].start != ei.blk[i].end && - ei.blk[i].nid != NUMA_NO_NODE) - node_set(ei.blk[i].nid, numa_nodes_parsed); - - /* - * Transform __apicid_to_node table to use emulated nids by - * reverse-mapping phys_nid. The maps should always exist but fall - * back to zero just in case. - */ - for (i = 0; i < ARRAY_SIZE(__apicid_to_node); i++) { - if (__apicid_to_node[i] == NUMA_NO_NODE) - continue; - for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++) - if (__apicid_to_node[i] == emu_nid_to_phys[j]) - break; - __apicid_to_node[i] = j < ARRAY_SIZE(emu_nid_to_phys) ? j : 0; - } - - /* make sure all emulated nodes are mapped to a physical node */ - for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++) - if (emu_nid_to_phys[i] == NUMA_NO_NODE) - emu_nid_to_phys[i] = dfl_phys_nid; - - /* transform distance table */ - numa_reset_distance(); - for (i = 0; i < max_emu_nid + 1; i++) { - for (j = 0; j < max_emu_nid + 1; j++) { - int physi = emu_nid_to_phys[i]; - int physj = emu_nid_to_phys[j]; - int dist; - - if (get_option(&emu_cmdline, &dist) == 2) - ; - else if (physi >= numa_dist_cnt || physj >= numa_dist_cnt) - dist = physi == physj ? - LOCAL_DISTANCE : REMOTE_DISTANCE; - else - dist = phys_dist[physi * numa_dist_cnt + physj]; - - numa_set_distance(i, j, dist); - } - } - - /* free the copied physical distance table */ - memblock_free(phys_dist, phys_size); - return; - -no_emu: - /* No emulation. Build identity emu_nid_to_phys[] for numa_add_cpu() */ - for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++) - emu_nid_to_phys[i] = i; -} - -#ifndef CONFIG_DEBUG_PER_CPU_MAPS -void numa_add_cpu(int cpu) -{ - int physnid, nid; - - nid = early_cpu_to_node(cpu); - BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); - - physnid = emu_nid_to_phys[nid]; - - /* - * Map the cpu to each emulated node that is allocated on the physical - * node of the cpu's apic id. - */ - for_each_online_node(nid) - if (emu_nid_to_phys[nid] == physnid) - cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); -} - -void numa_remove_cpu(int cpu) -{ - int i; - - for_each_online_node(i) - cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); -} -#else /* !CONFIG_DEBUG_PER_CPU_MAPS */ -static void numa_set_cpumask(int cpu, bool enable) -{ - int nid, physnid; - - nid = early_cpu_to_node(cpu); - if (nid == NUMA_NO_NODE) { - /* early_cpu_to_node() already emits a warning and trace */ - return; - } - - physnid = emu_nid_to_phys[nid]; - - for_each_online_node(nid) { - if (emu_nid_to_phys[nid] != physnid) - continue; - - debug_cpumask_set_cpu(cpu, nid, enable); - } -} - -void numa_add_cpu(int cpu) -{ - numa_set_cpumask(cpu, true); -} - -void numa_remove_cpu(int cpu) -{ - numa_set_cpumask(cpu, false); -} -#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ diff --git a/arch/x86/mm/numa_internal.h b/arch/x86/mm/numa_internal.h index 86860f279662..11e1ff370c10 100644 --- a/arch/x86/mm/numa_internal.h +++ b/arch/x86/mm/numa_internal.h @@ -5,30 +5,6 @@ #include <linux/types.h> #include <asm/numa.h> -struct numa_memblk { - u64 start; - u64 end; - int nid; -}; - -struct numa_meminfo { - int nr_blks; - struct numa_memblk blk[NR_NODE_MEMBLKS]; -}; - -void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi); -int __init numa_cleanup_meminfo(struct numa_meminfo *mi); -void __init numa_reset_distance(void); - void __init x86_numa_init(void); -#ifdef CONFIG_NUMA_EMU -void __init numa_emulation(struct numa_meminfo *numa_meminfo, - int numa_dist_cnt); -#else -static inline void numa_emulation(struct numa_meminfo *numa_meminfo, - int numa_dist_cnt) -{ } -#endif - #endif /* __X86_MM_NUMA_INTERNAL_H */ diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c index bdc2a240c2aa..feb8cc6a12bf 100644 --- a/arch/x86/mm/pat/memtype.c +++ b/arch/x86/mm/pat/memtype.c @@ -104,7 +104,7 @@ __setup("debugpat", pat_debug_setup); #ifdef CONFIG_X86_PAT /* - * X86 PAT uses page flags arch_1 and uncached together to keep track of + * X86 PAT uses page flags arch_1 and arch_2 together to keep track of * memory type of pages that have backing page struct. * * X86 PAT supports 4 different memory types: @@ -118,9 +118,9 @@ __setup("debugpat", pat_debug_setup); #define _PGMT_WB 0 #define _PGMT_WC (1UL << PG_arch_1) -#define _PGMT_UC_MINUS (1UL << PG_uncached) -#define _PGMT_WT (1UL << PG_uncached | 1UL << PG_arch_1) -#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1) +#define _PGMT_UC_MINUS (1UL << PG_arch_2) +#define _PGMT_WT (1UL << PG_arch_2 | 1UL << PG_arch_1) +#define _PGMT_MASK (1UL << PG_arch_2 | 1UL << PG_arch_1) #define _PGMT_CLEAR_MASK (~_PGMT_MASK) static inline enum page_cache_mode get_page_memtype(struct page *pg) @@ -176,15 +176,6 @@ static inline void set_page_memtype(struct page *pg, } #endif -enum { - PAT_UC = 0, /* uncached */ - PAT_WC = 1, /* Write combining */ - PAT_WT = 4, /* Write Through */ - PAT_WP = 5, /* Write Protected */ - PAT_WB = 6, /* Write Back (default) */ - PAT_UC_MINUS = 7, /* UC, but can be overridden by MTRR */ -}; - #define CM(c) (_PAGE_CACHE_MODE_ ## c) static enum page_cache_mode __init pat_get_cache_mode(unsigned int pat_val, @@ -194,13 +185,13 @@ static enum page_cache_mode __init pat_get_cache_mode(unsigned int pat_val, char *cache_mode; switch (pat_val) { - case PAT_UC: cache = CM(UC); cache_mode = "UC "; break; - case PAT_WC: cache = CM(WC); cache_mode = "WC "; break; - case PAT_WT: cache = CM(WT); cache_mode = "WT "; break; - case PAT_WP: cache = CM(WP); cache_mode = "WP "; break; - case PAT_WB: cache = CM(WB); cache_mode = "WB "; break; - case PAT_UC_MINUS: cache = CM(UC_MINUS); cache_mode = "UC- "; break; - default: cache = CM(WB); cache_mode = "WB "; break; + case X86_MEMTYPE_UC: cache = CM(UC); cache_mode = "UC "; break; + case X86_MEMTYPE_WC: cache = CM(WC); cache_mode = "WC "; break; + case X86_MEMTYPE_WT: cache = CM(WT); cache_mode = "WT "; break; + case X86_MEMTYPE_WP: cache = CM(WP); cache_mode = "WP "; break; + case X86_MEMTYPE_WB: cache = CM(WB); cache_mode = "WB "; break; + case X86_MEMTYPE_UC_MINUS: cache = CM(UC_MINUS); cache_mode = "UC- "; break; + default: cache = CM(WB); cache_mode = "WB "; break; } memcpy(msg, cache_mode, 4); @@ -257,12 +248,6 @@ void pat_cpu_init(void) void __init pat_bp_init(void) { struct cpuinfo_x86 *c = &boot_cpu_data; -#define PAT(p0, p1, p2, p3, p4, p5, p6, p7) \ - (((u64)PAT_ ## p0) | ((u64)PAT_ ## p1 << 8) | \ - ((u64)PAT_ ## p2 << 16) | ((u64)PAT_ ## p3 << 24) | \ - ((u64)PAT_ ## p4 << 32) | ((u64)PAT_ ## p5 << 40) | \ - ((u64)PAT_ ## p6 << 48) | ((u64)PAT_ ## p7 << 56)) - if (!IS_ENABLED(CONFIG_X86_PAT)) pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n"); @@ -293,7 +278,7 @@ void __init pat_bp_init(void) * NOTE: When WC or WP is used, it is redirected to UC- per * the default setup in __cachemode2pte_tbl[]. */ - pat_msr_val = PAT(WB, WT, UC_MINUS, UC, WB, WT, UC_MINUS, UC); + pat_msr_val = PAT_VALUE(WB, WT, UC_MINUS, UC, WB, WT, UC_MINUS, UC); } /* @@ -328,7 +313,7 @@ void __init pat_bp_init(void) * NOTE: When WT or WP is used, it is redirected to UC- per * the default setup in __cachemode2pte_tbl[]. */ - pat_msr_val = PAT(WB, WC, UC_MINUS, UC, WB, WC, UC_MINUS, UC); + pat_msr_val = PAT_VALUE(WB, WC, UC_MINUS, UC, WB, WC, UC_MINUS, UC); } else { /* * Full PAT support. We put WT in slot 7 to improve @@ -356,13 +341,12 @@ void __init pat_bp_init(void) * The reserved slots are unused, but mapped to their * corresponding types in the presence of PAT errata. */ - pat_msr_val = PAT(WB, WC, UC_MINUS, UC, WB, WP, UC_MINUS, WT); + pat_msr_val = PAT_VALUE(WB, WC, UC_MINUS, UC, WB, WP, UC_MINUS, WT); } memory_caching_control |= CACHE_PAT; init_cache_modes(pat_msr_val); -#undef PAT } static DEFINE_SPINLOCK(memtype_lock); /* protects memtype accesses */ @@ -951,23 +935,20 @@ static void free_pfn_range(u64 paddr, unsigned long size) static int follow_phys(struct vm_area_struct *vma, unsigned long *prot, resource_size_t *phys) { - pte_t *ptep, pte; - spinlock_t *ptl; + struct follow_pfnmap_args args = { .vma = vma, .address = vma->vm_start }; - if (follow_pte(vma, vma->vm_start, &ptep, &ptl)) + if (follow_pfnmap_start(&args)) return -EINVAL; - pte = ptep_get(ptep); - /* Never return PFNs of anon folios in COW mappings. */ - if (vm_normal_folio(vma, vma->vm_start, pte)) { - pte_unmap_unlock(ptep, ptl); + if (!args.special) { + follow_pfnmap_end(&args); return -EINVAL; } - *prot = pgprot_val(pte_pgprot(pte)); - *phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT; - pte_unmap_unlock(ptep, ptl); + *prot = pgprot_val(args.pgprot); + *phys = (resource_size_t)args.pfn << PAGE_SHIFT; + follow_pfnmap_end(&args); return 0; } diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index f5931499c2d6..5745a354a241 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -641,6 +641,18 @@ pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address, } #endif +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \ + defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) +pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address, + pud_t *pudp) +{ + VM_WARN_ON_ONCE(!pud_present(*pudp)); + pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp)); + flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE); + return old; +} +#endif + /** * reserve_top_address - reserves a hole in the top of kernel address space * @reserve - size of hole to reserve @@ -926,3 +938,9 @@ void arch_check_zapped_pmd(struct vm_area_struct *vma, pmd_t pmd) VM_WARN_ON_ONCE(!(vma->vm_flags & VM_SHADOW_STACK) && pmd_shstk(pmd)); } + +void arch_check_zapped_pud(struct vm_area_struct *vma, pud_t pud) +{ + /* See note in arch_check_zapped_pte() */ + VM_WARN_ON_ONCE(!(vma->vm_flags & VM_SHADOW_STACK) && pud_shstk(pud)); +} diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 9c52a95937ad..6f8e0f21c710 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -57,8 +57,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) } set_apicid_to_node(apic_id, node); node_set(node, numa_nodes_parsed); - printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", - pxm, apic_id, node); + pr_debug("SRAT: PXM %u -> APIC 0x%04x -> Node %u\n", pxm, apic_id, node); } /* Callback for Proximity Domain -> LAPIC mapping */ @@ -98,8 +97,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) set_apicid_to_node(apic_id, node); node_set(node, numa_nodes_parsed); - printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", - pxm, apic_id, node); + pr_debug("SRAT: PXM %u -> APIC 0x%02x -> Node %u\n", pxm, apic_id, node); } int __init x86_acpi_numa_init(void) diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index bda73cb7a044..ae295659ca14 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c @@ -144,3 +144,4 @@ static void __exit cleanup(void) module_init(init); module_exit(cleanup); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Test module for mmiotrace"); diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 44ac64f3a047..b0d5a644fc84 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -11,6 +11,7 @@ #include <linux/sched/smt.h> #include <linux/task_work.h> #include <linux/mmu_notifier.h> +#include <linux/mmu_context.h> #include <asm/tlbflush.h> #include <asm/mmu_context.h> @@ -85,9 +86,6 @@ * */ -/* There are 12 bits of space for ASIDS in CR3 */ -#define CR3_HW_ASID_BITS 12 - /* * When enabled, MITIGATION_PAGE_TABLE_ISOLATION consumes a single bit for * user/kernel switches @@ -160,7 +158,6 @@ static inline unsigned long build_cr3(pgd_t *pgd, u16 asid, unsigned long lam) unsigned long cr3 = __sme_pa(pgd) | lam; if (static_cpu_has(X86_FEATURE_PCID)) { - VM_WARN_ON_ONCE(asid > MAX_ASID_AVAILABLE); cr3 |= kern_pcid(asid); } else { VM_WARN_ON_ONCE(asid != 0); @@ -503,9 +500,9 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, { struct mm_struct *prev = this_cpu_read(cpu_tlbstate.loaded_mm); u16 prev_asid = this_cpu_read(cpu_tlbstate.loaded_mm_asid); - unsigned long new_lam = mm_lam_cr3_mask(next); bool was_lazy = this_cpu_read(cpu_tlbstate_shared.is_lazy); unsigned cpu = smp_processor_id(); + unsigned long new_lam; u64 next_tlb_gen; bool need_flush; u16 new_asid; @@ -571,7 +568,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, * mm_cpumask. The TLB shootdown code can figure out from * cpu_tlbstate_shared.is_lazy whether or not to send an IPI. */ - if (WARN_ON_ONCE(prev != &init_mm && + if (IS_ENABLED(CONFIG_DEBUG_VM) && WARN_ON_ONCE(prev != &init_mm && !cpumask_test_cpu(cpu, mm_cpumask(next)))) cpumask_set_cpu(cpu, mm_cpumask(next)); @@ -619,9 +616,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, cpumask_clear_cpu(cpu, mm_cpumask(prev)); } - /* - * Start remote flushes and then read tlb_gen. - */ + /* Start receiving IPIs and then read tlb_gen (and LAM below) */ if (next != &init_mm) cpumask_set_cpu(cpu, mm_cpumask(next)); next_tlb_gen = atomic64_read(&next->context.tlb_gen); @@ -633,7 +628,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, barrier(); } - set_tlbstate_lam_mode(next); + new_lam = mm_lam_cr3_mask(next); if (need_flush) { this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen); @@ -652,6 +647,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next, this_cpu_write(cpu_tlbstate.loaded_mm, next); this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid); + cpu_tlbstate_update_lam(new_lam, mm_untag_mask(next)); if (next != prev) { cr4_update_pce_mm(next); @@ -698,6 +694,7 @@ void initialize_tlbstate_and_flush(void) int i; struct mm_struct *mm = this_cpu_read(cpu_tlbstate.loaded_mm); u64 tlb_gen = atomic64_read(&init_mm.context.tlb_gen); + unsigned long lam = mm_lam_cr3_mask(mm); unsigned long cr3 = __read_cr3(); /* Assert that CR3 already references the right mm. */ @@ -705,7 +702,7 @@ void initialize_tlbstate_and_flush(void) /* LAM expected to be disabled */ WARN_ON(cr3 & (X86_CR3_LAM_U48 | X86_CR3_LAM_U57)); - WARN_ON(mm_lam_cr3_mask(mm)); + WARN_ON(lam); /* * Assert that CR4.PCIDE is set if needed. (CR4.PCIDE initialization @@ -724,7 +721,7 @@ void initialize_tlbstate_and_flush(void) this_cpu_write(cpu_tlbstate.next_asid, 1); this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id); this_cpu_write(cpu_tlbstate.ctxs[0].tlb_gen, tlb_gen); - set_tlbstate_lam_mode(mm); + cpu_tlbstate_update_lam(lam, mm_untag_mask(mm)); for (i = 1; i < TLB_NR_DYN_ASIDS; i++) this_cpu_write(cpu_tlbstate.ctxs[i].ctx_id, 0); diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index d25d81c8ecc0..06b080b61aa5 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -64,6 +64,56 @@ static bool is_imm8(int value) return value <= 127 && value >= -128; } +/* + * Let us limit the positive offset to be <= 123. + * This is to ensure eventual jit convergence For the following patterns: + * ... + * pass4, final_proglen=4391: + * ... + * 20e: 48 85 ff test rdi,rdi + * 211: 74 7d je 0x290 + * 213: 48 8b 77 00 mov rsi,QWORD PTR [rdi+0x0] + * ... + * 289: 48 85 ff test rdi,rdi + * 28c: 74 17 je 0x2a5 + * 28e: e9 7f ff ff ff jmp 0x212 + * 293: bf 03 00 00 00 mov edi,0x3 + * Note that insn at 0x211 is 2-byte cond jump insn for offset 0x7d (-125) + * and insn at 0x28e is 5-byte jmp insn with offset -129. + * + * pass5, final_proglen=4392: + * ... + * 20e: 48 85 ff test rdi,rdi + * 211: 0f 84 80 00 00 00 je 0x297 + * 217: 48 8b 77 00 mov rsi,QWORD PTR [rdi+0x0] + * ... + * 28d: 48 85 ff test rdi,rdi + * 290: 74 1a je 0x2ac + * 292: eb 84 jmp 0x218 + * 294: bf 03 00 00 00 mov edi,0x3 + * Note that insn at 0x211 is 6-byte cond jump insn now since its offset + * becomes 0x80 based on previous round (0x293 - 0x213 = 0x80). + * At the same time, insn at 0x292 is a 2-byte insn since its offset is + * -124. + * + * pass6 will repeat the same code as in pass4 and this will prevent + * eventual convergence. + * + * To fix this issue, we need to break je (2->6 bytes) <-> jmp (5->2 bytes) + * cycle in the above. In the above example je offset <= 0x7c should work. + * + * For other cases, je <-> je needs offset <= 0x7b to avoid no convergence + * issue. For jmp <-> je and jmp <-> jmp cases, jmp offset <= 0x7c should + * avoid no convergence issue. + * + * Overall, let us limit the positive offset for 8bit cond/uncond jmp insn + * to maximum 123 (0x7b). This way, the jit pass can eventually converge. + */ +static bool is_imm8_jmp_offset(int value) +{ + return value <= 123 && value >= -128; +} + static bool is_simm32(s64 value) { return value == (s64)(s32)value; @@ -273,7 +323,7 @@ struct jit_context { /* Number of bytes emit_patch() needs to generate instructions */ #define X86_PATCH_SIZE 5 /* Number of bytes that will be skipped on tailcall */ -#define X86_TAIL_CALL_OFFSET (11 + ENDBR_INSN_SIZE) +#define X86_TAIL_CALL_OFFSET (12 + ENDBR_INSN_SIZE) static void push_r12(u8 **pprog) { @@ -403,6 +453,37 @@ static void emit_cfi(u8 **pprog, u32 hash) *pprog = prog; } +static void emit_prologue_tail_call(u8 **pprog, bool is_subprog) +{ + u8 *prog = *pprog; + + if (!is_subprog) { + /* cmp rax, MAX_TAIL_CALL_CNT */ + EMIT4(0x48, 0x83, 0xF8, MAX_TAIL_CALL_CNT); + EMIT2(X86_JA, 6); /* ja 6 */ + /* rax is tail_call_cnt if <= MAX_TAIL_CALL_CNT. + * case1: entry of main prog. + * case2: tail callee of main prog. + */ + EMIT1(0x50); /* push rax */ + /* Make rax as tail_call_cnt_ptr. */ + EMIT3(0x48, 0x89, 0xE0); /* mov rax, rsp */ + EMIT2(0xEB, 1); /* jmp 1 */ + /* rax is tail_call_cnt_ptr if > MAX_TAIL_CALL_CNT. + * case: tail callee of subprog. + */ + EMIT1(0x50); /* push rax */ + /* push tail_call_cnt_ptr */ + EMIT1(0x50); /* push rax */ + } else { /* is_subprog */ + /* rax is tail_call_cnt_ptr. */ + EMIT1(0x50); /* push rax */ + EMIT1(0x50); /* push rax */ + } + + *pprog = prog; +} + /* * Emit x86-64 prologue code for BPF program. * bpf_tail_call helper will skip the first X86_TAIL_CALL_OFFSET bytes @@ -424,10 +505,10 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, /* When it's the entry of the whole tailcall context, * zeroing rax means initialising tail_call_cnt. */ - EMIT2(0x31, 0xC0); /* xor eax, eax */ + EMIT3(0x48, 0x31, 0xC0); /* xor rax, rax */ else /* Keep the same instruction layout. */ - EMIT2(0x66, 0x90); /* nop2 */ + emit_nops(&prog, 3); /* nop3 */ } /* Exception callback receives FP as third parameter */ if (is_exception_cb) { @@ -453,7 +534,7 @@ static void emit_prologue(u8 **pprog, u32 stack_depth, bool ebpf_from_cbpf, if (stack_depth) EMIT3_off32(0x48, 0x81, 0xEC, round_up(stack_depth, 8)); if (tail_call_reachable) - EMIT1(0x50); /* push rax */ + emit_prologue_tail_call(&prog, is_subprog); *pprog = prog; } @@ -589,13 +670,15 @@ static void emit_return(u8 **pprog, u8 *ip) *pprog = prog; } +#define BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack) (-16 - round_up(stack, 8)) + /* * Generate the following code: * * ... bpf_tail_call(void *ctx, struct bpf_array *array, u64 index) ... * if (index >= array->map.max_entries) * goto out; - * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) + * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) * goto out; * prog = array->ptrs[index]; * if (prog == NULL) @@ -608,7 +691,7 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, u32 stack_depth, u8 *ip, struct jit_context *ctx) { - int tcc_off = -4 - round_up(stack_depth, 8); + int tcc_ptr_off = BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack_depth); u8 *prog = *pprog, *start = *pprog; int offset; @@ -630,16 +713,14 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, EMIT2(X86_JBE, offset); /* jbe out */ /* - * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) + * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) * goto out; */ - EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ - EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ + EMIT3_off32(0x48, 0x8B, 0x85, tcc_ptr_off); /* mov rax, qword ptr [rbp - tcc_ptr_off] */ + EMIT4(0x48, 0x83, 0x38, MAX_TAIL_CALL_CNT); /* cmp qword ptr [rax], MAX_TAIL_CALL_CNT */ offset = ctx->tail_call_indirect_label - (prog + 2 - start); EMIT2(X86_JAE, offset); /* jae out */ - EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ - EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ /* prog = array->ptrs[index]; */ EMIT4_off32(0x48, 0x8B, 0x8C, 0xD6, /* mov rcx, [rsi + rdx * 8 + offsetof(...)] */ @@ -654,6 +735,9 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, offset = ctx->tail_call_indirect_label - (prog + 2 - start); EMIT2(X86_JE, offset); /* je out */ + /* Inc tail_call_cnt if the slot is populated. */ + EMIT4(0x48, 0x83, 0x00, 0x01); /* add qword ptr [rax], 1 */ + if (bpf_prog->aux->exception_boundary) { pop_callee_regs(&prog, all_callee_regs_used); pop_r12(&prog); @@ -663,6 +747,11 @@ static void emit_bpf_tail_call_indirect(struct bpf_prog *bpf_prog, pop_r12(&prog); } + /* Pop tail_call_cnt_ptr. */ + EMIT1(0x58); /* pop rax */ + /* Pop tail_call_cnt, if it's main prog. + * Pop tail_call_cnt_ptr, if it's subprog. + */ EMIT1(0x58); /* pop rax */ if (stack_depth) EMIT3_off32(0x48, 0x81, 0xC4, /* add rsp, sd */ @@ -691,21 +780,19 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, bool *callee_regs_used, u32 stack_depth, struct jit_context *ctx) { - int tcc_off = -4 - round_up(stack_depth, 8); + int tcc_ptr_off = BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack_depth); u8 *prog = *pprog, *start = *pprog; int offset; /* - * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT) + * if ((*tcc_ptr)++ >= MAX_TAIL_CALL_CNT) * goto out; */ - EMIT2_off32(0x8B, 0x85, tcc_off); /* mov eax, dword ptr [rbp - tcc_off] */ - EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */ + EMIT3_off32(0x48, 0x8B, 0x85, tcc_ptr_off); /* mov rax, qword ptr [rbp - tcc_ptr_off] */ + EMIT4(0x48, 0x83, 0x38, MAX_TAIL_CALL_CNT); /* cmp qword ptr [rax], MAX_TAIL_CALL_CNT */ offset = ctx->tail_call_direct_label - (prog + 2 - start); EMIT2(X86_JAE, offset); /* jae out */ - EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */ - EMIT2_off32(0x89, 0x85, tcc_off); /* mov dword ptr [rbp - tcc_off], eax */ poke->tailcall_bypass = ip + (prog - start); poke->adj_off = X86_TAIL_CALL_OFFSET; @@ -715,6 +802,9 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, emit_jump(&prog, (u8 *)poke->tailcall_target + X86_PATCH_SIZE, poke->tailcall_bypass); + /* Inc tail_call_cnt if the slot is populated. */ + EMIT4(0x48, 0x83, 0x00, 0x01); /* add qword ptr [rax], 1 */ + if (bpf_prog->aux->exception_boundary) { pop_callee_regs(&prog, all_callee_regs_used); pop_r12(&prog); @@ -724,6 +814,11 @@ static void emit_bpf_tail_call_direct(struct bpf_prog *bpf_prog, pop_r12(&prog); } + /* Pop tail_call_cnt_ptr. */ + EMIT1(0x58); /* pop rax */ + /* Pop tail_call_cnt, if it's main prog. + * Pop tail_call_cnt_ptr, if it's subprog. + */ EMIT1(0x58); /* pop rax */ if (stack_depth) EMIT3_off32(0x48, 0x81, 0xC4, round_up(stack_depth, 8)); @@ -1311,9 +1406,11 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op) #define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp))) -/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */ -#define RESTORE_TAIL_CALL_CNT(stack) \ - EMIT3_off32(0x48, 0x8B, 0x85, -round_up(stack, 8) - 8) +#define __LOAD_TCC_PTR(off) \ + EMIT3_off32(0x48, 0x8B, 0x85, off) +/* mov rax, qword ptr [rbp - rounded_stack_depth - 16] */ +#define LOAD_TAIL_CALL_CNT_PTR(stack) \ + __LOAD_TCC_PTR(BPF_TAIL_CALL_CNT_PTR_STACK_OFF(stack)) static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image, int oldproglen, struct jit_context *ctx, bool jmp_padding) @@ -2031,7 +2128,7 @@ populate_extable: func = (u8 *) __bpf_call_base + imm32; if (tail_call_reachable) { - RESTORE_TAIL_CALL_CNT(bpf_prog->aux->stack_depth); + LOAD_TAIL_CALL_CNT_PTR(bpf_prog->aux->stack_depth); ip += 7; } if (!imm32) @@ -2184,7 +2281,7 @@ emit_cond_jmp: /* Convert BPF opcode to x86 */ return -EFAULT; } jmp_offset = addrs[i + insn->off] - addrs[i]; - if (is_imm8(jmp_offset)) { + if (is_imm8_jmp_offset(jmp_offset)) { if (jmp_padding) { /* To keep the jmp_offset valid, the extra bytes are * padded before the jump insn, so we subtract the @@ -2266,7 +2363,7 @@ emit_cond_jmp: /* Convert BPF opcode to x86 */ break; } emit_jmp: - if (is_imm8(jmp_offset)) { + if (is_imm8_jmp_offset(jmp_offset)) { if (jmp_padding) { /* To avoid breaking jmp_offset, the extra bytes * are padded before the actual jmp insn, so @@ -2706,6 +2803,10 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog, return 0; } +/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */ +#define LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack) \ + __LOAD_TCC_PTR(-round_up(stack, 8) - 8) + /* Example: * __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); * its 'struct btf_func_model' will be nr_args=2 @@ -2826,7 +2927,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im * [ ... ] * [ stack_arg2 ] * RBP - arg_stack_off [ stack_arg1 ] - * RSP [ tail_call_cnt ] BPF_TRAMP_F_TAIL_CALL_CTX + * RSP [ tail_call_cnt_ptr ] BPF_TRAMP_F_TAIL_CALL_CTX */ /* room for return value of orig_call or fentry prog */ @@ -2955,10 +3056,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im save_args(m, &prog, arg_stack_off, true); if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) { - /* Before calling the original function, restore the - * tail_call_cnt from stack to rax. + /* Before calling the original function, load the + * tail_call_cnt_ptr from stack to rax. */ - RESTORE_TAIL_CALL_CNT(stack_size); + LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack_size); } if (flags & BPF_TRAMP_F_ORIG_STACK) { @@ -3017,10 +3118,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im goto cleanup; } } else if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) { - /* Before running the original function, restore the - * tail_call_cnt from stack to rax. + /* Before running the original function, load the + * tail_call_cnt_ptr from stack to rax. */ - RESTORE_TAIL_CALL_CNT(stack_size); + LOAD_TRAMP_TAIL_CALL_CNT_PTR(stack_size); } /* restore return value of orig_call or fentry prog back into RAX */ diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index b33afb240601..98a9bb92d75c 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -980,7 +980,7 @@ static void amd_rp_pme_suspend(struct pci_dev *dev) return; rp = pcie_find_root_port(dev); - if (!rp->pm_cap) + if (!rp || !rp->pm_cap) return; rp->pme_support &= ~((PCI_PM_CAP_PME_D3hot|PCI_PM_CAP_PME_D3cold) >> @@ -994,7 +994,7 @@ static void amd_rp_pme_resume(struct pci_dev *dev) u16 pmc; rp = pcie_find_root_port(dev); - if (!rp->pm_cap) + if (!rp || !rp->pm_cap) return; pci_read_config_word(rp, rp->pm_cap + PCI_PM_PMC, &pmc); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 88a96816de9a..a7ff189421c3 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -54,14 +54,12 @@ #include <asm/uv/uv.h> static unsigned long efi_systab_phys __initdata; -static unsigned long prop_phys = EFI_INVALID_TABLE_ADDR; static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR; static unsigned long efi_runtime, efi_nr_tables; unsigned long efi_fw_vendor, efi_config_table; static const efi_config_table_type_t arch_tables[] __initconst = { - {EFI_PROPERTIES_TABLE_GUID, &prop_phys, "PROP" }, {UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" }, #ifdef CONFIG_X86_UV {UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" }, @@ -82,7 +80,6 @@ static const unsigned long * const efi_tables[] = { &efi_runtime, &efi_config_table, &efi.esrt, - &prop_phys, &efi_mem_attr_table, #ifdef CONFIG_EFI_RCI2_TABLE &rci2_table_phys, @@ -502,22 +499,6 @@ void __init efi_init(void) return; } - /* Parse the EFI Properties table if it exists */ - if (prop_phys != EFI_INVALID_TABLE_ADDR) { - efi_properties_table_t *tbl; - - tbl = early_memremap_ro(prop_phys, sizeof(*tbl)); - if (tbl == NULL) { - pr_err("Could not map Properties table!\n"); - } else { - if (tbl->memory_protection_attribute & - EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) - set_bit(EFI_NX_PE_DATA, &efi.flags); - - early_memunmap(tbl, sizeof(*tbl)); - } - } - set_bit(EFI_RUNTIME_SERVICES, &efi.flags); efi_clean_memmap(); @@ -784,6 +765,7 @@ static void __init kexec_enter_virtual_mode(void) efi_sync_low_kernel_mappings(); efi_native_runtime_setup(); + efi_runtime_update_mappings(); #endif } diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 91d31ac422d6..ac57259a432b 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -412,51 +412,9 @@ static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *m void __init efi_runtime_update_mappings(void) { - efi_memory_desc_t *md; - - /* - * Use the EFI Memory Attribute Table for mapping permissions if it - * exists, since it is intended to supersede EFI_PROPERTIES_TABLE. - */ if (efi_enabled(EFI_MEM_ATTR)) { efi_disable_ibt_for_runtime = false; efi_memattr_apply_permissions(NULL, efi_update_mem_attr); - return; - } - - /* - * EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace - * EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update - * permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not - * published by the firmware. Even if we find a buggy implementation of - * EFI_MEMORY_ATTRIBUTES_TABLE, don't fall back to - * EFI_PROPERTIES_TABLE, because of the same reason. - */ - - if (!efi_enabled(EFI_NX_PE_DATA)) - return; - - for_each_efi_memory_desc(md) { - unsigned long pf = 0; - - if (!(md->attribute & EFI_MEMORY_RUNTIME)) - continue; - - if (!(md->attribute & EFI_MEMORY_WB)) - pf |= _PAGE_PCD; - - if ((md->attribute & EFI_MEMORY_XP) || - (md->type == EFI_RUNTIME_SERVICES_DATA)) - pf |= _PAGE_NX; - - if (!(md->attribute & EFI_MEMORY_RO) && - (md->type != EFI_RUNTIME_SERVICES_CODE)) - pf |= _PAGE_RW; - - if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) - pf |= _PAGE_ENC; - - efi_update_mappings(md, pf); } } diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index f0cc00032751..846bf49f2508 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -656,8 +656,7 @@ static int qrk_capsule_setup_info(struct capsule_info *cap_info, void **pkbuff, } static const struct x86_cpu_id efi_capsule_quirk_ids[] = { - X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, - &qrk_capsule_setup_info), + X86_MATCH_VFM(INTEL_QUARK_X1000, &qrk_capsule_setup_info), { } }; diff --git a/arch/x86/platform/geode/Makefile b/arch/x86/platform/geode/Makefile index a8a6b1dedb01..34b53e97a0ad 100644 --- a/arch/x86/platform/geode/Makefile +++ b/arch/x86/platform/geode/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_GEODE_COMMON) += geode-common.o obj-$(CONFIG_ALIX) += alix.o obj-$(CONFIG_NET5501) += net5501.o obj-$(CONFIG_GEOS) += geos.o diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c index b39bf3b5e108..be65cd704e21 100644 --- a/arch/x86/platform/geode/alix.c +++ b/arch/x86/platform/geode/alix.c @@ -18,15 +18,12 @@ #include <linux/io.h> #include <linux/string.h> #include <linux/moduleparam.h> -#include <linux/leds.h> -#include <linux/platform_device.h> -#include <linux/input.h> -#include <linux/gpio_keys.h> -#include <linux/gpio/machine.h> #include <linux/dmi.h> #include <asm/geode.h> +#include "geode-common.h" + #define BIOS_SIGNATURE_TINYBIOS 0xf0000 #define BIOS_SIGNATURE_COREBOOT 0x500 #define BIOS_REGION_SIZE 0x10000 @@ -41,79 +38,16 @@ module_param(force, bool, 0444); /* FIXME: Award bios is not automatically detected as Alix platform */ MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); -static struct gpio_keys_button alix_gpio_buttons[] = { - { - .code = KEY_RESTART, - .gpio = 24, - .active_low = 1, - .desc = "Reset button", - .type = EV_KEY, - .wakeup = 0, - .debounce_interval = 100, - .can_disable = 0, - } -}; -static struct gpio_keys_platform_data alix_buttons_data = { - .buttons = alix_gpio_buttons, - .nbuttons = ARRAY_SIZE(alix_gpio_buttons), - .poll_interval = 20, -}; - -static struct platform_device alix_buttons_dev = { - .name = "gpio-keys-polled", - .id = 1, - .dev = { - .platform_data = &alix_buttons_data, - } -}; - -static struct gpio_led alix_leds[] = { - { - .name = "alix:1", - .default_trigger = "default-on", - }, - { - .name = "alix:2", - .default_trigger = "default-off", - }, - { - .name = "alix:3", - .default_trigger = "default-off", - }, -}; - -static struct gpio_led_platform_data alix_leds_data = { - .num_leds = ARRAY_SIZE(alix_leds), - .leds = alix_leds, -}; - -static struct gpiod_lookup_table alix_leds_gpio_table = { - .dev_id = "leds-gpio", - .table = { - /* The Geode GPIOs should be on the CS5535 companion chip */ - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("cs5535-gpio", 25, NULL, 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("cs5535-gpio", 27, NULL, 2, GPIO_ACTIVE_LOW), - { } - }, -}; - -static struct platform_device alix_leds_dev = { - .name = "leds-gpio", - .id = -1, - .dev.platform_data = &alix_leds_data, -}; - -static struct platform_device *alix_devs[] __initdata = { - &alix_buttons_dev, - &alix_leds_dev, +static const struct geode_led alix_leds[] __initconst = { + { 6, true }, + { 25, false }, + { 27, false }, }; static void __init register_alix(void) { - /* Setup LED control through leds-gpio driver */ - gpiod_add_lookup_table(&alix_leds_gpio_table); - platform_add_devices(alix_devs, ARRAY_SIZE(alix_devs)); + geode_create_restart_key(24); + geode_create_leds("alix", alix_leds, ARRAY_SIZE(alix_leds)); } static bool __init alix_present(unsigned long bios_phys, diff --git a/arch/x86/platform/geode/geode-common.c b/arch/x86/platform/geode/geode-common.c new file mode 100644 index 000000000000..8fd78e60bf15 --- /dev/null +++ b/arch/x86/platform/geode/geode-common.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Shared helpers to register GPIO-connected buttons and LEDs + * on AMD Geode boards. + */ + +#include <linux/err.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/property.h> +#include <linux/input.h> +#include <linux/leds.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "geode-common.h" + +static const struct software_node geode_gpiochip_node = { + .name = "cs5535-gpio", +}; + +static const struct property_entry geode_gpio_keys_props[] = { + PROPERTY_ENTRY_U32("poll-interval", 20), + { } +}; + +static const struct software_node geode_gpio_keys_node = { + .name = "geode-gpio-keys", + .properties = geode_gpio_keys_props, +}; + +static struct property_entry geode_restart_key_props[] = { + { /* Placeholder for GPIO property */ }, + PROPERTY_ENTRY_U32("linux,code", KEY_RESTART), + PROPERTY_ENTRY_STRING("label", "Reset button"), + PROPERTY_ENTRY_U32("debounce-interval", 100), + { } +}; + +static const struct software_node geode_restart_key_node = { + .parent = &geode_gpio_keys_node, + .properties = geode_restart_key_props, +}; + +static const struct software_node *geode_gpio_keys_swnodes[] __initconst = { + &geode_gpiochip_node, + &geode_gpio_keys_node, + &geode_restart_key_node, + NULL +}; + +/* + * Creates gpio-keys-polled device for the restart key. + * + * Note that it needs to be called first, before geode_create_leds(), + * because it registers gpiochip software node used by both gpio-keys and + * leds-gpio devices. + */ +int __init geode_create_restart_key(unsigned int pin) +{ + struct platform_device_info keys_info = { + .name = "gpio-keys-polled", + .id = 1, + }; + struct platform_device *pd; + int err; + + geode_restart_key_props[0] = PROPERTY_ENTRY_GPIO("gpios", + &geode_gpiochip_node, + pin, GPIO_ACTIVE_LOW); + + err = software_node_register_node_group(geode_gpio_keys_swnodes); + if (err) { + pr_err("failed to register gpio-keys software nodes: %d\n", err); + return err; + } + + keys_info.fwnode = software_node_fwnode(&geode_gpio_keys_node); + + pd = platform_device_register_full(&keys_info); + err = PTR_ERR_OR_ZERO(pd); + if (err) { + pr_err("failed to create gpio-keys device: %d\n", err); + software_node_unregister_node_group(geode_gpio_keys_swnodes); + return err; + } + + return 0; +} + +static const struct software_node geode_gpio_leds_node = { + .name = "geode-leds", +}; + +#define MAX_LEDS 3 + +int __init geode_create_leds(const char *label, const struct geode_led *leds, + unsigned int n_leds) +{ + const struct software_node *group[MAX_LEDS + 2] = { 0 }; + struct software_node *swnodes; + struct property_entry *props; + struct platform_device_info led_info = { + .name = "leds-gpio", + .id = PLATFORM_DEVID_NONE, + }; + struct platform_device *led_dev; + const char *node_name; + int err; + int i; + + if (n_leds > MAX_LEDS) { + pr_err("%s: too many LEDs\n", __func__); + return -EINVAL; + } + + swnodes = kcalloc(n_leds, sizeof(*swnodes), GFP_KERNEL); + if (!swnodes) + return -ENOMEM; + + /* + * Each LED is represented by 3 properties: "gpios", + * "linux,default-trigger", and am empty terminator. + */ + props = kcalloc(n_leds * 3, sizeof(*props), GFP_KERNEL); + if (!props) { + err = -ENOMEM; + goto err_free_swnodes; + } + + group[0] = &geode_gpio_leds_node; + for (i = 0; i < n_leds; i++) { + node_name = kasprintf(GFP_KERNEL, "%s:%d", label, i); + if (!node_name) { + err = -ENOMEM; + goto err_free_names; + } + + props[i * 3 + 0] = + PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node, + leds[i].pin, GPIO_ACTIVE_LOW); + props[i * 3 + 1] = + PROPERTY_ENTRY_STRING("linux,default-trigger", + leds[i].default_on ? + "default-on" : "default-off"); + /* props[i * 3 + 2] is an empty terminator */ + + swnodes[i] = SOFTWARE_NODE(node_name, &props[i * 3], + &geode_gpio_leds_node); + group[i + 1] = &swnodes[i]; + } + + err = software_node_register_node_group(group); + if (err) { + pr_err("failed to register LED software nodes: %d\n", err); + goto err_free_names; + } + + led_info.fwnode = software_node_fwnode(&geode_gpio_leds_node); + + led_dev = platform_device_register_full(&led_info); + err = PTR_ERR_OR_ZERO(led_dev); + if (err) { + pr_err("failed to create LED device: %d\n", err); + goto err_unregister_group; + } + + return 0; + +err_unregister_group: + software_node_unregister_node_group(group); +err_free_names: + while (--i >= 0) + kfree(swnodes[i].name); + kfree(props); +err_free_swnodes: + kfree(swnodes); + return err; +} diff --git a/arch/x86/platform/geode/geode-common.h b/arch/x86/platform/geode/geode-common.h new file mode 100644 index 000000000000..9e0afd34bfad --- /dev/null +++ b/arch/x86/platform/geode/geode-common.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Shared helpers to register GPIO-connected buttons and LEDs + * on AMD Geode boards. + */ + +#ifndef __PLATFORM_GEODE_COMMON_H +#define __PLATFORM_GEODE_COMMON_H + +#include <linux/property.h> + +struct geode_led { + unsigned int pin; + bool default_on; +}; + +int geode_create_restart_key(unsigned int pin); +int geode_create_leds(const char *label, const struct geode_led *leds, + unsigned int n_leds); + +#endif /* __PLATFORM_GEODE_COMMON_H */ diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c index d263528c90bb..98027fb1ec32 100644 --- a/arch/x86/platform/geode/geos.c +++ b/arch/x86/platform/geode/geos.c @@ -16,88 +16,22 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/string.h> -#include <linux/leds.h> -#include <linux/platform_device.h> -#include <linux/input.h> -#include <linux/gpio_keys.h> -#include <linux/gpio/machine.h> #include <linux/dmi.h> #include <asm/geode.h> -static struct gpio_keys_button geos_gpio_buttons[] = { - { - .code = KEY_RESTART, - .gpio = 3, - .active_low = 1, - .desc = "Reset button", - .type = EV_KEY, - .wakeup = 0, - .debounce_interval = 100, - .can_disable = 0, - } -}; -static struct gpio_keys_platform_data geos_buttons_data = { - .buttons = geos_gpio_buttons, - .nbuttons = ARRAY_SIZE(geos_gpio_buttons), - .poll_interval = 20, -}; - -static struct platform_device geos_buttons_dev = { - .name = "gpio-keys-polled", - .id = 1, - .dev = { - .platform_data = &geos_buttons_data, - } -}; - -static struct gpio_led geos_leds[] = { - { - .name = "geos:1", - .default_trigger = "default-on", - }, - { - .name = "geos:2", - .default_trigger = "default-off", - }, - { - .name = "geos:3", - .default_trigger = "default-off", - }, -}; - -static struct gpio_led_platform_data geos_leds_data = { - .num_leds = ARRAY_SIZE(geos_leds), - .leds = geos_leds, -}; - -static struct gpiod_lookup_table geos_leds_gpio_table = { - .dev_id = "leds-gpio", - .table = { - /* The Geode GPIOs should be on the CS5535 companion chip */ - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("cs5535-gpio", 25, NULL, 1, GPIO_ACTIVE_LOW), - GPIO_LOOKUP_IDX("cs5535-gpio", 27, NULL, 2, GPIO_ACTIVE_LOW), - { } - }, -}; - -static struct platform_device geos_leds_dev = { - .name = "leds-gpio", - .id = -1, - .dev.platform_data = &geos_leds_data, -}; +#include "geode-common.h" -static struct platform_device *geos_devs[] __initdata = { - &geos_buttons_dev, - &geos_leds_dev, +static const struct geode_led geos_leds[] __initconst = { + { 6, true }, + { 25, false }, + { 27, false }, }; static void __init register_geos(void) { - /* Setup LED control through leds-gpio driver */ - gpiod_add_lookup_table(&geos_leds_gpio_table); - platform_add_devices(geos_devs, ARRAY_SIZE(geos_devs)); + geode_create_restart_key(3); + geode_create_leds("geos", geos_leds, ARRAY_SIZE(geos_leds)); } static int __init geos_init(void) diff --git a/arch/x86/platform/geode/net5501.c b/arch/x86/platform/geode/net5501.c index 558384acd777..c9cee7dea99b 100644 --- a/arch/x86/platform/geode/net5501.c +++ b/arch/x86/platform/geode/net5501.c @@ -16,80 +16,25 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/string.h> -#include <linux/leds.h> -#include <linux/platform_device.h> #include <linux/input.h> -#include <linux/gpio_keys.h> #include <linux/gpio/machine.h> +#include <linux/gpio/property.h> #include <asm/geode.h> +#include "geode-common.h" + #define BIOS_REGION_BASE 0xffff0000 #define BIOS_REGION_SIZE 0x00010000 -static struct gpio_keys_button net5501_gpio_buttons[] = { - { - .code = KEY_RESTART, - .gpio = 24, - .active_low = 1, - .desc = "Reset button", - .type = EV_KEY, - .wakeup = 0, - .debounce_interval = 100, - .can_disable = 0, - } -}; -static struct gpio_keys_platform_data net5501_buttons_data = { - .buttons = net5501_gpio_buttons, - .nbuttons = ARRAY_SIZE(net5501_gpio_buttons), - .poll_interval = 20, -}; - -static struct platform_device net5501_buttons_dev = { - .name = "gpio-keys-polled", - .id = 1, - .dev = { - .platform_data = &net5501_buttons_data, - } -}; - -static struct gpio_led net5501_leds[] = { - { - .name = "net5501:1", - .default_trigger = "default-on", - }, -}; - -static struct gpio_led_platform_data net5501_leds_data = { - .num_leds = ARRAY_SIZE(net5501_leds), - .leds = net5501_leds, -}; - -static struct gpiod_lookup_table net5501_leds_gpio_table = { - .dev_id = "leds-gpio", - .table = { - /* The Geode GPIOs should be on the CS5535 companion chip */ - GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_HIGH), - { } - }, -}; - -static struct platform_device net5501_leds_dev = { - .name = "leds-gpio", - .id = -1, - .dev.platform_data = &net5501_leds_data, -}; - -static struct platform_device *net5501_devs[] __initdata = { - &net5501_buttons_dev, - &net5501_leds_dev, +static const struct geode_led net5501_leds[] __initconst = { + { 6, true }, }; static void __init register_net5501(void) { - /* Setup LED control through leds-gpio driver */ - gpiod_add_lookup_table(&net5501_leds_gpio_table); - platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs)); + geode_create_restart_key(24); + geode_create_leds("net5501", net5501_leds, ARRAY_SIZE(net5501_leds)); } struct net5501_board { diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c index f83bbe0acd4a..a8e75f8c14fd 100644 --- a/arch/x86/platform/intel-mid/intel-mid.c +++ b/arch/x86/platform/intel-mid/intel-mid.c @@ -27,9 +27,10 @@ #include <asm/intel-mid.h> #include <asm/io.h> #include <asm/i8259.h> -#include <asm/intel_scu_ipc.h> #include <asm/reboot.h> +#include <linux/platform_data/x86/intel_scu_ipc.h> + #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ #define IPCMSG_COLD_RESET 0xF1 diff --git a/arch/x86/platform/intel-mid/pwr.c b/arch/x86/platform/intel-mid/pwr.c index 27288d8d3f71..cd7e0c71adde 100644 --- a/arch/x86/platform/intel-mid/pwr.c +++ b/arch/x86/platform/intel-mid/pwr.c @@ -358,18 +358,18 @@ static int mid_pwr_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } - ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); - if (ret) { - dev_err(&pdev->dev, "I/O memory remapping failed\n"); - return ret; - } - pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL); if (!pwr) return -ENOMEM; + pwr->regs = pcim_iomap_region(pdev, 0, "intel_mid_pwr"); + ret = PTR_ERR_OR_ZERO(pwr->regs); + if (ret) { + dev_err(&pdev->dev, "Could not request / ioremap I/O-Mem: %d\n", ret); + return ret; + } + pwr->dev = dev; - pwr->regs = pcim_iomap_table(pdev)[0]; pwr->irq = pdev->irq; mutex_init(&pwr->lock); diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c index d3d456925b2a..ee25b032c0b3 100644 --- a/arch/x86/platform/intel-quark/imr.c +++ b/arch/x86/platform/intel-quark/imr.c @@ -569,7 +569,7 @@ static void __init imr_fixup_memmap(struct imr_device *idev) } static const struct x86_cpu_id imr_ids[] __initconst = { - X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL), + X86_MATCH_VFM(INTEL_QUARK_X1000, NULL), {} }; diff --git a/arch/x86/platform/intel-quark/imr_selftest.c b/arch/x86/platform/intel-quark/imr_selftest.c index 84ba715f44d1..657925b0f428 100644 --- a/arch/x86/platform/intel-quark/imr_selftest.c +++ b/arch/x86/platform/intel-quark/imr_selftest.c @@ -105,7 +105,7 @@ static void __init imr_self_test(void) } static const struct x86_cpu_id imr_ids[] __initconst = { - X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL), + X86_MATCH_VFM(INTEL_QUARK_X1000, NULL), {} }; diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c index c5f3bbdbdcfe..5591a2d9cfe8 100644 --- a/arch/x86/platform/iris/iris.c +++ b/arch/x86/platform/iris/iris.c @@ -73,7 +73,7 @@ static struct platform_driver iris_driver = { .name = "iris", }, .probe = iris_probe, - .remove_new = iris_remove, + .remove = iris_remove, }; static struct resource iris_resources[] = { diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index 6a9c42de74e7..424eeae12759 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -159,7 +159,7 @@ static struct platform_driver cs5535_pms_driver = { .name = "cs5535-pms", }, .probe = xo1_pm_probe, - .remove_new = xo1_pm_remove, + .remove = xo1_pm_remove, }; static struct platform_driver cs5535_acpi_driver = { @@ -167,7 +167,7 @@ static struct platform_driver cs5535_acpi_driver = { .name = "olpc-xo1-pm-acpi", }, .probe = xo1_pm_probe, - .remove_new = xo1_pm_remove, + .remove = xo1_pm_remove, }; static int __init xo1_pm_init(void) diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 46d42ff6e18a..ccb23c73cbe8 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -616,7 +616,7 @@ static struct platform_driver xo1_sci_driver = { .dev_groups = lid_groups, }, .probe = xo1_sci_probe, - .remove_new = xo1_sci_remove, + .remove = xo1_sci_remove, .suspend = xo1_sci_suspend, .resume = xo1_sci_resume, }; diff --git a/arch/x86/platform/pvh/Makefile b/arch/x86/platform/pvh/Makefile index 5dec5067c9fb..c43fb7964dc4 100644 --- a/arch/x86/platform/pvh/Makefile +++ b/arch/x86/platform/pvh/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 OBJECT_FILES_NON_STANDARD_head.o := y +KASAN_SANITIZE := n obj-$(CONFIG_PVH) += enlighten.o obj-$(CONFIG_PVH) += head.o diff --git a/arch/x86/platform/pvh/enlighten.c b/arch/x86/platform/pvh/enlighten.c index 944e0290f2c0..2263885d16ba 100644 --- a/arch/x86/platform/pvh/enlighten.c +++ b/arch/x86/platform/pvh/enlighten.c @@ -130,7 +130,11 @@ void __init xen_prepare_pvh(void) BUG(); } - memset(&pvh_bootparams, 0, sizeof(pvh_bootparams)); + /* + * This must not compile to "call memset" because memset() may be + * instrumented. + */ + __builtin_memset(&pvh_bootparams, 0, sizeof(pvh_bootparams)); hypervisor_specific_init(xen_guest); diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S index f7235ef87bc3..4733a5f467b8 100644 --- a/arch/x86/platform/pvh/head.S +++ b/arch/x86/platform/pvh/head.S @@ -6,7 +6,10 @@ .code32 .text +#ifdef CONFIG_X86_32 #define _pa(x) ((x) - __START_KERNEL_map) +#endif +#define rva(x) ((x) - pvh_start_xen) #include <linux/elfnote.h> #include <linux/init.h> @@ -15,6 +18,7 @@ #include <asm/segment.h> #include <asm/asm.h> #include <asm/boot.h> +#include <asm/pgtable.h> #include <asm/processor-flags.h> #include <asm/msr.h> #include <asm/nospec-branch.h> @@ -50,11 +54,28 @@ #define PVH_CS_SEL (PVH_GDT_ENTRY_CS * 8) #define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8) -SYM_CODE_START_LOCAL(pvh_start_xen) +SYM_CODE_START(pvh_start_xen) UNWIND_HINT_END_OF_STACK cld - lgdt (_pa(gdt)) + /* + * See the comment for startup_32 for more details. We need to + * execute a call to get the execution address to be position + * independent, but we don't have a stack. Save and restore the + * magic field of start_info in ebx, and use that as the stack. + */ + mov (%ebx), %eax + leal 4(%ebx), %esp + ANNOTATE_INTRA_FUNCTION_CALL + call 1f +1: popl %ebp + mov %eax, (%ebx) + subl $rva(1b), %ebp + movl $0, %esp + + leal rva(gdt)(%ebp), %eax + addl %eax, 2(%eax) + lgdt (%eax) mov $PVH_DS_SEL,%eax mov %eax,%ds @@ -62,14 +83,14 @@ SYM_CODE_START_LOCAL(pvh_start_xen) mov %eax,%ss /* Stash hvm_start_info. */ - mov $_pa(pvh_start_info), %edi + leal rva(pvh_start_info)(%ebp), %edi mov %ebx, %esi - mov _pa(pvh_start_info_sz), %ecx + movl rva(pvh_start_info_sz)(%ebp), %ecx shr $2,%ecx rep movsl - mov $_pa(early_stack_end), %esp + leal rva(early_stack_end)(%ebp), %esp /* Enable PAE mode. */ mov %cr4, %eax @@ -83,31 +104,91 @@ SYM_CODE_START_LOCAL(pvh_start_xen) btsl $_EFER_LME, %eax wrmsr + /* + * Reuse the non-relocatable symbol emitted for the ELF note to + * subtract the build time physical address of pvh_start_xen() from + * its actual runtime address, without relying on absolute 32-bit ELF + * relocations, as these are not supported by the linker when running + * in -pie mode, and should be avoided in .head.text in general. + */ + mov %ebp, %ebx + subl rva(xen_elfnote_phys32_entry)(%ebp), %ebx + jz .Lpagetable_done + + /* + * Store the resulting load offset in phys_base. __pa() needs + * phys_base set to calculate the hypercall page in xen_pvh_init(). + */ + movl %ebx, rva(phys_base)(%ebp) + + /* Fixup page-tables for relocation. */ + leal rva(pvh_init_top_pgt)(%ebp), %edi + movl $PTRS_PER_PGD, %ecx +2: + testl $_PAGE_PRESENT, 0x00(%edi) + jz 1f + addl %ebx, 0x00(%edi) +1: + addl $8, %edi + decl %ecx + jnz 2b + + /* L3 ident has a single entry. */ + leal rva(pvh_level3_ident_pgt)(%ebp), %edi + addl %ebx, 0x00(%edi) + + leal rva(pvh_level3_kernel_pgt)(%ebp), %edi + addl %ebx, (PAGE_SIZE - 16)(%edi) + addl %ebx, (PAGE_SIZE - 8)(%edi) + + /* pvh_level2_ident_pgt is fine - large pages */ + + /* pvh_level2_kernel_pgt needs adjustment - large pages */ + leal rva(pvh_level2_kernel_pgt)(%ebp), %edi + movl $PTRS_PER_PMD, %ecx +2: + testl $_PAGE_PRESENT, 0x00(%edi) + jz 1f + addl %ebx, 0x00(%edi) +1: + addl $8, %edi + decl %ecx + jnz 2b + +.Lpagetable_done: /* Enable pre-constructed page tables. */ - mov $_pa(init_top_pgt), %eax + leal rva(pvh_init_top_pgt)(%ebp), %eax mov %eax, %cr3 mov $(X86_CR0_PG | X86_CR0_PE), %eax mov %eax, %cr0 /* Jump to 64-bit mode. */ - ljmp $PVH_CS_SEL, $_pa(1f) + pushl $PVH_CS_SEL + leal rva(1f)(%ebp), %eax + pushl %eax + lretl /* 64-bit entry point. */ .code64 1: + UNWIND_HINT_END_OF_STACK + /* Set base address in stack canary descriptor. */ mov $MSR_GS_BASE,%ecx - mov $_pa(canary), %eax + leal canary(%rip), %eax xor %edx, %edx wrmsr - call xen_prepare_pvh + /* Call xen_prepare_pvh() via the kernel virtual mapping */ + leaq xen_prepare_pvh(%rip), %rax + subq phys_base(%rip), %rax + addq $__START_KERNEL_map, %rax + ANNOTATE_RETPOLINE_SAFE + call *%rax /* startup_64 expects boot_params in %rsi. */ - mov $_pa(pvh_bootparams), %rsi - mov $_pa(startup_64), %rax - ANNOTATE_RETPOLINE_SAFE - jmp *%rax + lea pvh_bootparams(%rip), %rsi + jmp startup_64 #else /* CONFIG_X86_64 */ @@ -142,8 +223,8 @@ SYM_CODE_END(pvh_start_xen) .section ".init.data","aw" .balign 8 SYM_DATA_START_LOCAL(gdt) - .word gdt_end - gdt_start - .long _pa(gdt_start) + .word gdt_end - gdt_start - 1 + .long gdt_start - gdt .word 0 SYM_DATA_END(gdt) SYM_DATA_START_LOCAL(gdt_start) @@ -163,5 +244,67 @@ SYM_DATA_START_LOCAL(early_stack) .fill BOOT_STACK_SIZE, 1, 0 SYM_DATA_END_LABEL(early_stack, SYM_L_LOCAL, early_stack_end) - ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, - _ASM_PTR (pvh_start_xen - __START_KERNEL_map)) +#ifdef CONFIG_X86_64 +/* + * Xen PVH needs a set of identity mapped and kernel high mapping + * page tables. pvh_start_xen starts running on the identity mapped + * page tables, but xen_prepare_pvh calls into the high mapping. + * These page tables need to be relocatable and are only used until + * startup_64 transitions to init_top_pgt. + */ +SYM_DATA_START_PAGE_ALIGNED(pvh_init_top_pgt) + .quad pvh_level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC + .org pvh_init_top_pgt + L4_PAGE_OFFSET * 8, 0 + .quad pvh_level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC + .org pvh_init_top_pgt + L4_START_KERNEL * 8, 0 + /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ + .quad pvh_level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC +SYM_DATA_END(pvh_init_top_pgt) + +SYM_DATA_START_PAGE_ALIGNED(pvh_level3_ident_pgt) + .quad pvh_level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC + .fill 511, 8, 0 +SYM_DATA_END(pvh_level3_ident_pgt) +SYM_DATA_START_PAGE_ALIGNED(pvh_level2_ident_pgt) + /* + * Since I easily can, map the first 1G. + * Don't set NX because code runs from these pages. + * + * Note: This sets _PAGE_GLOBAL despite whether + * the CPU supports it or it is enabled. But, + * the CPU should ignore the bit. + */ + PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) +SYM_DATA_END(pvh_level2_ident_pgt) +SYM_DATA_START_PAGE_ALIGNED(pvh_level3_kernel_pgt) + .fill L3_START_KERNEL, 8, 0 + /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ + .quad pvh_level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC + .quad 0 /* no fixmap */ +SYM_DATA_END(pvh_level3_kernel_pgt) + +SYM_DATA_START_PAGE_ALIGNED(pvh_level2_kernel_pgt) + /* + * Kernel high mapping. + * + * The kernel code+data+bss must be located below KERNEL_IMAGE_SIZE in + * virtual address space, which is 1 GiB if RANDOMIZE_BASE is enabled, + * 512 MiB otherwise. + * + * (NOTE: after that starts the module area, see MODULES_VADDR.) + * + * This table is eventually used by the kernel during normal runtime. + * Care must be taken to clear out undesired bits later, like _PAGE_RW + * or _PAGE_GLOBAL in some cases. + */ + PMDS(0, __PAGE_KERNEL_LARGE_EXEC, KERNEL_IMAGE_SIZE / PMD_SIZE) +SYM_DATA_END(pvh_level2_kernel_pgt) + + ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_RELOC, + .long CONFIG_PHYSICAL_ALIGN; + .long LOAD_PHYSICAL_ADDR; + .long KERNEL_IMAGE_SIZE - 1) +#endif + + ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .global xen_elfnote_phys32_entry; + xen_elfnote_phys32_entry: _ASM_PTR xen_elfnote_phys32_entry_value - .) diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index c101bed61940..27441e5863b2 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -56,6 +56,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { [S_ABS] = "^(xen_irq_disable_direct_reloc$|" "xen_save_fl_direct_reloc$|" + "xen_elfnote_.+_offset$|" "VDSO|" "__kcfi_typeid_|" "__crc_)", @@ -89,7 +90,6 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { "init_per_cpu__.*|" "__end_rodata_hpage_align|" #endif - "__vvar_page|" "_end)$" }; diff --git a/arch/x86/um/sysrq_32.c b/arch/x86/um/sysrq_32.c index f2383484840d..a1ee415c008d 100644 --- a/arch/x86/um/sysrq_32.c +++ b/arch/x86/um/sysrq_32.c @@ -9,7 +9,6 @@ #include <linux/sched/debug.h> #include <linux/kallsyms.h> #include <asm/ptrace.h> -#include <asm/sysrq.h> /* This is declared by <linux/sched.h> */ void show_regs(struct pt_regs *regs) diff --git a/arch/x86/um/sysrq_64.c b/arch/x86/um/sysrq_64.c index 0bf6de40abff..340d8a243c8a 100644 --- a/arch/x86/um/sysrq_64.c +++ b/arch/x86/um/sysrq_64.c @@ -12,7 +12,6 @@ #include <linux/utsname.h> #include <asm/current.h> #include <asm/ptrace.h> -#include <asm/sysrq.h> void show_regs(struct pt_regs *regs) { diff --git a/arch/x86/um/vdso/vma.c b/arch/x86/um/vdso/vma.c index 76d9f6ce7a3d..f238f7b33cdd 100644 --- a/arch/x86/um/vdso/vma.c +++ b/arch/x86/um/vdso/vma.c @@ -52,8 +52,11 @@ subsys_initcall(init_vdso); int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { - int err; + struct vm_area_struct *vma; struct mm_struct *mm = current->mm; + static struct vm_special_mapping vdso_mapping = { + .name = "[vdso]", + }; if (!vdso_enabled) return 0; @@ -61,12 +64,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) if (mmap_write_lock_killable(mm)) return -EINTR; - err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, + vdso_mapping.pages = vdsop; + vma = _install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - vdsop); + &vdso_mapping); mmap_write_unlock(mm); - return err; + return IS_ERR(vma) ? PTR_ERR(vma) : 0; } diff --git a/arch/x86/virt/svm/Makefile b/arch/x86/virt/svm/Makefile index ef2a31bdcc70..eca6d71355fa 100644 --- a/arch/x86/virt/svm/Makefile +++ b/arch/x86/virt/svm/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_KVM_AMD_SEV) += sev.o +obj-$(CONFIG_CPU_SUP_AMD) += cmdline.o diff --git a/arch/x86/virt/svm/cmdline.c b/arch/x86/virt/svm/cmdline.c new file mode 100644 index 000000000000..affa2759fa20 --- /dev/null +++ b/arch/x86/virt/svm/cmdline.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD SVM-SEV command line parsing support + * + * Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. + * + * Author: Michael Roth <michael.roth@amd.com> + */ + +#include <linux/string.h> +#include <linux/printk.h> +#include <linux/cache.h> +#include <linux/cpufeature.h> + +#include <asm/sev-common.h> + +struct sev_config sev_cfg __read_mostly; + +static int __init init_sev_config(char *str) +{ + char *s; + + while ((s = strsep(&str, ","))) { + if (!strcmp(s, "debug")) { + sev_cfg.debug = true; + continue; + } + + if (!strcmp(s, "nosnp")) { + if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) { + setup_clear_cpu_cap(X86_FEATURE_SEV_SNP); + cc_platform_clear(CC_ATTR_HOST_SEV_SNP); + continue; + } else { + goto warn; + } + } + +warn: + pr_info("SEV command-line option '%s' was not recognized\n", s); + } + + return 1; +} +__setup("sev=", init_sev_config); diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index 0ce17766c0e5..9a6a943d8e41 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -173,6 +173,8 @@ static void __init __snp_fixup_e820_tables(u64 pa) e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED); e820__range_update_table(e820_table_kexec, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED); e820__range_update_table(e820_table_firmware, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED); + if (!memblock_is_region_reserved(pa, PMD_SIZE)) + memblock_reserve(pa, PMD_SIZE); } } diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 2c12ae42dc8b..d6818c6cafda 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -1032,6 +1032,10 @@ static u64 xen_do_read_msr(unsigned int msr, int *err) switch (msr) { case MSR_IA32_APICBASE: val &= ~X2APIC_ENABLE; + if (smp_processor_id() == 0) + val |= MSR_IA32_APICBASE_BSP; + else + val &= ~MSR_IA32_APICBASE_BSP; break; } return val; diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index 728a4366ca85..bf68c329fc01 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c @@ -4,6 +4,7 @@ #include <linux/mm.h> #include <xen/hvc-console.h> +#include <xen/acpi.h> #include <asm/bootparam.h> #include <asm/io_apic.h> @@ -28,6 +29,28 @@ bool __ro_after_init xen_pvh; EXPORT_SYMBOL_GPL(xen_pvh); +#ifdef CONFIG_XEN_DOM0 +int xen_pvh_setup_gsi(int gsi, int trigger, int polarity) +{ + int ret; + struct physdev_setup_gsi setup_gsi; + + setup_gsi.gsi = gsi; + setup_gsi.triggering = (trigger == ACPI_EDGE_SENSITIVE ? 0 : 1); + setup_gsi.polarity = (polarity == ACPI_ACTIVE_HIGH ? 0 : 1); + + ret = HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi, &setup_gsi); + if (ret == -EEXIST) { + xen_raw_printk("Already setup the GSI :%d\n", gsi); + ret = 0; + } else if (ret) + xen_raw_printk("Fail to setup GSI (%d)!\n", gsi); + + return ret; +} +EXPORT_SYMBOL_GPL(xen_pvh_setup_gsi); +#endif + /* * Reserve e820 UNUSABLE regions to inflate the memory balloon. * diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index f1ce39d6d32c..55a4996d0c04 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -665,7 +665,7 @@ static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm) { spinlock_t *ptl = NULL; -#if USE_SPLIT_PTE_PTLOCKS +#if defined(CONFIG_SPLIT_PTE_PTLOCKS) ptl = ptlock_ptr(page_ptdesc(page)); spin_lock_nest_lock(ptl, &mm->page_table_lock); #endif @@ -1553,7 +1553,8 @@ static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, __set_pfn_prot(pfn, PAGE_KERNEL_RO); - if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS && !pinned) + if (level == PT_PTE && IS_ENABLED(CONFIG_SPLIT_PTE_PTLOCKS) && + !pinned) __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); xen_mc_issue(XEN_LAZY_MMU); @@ -1581,7 +1582,7 @@ static inline void xen_release_ptpage(unsigned long pfn, unsigned level) if (pinned) { xen_mc_batch(); - if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS) + if (level == PT_PTE && IS_ENABLED(CONFIG_SPLIT_PTE_PTLOCKS)) __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); __set_pfn_prot(pfn, PAGE_KERNEL); @@ -2018,10 +2019,7 @@ void __init xen_reserve_special_pages(void) void __init xen_pt_check_e820(void) { - if (xen_is_e820_reserved(xen_pt_base, xen_pt_size)) { - xen_raw_console_write("Xen hypervisor allocated page table memory conflicts with E820 map\n"); - BUG(); - } + xen_chk_is_e820_usable(xen_pt_base, xen_pt_size, "page table"); } static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 7c735b730acd..b52d3e17e2c1 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -70,6 +70,7 @@ #include <linux/memblock.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/acpi.h> #include <asm/cache.h> #include <asm/setup.h> @@ -80,6 +81,7 @@ #include <asm/xen/hypervisor.h> #include <xen/balloon.h> #include <xen/grant_table.h> +#include <xen/hvc-console.h> #include "xen-ops.h" @@ -792,6 +794,102 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, return ret; } +/* Remapped non-RAM areas */ +#define NR_NONRAM_REMAP 4 +static struct nonram_remap { + phys_addr_t maddr; + phys_addr_t paddr; + size_t size; +} xen_nonram_remap[NR_NONRAM_REMAP] __ro_after_init; +static unsigned int nr_nonram_remap __ro_after_init; + +/* + * Do the real remapping of non-RAM regions as specified in the + * xen_nonram_remap[] array. + * In case of an error just crash the system. + */ +void __init xen_do_remap_nonram(void) +{ + unsigned int i; + unsigned int remapped = 0; + const struct nonram_remap *remap = xen_nonram_remap; + unsigned long pfn, mfn, end_pfn; + + for (i = 0; i < nr_nonram_remap; i++) { + end_pfn = PFN_UP(remap->paddr + remap->size); + pfn = PFN_DOWN(remap->paddr); + mfn = PFN_DOWN(remap->maddr); + while (pfn < end_pfn) { + if (!set_phys_to_machine(pfn, mfn)) + panic("Failed to set p2m mapping for pfn=%lx mfn=%lx\n", + pfn, mfn); + + pfn++; + mfn++; + remapped++; + } + + remap++; + } + + pr_info("Remapped %u non-RAM page(s)\n", remapped); +} + +#ifdef CONFIG_ACPI +/* + * Xen variant of acpi_os_ioremap() taking potentially remapped non-RAM + * regions into account. + * Any attempt to map an area crossing a remap boundary will produce a + * WARN() splat. + * phys is related to remap->maddr on input and will be rebased to remap->paddr. + */ +static void __iomem *xen_acpi_os_ioremap(acpi_physical_address phys, + acpi_size size) +{ + unsigned int i; + const struct nonram_remap *remap = xen_nonram_remap; + + for (i = 0; i < nr_nonram_remap; i++) { + if (phys + size > remap->maddr && + phys < remap->maddr + remap->size) { + WARN_ON(phys < remap->maddr || + phys + size > remap->maddr + remap->size); + phys += remap->paddr - remap->maddr; + break; + } + } + + return x86_acpi_os_ioremap(phys, size); +} +#endif /* CONFIG_ACPI */ + +/* + * Add a new non-RAM remap entry. + * In case of no free entry found, just crash the system. + */ +void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr, + unsigned long size) +{ + BUG_ON((maddr & ~PAGE_MASK) != (paddr & ~PAGE_MASK)); + + if (nr_nonram_remap == NR_NONRAM_REMAP) { + xen_raw_console_write("Number of required E820 entry remapping actions exceed maximum value\n"); + BUG(); + } + +#ifdef CONFIG_ACPI + /* Switch to the Xen acpi_os_ioremap() variant. */ + if (nr_nonram_remap == 0) + acpi_os_ioremap = xen_acpi_os_ioremap; +#endif + + xen_nonram_remap[nr_nonram_remap].maddr = maddr; + xen_nonram_remap[nr_nonram_remap].paddr = paddr; + xen_nonram_remap[nr_nonram_remap].size = size; + + nr_nonram_remap++; +} + #ifdef CONFIG_XEN_DEBUG_FS #include <linux/debugfs.h> static int p2m_dump_show(struct seq_file *m, void *v) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 806ddb2391d9..c3db71d96c43 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -15,12 +15,12 @@ #include <linux/cpuidle.h> #include <linux/cpufreq.h> #include <linux/memory_hotplug.h> +#include <linux/acpi.h> #include <asm/elf.h> #include <asm/vdso.h> #include <asm/e820/api.h> #include <asm/setup.h> -#include <asm/acpi.h> #include <asm/numa.h> #include <asm/idtentry.h> #include <asm/xen/hypervisor.h> @@ -46,6 +46,9 @@ bool xen_pv_pci_possible; /* E820 map used during setting up memory. */ static struct e820_table xen_e820_table __initdata; +/* Number of initially usable memory pages. */ +static unsigned long ini_nr_pages __initdata; + /* * Buffer used to remap identity mapped pages. We only need the virtual space. * The physical page behind this address is remapped as needed to different @@ -212,7 +215,7 @@ static int __init xen_free_mfn(unsigned long mfn) * as a fallback if the remapping fails. */ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, - unsigned long end_pfn, unsigned long nr_pages) + unsigned long end_pfn) { unsigned long pfn, end; int ret; @@ -220,7 +223,7 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, WARN_ON(start_pfn > end_pfn); /* Release pages first. */ - end = min(end_pfn, nr_pages); + end = min(end_pfn, ini_nr_pages); for (pfn = start_pfn; pfn < end; pfn++) { unsigned long mfn = pfn_to_mfn(pfn); @@ -341,15 +344,14 @@ static void __init xen_do_set_identity_and_remap_chunk( * to Xen and not remapped. */ static unsigned long __init xen_set_identity_and_remap_chunk( - unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, - unsigned long remap_pfn) + unsigned long start_pfn, unsigned long end_pfn, unsigned long remap_pfn) { unsigned long pfn; unsigned long i = 0; unsigned long n = end_pfn - start_pfn; if (remap_pfn == 0) - remap_pfn = nr_pages; + remap_pfn = ini_nr_pages; while (i < n) { unsigned long cur_pfn = start_pfn + i; @@ -358,19 +360,19 @@ static unsigned long __init xen_set_identity_and_remap_chunk( unsigned long remap_range_size; /* Do not remap pages beyond the current allocation */ - if (cur_pfn >= nr_pages) { + if (cur_pfn >= ini_nr_pages) { /* Identity map remaining pages */ set_phys_range_identity(cur_pfn, cur_pfn + size); break; } - if (cur_pfn + size > nr_pages) - size = nr_pages - cur_pfn; + if (cur_pfn + size > ini_nr_pages) + size = ini_nr_pages - cur_pfn; remap_range_size = xen_find_pfn_range(&remap_pfn); if (!remap_range_size) { pr_warn("Unable to find available pfn range, not remapping identity pages\n"); xen_set_identity_and_release_chunk(cur_pfn, - cur_pfn + left, nr_pages); + cur_pfn + left); break; } /* Adjust size to fit in current e820 RAM region */ @@ -397,18 +399,18 @@ static unsigned long __init xen_set_identity_and_remap_chunk( } static unsigned long __init xen_count_remap_pages( - unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, + unsigned long start_pfn, unsigned long end_pfn, unsigned long remap_pages) { - if (start_pfn >= nr_pages) + if (start_pfn >= ini_nr_pages) return remap_pages; - return remap_pages + min(end_pfn, nr_pages) - start_pfn; + return remap_pages + min(end_pfn, ini_nr_pages) - start_pfn; } -static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, +static unsigned long __init xen_foreach_remap_area( unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn, - unsigned long nr_pages, unsigned long last_val)) + unsigned long last_val)) { phys_addr_t start = 0; unsigned long ret_val = 0; @@ -436,8 +438,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, end_pfn = PFN_UP(entry->addr); if (start_pfn < end_pfn) - ret_val = func(start_pfn, end_pfn, nr_pages, - ret_val); + ret_val = func(start_pfn, end_pfn, ret_val); start = end; } } @@ -494,6 +495,8 @@ void __init xen_remap_memory(void) set_pte_mfn(buf, mfn_save, PAGE_KERNEL); pr_info("Remapped %ld page(s)\n", remapped); + + xen_do_remap_nonram(); } static unsigned long __init xen_get_pages_limit(void) @@ -567,7 +570,7 @@ static void __init xen_ignore_unusable(void) } } -bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) +static bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) { struct e820_entry *entry; unsigned mapcnt; @@ -625,6 +628,111 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size) } /* + * Swap a non-RAM E820 map entry with RAM above ini_nr_pages. + * Note that the E820 map is modified accordingly, but the P2M map isn't yet. + * The adaption of the P2M must be deferred until page allocation is possible. + */ +static void __init xen_e820_swap_entry_with_ram(struct e820_entry *swap_entry) +{ + struct e820_entry *entry; + unsigned int mapcnt; + phys_addr_t mem_end = PFN_PHYS(ini_nr_pages); + phys_addr_t swap_addr, swap_size, entry_end; + + swap_addr = PAGE_ALIGN_DOWN(swap_entry->addr); + swap_size = PAGE_ALIGN(swap_entry->addr - swap_addr + swap_entry->size); + entry = xen_e820_table.entries; + + for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) { + entry_end = entry->addr + entry->size; + if (entry->type == E820_TYPE_RAM && entry->size >= swap_size && + entry_end - swap_size >= mem_end) { + /* Reduce RAM entry by needed space (whole pages). */ + entry->size -= swap_size; + + /* Add new entry at the end of E820 map. */ + entry = xen_e820_table.entries + + xen_e820_table.nr_entries; + xen_e820_table.nr_entries++; + + /* Fill new entry (keep size and page offset). */ + entry->type = swap_entry->type; + entry->addr = entry_end - swap_size + + swap_addr - swap_entry->addr; + entry->size = swap_entry->size; + + /* Convert old entry to RAM, align to pages. */ + swap_entry->type = E820_TYPE_RAM; + swap_entry->addr = swap_addr; + swap_entry->size = swap_size; + + /* Remember PFN<->MFN relation for P2M update. */ + xen_add_remap_nonram(swap_addr, entry_end - swap_size, + swap_size); + + /* Order E820 table and merge entries. */ + e820__update_table(&xen_e820_table); + + return; + } + + entry++; + } + + xen_raw_console_write("No suitable area found for required E820 entry remapping action\n"); + BUG(); +} + +/* + * Look for non-RAM memory types in a specific guest physical area and move + * those away if possible (ACPI NVS only for now). + */ +static void __init xen_e820_resolve_conflicts(phys_addr_t start, + phys_addr_t size) +{ + struct e820_entry *entry; + unsigned int mapcnt; + phys_addr_t end; + + if (!size) + return; + + end = start + size; + entry = xen_e820_table.entries; + + for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) { + if (entry->addr >= end) + return; + + if (entry->addr + entry->size > start && + entry->type == E820_TYPE_NVS) + xen_e820_swap_entry_with_ram(entry); + + entry++; + } +} + +/* + * Check for an area in physical memory to be usable for non-movable purposes. + * An area is considered to usable if the used E820 map lists it to be RAM or + * some other type which can be moved to higher PFNs while keeping the MFNs. + * In case the area is not usable, crash the system with an error message. + */ +void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size, + const char *component) +{ + xen_e820_resolve_conflicts(start, size); + + if (!xen_is_e820_reserved(start, size)) + return; + + xen_raw_console_write("Xen hypervisor allocated "); + xen_raw_console_write(component); + xen_raw_console_write(" memory conflicts with E820 map\n"); + BUG(); +} + +/* * Like memcpy, but with physical addresses for dest and src. */ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src, @@ -683,7 +791,7 @@ static void __init xen_reserve_xen_mfnlist(void) **/ char * __init xen_memory_setup(void) { - unsigned long max_pfn, pfn_s, n_pfns; + unsigned long pfn_s, n_pfns; phys_addr_t mem_end, addr, size, chunk_size; u32 type; int rc; @@ -695,9 +803,8 @@ char * __init xen_memory_setup(void) int op; xen_parse_512gb(); - max_pfn = xen_get_pages_limit(); - max_pfn = min(max_pfn, xen_start_info->nr_pages); - mem_end = PFN_PHYS(max_pfn); + ini_nr_pages = min(xen_get_pages_limit(), xen_start_info->nr_pages); + mem_end = PFN_PHYS(ini_nr_pages); memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries); set_xen_guest_handle(memmap.buffer, xen_e820_table.entries); @@ -747,13 +854,35 @@ char * __init xen_memory_setup(void) /* Make sure the Xen-supplied memory map is well-ordered. */ e820__update_table(&xen_e820_table); + /* + * Check whether the kernel itself conflicts with the target E820 map. + * Failing now is better than running into weird problems later due + * to relocating (and even reusing) pages with kernel text or data. + */ + xen_chk_is_e820_usable(__pa_symbol(_text), + __pa_symbol(_end) - __pa_symbol(_text), + "kernel"); + + /* + * Check for a conflict of the xen_start_info memory with the target + * E820 map. + */ + xen_chk_is_e820_usable(__pa(xen_start_info), sizeof(*xen_start_info), + "xen_start_info"); + + /* + * Check for a conflict of the hypervisor supplied page tables with + * the target E820 map. + */ + xen_pt_check_e820(); + max_pages = xen_get_max_pages(); /* How many extra pages do we need due to remapping? */ - max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages); + max_pages += xen_foreach_remap_area(xen_count_remap_pages); - if (max_pages > max_pfn) - extra_pages += max_pages - max_pfn; + if (max_pages > ini_nr_pages) + extra_pages += max_pages - ini_nr_pages; /* * Clamp the amount of extra memory to a EXTRA_MEM_RATIO @@ -762,8 +891,8 @@ char * __init xen_memory_setup(void) * Make sure we have no memory above max_pages, as this area * isn't handled by the p2m management. */ - maxmem_pages = EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)); - extra_pages = min3(maxmem_pages, extra_pages, max_pages - max_pfn); + maxmem_pages = EXTRA_MEM_RATIO * min(ini_nr_pages, PFN_DOWN(MAXMEM)); + extra_pages = min3(maxmem_pages, extra_pages, max_pages - ini_nr_pages); i = 0; addr = xen_e820_table.entries[0].addr; size = xen_e820_table.entries[0].size; @@ -819,23 +948,6 @@ char * __init xen_memory_setup(void) e820__update_table(e820_table); - /* - * Check whether the kernel itself conflicts with the target E820 map. - * Failing now is better than running into weird problems later due - * to relocating (and even reusing) pages with kernel text or data. - */ - if (xen_is_e820_reserved(__pa_symbol(_text), - __pa_symbol(__bss_stop) - __pa_symbol(_text))) { - xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n"); - BUG(); - } - - /* - * Check for a conflict of the hypervisor supplied page tables with - * the target E820 map. - */ - xen_pt_check_e820(); - xen_reserve_xen_mfnlist(); /* Check for a conflict of the initrd with the target E820 map. */ @@ -863,7 +975,7 @@ char * __init xen_memory_setup(void) * Set identity map on non-RAM pages and prepare remapping the * underlying RAM. */ - xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk); + xen_foreach_remap_area(xen_set_identity_and_remap_chunk); pr_info("Released %ld page(s)\n", xen_released_pages); diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 758bcd47b72d..7f6c69dbb816 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S @@ -94,7 +94,8 @@ SYM_CODE_END(xen_cpu_bringup_again) ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR __START_KERNEL_map) /* Map the p2m table to a 512GB-aligned user address. */ ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad (PUD_SIZE * PTRS_PER_PUD)) - ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen) + ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .globl xen_elfnote_entry; + xen_elfnote_entry: _ASM_PTR xen_elfnote_entry_value - .) ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .ascii "!writable_page_tables") ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes") ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, @@ -115,7 +116,8 @@ SYM_CODE_END(xen_cpu_bringup_again) #else # define FEATURES_DOM0 0 #endif - ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page) + ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .globl xen_elfnote_hypercall_page; + xen_elfnote_hypercall_page: _ASM_PTR xen_elfnote_hypercall_page_value - .) ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, .long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0) ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 0cf16fc79e0b..e1b782e823e6 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -47,8 +47,12 @@ void xen_mm_unpin_all(void); #ifdef CONFIG_X86_64 void __init xen_relocate_p2m(void); #endif +void __init xen_do_remap_nonram(void); +void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr, + unsigned long size); -bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size); +void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size, + const char *component); unsigned long __ref xen_chk_extra_mem(unsigned long pfn); void __init xen_inv_extra_mem(void); void __init xen_remap_memory(void); diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index f200a4ec044e..d3db28f2f811 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -14,6 +14,7 @@ config XTENSA select ARCH_HAS_DMA_SET_UNCACHED if MMU select ARCH_HAS_STRNCPY_FROM_USER if !KASAN select ARCH_HAS_STRNLEN_USER + select ARCH_NEED_CMPXCHG_1_EMU select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index 675a11ea8de7..95e33a913962 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h @@ -15,6 +15,7 @@ #include <linux/bits.h> #include <linux/stringify.h> +#include <linux/cmpxchg-emu.h> /* * cmpxchg @@ -74,6 +75,7 @@ static __inline__ unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) { switch (size) { + case 1: return cmpxchg_emu_u8(ptr, old, new); case 4: return __cmpxchg_u32(ptr, old, new); default: __cmpxchg_called_with_bad_pointer(); return old; diff --git a/arch/xtensa/include/asm/flat.h b/arch/xtensa/include/asm/flat.h index ed5870c779f9..4854419dcd86 100644 --- a/arch/xtensa/include/asm/flat.h +++ b/arch/xtensa/include/asm/flat.h @@ -2,7 +2,7 @@ #ifndef __ASM_XTENSA_FLAT_H #define __ASM_XTENSA_FLAT_H -#include <asm/unaligned.h> +#include <linux/unaligned.h> static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags, u32 *addr) diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 4db56ef052d2..595c1037b738 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h @@ -18,13 +18,7 @@ #include <asm/cache.h> #include <asm/kmem_layout.h> -/* - * PAGE_SHIFT determines the page size - */ - -#define PAGE_SHIFT CONFIG_PAGE_SHIFT -#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +#include <vdso/page.h> #ifdef CONFIG_MMU #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index bdec4a773af0..e51f2060e830 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -216,7 +216,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, void __init early_init_devtree(void *params) { - early_init_dt_scan(params); + early_init_dt_scan(params, __pa(params)); of_scan_flat_dt(xtensa_dt_io_area, NULL); if (!command_line[0]) diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index b3c2450d6f23..dc54f854c2f5 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -55,7 +55,8 @@ asmlinkage long xtensa_fadvise64_64(int fd, int advice, #ifdef CONFIG_MMU unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) + unsigned long len, unsigned long pgoff, unsigned long flags, + vm_flags_t vm_flags) { struct vm_area_struct *vmm; struct vma_iterator vmi; diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 67083fc1b2f5..37effc1b134e 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -433,3 +433,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common setxattrat sys_setxattrat +464 common getxattrat sys_getxattrat +465 common listxattrat sys_listxattrat +466 common removexattrat sys_removexattrat |