diff options
Diffstat (limited to 'arch')
1330 files changed, 56636 insertions, 27069 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 5b4f88363453..620b0a711ee4 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -31,6 +31,8 @@ config ALPHA select ODD_RT_SIGACTION select OLD_SIGSUSPEND select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67 + select HAVE_MEMBLOCK + select NO_BOOTMEM help The Alpha is a 64-bit general-purpose processor designed and marketed by the Digital Equipment Corporation of blessed memory, diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index d6e29a1de4cc..9ff37aa1165f 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -6,6 +6,7 @@ #define NR_SYSCALLS 523 +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME @@ -13,6 +14,7 @@ #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_CLONE diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h index 3729d92d3fa8..1e9121c9b3c7 100644 --- a/arch/alpha/include/uapi/asm/ioctls.h +++ b/arch/alpha/include/uapi/asm/ioctls.h @@ -102,6 +102,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff --git a/arch/alpha/include/uapi/asm/siginfo.h b/arch/alpha/include/uapi/asm/siginfo.h index db3f0138536f..6e1a2af2f962 100644 --- a/arch/alpha/include/uapi/asm/siginfo.h +++ b/arch/alpha/include/uapi/asm/siginfo.h @@ -2,7 +2,6 @@ #ifndef _ALPHA_SIGINFO_H #define _ALPHA_SIGINFO_H -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define __ARCH_SI_TRAPNO #include <asm-generic/siginfo.h> diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c index aec757250e07..f70986683fc6 100644 --- a/arch/alpha/kernel/core_irongate.c +++ b/arch/alpha/kernel/core_irongate.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/initrd.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <asm/ptrace.h> #include <asm/cacheflush.h> @@ -241,8 +242,7 @@ albacore_init_arch(void) size / 1024); } #endif - reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop - - pci_mem, BOOTMEM_DEFAULT); + memblock_reserve(pci_mem, memtop - pci_mem); printk("irongate_init_arch: temporarily reserving " "region %08lx-%08lx for PCI\n", pci_mem, memtop - 1); } diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index c64806a2daf5..2e09248f8324 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -473,7 +473,7 @@ entSys: bne $3, strace beq $4, 1f ldq $27, 0($5) -1: jsr $26, ($27), alpha_ni_syscall +1: jsr $26, ($27), sys_ni_syscall ldgp $gp, 0($26) blt $0, $syscall_error /* the call failed */ stq $0, 0($sp) @@ -587,7 +587,7 @@ strace: /* get the system call pointer.. */ lda $1, NR_SYSCALLS($31) lda $2, sys_call_table - lda $27, alpha_ni_syscall + lda $27, sys_ni_syscall cmpult $0, $1, $1 s8addq $0, $2, $2 beq $1, 1f @@ -791,7 +791,7 @@ ret_from_kernel_thread: /* * Special system calls. Most of these are special in that they either - * have to play switch_stack games or in some way use the pt_regs struct. + * have to play switch_stack games. */ .macro fork_like name @@ -812,46 +812,41 @@ fork_like fork fork_like vfork fork_like clone +.macro sigreturn_like name .align 4 - .globl sys_sigreturn - .ent sys_sigreturn -sys_sigreturn: + .globl sys_\name + .ent sys_\name +sys_\name: .prologue 0 lda $9, ret_from_straced cmpult $26, $9, $9 lda $sp, -SWITCH_STACK_SIZE($sp) - jsr $26, do_sigreturn + jsr $26, do_\name bne $9, 1f jsr $26, syscall_trace_leave 1: br $1, undo_switch_stack br ret_from_sys_call -.end sys_sigreturn +.end sys_\name +.endm - .align 4 - .globl sys_rt_sigreturn - .ent sys_rt_sigreturn -sys_rt_sigreturn: - .prologue 0 - lda $9, ret_from_straced - cmpult $26, $9, $9 - lda $sp, -SWITCH_STACK_SIZE($sp) - jsr $26, do_rt_sigreturn - bne $9, 1f - jsr $26, syscall_trace_leave -1: br $1, undo_switch_stack - br ret_from_sys_call -.end sys_rt_sigreturn +sigreturn_like sigreturn +sigreturn_like rt_sigreturn .align 4 - .globl alpha_ni_syscall - .ent alpha_ni_syscall -alpha_ni_syscall: + .globl alpha_syscall_zero + .ent alpha_syscall_zero +alpha_syscall_zero: .prologue 0 - /* Special because it also implements overflow handling via - syscall number 0. And if you recall, zero is a special - trigger for "not an error". Store large non-zero there. */ + /* Special because it needs to do something opposite to + force_successful_syscall_return(). We use the saved + syscall number for that, zero meaning "not an error". + That works nicely, but for real syscall 0 we need to + make sure that this logics doesn't get confused. + Store a non-zero there - -ENOSYS we need in register + for our return value will do just fine. + */ lda $0, -ENOSYS unop stq $0, 0($sp) ret -.end alpha_ni_syscall +.end alpha_syscall_zero diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 5576f7646fb6..4f0d94471bc9 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -30,6 +30,7 @@ #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/pci.h> #include <linux/seq_file.h> #include <linux/root_dev.h> @@ -312,9 +313,7 @@ setup_memory(void *kernel_end) { struct memclust_struct * cluster; struct memdesc_struct * memdesc; - unsigned long start_kernel_pfn, end_kernel_pfn; - unsigned long bootmap_size, bootmap_pages, bootmap_start; - unsigned long start, end; + unsigned long kernel_size; unsigned long i; /* Find free clusters, and init and free the bootmem accordingly. */ @@ -322,6 +321,8 @@ setup_memory(void *kernel_end) (hwrpb->mddt_offset + (unsigned long) hwrpb); for_each_mem_cluster(memdesc, cluster, i) { + unsigned long end; + printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n", i, cluster->usage, cluster->start_pfn, cluster->start_pfn + cluster->numpages); @@ -335,6 +336,9 @@ setup_memory(void *kernel_end) end = cluster->start_pfn + cluster->numpages; if (end > max_low_pfn) max_low_pfn = end; + + memblock_add(PFN_PHYS(cluster->start_pfn), + cluster->numpages << PAGE_SHIFT); } /* @@ -363,87 +367,9 @@ setup_memory(void *kernel_end) max_low_pfn = mem_size_limit; } - /* Find the bounds of kernel memory. */ - start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); - end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); - bootmap_start = -1; - - try_again: - if (max_low_pfn <= end_kernel_pfn) - panic("not enough memory to boot"); - - /* We need to know how many physically contiguous pages - we'll need for the bootmap. */ - bootmap_pages = bootmem_bootmap_pages(max_low_pfn); - - /* Now find a good region where to allocate the bootmap. */ - for_each_mem_cluster(memdesc, cluster, i) { - if (cluster->usage & 3) - continue; - - start = cluster->start_pfn; - end = start + cluster->numpages; - if (start >= max_low_pfn) - continue; - if (end > max_low_pfn) - end = max_low_pfn; - if (start < start_kernel_pfn) { - if (end > end_kernel_pfn - && end - end_kernel_pfn >= bootmap_pages) { - bootmap_start = end_kernel_pfn; - break; - } else if (end > start_kernel_pfn) - end = start_kernel_pfn; - } else if (start < end_kernel_pfn) - start = end_kernel_pfn; - if (end - start >= bootmap_pages) { - bootmap_start = start; - break; - } - } - - if (bootmap_start == ~0UL) { - max_low_pfn >>= 1; - goto try_again; - } - - /* Allocate the bootmap and mark the whole MM as reserved. */ - bootmap_size = init_bootmem(bootmap_start, max_low_pfn); - - /* Mark the free regions. */ - for_each_mem_cluster(memdesc, cluster, i) { - if (cluster->usage & 3) - continue; - - start = cluster->start_pfn; - end = cluster->start_pfn + cluster->numpages; - if (start >= max_low_pfn) - continue; - if (end > max_low_pfn) - end = max_low_pfn; - if (start < start_kernel_pfn) { - if (end > end_kernel_pfn) { - free_bootmem(PFN_PHYS(start), - (PFN_PHYS(start_kernel_pfn) - - PFN_PHYS(start))); - printk("freeing pages %ld:%ld\n", - start, start_kernel_pfn); - start = end_kernel_pfn; - } else if (end > start_kernel_pfn) - end = start_kernel_pfn; - } else if (start < end_kernel_pfn) - start = end_kernel_pfn; - if (start >= end) - continue; - - free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); - printk("freeing pages %ld:%ld\n", start, end); - } - - /* Reserve the bootmap memory. */ - reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size, - BOOTMEM_DEFAULT); - printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); + /* Reserve the kernel memory. */ + kernel_size = virt_to_phys(kernel_end) - KERNEL_START_PHYS; + memblock_reserve(KERNEL_START_PHYS, kernel_size); #ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; @@ -459,8 +385,8 @@ setup_memory(void *kernel_end) initrd_end, phys_to_virt(PFN_PHYS(max_low_pfn))); } else { - reserve_bootmem(virt_to_phys((void *)initrd_start), - INITRD_SIZE, BOOTMEM_DEFAULT); + memblock_reserve(virt_to_phys((void *)initrd_start), + INITRD_SIZE); } } #endif /* CONFIG_BLK_DEV_INITRD */ diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 1374e591511f..5b2e8ecb7ce3 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -11,93 +11,93 @@ .align 3 .globl sys_call_table sys_call_table: - .quad alpha_ni_syscall /* 0 */ + .quad alpha_syscall_zero /* 0 */ .quad sys_exit .quad alpha_fork .quad sys_read .quad sys_write - .quad alpha_ni_syscall /* 5 */ + .quad sys_ni_syscall /* 5 */ .quad sys_close .quad sys_osf_wait4 - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_link .quad sys_unlink /* 10 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_chdir .quad sys_fchdir .quad sys_mknod .quad sys_chmod /* 15 */ .quad sys_chown .quad sys_osf_brk - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_lseek .quad sys_getxpid /* 20 */ .quad sys_osf_mount .quad sys_umount .quad sys_setuid .quad sys_getxuid - .quad alpha_ni_syscall /* 25 */ + .quad sys_ni_syscall /* 25 */ .quad sys_ptrace - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 30 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 30 */ + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_access - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 35 */ + .quad sys_ni_syscall + .quad sys_ni_syscall /* 35 */ .quad sys_sync .quad sys_kill - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_setpgid - .quad alpha_ni_syscall /* 40 */ + .quad sys_ni_syscall /* 40 */ .quad sys_dup .quad sys_alpha_pipe .quad sys_osf_set_program_attributes - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_open /* 45 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_getxgid .quad sys_osf_sigprocmask - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 50 */ + .quad sys_ni_syscall + .quad sys_ni_syscall /* 50 */ .quad sys_acct .quad sys_sigpending - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_ioctl - .quad alpha_ni_syscall /* 55 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall /* 55 */ + .quad sys_ni_syscall .quad sys_symlink .quad sys_readlink .quad sys_execve .quad sys_umask /* 60 */ .quad sys_chroot - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_getpgrp .quad sys_getpagesize - .quad alpha_ni_syscall /* 65 */ + .quad sys_ni_syscall /* 65 */ .quad alpha_vfork .quad sys_newstat .quad sys_newlstat - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 70 */ + .quad sys_ni_syscall + .quad sys_ni_syscall /* 70 */ .quad sys_osf_mmap - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_munmap .quad sys_mprotect .quad sys_madvise /* 75 */ .quad sys_vhangup - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_getgroups /* map BSD's setpgrp to sys_setpgid for binary compatibility: */ .quad sys_setgroups /* 80 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_setpgid .quad sys_osf_setitimer - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 85 */ + .quad sys_ni_syscall + .quad sys_ni_syscall /* 85 */ .quad sys_osf_getitimer .quad sys_gethostname .quad sys_sethostname @@ -119,19 +119,19 @@ sys_call_table: .quad sys_bind .quad sys_setsockopt /* 105 */ .quad sys_listen - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 110 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 110 */ .quad sys_sigsuspend .quad sys_osf_sigstack .quad sys_recvmsg .quad sys_sendmsg - .quad alpha_ni_syscall /* 115 */ + .quad sys_ni_syscall /* 115 */ .quad sys_osf_gettimeofday .quad sys_osf_getrusage .quad sys_getsockopt - .quad alpha_ni_syscall + .quad sys_ni_syscall #ifdef CONFIG_OSF4_COMPAT .quad sys_osf_readv /* 120 */ .quad sys_osf_writev @@ -156,66 +156,66 @@ sys_call_table: .quad sys_mkdir .quad sys_rmdir .quad sys_osf_utimes - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 140 */ + .quad sys_ni_syscall + .quad sys_ni_syscall /* 140 */ .quad sys_getpeername - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_getrlimit .quad sys_setrlimit /* 145 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_setsid .quad sys_quotactl - .quad alpha_ni_syscall + .quad sys_ni_syscall .quad sys_getsockname /* 150 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 155 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 155 */ .quad sys_osf_sigaction - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_osf_getdirentries .quad sys_osf_statfs /* 160 */ .quad sys_osf_fstatfs - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_osf_getdomainname /* 165 */ .quad sys_setdomainname - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 170 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 175 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 180 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 185 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 190 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 195 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 170 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 175 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 180 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 185 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 190 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 195 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* The OSF swapon has two extra arguments, but we ignore them. */ .quad sys_swapon .quad sys_msgctl /* 200 */ @@ -231,93 +231,93 @@ sys_call_table: .quad sys_shmctl /* 210 */ .quad sys_shmdt .quad sys_shmget - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 215 */ - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 215 */ + .quad sys_ni_syscall .quad sys_msync - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 220 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 220 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_osf_stat .quad sys_osf_lstat /* 225 */ .quad sys_osf_fstat .quad sys_osf_statfs64 .quad sys_osf_fstatfs64 - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 230 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 230 */ + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_getpgid .quad sys_getsid .quad sys_sigaltstack /* 235 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 240 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 240 */ .quad sys_osf_sysinfo - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_osf_proplist_syscall - .quad alpha_ni_syscall /* 245 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 250 */ + .quad sys_ni_syscall /* 245 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 250 */ .quad sys_osf_usleep_thread - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall .quad sys_sysfs - .quad alpha_ni_syscall /* 255 */ + .quad sys_ni_syscall /* 255 */ .quad sys_osf_getsysinfo .quad sys_osf_setsysinfo - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 260 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 265 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 270 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 275 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 280 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 285 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 290 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall /* 295 */ - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall - .quad alpha_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 260 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 265 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 270 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 275 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 280 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 285 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 290 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* 295 */ + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall + .quad sys_ni_syscall /* linux-specific system calls start at 300 */ .quad sys_bdflush /* 300 */ .quad sys_sethae diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index a9e86475f169..26cd925d19b1 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/swap.h> #include <linux/initrd.h> #include <linux/pfn.h> @@ -59,12 +60,10 @@ setup_memory_node(int nid, void *kernel_end) struct memclust_struct * cluster; struct memdesc_struct * memdesc; unsigned long start_kernel_pfn, end_kernel_pfn; - unsigned long bootmap_size, bootmap_pages, bootmap_start; unsigned long start, end; unsigned long node_pfn_start, node_pfn_end; unsigned long node_min_pfn, node_max_pfn; int i; - unsigned long node_datasz = PFN_UP(sizeof(pg_data_t)); int show_init = 0; /* Find the bounds of current node */ @@ -134,24 +133,14 @@ setup_memory_node(int nid, void *kernel_end) /* Cute trick to make sure our local node data is on local memory */ node_data[nid] = (pg_data_t *)(__va(node_min_pfn << PAGE_SHIFT)); #endif - /* Quasi-mark the pg_data_t as in-use */ - node_min_pfn += node_datasz; - if (node_min_pfn >= node_max_pfn) { - printk(" not enough mem to reserve NODE_DATA"); - return; - } - NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; - printk(" Detected node memory: start %8lu, end %8lu\n", node_min_pfn, node_max_pfn); DBGDCONT(" DISCONTIG: node_data[%d] is at 0x%p\n", nid, NODE_DATA(nid)); - DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata); /* Find the bounds of kernel memory. */ start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); - bootmap_start = -1; if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn)) panic("kernel loaded out of ram"); @@ -161,89 +150,11 @@ setup_memory_node(int nid, void *kernel_end) has much larger alignment than 8Mb, so it's safe. */ node_min_pfn &= ~((1UL << (MAX_ORDER-1))-1); - /* We need to know how many physically contiguous pages - we'll need for the bootmap. */ - bootmap_pages = bootmem_bootmap_pages(node_max_pfn-node_min_pfn); - - /* Now find a good region where to allocate the bootmap. */ - for_each_mem_cluster(memdesc, cluster, i) { - if (cluster->usage & 3) - continue; - - start = cluster->start_pfn; - end = start + cluster->numpages; - - if (start >= node_max_pfn || end <= node_min_pfn) - continue; - - if (end > node_max_pfn) - end = node_max_pfn; - if (start < node_min_pfn) - start = node_min_pfn; - - if (start < start_kernel_pfn) { - if (end > end_kernel_pfn - && end - end_kernel_pfn >= bootmap_pages) { - bootmap_start = end_kernel_pfn; - break; - } else if (end > start_kernel_pfn) - end = start_kernel_pfn; - } else if (start < end_kernel_pfn) - start = end_kernel_pfn; - if (end - start >= bootmap_pages) { - bootmap_start = start; - break; - } - } - - if (bootmap_start == -1) - panic("couldn't find a contiguous place for the bootmap"); - - /* Allocate the bootmap and mark the whole MM as reserved. */ - bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start, - node_min_pfn, node_max_pfn); - DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n", - bootmap_start, bootmap_size, bootmap_pages); + memblock_add(PFN_PHYS(node_min_pfn), + (node_max_pfn - node_min_pfn) << PAGE_SHIFT); - /* Mark the free regions. */ - for_each_mem_cluster(memdesc, cluster, i) { - if (cluster->usage & 3) - continue; - - start = cluster->start_pfn; - end = cluster->start_pfn + cluster->numpages; - - if (start >= node_max_pfn || end <= node_min_pfn) - continue; - - if (end > node_max_pfn) - end = node_max_pfn; - if (start < node_min_pfn) - start = node_min_pfn; - - if (start < start_kernel_pfn) { - if (end > end_kernel_pfn) { - free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), - (PFN_PHYS(start_kernel_pfn) - - PFN_PHYS(start))); - printk(" freeing pages %ld:%ld\n", - start, start_kernel_pfn); - start = end_kernel_pfn; - } else if (end > start_kernel_pfn) - end = start_kernel_pfn; - } else if (start < end_kernel_pfn) - start = end_kernel_pfn; - if (start >= end) - continue; - - free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); - printk(" freeing pages %ld:%ld\n", start, end); - } - - /* Reserve the bootmap memory. */ - reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), - bootmap_size, BOOTMEM_DEFAULT); - printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); + NODE_DATA(nid)->node_start_pfn = node_min_pfn; + NODE_DATA(nid)->node_present_pages = node_max_pfn - node_min_pfn; node_set_online(nid); } @@ -251,6 +162,7 @@ setup_memory_node(int nid, void *kernel_end) void __init setup_memory(void *kernel_end) { + unsigned long kernel_size; int nid; show_mem_layout(); @@ -262,6 +174,9 @@ setup_memory(void *kernel_end) for (nid = 0; nid < MAX_NUMNODES; nid++) setup_memory_node(nid, kernel_end); + kernel_size = virt_to_phys(kernel_end) - KERNEL_START_PHYS; + memblock_reserve(KERNEL_START_PHYS, kernel_size); + #ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; if (initrd_start) { @@ -279,9 +194,8 @@ setup_memory(void *kernel_end) phys_to_virt(PFN_PHYS(max_low_pfn))); } else { nid = kvaddr_to_nid(initrd_start); - reserve_bootmem_node(NODE_DATA(nid), - virt_to_phys((void *)initrd_start), - INITRD_SIZE, BOOTMEM_DEFAULT); + memblock_reserve(virt_to_phys((void *)initrd_start), + INITRD_SIZE); } } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -303,9 +217,8 @@ void __init paging_init(void) dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; for_each_online_node(nid) { - bootmem_data_t *bdata = &bootmem_node_data[nid]; - unsigned long start_pfn = bdata->node_min_pfn; - unsigned long end_pfn = bdata->node_low_pfn; + unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn; + unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_present_pages; if (dma_local_pfn >= end_pfn - start_pfn) zones_size[ZONE_DMA] = end_pfn - start_pfn; diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 644815c0516e..c64c505d966c 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -102,11 +102,5 @@ boot_targets += uImage uImage.bin uImage.gz $(boot_targets): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -%.dtb %.dtb.S %.dtb.o: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - -dtbs: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts - archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/arc/include/uapi/asm/unistd.h b/arch/arc/include/uapi/asm/unistd.h index 517178b1daef..3b3543fd151c 100644 --- a/arch/arc/include/uapi/asm/unistd.h +++ b/arch/arc/include/uapi/asm/unistd.h @@ -17,6 +17,7 @@ #define _UAPI_ASM_ARC_UNISTD_H #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_VFORK diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index b123558bf0bb..a7fcbc0d3943 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -42,21 +42,22 @@ void die(const char *str, struct pt_regs *regs, unsigned long address) * -for kernel, chk if due to copy_(to|from)_user, otherwise die() */ static noinline int -unhandled_exception(const char *str, struct pt_regs *regs, siginfo_t *info) +unhandled_exception(const char *str, struct pt_regs *regs, + int signo, int si_code, void __user *addr) { if (user_mode(regs)) { struct task_struct *tsk = current; - tsk->thread.fault_address = (__force unsigned int)info->si_addr; + tsk->thread.fault_address = (__force unsigned int)addr; - force_sig_info(info->si_signo, info, tsk); + force_sig_fault(signo, si_code, addr, tsk); } else { /* If not due to copy_(to|from)_user, we are doomed */ if (fixup_exception(regs)) return 0; - die(str, regs, (unsigned long)info->si_addr); + die(str, regs, (unsigned long)addr); } return 1; @@ -64,16 +65,9 @@ unhandled_exception(const char *str, struct pt_regs *regs, siginfo_t *info) #define DO_ERROR_INFO(signr, str, name, sicode) \ int name(unsigned long address, struct pt_regs *regs) \ -{ \ - siginfo_t info; \ - \ - clear_siginfo(&info); \ - info.si_signo = signr; \ - info.si_errno = 0; \ - info.si_code = sicode; \ - info.si_addr = (void __user *)address; \ - \ - return unhandled_exception(str, regs, &info);\ +{ \ + return unhandled_exception(str, regs, signr, sicode, \ + (void __user *)address); \ } /* diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index f35ed578e007..8fb16bdabdcf 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -71,7 +71,6 @@ SECTIONS INIT_SETUP(L1_CACHE_BYTES) INIT_CALLS CON_INITCALL - SECURITY_INITCALL } .init.arch.info : { diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index db6913094be3..c9da6102eb4f 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -66,14 +66,12 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) struct vm_area_struct *vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - siginfo_t info; + int si_code; int ret; vm_fault_t fault; int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; - clear_siginfo(&info); - /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -91,7 +89,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) return; } - info.si_code = SEGV_MAPERR; + si_code = SEGV_MAPERR; /* * If we're in an interrupt or have no user @@ -119,7 +117,7 @@ retry: * we can handle it.. */ good_area: - info.si_code = SEGV_ACCERR; + si_code = SEGV_ACCERR; /* Handle protection violation, execute on heap or stack */ @@ -199,11 +197,7 @@ bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.fault_address = address; - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code has been set above */ - info.si_addr = (void __user *)address; - force_sig_info(SIGSEGV, &info, tsk); + force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk); return; } @@ -238,9 +232,5 @@ do_sigbus: goto no_context; tsk->thread.fault_address = address; - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void __user *)address; - force_sig_info(SIGBUS, &info, tsk); + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk); } diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e8cd55a5b04c..b8c6062ca0c1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -701,6 +701,7 @@ config ARCH_VIRT select ARM_GIC_V3_ITS if PCI select ARM_PSCI select HAVE_ARM_ARCH_TIMER + select ARCH_SUPPORTS_BIG_ENDIAN # # This is sorted alphabetically by mach-* pathname. However, plat-* diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index a810fa8ba404..d6a49f59ecd9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -947,12 +947,13 @@ choice config DEBUG_RCAR_GEN2_SCIF0 bool "Kernel low-level debugging messages via SCIF0 on R-Car Gen2 and RZ/G1" - depends on ARCH_R8A7743 || ARCH_R8A7790 || ARCH_R8A7791 || \ - ARCH_R8A7792 || ARCH_R8A7793 + depends on ARCH_R8A7743 || ARCH_R8A7744 || ARCH_R8A7790 || \ + ARCH_R8A7791 || ARCH_R8A7792 || ARCH_R8A7793 help Say Y here if you want kernel low-level debugging support - via SCIF0 on Renesas RZ/G1M (R8A7743), R-Car H2 (R8A7790), - M2-W (R8A7791), V2H (R8A7792), or M2-N (R8A7793). + via SCIF0 on Renesas RZ/G1M (R8A7743), RZ/G1N (R8A7744), + R-Car H2 (R8A7790), M2-W (R8A7791), V2H (R8A7792), or + M2-N (R8A7793). config DEBUG_RCAR_GEN2_SCIF1 bool "Kernel low-level debugging messages via SCIF1 on R8A77470" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 5c91e0093ee8..05a91d8b89f3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -303,12 +303,7 @@ else KBUILD_IMAGE := $(boot)/zImage endif -# Build the DT binary blobs if we have OF configured -ifeq ($(CONFIG_USE_OF),y) -KBUILD_DTBS := dtbs -endif - -all: $(notdir $(KBUILD_IMAGE)) $(KBUILD_DTBS) +all: $(notdir $(KBUILD_IMAGE)) archheaders: @@ -335,17 +330,6 @@ $(BOOT_TARGETS): vmlinux $(INSTALL_TARGETS): $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ -%.dtb: | scripts - $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ - -PHONY += dtbs dtbs_install - -dtbs: prepare scripts - $(Q)$(MAKE) $(build)=$(boot)/dts - -dtbs_install: - $(Q)$(MAKE) $(dtbinst)=$(boot)/dts - PHONY += vdso_install vdso_install: ifeq ($(CONFIG_VDSO),y) @@ -367,8 +351,6 @@ define archhelp echo ' uImage - U-Boot wrapped zImage' echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=<path>)' - echo '* dtbs - Build device tree blobs for enabled boards' - echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' echo ' uinstall - Install U-Boot wrapped compressed kernel' diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h index 07437816e098..b36c0289a308 100644 --- a/arch/arm/boot/compressed/libfdt_env.h +++ b/arch/arm/boot/compressed/libfdt_env.h @@ -6,6 +6,8 @@ #include <linux/string.h> #include <asm/byteorder.h> +#define INT_MAX ((int)(~0U>>1)) + typedef __be16 fdt16_t; typedef __be32 fdt32_t; typedef __be64 fdt64_t; diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b5bd3de87c33..b0e966d625b9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -81,6 +81,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ bcm2836-rpi-2-b.dtb \ bcm2837-rpi-3-b.dtb \ bcm2837-rpi-3-b-plus.dtb \ + bcm2837-rpi-cm3-io3.dtb \ bcm2835-rpi-zero.dtb \ bcm2835-rpi-zero-w.dtb dtb-$(CONFIG_ARCH_BCM_5301X) += \ @@ -321,6 +322,7 @@ dtb-$(CONFIG_MACH_MESON6) += \ meson6-atv1200.dtb dtb-$(CONFIG_MACH_MESON8) += \ meson8-minix-neo-x8.dtb \ + meson8b-ec100.dtb \ meson8b-mxq.dtb \ meson8b-odroidc1.dtb \ meson8m2-mxiii-plus.dtb @@ -548,6 +550,7 @@ dtb-$(CONFIG_SOC_IMX6SX) += \ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-14x14-evk.dtb \ imx6ul-ccimx6ulsbcexpress.dtb \ + imx6ul-ccimx6ulsbcpro.dtb \ imx6ul-geam.dtb \ imx6ul-isiot-emmc.dtb \ imx6ul-isiot-nand.dtb \ @@ -559,7 +562,8 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ul-tx6ul-mainboard.dtb \ imx6ull-14x14-evk.dtb \ imx6ull-colibri-eval-v3.dtb \ - imx6ull-colibri-wifi-eval-v3.dtb + imx6ull-colibri-wifi-eval-v3.dtb \ + imx6ulz-14x14-evk.dtb dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ @@ -649,6 +653,7 @@ dtb-$(CONFIG_ARCH_OMAP3) += \ omap3-gta04a3.dtb \ omap3-gta04a4.dtb \ omap3-gta04a5.dtb \ + omap3-gta04a5one.dtb \ omap3-ha.dtb \ omap3-ha-lcd.dtb \ omap3-igep0020.dtb \ @@ -706,6 +711,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \ am335x-evmsk.dtb \ am335x-icev2.dtb \ am335x-lxm.dtb \ + am335x-moxa-uc-2101.dtb \ am335x-moxa-uc-8100-me-t.dtb \ am335x-nano.dtb \ am335x-pdu001.dtb \ @@ -864,6 +870,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-r89.dtb \ rk3288-rock2-square.dtb \ rk3288-tinker.dtb \ + rk3288-tinker-s.dtb \ rk3288-veyron-brain.dtb \ rk3288-veyron-jaq.dtb \ rk3288-veyron-jerry.dtb \ @@ -892,7 +899,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) += \ socfpga_arria10_socdk_sdmmc.dtb \ socfpga_cyclone5_mcvevk.dtb \ socfpga_cyclone5_socdk.dtb \ - socfpga_cyclone5_de0_sockit.dtb \ + socfpga_cyclone5_de0_nano_soc.dtb \ socfpga_cyclone5_sockit.dtb \ socfpga_cyclone5_socrates.dtb \ socfpga_cyclone5_sodia.dtb \ @@ -1033,6 +1040,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-h2-plus-orangepi-r1.dtb \ sun8i-h2-plus-orangepi-zero.dtb \ sun8i-h3-bananapi-m2-plus.dtb \ + sun8i-h3-bananapi-m2-plus-v1.2.dtb \ sun8i-h3-beelink-x2.dtb \ sun8i-h3-libretech-all-h3-cc.dtb \ sun8i-h3-nanopi-m1.dtb \ @@ -1046,6 +1054,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-h3-orangepi-pc-plus.dtb \ sun8i-h3-orangepi-plus.dtb \ sun8i-h3-orangepi-plus2e.dtb \ + sun8i-h3-orangepi-zero-plus2.dtb \ sun8i-r16-bananapi-m2m.dtb \ sun8i-r16-nintendo-nes-classic.dtb \ sun8i-r16-nintendo-super-nes-classic.dtb \ @@ -1061,6 +1070,7 @@ dtb-$(CONFIG_ARCH_TANGO) += \ tango4-vantage-1172.dtb dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ tegra20-harmony.dtb \ + tegra20-colibri-eval-v3.dtb \ tegra20-colibri-iris.dtb \ tegra20-medcom-wide.dtb \ tegra20-paz00.dtb \ @@ -1071,6 +1081,7 @@ dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ tegra20-ventana.dtb dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += \ tegra30-apalis-eval.dtb \ + tegra30-apalis-v1.1-eval.dtb \ tegra30-beaver.dtb \ tegra30-cardhu-a02.dtb \ tegra30-cardhu-a04.dtb \ @@ -1149,6 +1160,7 @@ dtb-$(CONFIG_MACH_ARMADA_370) += \ dtb-$(CONFIG_MACH_ARMADA_375) += \ armada-375-db.dtb dtb-$(CONFIG_MACH_ARMADA_38X) += \ + armada-385-db-88f6820-amc.dtb \ armada-385-db-ap.dtb \ armada-385-linksys-caiman.dtb \ armada-385-linksys-cobra.dtb \ @@ -1199,6 +1211,8 @@ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-ast2500-evb.dtb \ aspeed-bmc-arm-centriq2400-rep.dtb \ + aspeed-bmc-arm-stardragon4800-rep2.dtb \ + aspeed-bmc-facebook-tiogapass.dtb \ aspeed-bmc-intel-s2600wf.dtb \ aspeed-bmc-opp-lanyang.dtb \ aspeed-bmc-opp-palmetto.dtb \ diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi index 73b514dddf65..9e5e75ea87f5 100644 --- a/arch/arm/boot/dts/am335x-bone-common.dtsi +++ b/arch/arm/boot/dts/am335x-bone-common.dtsi @@ -379,7 +379,7 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "mii"; }; @@ -396,6 +396,10 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &mmc1 { diff --git a/arch/arm/boot/dts/am335x-boneblack-common.dtsi b/arch/arm/boot/dts/am335x-boneblack-common.dtsi index 325daae40278..e543c2bee8c2 100644 --- a/arch/arm/boot/dts/am335x-boneblack-common.dtsi +++ b/arch/arm/boot/dts/am335x-boneblack-common.dtsi @@ -7,6 +7,7 @@ */ #include <dt-bindings/display/tda998x.h> +#include <dt-bindings/interrupt-controller/irq.h> &ldo3_reg { regulator-min-microvolt = <1800000>; @@ -88,9 +89,11 @@ }; &i2c0 { - tda19988: tda19988 { + tda19988: tda19988@70 { compatible = "nxp,tda998x"; reg = <0x70>; + nxp,calib-gpios = <&gpio1 25 0>; + interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default", "off"; pinctrl-0 = <&nxp_hdmi_bonelt_pins>; diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/am335x-chiliboard.dts index 59431b235944..9c2a947aacf5 100644 --- a/arch/arm/boot/dts/am335x-chiliboard.dts +++ b/arch/arm/boot/dts/am335x-chiliboard.dts @@ -140,10 +140,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rmii"; }; diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts index 947c81b7aaaf..c4d3e1f1a95e 100644 --- a/arch/arm/boot/dts/am335x-cm-t335.dts +++ b/arch/arm/boot/dts/am335x-cm-t335.dts @@ -486,10 +486,14 @@ status = "okay"; pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; }; diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index c87d01297a01..98ec9c3e49ba 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -713,6 +713,7 @@ pinctrl-0 = <&cpsw_default>; pinctrl-1 = <&cpsw_sleep>; status = "okay"; + slaves = <1>; }; &davinci_mdio { @@ -720,15 +721,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; -}; -&cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; - phy-mode = "rgmii-txid"; + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; -&cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; +&cpsw_emac0 { + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; }; diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index bf1a40e45c97..245868f58fe3 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -639,16 +639,24 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi index a5769a8f5fc8..55b4c94cfafb 100644 --- a/arch/arm/boot/dts/am335x-igep0033.dtsi +++ b/arch/arm/boot/dts/am335x-igep0033.dtsi @@ -102,15 +102,24 @@ &davinci_mdio { status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rmii"; + }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rmii"; }; diff --git a/arch/arm/boot/dts/am335x-lxm.dts b/arch/arm/boot/dts/am335x-lxm.dts index 1d6c6fa703e4..481edcfaf121 100644 --- a/arch/arm/boot/dts/am335x-lxm.dts +++ b/arch/arm/boot/dts/am335x-lxm.dts @@ -317,13 +317,13 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <5>; + phy-handle = <ðphy0>; phy-mode = "rmii"; dual_emac_res_vlan = <2>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <4>; + phy-handle = <ðphy1>; phy-mode = "rmii"; dual_emac_res_vlan = <3>; }; @@ -345,6 +345,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@5 { + reg = <5>; + }; + + ethphy1: ethernet-phy@4 { + reg = <4>; + }; }; &mmc1 { diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi new file mode 100644 index 000000000000..14f781953475 --- /dev/null +++ b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MOXA Inc. - https://www.moxa.com/ + * + * Authors: SZ Lin (林上智) <sz.lin@moxa.com> + * Wes Huang (黃淵河) <wes.huang@moxa.com> + * Fero JD Zhou (周俊達) <FeroJD.Zhou@moxa.com> + */ + +#include "am33xx.dtsi" + +/ { + vbat: vbat-regulator { + compatible = "regulator-fixed"; + }; + + /* Power supply provides a fixed 3.3V @3A */ + vmmcsd_fixed: vmmcsd-regulator { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + buttons: push_button { + compatible = "gpio-keys"; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + push_button_pins: pinmux_push_button { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2_23 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + mmc1_pins_default: pinmux_mmc1_pins { + pinctrl-single,pins = < + /* eMMC */ + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad12.mmc1_dat0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad13.mmc1_dat1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad14.mmc1_dat2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad15.mmc1_dat3 */ + AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad8.mmc1_dat4 */ + AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad9.mmc1_dat5 */ + AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad10.mmc1_dat6 */ + AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad11.mmc1_dat7 */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + >; + }; + + spi0_pins: pinmux_spi0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */ + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */ + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */ + >; + }; +}; + +&uart0 { + /* Console */ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + eeprom: eeprom@50 { + compatible = "atmel,24c16"; + pagesize = <16>; + reg = <0x50>; + }; + + rtc_wdt: rtc_wdt@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +/* Power */ +&vbat { + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +}; + +&mac { + pinctrl-names = "default"; + pinctrl-0 = <&cpsw_default>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&davinci_mdio_default>; + status = "okay"; +}; + +&cpsw_emac0 { + status = "okay"; +}; + +&cpsw_emac1 { + status = "okay"; +}; + +&phy_sel { + reg= <0x44e10650 0xf5>; + rmii-clock-ext; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + ti,no-reset-on-init; +}; + +&mmc2 { + pinctrl-names = "default"; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <8>; + pinctrl-0 = <&mmc1_pins_default>; + ti,non-removable; + status = "okay"; +}; + +&buttons { + pinctrl-names = "default"; + pinctrl-0 = <&push_button_pins>; + #address-cells = <1>; + #size-cells = <0>; + + button@0 { + label = "push_button"; + linux,code = <0x100>; + gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; + }; +}; + +/* SPI Busses */ +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + m25p80@0 { + compatible = "mx25l6405d"; + spi-max-frequency = <40000000>; + + reg = <0>; + spi-cpol; + spi-cpha; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* reg : The partition's offset and size within the mtd bank. */ + partitions@0 { + label = "MLO"; + reg = <0x0 0x80000>; + }; + + partitions@1 { + label = "U-Boot"; + reg = <0x80000 0x100000>; + }; + + partitions@2 { + label = "U-Boot Env"; + reg = <0x180000 0x40000>; + }; + }; + }; +}; + +&spi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + + tpm_spi_tis@0 { + compatible = "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <500000>; + }; +}; diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2101.dts b/arch/arm/boot/dts/am335x-moxa-uc-2101.dts new file mode 100644 index 000000000000..48aee6de4cdb --- /dev/null +++ b/arch/arm/boot/dts/am335x-moxa-uc-2101.dts @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MOXA Inc. - https://www.moxa.com/ + * + * Authors: SZ Lin (林上智) <sz.lin@moxa.com> + * Wes Huang (黃淵河) <wes.huang@moxa.com> + * Fero JD Zhou (周俊達) <FeroJD.Zhou@moxa.com> + */ + +/dts-v1/; + +#include "am335x-moxa-uc-2100-common.dtsi" + +/ { + model = "Moxa UC-2101"; + compatible = "moxa,uc-2101", "ti,am33xx"; + + leds { + compatible = "gpio-leds"; + led1 { + label = "UC2100:GREEN:USER"; + gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mii1_refclk.rmii1_refclk */ + >; + }; + + spi1_pins: pinmux_spi1 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE4) /* ecap0_in_pwm0_out.spi1_sclk */ + AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE4) /* uart1_ctsn.spi1_cs0 */ + AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE4) /* uart0_ctsn.spi1_d0 */ + AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE4) /* uart0_rtsn.spi1_d1 */ + >; + }; +}; + +&davinci_mdio { + phy0: ethernet-phy@4 { + reg = <4>; + }; +}; + +&cpsw_emac0 { + status = "okay"; + phy-handle = <&phy0>; + phy-mode = "rmii"; +}; + +&cpsw_emac1 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts b/arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts index f82233cd18e0..5a58efc0c874 100644 --- a/arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts +++ b/arch/arm/boot/dts/am335x-moxa-uc-8100-me-t.dts @@ -422,18 +422,26 @@ pinctrl-names = "default"; pinctrl-0 = <&davinci_mdio_default>; status = "okay"; + + ethphy0: ethernet-phy@4 { + reg = <4>; + }; + + ethphy1: ethernet-phy@5 { + reg = <5>; + }; }; &cpsw_emac0 { status = "okay"; - phy_id = <&davinci_mdio>, <4>; + phy-handle = <ðphy0>; phy-mode = "rmii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { status = "okay"; - phy_id = <&davinci_mdio>, <5>; + phy-handle = <ðphy1>; phy-mode = "rmii"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am335x-nano.dts b/arch/arm/boot/dts/am335x-nano.dts index 946d7069f417..9c9143ed4003 100644 --- a/arch/arm/boot/dts/am335x-nano.dts +++ b/arch/arm/boot/dts/am335x-nano.dts @@ -380,16 +380,24 @@ &davinci_mdio { status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "mii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "mii"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts index 4d969013f99a..85cd1d0a73ca 100644 --- a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts +++ b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts @@ -161,7 +161,7 @@ invensense,key = [4e cc 7e eb f6 1e 35 22 00 34 0d 65 32 e9 94 89];*/ }; - bmp280: pressure@78 { + bmp280: pressure@76 { compatible = "bosch,bmp280"; reg = <0x76>; }; @@ -424,7 +424,7 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <4>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; }; @@ -441,6 +441,10 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@4 { + reg = <4>; + }; }; &mmc1 { diff --git a/arch/arm/boot/dts/am335x-pdu001.dts b/arch/arm/boot/dts/am335x-pdu001.dts index 1ad530a39a95..6dd9d487aaeb 100644 --- a/arch/arm/boot/dts/am335x-pdu001.dts +++ b/arch/arm/boot/dts/am335x-pdu001.dts @@ -373,7 +373,7 @@ ti,pindir-d0-out-d1-in; status = "okay"; - cfaf240320a032t { + display-controller@0 { compatible = "orisetech,otm3225a"; reg = <0>; spi-max-frequency = <1000000>; @@ -533,16 +533,24 @@ pinctrl-names = "default"; pinctrl-0 = <&davinci_mdio_default>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "mii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "mii"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts index 9fb7426070ce..6be79b8349ac 100644 --- a/arch/arm/boot/dts/am335x-pepper.dts +++ b/arch/arm/boot/dts/am335x-pepper.dts @@ -265,13 +265,13 @@ /* Ethernet */ &cpsw_emac0 { status = "okay"; - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; &cpsw_emac1 { status = "okay"; - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; }; @@ -279,6 +279,14 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&mdio_pins>; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &mac { diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/am335x-sancloud-bbe.dts index 7b8e7417a11e..35527fdf56cc 100644 --- a/arch/arm/boot/dts/am335x-sancloud-bbe.dts +++ b/arch/arm/boot/dts/am335x-sancloud-bbe.dts @@ -103,10 +103,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; }; diff --git a/arch/arm/boot/dts/am335x-shc.dts b/arch/arm/boot/dts/am335x-shc.dts index 4f6a286ea293..1d925ed2b102 100644 --- a/arch/arm/boot/dts/am335x-shc.dts +++ b/arch/arm/boot/dts/am335x-shc.dts @@ -206,7 +206,6 @@ status = "okay"; slaves = <1>; cpsw_emac0: slave@4a100200 { - phy_id = <&davinci_mdio>, <0>; phy-mode = "mii"; phy-handle = <ðernetphy0>; }; diff --git a/arch/arm/boot/dts/am3517-evm-ui.dtsi b/arch/arm/boot/dts/am3517-evm-ui.dtsi new file mode 100644 index 000000000000..e841918c1c26 --- /dev/null +++ b/arch/arm/boot/dts/am3517-evm-ui.dtsi @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2018 Logic PD, Inc - http://www.logicpd.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 + * published by the Free Software Foundation. + */ + +#include <dt-bindings/input/input.h> + +/ { + codec1 { + compatible = "simple-audio-card"; + simple-audio-card,name = "tlv320aic23-hifi"; + + simple-audio-card,widgets = + "Microphone", "Mic In", + "Line", "Line In", + "Line", "Line Out"; + + simple-audio-card,routing = + "Line Out", "LOUT", + "Line Out", "ROUT", + "LLINEIN", "Line In", + "RLINEIN", "Line In", + "MICIN", "Mic In"; + + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&sound_master>; + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { + sound-dai = <&mcbsp1>; + }; + + sound_master: simple-audio-card,codec { + sound-dai = <&tlv320aic23_1>; + system-clock-frequency = <12000000>; + }; + }; + + codec2 { + compatible = "simple-audio-card"; + simple-audio-card,name = "tlv320aic23-hifi"; + + simple-audio-card,widgets = + "Microphone", "Mic In", + "Line", "Line In", + "Line", "Line Out"; + + simple-audio-card,routing = + "Line Out", "LOUT", + "Line Out", "ROUT", + "LLINEIN", "Line In", + "RLINEIN", "Line In", + "MICIN", "Mic In"; + + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&sound_master2>; + simple-audio-card,frame-master = <&sound_master2>; + + simple-audio-card,cpu { + sound-dai = <&mcbsp2>; + }; + + sound_master2: simple-audio-card,codec { + sound-dai = <&tlv320aic23_2>; + system-clock-frequency = <12000000>; + }; + }; + + expander-keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + record { + label = "Record"; + /* linux,code = <BTN_0>; */ + gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>; + }; + + play { + label = "Play"; + linux,code = <KEY_PLAY>; + gpios = <&tca6416_2 14 GPIO_ACTIVE_LOW>; + }; + + Stop { + label = "Stop"; + linux,code = <KEY_STOP>; + gpios = <&tca6416_2 13 GPIO_ACTIVE_LOW>; + }; + + fwd { + label = "FWD"; + linux,code = <KEY_FASTFORWARD>; + gpios = <&tca6416_2 12 GPIO_ACTIVE_LOW>; + }; + + rwd { + label = "RWD"; + linux,code = <KEY_REWIND>; + gpios = <&tca6416_2 11 GPIO_ACTIVE_LOW>; + }; + + shift { + label = "Shift"; + linux,code = <KEY_LEFTSHIFT>; + gpios = <&tca6416_2 10 GPIO_ACTIVE_LOW>; + }; + + Mode { + label = "Mode"; + linux,code = <BTN_MODE>; + gpios = <&tca6416_2 9 GPIO_ACTIVE_LOW>; + }; + + Menu { + label = "Menu"; + linux,code = <KEY_MENU>; + gpios = <&tca6416_2 8 GPIO_ACTIVE_LOW>; + }; + + Up { + label = "Up"; + linux,code = <KEY_UP>; + gpios = <&tca6416_2 7 GPIO_ACTIVE_LOW>; + }; + + Down { + label = "Down"; + linux,code = <KEY_DOWN>; + gpios = <&tca6416_2 6 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c2 { + /* Audio codecs */ + tlv320aic23_1: codec@1a { + compatible = "ti,tlv320aic23"; + reg = <0x1a>; + #sound-dai-cells= <0>; + status = "okay"; + }; + + tlv320aic23_2: codec@1b { + compatible = "ti,tlv320aic23"; + reg = <0x1b>; + #sound-dai-cells= <0>; + status = "okay"; + }; +}; + +&i2c3 { + /* Audio codecs */ + tlv320aic23_3: codec@1a { + compatible = "ti,tlv320aic23"; + reg = <0x1a>; + #sound-dai-cells= <0>; + status = "okay"; + }; + + /* GPIO Expanders */ + tca6416_2: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + vcc-supply = <&vdd_io_reg>; + }; + + tca6416_3: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + vcc-supply = <&vdd_io_reg>; + }; + + /* TVP5146 Analog Video decoder input */ + tvp5146@5c { + compatible = "ti,tvp5146m2"; + reg = <0x5c>; + }; +}; + +&mcbsp1 { + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp1_pins>; +}; + +&mcbsp2 { + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp2_pins>; +}; + +&omap3_pmx_core { + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dx */ + OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dr */ + OMAP3_CORE1_IOPAD(0x2196, PIN_INPUT | MUX_MODE0) /* mcbsp_clks.mcbsp1_fsx */ + OMAP3_CORE1_IOPAD(0x2198, PIN_INPUT | MUX_MODE0) /* mcbsp1_clkx.mcbsp1_clkx */ + >; + }; + + mcbsp2_pins: pinmux_mcbsp2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ + OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ + OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0) /* mcbsp2_dr.mcbsp2.dr */ + OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dx.mcbsp2_dx */ + >; + }; +}; diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts index 1d158cfda15f..d4d33cd7adad 100644 --- a/arch/arm/boot/dts/am3517-evm.dts +++ b/arch/arm/boot/dts/am3517-evm.dts @@ -9,6 +9,7 @@ #include "am3517.dtsi" #include "am3517-som.dtsi" +#include "am3517-evm-ui.dtsi" #include <dt-bindings/input/input.h> / { diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index d4b7c59eec68..a68e89dae7a1 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -1101,7 +1101,7 @@ }; }; - qspi: qspi@47900000 { + qspi: spi@47900000 { compatible = "ti,am4372-qspi"; reg = <0x47900000 0x100>, <0x30000000 0x4000000>; diff --git a/arch/arm/boot/dts/am437x-cm-t43.dts b/arch/arm/boot/dts/am437x-cm-t43.dts index bff5abe69bdb..4fcf647815a2 100644 --- a/arch/arm/boot/dts/am437x-cm-t43.dts +++ b/arch/arm/boot/dts/am437x-cm-t43.dts @@ -339,16 +339,24 @@ pinctrl-names = "default"; pinctrl-0 = <&davinci_mdio_default>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 5b97c20c5ed4..601bf4daaeb7 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -831,10 +831,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts index 20132477a871..bb285409473e 100644 --- a/arch/arm/boot/dts/am437x-idk-evm.dts +++ b/arch/arm/boot/dts/am437x-idk-evm.dts @@ -499,10 +499,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index d4be3fd0b6f4..088cba09d34d 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -799,16 +799,24 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@4 { + reg = <4>; + }; + + ethphy1: ethernet-phy@5 { + reg = <5>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <4>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <5>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 6502d3397653..4ea753b3ee43 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -575,10 +575,14 @@ pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; status = "okay"; + + ethphy0: ethernet-phy@16 { + reg = <16>; + }; }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <16>; + phy-handle = <ðphy0>; phy-mode = "rmii"; }; diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/am571x-idk.dts index d9a2049a1ea8..6432309b39e3 100644 --- a/arch/arm/boot/dts/am571x-idk.dts +++ b/arch/arm/boot/dts/am571x-idk.dts @@ -64,6 +64,82 @@ linux,default-trigger = "mmc0"; }; }; + + idk-leds { + status = "disabled"; + compatible = "gpio-leds"; + red0-led { + label = "idk:red0"; + gpios = <&gpio6 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green0-led { + label = "idk:green0"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue0-led { + label = "idk:blue0"; + gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red1-led { + label = "idk:red1"; + gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green1-led { + label = "idk:green1"; + gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue1-led { + label = "idk:blue1"; + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red2-led { + label = "idk:red2"; + gpios = <&gpio7 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green2-led { + label = "idk:green2"; + gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue2-led { + label = "idk:blue2"; + gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red3-led { + label = "idk:red3"; + gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green3-led { + label = "idk:green3"; + gpios = <&gpio7 25 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue3-led { + label = "idk:blue3"; + gpios = <&gpio7 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; }; &extcon_usb2 { @@ -71,6 +147,10 @@ vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>; }; +&sn65hvs882 { + load-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; +}; + &mailbox5 { status = "okay"; mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { @@ -114,7 +194,3 @@ pinctrl-1 = <&mmc2_pins_hs>; pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>; }; - -&cpu0 { - vdd-supply = <&smps12_reg>; -}; diff --git a/arch/arm/boot/dts/am572x-idk-common.dtsi b/arch/arm/boot/dts/am572x-idk-common.dtsi index 784639ddf451..a064f13b3880 100644 --- a/arch/arm/boot/dts/am572x-idk-common.dtsi +++ b/arch/arm/boot/dts/am572x-idk-common.dtsi @@ -55,6 +55,82 @@ linux,default-trigger = "mmc0"; }; }; + + idk-leds { + status = "disabled"; + compatible = "gpio-leds"; + red0-led { + label = "idk:red0"; + gpios = <&gpio6 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green0-led { + label = "idk:green0"; + gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue0-led { + label = "idk:blue0"; + gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red1-led { + label = "idk:red1"; + gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green1-led { + label = "idk:green1"; + gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue1-led { + label = "idk:blue1"; + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red2-led { + label = "idk:red2"; + gpios = <&gpio7 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green2-led { + label = "idk:green2"; + gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue2-led { + label = "idk:blue2"; + gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red3-led { + label = "idk:red3"; + gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green3-led { + label = "idk:green3"; + gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + blue3-led { + label = "idk:blue3"; + gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; }; &extcon_usb2 { diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/am572x-idk.dts index 3ef9111d0e8b..b2fb6e097be7 100644 --- a/arch/arm/boot/dts/am572x-idk.dts +++ b/arch/arm/boot/dts/am572x-idk.dts @@ -36,7 +36,3 @@ pinctrl-1 = <&mmc2_pins_hs>; pinctrl-2 = <&mmc2_pins_ddr_rev20>; }; - -&cpu0 { - vdd-supply = <&smps12_reg>; -}; diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts index 203266f88480..4748ce8747ad 100644 --- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts +++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts @@ -518,7 +518,7 @@ }; /* touch controller */ - ads7846@0 { + touchscreen@1 { pinctrl-names = "default"; pinctrl-0 = <&ads7846_pins>; @@ -558,13 +558,13 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <0>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii-txid"; dual_emac_res_vlan = <1>; }; @@ -573,6 +573,14 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&davinci_mdio_pins_default>; pinctrl-1 = <&davinci_mdio_pins_sleep>; + + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; }; &usb2_phy1 { diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi index c9063ffca524..f7bd26458915 100644 --- a/arch/arm/boot/dts/am57xx-idk-common.dtsi +++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi @@ -372,17 +372,27 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; dual_emac_res_vlan = <2>; }; +&davinci_mdio { + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &usb2_phy1 { phy-supply = <&ldousb_reg>; }; @@ -478,3 +488,7 @@ }; }; }; + +&cpu0 { + vdd-supply = <&smps12_reg>; +}; diff --git a/arch/arm/boot/dts/arm-realview-eb.dtsi b/arch/arm/boot/dts/arm-realview-eb.dtsi index a917cf8825ca..0e4c7c4c8c09 100644 --- a/arch/arm/boot/dts/arm-realview-eb.dtsi +++ b/arch/arm/boot/dts/arm-realview-eb.dtsi @@ -371,7 +371,7 @@ clock-names = "uartclk", "apb_pclk"; }; - ssp: ssp@1000d000 { + ssp: spi@1000d000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x1000d000 0x1000>; clocks = <&sspclk>, <&pclk>; diff --git a/arch/arm/boot/dts/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm-realview-pb1176.dts index f935b72d3d96..f2a1d25eb6cf 100644 --- a/arch/arm/boot/dts/arm-realview-pb1176.dts +++ b/arch/arm/boot/dts/arm-realview-pb1176.dts @@ -380,7 +380,7 @@ clock-names = "apb_pclk"; }; - pb1176_ssp: ssp@1010b000 { + pb1176_ssp: spi@1010b000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x1010b000 0x1000>; interrupt-parent = <&intc_dc1176>; diff --git a/arch/arm/boot/dts/arm-realview-pb11mp.dts b/arch/arm/boot/dts/arm-realview-pb11mp.dts index 36203288de42..7f9cbdf33a51 100644 --- a/arch/arm/boot/dts/arm-realview-pb11mp.dts +++ b/arch/arm/boot/dts/arm-realview-pb11mp.dts @@ -523,7 +523,7 @@ clock-names = "uartclk", "apb_pclk"; }; - ssp@1000d000 { + spi@1000d000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x1000d000 0x1000>; interrupt-parent = <&intc_pb11mp>; diff --git a/arch/arm/boot/dts/arm-realview-pbx.dtsi b/arch/arm/boot/dts/arm-realview-pbx.dtsi index 10868ba3277f..a5676697ff3b 100644 --- a/arch/arm/boot/dts/arm-realview-pbx.dtsi +++ b/arch/arm/boot/dts/arm-realview-pbx.dtsi @@ -362,7 +362,7 @@ clock-names = "uartclk", "apb_pclk"; }; - ssp: ssp@1000d000 { + ssp: spi@1000d000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x1000d000 0x1000>; clocks = <&sspclk>, <&pclk>; diff --git a/arch/arm/boot/dts/armada-385-db-88f6820-amc.dts b/arch/arm/boot/dts/armada-385-db-88f6820-amc.dts new file mode 100644 index 000000000000..7881df3b28a0 --- /dev/null +++ b/arch/arm/boot/dts/armada-385-db-88f6820-amc.dts @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device Tree file for Marvell Armada 385 AMC board + * (DB-88F6820-AMC) + * + * Copyright (C) 2017 Allied Telesis Labs + */ + +/dts-v1/; +#include "armada-385.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "Marvell Armada 385 AMC"; + compatible = "marvell,a385-db-amc", "marvell,armada385", "marvell,armada380"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + ethernet1 = ð1; + spi1 = &spi1; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; +}; + +&uart0 { + /* + * Exported on the micro USB connector CON3 + * through an FTDI + */ + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + + +ð0 { + pinctrl-names = "default"; + /* + * The Reference Clock 0 is used to provide a + * clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; +}; + +ð2 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; +}; + +&usb0 { + status = "okay"; +}; + + + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@0 { + reg = <0>; + }; +}; + +&nand_controller { + status = "okay"; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + nand-on-flash-bbt; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + reg = <0x00000000 0x40000000>; + label = "user"; + }; + }; + }; +}; + +&pciec { + status = "okay"; +}; + +&pcie1 { + /* Port 0, Lane 0 */ + status = "okay"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + reg = <0x00000000 0x00100000>; + label = "u-boot"; + }; + partition@100000 { + reg = <0x00100000 0x00040000>; + label = "u-boot-env"; + }; + }; + }; +}; + +&refclk { + clock-frequency = <20000000>; +}; diff --git a/arch/arm/boot/dts/armada-388-clearfog.dtsi b/arch/arm/boot/dts/armada-388-clearfog.dtsi index 7c6ad2afb094..1b0d0680c8b6 100644 --- a/arch/arm/boot/dts/armada-388-clearfog.dtsi +++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi @@ -48,7 +48,7 @@ &clearfog_sdhci_cd_pins>; pinctrl-names = "default"; status = "okay"; - vmmc = <®_3p3v>; + vmmc-supply = <®_3p3v>; wp-inverted; }; diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi index 8d708cc22495..59753470cd34 100644 --- a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi +++ b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi @@ -189,7 +189,7 @@ }; }; - nand: nand@d0000 { + nand_controller: nand-controller@d0000 { clocks = <&dfx_coredivclk 0>; }; @@ -243,7 +243,7 @@ ranges = <0 MBUS_ID(0x03, 0x00) 0 0x100000>; pp0: packet-processor@0 { - compatible = "marvell,prestera-98dx3236"; + compatible = "marvell,prestera-98dx3236", "marvell,prestera"; reg = <0 0x4000000>; interrupts = <33>, <34>, <35>; dfx = <&dfx>; diff --git a/arch/arm/boot/dts/armada-xp-98dx3336.dtsi b/arch/arm/boot/dts/armada-xp-98dx3336.dtsi index 2f5fc67dd6dc..1d9d8a8ea60c 100644 --- a/arch/arm/boot/dts/armada-xp-98dx3336.dtsi +++ b/arch/arm/boot/dts/armada-xp-98dx3336.dtsi @@ -35,5 +35,5 @@ }; &pp0 { - compatible = "marvell,prestera-98dx3336"; + compatible = "marvell,prestera-98dx3336", "marvell,prestera"; }; diff --git a/arch/arm/boot/dts/armada-xp-98dx4251.dtsi b/arch/arm/boot/dts/armada-xp-98dx4251.dtsi index 7a9e8839880b..48ffdc72bfc7 100644 --- a/arch/arm/boot/dts/armada-xp-98dx4251.dtsi +++ b/arch/arm/boot/dts/armada-xp-98dx4251.dtsi @@ -49,6 +49,6 @@ }; &pp0 { - compatible = "marvell,prestera-98dx4251"; + compatible = "marvell,prestera-98dx4251", "marvell,prestera"; interrupts = <33>, <34>, <35>, <36>; }; diff --git a/arch/arm/boot/dts/armada-xp-db-dxbc2.dts b/arch/arm/boot/dts/armada-xp-db-dxbc2.dts index f42fc6118b7c..8a3aa616bbd0 100644 --- a/arch/arm/boot/dts/armada-xp-db-dxbc2.dts +++ b/arch/arm/boot/dts/armada-xp-db-dxbc2.dts @@ -68,14 +68,18 @@ status = "okay"; }; -&nand { +&nand_controller { status = "okay"; - label = "pxa3xx_nand-0"; - num-cs = <1>; - marvell,nand-keep-config; - nand-on-flash-bbt; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + }; }; &sdio { diff --git a/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts b/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts index 8432f517e346..df048050615f 100644 --- a/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts +++ b/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts @@ -67,14 +67,18 @@ status = "okay"; }; -&nand { +&nand_controller { status = "okay"; - label = "pxa3xx_nand-0"; - num-cs = <1>; - marvell,nand-keep-config; - nand-on-flash-bbt; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + }; }; &spi0 { diff --git a/arch/arm/boot/dts/aspeed-bmc-arm-stardragon4800-rep2.dts b/arch/arm/boot/dts/aspeed-bmc-arm-stardragon4800-rep2.dts new file mode 100644 index 000000000000..bdfd8c9f3a7c --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-arm-stardragon4800-rep2.dts @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +#include "aspeed-g5.dtsi" +#include <dt-bindings/gpio/aspeed-gpio.h> + +/ { + model = "HXT StarDragon 4800 REP2 AST2520"; + compatible = "hxt,stardragon4800-rep2-bmc", "aspeed,ast2500"; + + chosen { + stdout-path = &uart5; + bootargs = "console=ttyS4,115200 earlyprintk"; + }; + + memory@80000000 { + reg = <0x80000000 0x40000000>; + }; + + iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, + <&adc 4>, <&adc 5>, <&adc 6>, <&adc 8>; + }; + + iio-hwmon-battery { + compatible = "iio-hwmon"; + io-channels = <&adc 7>; + }; + + leds { + compatible = "gpio-leds"; + + system_fault1 { + label = "System_fault1"; + gpios = <&gpio ASPEED_GPIO(I, 3) GPIO_ACTIVE_LOW>; + }; + + system_fault2 { + label = "System_fault2"; + gpios = <&gpio ASPEED_GPIO(I, 2) GPIO_ACTIVE_LOW>; + }; + }; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "bmc"; +#include "openbmc-flash-layout.dtsi" + }; +}; + +&spi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1_default>; + flash@0 { + status = "okay"; + }; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2ck_default + &pinctrl_spi2miso_default + &pinctrl_spi2mosi_default + &pinctrl_spi2cs0_default>; +}; + +&uart3 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd3_default &pinctrl_rxd3_default>; + current-speed = <115200>; +}; + +&uart5 { + status = "okay"; +}; + +&mac0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii1_default &pinctrl_mdio1_default>; +}; + +&mac1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii2_default>; + use-ncsi; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + + tmp421@1e { + compatible = "ti,tmp421"; + reg = <0x1e>; + }; + tmp421@2a { + compatible = "ti,tmp421"; + reg = <0x2a>; + }; + tmp421@1c { + compatible = "ti,tmp421"; + reg = <0x1c>; + }; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2c6 { + status = "okay"; + + tmp421@1f { + compatible = "ti,tmp421"; + reg = <0x1f>; + }; + nvt210@4c { + compatible = "nvt210"; + reg = <0x4c>; + }; + eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + pagesize = <128>; + }; +}; + +&i2c7 { + status = "okay"; +}; + +&i2c8 { + status = "okay"; + + pca9641@70 { + compatible = "nxp,pca9641"; + reg = <0x70>; + i2c-arb { + #address-cells = <1>; + #size-cells = <0>; + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + }; + dps650ab@58 { + compatible = "dps650ab"; + reg = <0x58>; + }; + }; + }; +}; + +&i2c9 { + status = "okay"; +}; + +&vuart { + status = "okay"; +}; + +&gfx { + status = "okay"; +}; + +&pinctrl { + aspeed,external-nodes = <&gfx &lhc>; +}; + +&gpio { + pin_gpio_c7 { + gpio-hog; + gpios = <ASPEED_GPIO(C, 7) GPIO_ACTIVE_HIGH>; + output-low; + line-name = "BIOS_SPI_MUX_S"; + }; + pin_gpio_d1 { + gpio-hog; + gpios = <ASPEED_GPIO(D, 1) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "PHY2_RESET_N"; + }; +}; diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts new file mode 100644 index 000000000000..f8e7b71af7e6 --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2018 Facebook Inc. +// Author: Vijay Khemka <vijaykhemka@fb.com> +/dts-v1/; + +#include "aspeed-g5.dtsi" +#include <dt-bindings/gpio/aspeed-gpio.h> + +/ { + model = "Facebook TiogaPass BMC"; + compatible = "facebook,tiogapass-bmc", "aspeed,ast2500"; + aliases { + serial0 = &uart1; + serial4 = &uart5; + }; + chosen { + stdout-path = &uart5; + bootargs = "console=ttyS4,115200 earlyprintk"; + }; + + memory@80000000 { + reg = <0x80000000 0x20000000>; + }; +}; + +&fmc { + status = "okay"; + flash@0 { + status = "okay"; + m25p,fast-read; +#include "openbmc-flash-layout.dtsi" + }; +}; + +&spi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1_default>; + flash@0 { + status = "okay"; + m25p,fast-read; + label = "pnor"; + }; +}; + +&uart1 { + // Host Console + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default>; +}; + +&uart5 { + // BMC Console + status = "okay"; +}; + +&mac0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rmii1_default>; + use-ncsi; +}; + +&i2c0 { + status = "okay"; + //Airmax Conn B, CPU0 PIROM, CPU1 PIROM +}; + +&i2c1 { + status = "okay"; + //X24 Riser +}; + +&i2c2 { + status = "okay"; + // Mezz Management SMBus +}; + +&i2c3 { + status = "okay"; + // SMBus to Board ID EEPROM +}; + +&i2c4 { + status = "okay"; + // BMC Debug Header +}; + +&i2c5 { + status = "okay"; + // CPU Voltage regulators +}; + +&i2c6 { + status = "okay"; + tpm@20 { + compatible = "infineon,slb9645tt"; + reg = <0x20>; + }; + tmp421@4e { + compatible = "ti,tmp421"; + reg = <0x4e>; + }; + tmp421@4f { + compatible = "ti,tmp421"; + reg = <0x4f>; + }; + eeprom@54 { + compatible = "atmel,24c64"; + reg = <0x54>; + pagesize = <32>; + }; +}; + +&i2c7 { + status = "okay"; + //HSC, AirMax Conn A +}; + +&i2c8 { + status = "okay"; + //Mezz Sensor SMBus +}; + +&i2c9 { + status = "okay"; + //USB Debug Connector +}; + +&pwm_tacho { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>; + fan@0 { + reg = <0x00>; + aspeed,fan-tach-ch = /bits/ 8 <0x00>; + }; + + fan@1 { + reg = <0x00>; + aspeed,fan-tach-ch = /bits/ 8 <0x01>; + }; +}; diff --git a/arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts b/arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts index 76aa6ea1f988..385c0f4b69ee 100644 --- a/arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts +++ b/arch/arm/boot/dts/aspeed-bmc-quanta-q71l.dts @@ -7,6 +7,25 @@ model = "Quanta Q71L BMC"; compatible = "quanta,q71l-bmc", "aspeed,ast2400"; + aliases { + i2c14 = &i2c_pcie2; + i2c15 = &i2c_pcie3; + i2c16 = &i2c_pcie6; + i2c17 = &i2c_pcie7; + i2c18 = &i2c_pcie1; + i2c19 = &i2c_pcie4; + i2c20 = &i2c_pcie5; + i2c21 = &i2c_pcie8; + i2c22 = &i2c_pcie9; + i2c23 = &i2c_pcie10; + i2c24 = &i2c_ssd1; + i2c25 = &i2c_ssd2; + i2c26 = &i2c_psu4; + i2c27 = &i2c_psu1; + i2c28 = &i2c_psu3; + i2c29 = &i2c_psu2; + }; + chosen { stdout-path = &uart5; bootargs = "console=ttyS4,115200 earlyprintk"; @@ -93,6 +112,10 @@ &pinctrl_ddcclk_default &pinctrl_ddcdat_default>; }; +&ibt { + status = "okay"; +}; + &lpc_snoop { status = "okay"; snoop-ports = <0x80>; @@ -299,24 +322,44 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; + + psu@59 { + compatible = "pmbus"; + reg = <0x59>; + }; }; i2c_psu1: i2c@1 { #address-cells = <1>; #size-cells = <0>; reg = <1>; + + psu@58 { + compatible = "pmbus"; + reg = <0x58>; + }; }; i2c_psu3: i2c@2 { #address-cells = <1>; #size-cells = <0>; reg = <2>; + + psu@58 { + compatible = "pmbus"; + reg = <0x58>; + }; }; i2c_psu2: i2c@3 { #address-cells = <1>; #size-cells = <0>; reg = <3>; + + psu@59 { + compatible = "pmbus"; + reg = <0x59>; + }; }; }; @@ -345,6 +388,10 @@ status = "okay"; }; +&adc { + status = "okay"; +}; + &pwm_tacho { status = "okay"; diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index b23a983f95a5..69f6b9d2e7e7 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -350,7 +350,7 @@ status = "disabled"; }; - i2c: i2c@1e78a000 { + i2c: bus@1e78a000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index 87fdc146ff52..d107459fc0f8 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -410,7 +410,7 @@ status = "disabled"; }; - i2c: i2c@1e78a000 { + i2c: bus@1e78a000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi b/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi index bb86f17ed5ed..21876da7c442 100644 --- a/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi +++ b/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi @@ -70,9 +70,9 @@ &i2c1 { status = "okay"; - eeprom@87 { + eeprom@57 { compatible = "giantec,gt24c32a", "atmel,24c32"; - reg = <87>; + reg = <0x57>; pagesize = <32>; }; }; diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi b/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi index 4b9176dc5d02..df0f0cc575c1 100644 --- a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi +++ b/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi @@ -59,9 +59,9 @@ &i2c1 { status = "okay"; - ft5426@56 { + ft5426@38 { compatible = "focaltech,ft5426", "edt,edt-ft5406"; - reg = <56>; + reg = <0x38>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcd_ctp_int>; diff --git a/arch/arm/boot/dts/at91-nattis-2-natte-2.dts b/arch/arm/boot/dts/at91-nattis-2-natte-2.dts index af9f38456d04..911d2c7c1500 100644 --- a/arch/arm/boot/dts/at91-nattis-2-natte-2.dts +++ b/arch/arm/boot/dts/at91-nattis-2-natte-2.dts @@ -16,46 +16,6 @@ compatible = "axentia,nattis-2", "axentia,natte-2", "axentia,linea", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5"; - ahb { - apb { - pinctrl@fffff200 { - nattis { - pinctrl_usba_vbus: usba_vbus { - atmel,pins = - <AT91_PIOD 28 - AT91_PERIPH_GPIO - AT91_PINCTRL_DEGLITCH>; - }; - - pinctrl_mmc0_cd: mmc0_cd { - atmel,pins = - <AT91_PIOD 5 - AT91_PERIPH_GPIO - AT91_PINCTRL_PULL_UP_DEGLITCH>; - }; - - pinctrl_lcd_prlud0: lcd_prlud0 { - atmel,pins = - <AT91_PIOA 21 - AT91_PERIPH_GPIO - AT91_PINCTRL_OUTPUT_VAL(0)>; - }; - - pinctrl_lcd_hipow0: lcd_hipow0 { - atmel,pins = - <AT91_PIOA 23 - AT91_PERIPH_GPIO - AT91_PINCTRL_OUTPUT_VAL(0)>; - }; - }; - }; - - watchdog@fffffe40 { - status = "okay"; - }; - }; - }; - gpio-keys { compatible = "gpio-keys"; @@ -103,10 +63,29 @@ }; panel: panel { - compatible = "sharp,lq150x1lg11"; + compatible = "sharp,lq150x1lg11", "panel-lvds"; + backlight = <&panel_bl>; power-supply = <&panel_reg>; + width-mm = <304>; + height-mm = <228>; + + data-mapping = "jeida-18"; + + panel-timing { + // 1024x768 @ 60Hz (typical) + clock-frequency = <50000000 65000000 80000000>; + hactive = <1024>; + vactive = <768>; + hfront-porch = <48 88 88>; + hback-porch = <96 168 168>; + hsync-len = <32 64 64>; + vsync-len = <3 13 74>; + vfront-porch = <3 13 74>; + vback-porch = <3 12 74>; + }; + port { panel_input: endpoint { remote-endpoint = <&lvds_encoder_output>; @@ -115,7 +94,10 @@ }; lvds-encoder { - compatible = "lvds-encoder"; + compatible = "ti,ds90c185", "lvds-encoder"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lvds_prlud0 &pinctrl_lvds_hipow0>; ports { #address-cells = <1>; @@ -159,6 +141,36 @@ }; }; +&pinctrl { + nattis { + pinctrl_usba_vbus: usba_vbus { + atmel,pins = <AT91_PIOD 28 AT91_PERIPH_GPIO + AT91_PINCTRL_DEGLITCH>; + }; + + pinctrl_mmc0_cd: mmc0_cd { + atmel,pins = <AT91_PIOD 5 AT91_PERIPH_GPIO + AT91_PINCTRL_PULL_UP_DEGLITCH>; + }; + + pinctrl_lvds_prlud0: lvds_prlud0 { + atmel,pins = <AT91_PIOA 21 AT91_PERIPH_GPIO + (AT91_PINCTRL_OUTPUT | + AT91_PINCTRL_OUTPUT_VAL(0))>; + }; + + pinctrl_lvds_hipow0: lvds_hipow0 { + atmel,pins = <AT91_PIOA 23 AT91_PERIPH_GPIO + (AT91_PINCTRL_OUTPUT | + AT91_PINCTRL_OUTPUT_VAL(0))>; + }; + }; +}; + +&watchdog { + status = "okay"; +}; + &i2c0 { status = "okay"; @@ -195,14 +207,12 @@ hlcdc-display-controller { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_lcd_base - &pinctrl_lcd_rgb565 - &pinctrl_lcd_prlud0 - &pinctrl_lcd_hipow0>; + pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb565>; port@0 { hlcdc_output: endpoint { remote-endpoint = <&lvds_encoder_input>; + bus-width = <16>; }; }; }; @@ -219,6 +229,7 @@ reg = <0>; bus-width = <4>; cd-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>; + cd-inverted; }; }; diff --git a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts b/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts index e86e0c00eb6b..363a43d77424 100644 --- a/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts @@ -283,6 +283,13 @@ status = "okay"; }; + adc: adc@fc030000 { + vddana-supply = <&vddana>; + vref-supply = <&advref>; + + status = "disabled"; + }; + pinctrl@fc038000 { pinctrl_can1_default: can1_default { @@ -549,4 +556,39 @@ linux,default-trigger = "heartbeat"; }; }; + + vddin_3v3: fixed-regulator-vddin_3v3 { + compatible = "regulator-fixed"; + + regulator-name = "VDDIN_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + status = "okay"; + }; + + vddana: fixed-regulator-vddana { + compatible = "regulator-fixed"; + + regulator-name = "VDDANA"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vddin_3v3>; + status = "okay"; + }; + + advref: fixed-regulator-advref { + compatible = "regulator-fixed"; + + regulator-name = "advref"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vddana>; + status = "okay"; + }; }; diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts index 3b1baa8605a7..2214bfe7aa20 100644 --- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts +++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts @@ -92,13 +92,13 @@ reg = <0x40000 0xc0000>; }; - bootloaderenv@0x100000 { - label = "bootloader env"; + bootloaderenvred@0x100000 { + label = "bootloader env redundant"; reg = <0x100000 0x40000>; }; - bootloaderenvred@0x140000 { - label = "bootloader env redundant"; + bootloaderenv@0x140000 { + label = "bootloader env"; reg = <0x140000 0x40000>; }; diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index fcc85d70f36e..518e2b095ccf 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -281,6 +281,12 @@ status = "okay"; }; + i2s0: i2s@f8050000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s0_default>; + status = "disabled"; /* conflict with can0 */ + }; + can0: can@f8054000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can0_default>; @@ -424,6 +430,24 @@ bias-disable; }; + pinctrl_i2s0_default: i2s0_default { + pinmux = <PIN_PC1__I2SC0_CK>, + <PIN_PC2__I2SC0_MCK>, + <PIN_PC3__I2SC0_WS>, + <PIN_PC4__I2SC0_DI0>, + <PIN_PC5__I2SC0_DO0>; + bias-disable; + }; + + pinctrl_i2s1_default: i2s1_default { + pinmux = <PIN_PA15__I2SC1_CK>, + <PIN_PA14__I2SC1_MCK>, + <PIN_PA16__I2SC1_WS>, + <PIN_PA17__I2SC1_DI0>, + <PIN_PA18__I2SC1_DO0>; + bias-disable; + }; + pinctrl_key_gpio_default: key_gpio_default { pinmux = <PIN_PB9__GPIO>; bias-pull-up; @@ -546,6 +570,12 @@ status = "okay"; }; + i2s1: i2s@fc04c000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s1_default>; + status = "disabled"; /* conflict with spi0, sdmmc1 */ + }; + can1: can@fc050000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_default>; diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index 02c1d2958d78..322a744e4363 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -297,12 +297,17 @@ bootloader@40000 { label = "bootloader"; - reg = <0x40000 0x80000>; + reg = <0x40000 0xc0000>; }; - bootloaderenv@c0000 { + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x100000 0x40000>; + }; + + bootloaderenv@140000 { label = "bootloader env"; - reg = <0xc0000 0xc0000>; + reg = <0x140000 0x40000>; }; dtb@180000 { diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts index 4b7c762d5f22..43aef56ac74a 100644 --- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts @@ -232,12 +232,17 @@ bootloader@40000 { label = "bootloader"; - reg = <0x40000 0x80000>; + reg = <0x40000 0xc0000>; }; - bootloaderenv@c0000 { + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x100000 0x40000>; + }; + + bootloaderenv@140000 { label = "bootloader env"; - reg = <0xc0000 0xc0000>; + reg = <0x140000 0x40000>; }; dtb@180000 { @@ -252,7 +257,7 @@ rootfs@800000 { label = "rootfs"; - reg = <0x800000 0x0f800000>; + reg = <0x800000 0x1f800000>; }; }; }; diff --git a/arch/arm/boot/dts/at91-tse850-3.dts b/arch/arm/boot/dts/at91-tse850-3.dts index 2fbec69d9cd6..fe8876eaf917 100644 --- a/arch/arm/boot/dts/at91-tse850-3.dts +++ b/arch/arm/boot/dts/at91-tse850-3.dts @@ -16,25 +16,6 @@ compatible = "axentia,tse850v3", "axentia,linea", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5"; - ahb { - apb { - pinctrl@fffff200 { - tse850 { - pinctrl_usba_vbus: usba-vbus { - atmel,pins = - <AT91_PIOC 31 - AT91_PERIPH_GPIO - AT91_PINCTRL_DEGLITCH>; - }; - }; - }; - - watchdog@fffffe40 { - status = "okay"; - }; - }; - }; - sck: oscillator { compatible = "fixed-clock"; @@ -253,6 +234,19 @@ }; }; +&pinctrl { + tse850 { + pinctrl_usba_vbus: usba-vbus { + atmel,pins = <AT91_PIOC 31 AT91_PERIPH_GPIO + AT91_PINCTRL_DEGLITCH>; + }; + }; +}; + +&watchdog { + status = "okay"; +}; + &usart0 { status = "okay"; diff --git a/arch/arm/boot/dts/at91-vinco.dts b/arch/arm/boot/dts/at91-vinco.dts index 1be9889a2b3a..430277291e02 100644 --- a/arch/arm/boot/dts/at91-vinco.dts +++ b/arch/arm/boot/dts/at91-vinco.dts @@ -128,7 +128,7 @@ i2c2: i2c@f8024000 { status = "okay"; - rtc1: rtc@64 { + rtc1: rtc@32 { compatible = "epson,rx8900"; reg = <0x32>; }; diff --git a/arch/arm/boot/dts/at91sam9260ek.dts b/arch/arm/boot/dts/at91sam9260ek.dts index d2b865f60293..07d1b571e601 100644 --- a/arch/arm/boot/dts/at91sam9260ek.dts +++ b/arch/arm/boot/dts/at91sam9260ek.dts @@ -127,7 +127,7 @@ spi0: spi@fffc8000 { cs-gpios = <0>, <&pioC 11 0>, <0>, <0>; - mtd_dataflash@0 { + mtd_dataflash@1 { compatible = "atmel,at45", "atmel,dataflash"; spi-max-frequency = <50000000>; reg = <1>; diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts index a29fc0494076..a57f2d435dca 100644 --- a/arch/arm/boot/dts/at91sam9261ek.dts +++ b/arch/arm/boot/dts/at91sam9261ek.dts @@ -160,7 +160,7 @@ spi-max-frequency = <15000000>; }; - tsc2046@0 { + tsc2046@2 { reg = <2>; compatible = "ti,ads7843"; interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>; diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi index 71df3adfc7ca..ec1f17ab6753 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -109,7 +109,7 @@ spi0: spi@fffc8000 { cs-gpios = <0>, <&pioC 11 0>, <0>, <0>; - mtd_dataflash@0 { + mtd_dataflash@1 { compatible = "atmel,at45", "atmel,dataflash"; spi-max-frequency = <50000000>; reg = <1>; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 1ee25a475be8..d16db1fa7e15 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -570,7 +570,7 @@ }; }; - uart1 { + usart1 { pinctrl_usart1: usart1-0 { atmel,pins = <AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi index 4908ee07e628..c4cc9cc945fa 100644 --- a/arch/arm/boot/dts/at91sam9x5cm.dtsi +++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi @@ -85,12 +85,22 @@ uboot@40000 { label = "u-boot"; - reg = <0x40000 0x80000>; + reg = <0x40000 0xc0000>; }; - ubootenv@c0000 { + ubootenvred@100000 { + label = "U-Boot Env Redundant"; + reg = <0x100000 0x40000>; + }; + + ubootenv@140000 { label = "U-Boot Env"; - reg = <0xc0000 0x140000>; + reg = <0x140000 0x40000>; + }; + + dtb@180000 { + label = "device tree"; + reg = <0x180000 0x80000>; }; kernel@200000 { @@ -100,7 +110,7 @@ rootfs@800000 { label = "rootfs"; - reg = <0x800000 0x1f800000>; + reg = <0x800000 0x0f800000>; }; }; }; diff --git a/arch/arm/boot/dts/bcm-hr2.dtsi b/arch/arm/boot/dts/bcm-hr2.dtsi index 3084a7c95733..e4d49731287f 100644 --- a/arch/arm/boot/dts/bcm-hr2.dtsi +++ b/arch/arm/boot/dts/bcm-hr2.dtsi @@ -216,7 +216,7 @@ reg = <0x33000 0x14>; }; - qspi: qspi@27200 { + qspi: spi@27200 { compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi"; reg = <0x027200 0x184>, <0x027000 0x124>, diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi index 09ba85046322..2fd111d9d59c 100644 --- a/arch/arm/boot/dts/bcm-nsp.dtsi +++ b/arch/arm/boot/dts/bcm-nsp.dtsi @@ -273,7 +273,7 @@ brcm,nand-has-wp; }; - qspi: qspi@27200 { + qspi: spi@27200 { compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi"; reg = <0x027200 0x184>, <0x027000 0x124>, @@ -377,7 +377,36 @@ srab: srab@36000 { compatible = "brcm,nsp-srab"; - reg = <0x36000 0x1000>; + reg = <0x36000 0x1000>, + <0x3f308 0x8>, + <0x3f410 0xc>; + reg-names = "srab", "mux_config", "sgmii"; + interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <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>; + interrupt-names = "link_state_p0", + "link_state_p1", + "link_state_p2", + "link_state_p3", + "link_state_p4", + "link_state_p5", + "link_state_p7", + "link_state_p8", + "phy", + "ts", + "imp_sleep_timer_p5", + "imp_sleep_timer_p7", + "imp_sleep_timer_p8"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts new file mode 100644 index 000000000000..6c8233a36d86 --- /dev/null +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +#include "bcm2837-rpi-cm3.dtsi" +#include "bcm283x-rpi-usb-host.dtsi" + +/ { + compatible = "raspberrypi,3-compute-module", "brcm,bcm2837"; + model = "Raspberry Pi Compute Module 3 IO board V3.0"; +}; + +&gpio { + /* + * This is based on the official GPU firmware DT blob. + * + * Legend: + * "NC" = not connected (no rail from the SoC) + * "FOO" = GPIO line named "FOO" on the schematic + * "FOO_N" = GPIO line named "FOO" on schematic, active low + */ + gpio-line-names = "GPIO0", + "GPIO1", + "GPIO2", + "GPIO3", + "GPIO4", + "GPIO5", + "GPIO6", + "GPIO7", + "GPIO8", + "GPIO9", + "GPIO10", + "GPIO11", + "GPIO12", + "GPIO13", + "GPIO14", + "GPIO15", + "GPIO16", + "GPIO17", + "GPIO18", + "GPIO19", + "GPIO20", + "GPIO21", + "GPIO22", + "GPIO23", + "GPIO24", + "GPIO25", + "GPIO26", + "GPIO27", + "GPIO28", + "GPIO29", + "GPIO30", + "GPIO31", + "GPIO32", + "GPIO33", + "GPIO34", + "GPIO35", + "GPIO36", + "GPIO37", + "GPIO38", + "GPIO39", + "GPIO40", + "GPIO41", + "GPIO42", + "GPIO43", + "GPIO44", + "GPIO45", + "GPIO46", + "GPIO47", + /* Used by eMMC */ + "SD_CLK_R", + "SD_CMD_R", + "SD_DATA0_R", + "SD_DATA1_R", + "SD_DATA2_R", + "SD_DATA3_R"; + + pinctrl-0 = <&gpioout &alt0>; +}; + +&hdmi { + hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_gpio14>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi new file mode 100644 index 000000000000..7b7ab6aea988 --- /dev/null +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +#include "bcm2837.dtsi" +#include "bcm2835-rpi.dtsi" + +/ { + memory { + reg = <0 0x40000000>; + }; + + reg_3v3: fixed-regulator { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_1v8: fixed-regulator { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; +}; + +&firmware { + expgpio: gpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "HDMI_HPD_N", + "EMMC_EN_N", + "NC", + "NC", + "NC", + "NC", + "NC", + "NC"; + status = "okay"; + }; +}; + +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_gpio48>; + bus-width = <4>; + vmmc-supply = <®_3v3>; + vqmmc-supply = <®_1v8>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi b/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi index 9403da0990d0..70bece63f9a7 100644 --- a/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi +++ b/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi @@ -1,4 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include <dt-bindings/net/microchip-lan78xx.h> + / { aliases { ethernet0 = ðernet; @@ -21,6 +23,18 @@ ethernet: ethernet@1 { compatible = "usb424,7800"; reg = <1>; + + mdio { + #address-cells = <0x1>; + #size-cells = <0x0>; + eth_phy: ethernet-phy@1 { + reg = <1>; + microchip,led-modes = < + LAN78XX_LINK_1000_ACTIVITY + LAN78XX_LINK_10_100_ACTIVITY + >; + }; + }; }; }; }; diff --git a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts index 5f663f848db1..189cc3dcd6ef 100644 --- a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts +++ b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts @@ -94,6 +94,34 @@ &spi_nor { status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot@0 { + label = "boot"; + reg = <0x000000 0x040000>; + read-only; + }; + + os-image@100000 { + label = "os-image"; + reg = <0x040000 0x200000>; + compatible = "brcm,trx"; + }; + + rootfs@240000 { + label = "rootfs"; + reg = <0x240000 0xc00000>; + }; + + nvram@ff0000 { + label = "nvram"; + reg = <0xff0000 0x010000>; + }; + }; }; &usb2 { diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts index 2033411240c7..4cb10f88a95e 100644 --- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts @@ -66,3 +66,34 @@ &usb3_phy { status = "okay"; }; + +&nandcs { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot@0 { + label = "boot"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + nvram@80000 { + label = "nvram"; + reg = <0x00080000 0x00180000>; + }; + + firmware@200000 { + label = "firmware"; + reg = <0x00200000 0x07cc0000>; + compatible = "brcm,trx"; + }; + + asus@7ec0000 { + label = "asus"; + reg = <0x07ec0000 0x00140000>; + read-only; + }; + }; +}; diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts index c7143a9daa1a..b527d2ff987e 100644 --- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts +++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts @@ -103,6 +103,34 @@ &spi_nor { status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot@0 { + label = "boot"; + reg = <0x000000 0x040000>; + read-only; + }; + + os-image@100000 { + label = "os-image"; + reg = <0x040000 0x200000>; + compatible = "brcm,trx"; + }; + + rootfs@240000 { + label = "rootfs"; + reg = <0x240000 0xc00000>; + }; + + nvram@ff0000 { + label = "nvram"; + reg = <0xff0000 0x010000>; + }; + }; }; &usb3_phy { diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi index e5a2d62daf92..925a7c9ce5b7 100644 --- a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi +++ b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi @@ -12,6 +12,10 @@ reg = <0>; #address-cells = <1>; #size-cells = <1>; + + partitions { + compatible = "brcm,bcm947xx-cfe-partitions"; + }; }; }; }; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index bc607d11eef8..7a5c188c2676 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -475,8 +475,11 @@ compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <20000000>; - linux,part-probe = "ofpart", "bcm47xxpart"; status = "disabled"; + + partitions { + compatible = "brcm,bcm947xx-cfe-partitions"; + }; }; }; diff --git a/arch/arm/boot/dts/bcm958625hr.dts b/arch/arm/boot/dts/bcm958625hr.dts index ea3fc194f8f3..a53a2f629d74 100644 --- a/arch/arm/boot/dts/bcm958625hr.dts +++ b/arch/arm/boot/dts/bcm958625hr.dts @@ -58,6 +58,24 @@ open-source; priority = <200>; }; + + /* Hardware I2C block cannot do more than 63 bytes per transfer, + * which would prevent reading from a SFP's EEPROM (256 byte). + */ + i2c1: i2c { + compatible = "i2c-gpio"; + sda-gpios = <&gpioa 5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpioa 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + }; + + sfp: sfp { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + mod-def0-gpios = <&gpioa 28 GPIO_ACTIVE_LOW>; + los-gpios = <&gpioa 24 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&gpioa 30 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&gpioa 26 GPIO_ACTIVE_HIGH>; + }; }; &amac0 { @@ -210,6 +228,14 @@ reg = <4>; }; + port@5 { + label = "sfp"; + phy-mode = "sgmii"; + reg = <5>; + sfp = <&sfp>; + managed = "in-band-status"; + }; + port@8 { ethernet = <&amac2>; label = "cpu"; diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts index f9b757905845..a3c9b346721d 100644 --- a/arch/arm/boot/dts/da850-evm.dts +++ b/arch/arm/boot/dts/da850-evm.dts @@ -221,6 +221,12 @@ gpio-controller; #gpio-cells = <2>; }; + tca6416_bb: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + }; }; &wdt { diff --git a/arch/arm/boot/dts/da850-lego-ev3.dts b/arch/arm/boot/dts/da850-lego-ev3.dts index c4729d0e6c19..66fcadf0ba91 100644 --- a/arch/arm/boot/dts/da850-lego-ev3.dts +++ b/arch/arm/boot/dts/da850-lego-ev3.dts @@ -352,7 +352,8 @@ compatible = "ti,ads7957"; reg = <3>; #io-channel-cells = <1>; - spi-max-frequency = <10000000>; + spi-max-frequency = <1000000>; + ti,spi-wdelay = <63>; vref-supply = <&adc_ref>; }; }; diff --git a/arch/arm/boot/dts/dm8148-evm.dts b/arch/arm/boot/dts/dm8148-evm.dts index 85d7b5148b0a..2d201719ba69 100644 --- a/arch/arm/boot/dts/dm8148-evm.dts +++ b/arch/arm/boot/dts/dm8148-evm.dts @@ -27,15 +27,25 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; }; +&davinci_mdio { + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &gpmc { ranges = <0 0 0x04000000 0x01000000>; /* CS0: 16MB for NAND */ diff --git a/arch/arm/boot/dts/dm8148-t410.dts b/arch/arm/boot/dts/dm8148-t410.dts index c46a227b543d..63301bcacf19 100644 --- a/arch/arm/boot/dts/dm8148-t410.dts +++ b/arch/arm/boot/dts/dm8148-t410.dts @@ -36,15 +36,25 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; }; +&davinci_mdio { + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &mmc1 { status = "disabled"; }; diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts index 580e3cbcfbf7..3e1584e787ae 100644 --- a/arch/arm/boot/dts/dove-cubox.dts +++ b/arch/arm/boot/dts/dove-cubox.dts @@ -87,7 +87,7 @@ status = "okay"; clock-frequency = <100000>; - si5351: clock-generator { + si5351: clock-generator@60 { compatible = "silabs,si5351a-msop"; reg = <0x60>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 4a0a5115b298..250ad0535e8c 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -155,7 +155,7 @@ 0xffffe000 MBUS_ID(0x03, 0x01) 0 0x0000800 /* CESA SRAM 2k */ 0xfffff000 MBUS_ID(0x0d, 0x00) 0 0x0000800>; /* PMU SRAM 2k */ - spi0: spi-ctrl@10600 { + spi0: spi@10600 { compatible = "marvell,orion-spi"; #address-cells = <1>; #size-cells = <0>; @@ -168,7 +168,7 @@ status = "disabled"; }; - i2c: i2c-ctrl@11000 { + i2c: i2c@11000 { compatible = "marvell,mv64xxx-i2c"; reg = <0x11000 0x20>; #address-cells = <1>; @@ -218,7 +218,7 @@ status = "disabled"; }; - spi1: spi-ctrl@14600 { + spi1: spi@14600 { compatible = "marvell,orion-spi"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/dra62x-j5eco-evm.dts b/arch/arm/boot/dts/dra62x-j5eco-evm.dts index 31b824ad5d29..906aedde045d 100644 --- a/arch/arm/boot/dts/dra62x-j5eco-evm.dts +++ b/arch/arm/boot/dts/dra62x-j5eco-evm.dts @@ -27,15 +27,25 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <0>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <1>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; }; +&davinci_mdio { + ethphy0: ethernet-phy@0 { + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + }; +}; + &gpmc { ranges = <0 0 0x04000000 0x01000000>; /* CS0: 16MB for NAND */ diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 6ed5f9156270..cc079064a23b 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -512,17 +512,27 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <2>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <3>; + phy-handle = <ðphy1>; phy-mode = "rgmii"; dual_emac_res_vlan = <2>; }; +&davinci_mdio { + ethphy0: ethernet-phy@2 { + reg = <2>; + }; + + ethphy1: ethernet-phy@3 { + reg = <3>; + }; +}; + &dcan1 { status = "ok"; pinctrl-names = "default", "sleep", "active"; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index a0ddf497e8cd..7ce24b282d42 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -336,6 +336,7 @@ <0 0 0 2 &pcie1_intc 2>, <0 0 0 3 &pcie1_intc 3>, <0 0 0 4 &pcie1_intc 4>; + ti,syscon-unaligned-access = <&scm_conf1 0x14 1>; status = "disabled"; pcie1_intc: interrupt-controller { interrupt-controller; @@ -354,7 +355,7 @@ ti,hwmods = "pcie1"; phys = <&pcie1_phy>; phy-names = "pcie-phy0"; - ti,syscon-unaligned-access = <&scm_conf1 0x14 2>; + ti,syscon-unaligned-access = <&scm_conf1 0x14 1>; status = "disabled"; }; }; @@ -387,6 +388,7 @@ <0 0 0 2 &pcie2_intc 2>, <0 0 0 3 &pcie2_intc 3>, <0 0 0 4 &pcie2_intc 4>; + ti,syscon-unaligned-access = <&scm_conf1 0x14 2>; pcie2_intc: interrupt-controller { interrupt-controller; #address-cells = <0>; @@ -1369,7 +1371,7 @@ status = "disabled"; }; - qspi: qspi@4b300000 { + qspi: spi@4b300000 { compatible = "ti,dra7xxx-qspi"; reg = <0x4b300000 0x100>, <0x5c000000 0x4000000>; diff --git a/arch/arm/boot/dts/dra71-evm.dts b/arch/arm/boot/dts/dra71-evm.dts index c471bf3277b4..82cc7ec37af0 100644 --- a/arch/arm/boot/dts/dra71-evm.dts +++ b/arch/arm/boot/dts/dra71-evm.dts @@ -203,13 +203,13 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <2>; + phy-handle = <&dp83867_0>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <3>; + phy-handle = <&dp83867_1>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts index bf588d00728d..fafc2a4d7bb9 100644 --- a/arch/arm/boot/dts/dra72-evm-revc.dts +++ b/arch/arm/boot/dts/dra72-evm-revc.dts @@ -61,13 +61,13 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <2>; + phy-handle = <&dp83867_0>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <3>; + phy-handle = <&dp83867_1>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index c572693b1665..154b0a0ceb18 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -51,10 +51,16 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <3>; + phy-handle = <ðphy0>; phy-mode = "rgmii"; }; +&davinci_mdio { + ethphy0: ethernet-phy@3 { + reg = <3>; + }; +}; + &mmc1 { pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104"; pinctrl-0 = <&mmc1_pins_default>; diff --git a/arch/arm/boot/dts/dra76-evm.dts b/arch/arm/boot/dts/dra76-evm.dts index 5a46163d465f..8a57895fd8f3 100644 --- a/arch/arm/boot/dts/dra76-evm.dts +++ b/arch/arm/boot/dts/dra76-evm.dts @@ -375,13 +375,13 @@ }; &cpsw_emac0 { - phy_id = <&davinci_mdio>, <2>; + phy-handle = <&dp83867_0>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <1>; }; &cpsw_emac1 { - phy_id = <&davinci_mdio>, <3>; + phy-handle = <&dp83867_1>; phy-mode = "rgmii-id"; dual_emac_res_vlan = <2>; }; diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/exynos3250-artik5.dtsi index 620b50c19ead..7c22cbf6f3d4 100644 --- a/arch/arm/boot/dts/exynos3250-artik5.dtsi +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -69,6 +69,8 @@ compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx3>; interrupts = <5 IRQ_TYPE_NONE>; + pinctrl-names = "default"; + pinctrl-0 = <&s2mps14_irq>; reg = <0x66>; s2mps14_osc: clocks { @@ -350,6 +352,11 @@ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV3>; samsung,pin-val = <1>; }; + + s2mps14_irq: s2mps14-irq { + samsung,pins = "gpx3-5"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + }; }; &rtc { diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts index 2ab99f9f3d0a..dd9ec05eb0f7 100644 --- a/arch/arm/boot/dts/exynos4210-origen.dts +++ b/arch/arm/boot/dts/exynos4210-origen.dts @@ -151,6 +151,8 @@ reg = <0x66>; interrupt-parent = <&gpx0>; interrupts = <4 IRQ_TYPE_NONE>, <3 IRQ_TYPE_NONE>; + pinctrl-names = "default"; + pinctrl-0 = <&max8997_irq>; max8997,pmic-buck1-dvs-voltage = <1350000>; max8997,pmic-buck2-dvs-voltage = <1100000>; @@ -288,6 +290,13 @@ }; }; +&pinctrl_1 { + max8997_irq: max8997-irq { + samsung,pins = "gpx0-3", "gpx0-4"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + }; +}; + &sdhci_0 { bus-width = <4>; pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>; diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 6f1d76cb7951..f9bbc6315cd9 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -385,6 +385,12 @@ regulator-max-microvolt = <1800000>; }; + tflash_reg: LDO17 { + regulator-name = "VTF_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + vddq_reg: LDO21 { regulator-name = "VDDQ_M1M2_1.2V"; regulator-min-microvolt = <1200000>; @@ -452,6 +458,15 @@ status = "okay"; }; +&sdhci_2 { + bus-width = <4>; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>; + pinctrl-names = "default"; + vmmc-supply = <&tflash_reg>; + cd-gpios = <&gpx3 4 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + &serial_0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts index 4e6ff97e1ec4..5c3d98654f13 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -310,6 +310,9 @@ pmic@66 { compatible = "national,lp3974"; + interrupts-extended = <&gpx0 7 0>, <&gpx2 7 0>; + pinctrl-names = "default"; + pinctrl-0 = <&lp3974_irq>; reg = <0x66>; max8998,pmic-buck1-default-dvs-idx = <0>; @@ -503,6 +506,11 @@ }; &pinctrl_1 { + lp3974_irq: lp3974-irq { + samsung,pins = "gpx0-7", "gpx2-7"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + }; + hdmi_hpd: hdmi-hpd { samsung,pins = "gpx3-7"; samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; @@ -537,8 +545,7 @@ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>; pinctrl-names = "default"; vmmc-supply = <&ldo5_reg>; - cd-gpios = <&gpx3 4 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpx3 4 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos4412-midas.dtsi b/arch/arm/boot/dts/exynos4412-midas.dtsi index c0476c290977..aed2f2e2b0d1 100644 --- a/arch/arm/boot/dts/exynos4412-midas.dtsi +++ b/arch/arm/boot/dts/exynos4412-midas.dtsi @@ -1269,8 +1269,7 @@ &sdhci_2 { bus-width = <4>; - cd-gpios = <&gpx3 4 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpx3 4 GPIO_ACTIVE_LOW>; pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sdhci2_cd>; pinctrl-names = "default"; vmmc-supply = <&ldo21_reg>; diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index a09e46c9dbc0..2caa3132f34e 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -539,8 +539,7 @@ pinctrl-names = "default"; vmmc-supply = <&ldo21_reg>; vqmmc-supply = <&ldo4_reg>; - cd-gpios = <&gpk2 2 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpk2 2 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7a8a5c55701a..7d1f2dc59038 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -71,6 +71,17 @@ }; }; + panel: panel { + compatible = "boe,hv070wsa-100"; + power-supply = <&vcc_3v3_reg>; + enable-gpios = <&gpd1 3 GPIO_ACTIVE_HIGH>; + port { + panel_ep: endpoint { + remote-endpoint = <&bridge_out_ep>; + }; + }; + }; + regulators { compatible = "simple-bus"; #address-cells = <1>; @@ -97,6 +108,30 @@ reg = <2>; regulator-name = "hdmi-en"; }; + + vcc_1v2_reg: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "VCC_1V2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vcc_1v8_reg: regulator@4 { + compatible = "regulator-fixed"; + reg = <4>; + regulator-name = "VCC_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcc_3v3_reg: regulator@5 { + compatible = "regulator-fixed"; + reg = <5>; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; }; fixed-rate-clocks { @@ -119,6 +154,32 @@ cpu0-supply = <&buck2_reg>; }; +&dsi_0 { + vddcore-supply = <&ldo8_reg>; + vddio-supply = <&ldo10_reg>; + samsung,pll-clock-frequency = <24000000>; + samsung,burst-clock-frequency = <320000000>; + samsung,esc-clock-frequency = <10000000>; + status = "okay"; + + bridge@0 { + reg = <0>; + compatible = "toshiba,tc358764"; + vddc-supply = <&vcc_1v2_reg>; + vddio-supply = <&vcc_1v8_reg>; + vddlvds-supply = <&vcc_3v3_reg>; + reset-gpios = <&gpd1 6 GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <0>; + port@1 { + reg = <1>; + bridge_out_ep: endpoint { + remote-endpoint = <&panel_ep>; + }; + }; + }; +}; + &dp { status = "okay"; samsung,color-space = <0>; @@ -149,9 +210,11 @@ }; &hdmi { + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_hpd>; status = "okay"; - ddc = <&i2c_2>; - hpd-gpios = <&gpx3 7 GPIO_ACTIVE_LOW>; + ddc = <&i2c_ddc>; + hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>; vdd_osc-supply = <&ldo10_reg>; vdd_pll-supply = <&ldo8_reg>; vdd-supply = <&ldo8_reg>; @@ -168,6 +231,8 @@ reg = <0x66>; interrupt-parent = <&gpx3>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&s5m8767_irq>; vinb1-supply = <&main_dc_reg>; vinb2-supply = <&main_dc_reg>; @@ -452,13 +517,6 @@ }; }; -&i2c_2 { - status = "okay"; - /* used by HDMI DDC */ - samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <66000>; -}; - &i2c_3 { status = "okay"; @@ -535,6 +593,13 @@ cap-sd-highspeed; }; +&pinctrl_0 { + s5m8767_irq: s5m8767-irq { + samsung,pins = "gpx3-2"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + }; +}; + &rtc { status = "okay"; }; @@ -547,3 +612,22 @@ status = "okay"; samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>; }; + +&soc { + /* + * For unknown reasons HDMI-DDC does not work with Exynos I2C + * controllers. Lets use software I2C over GPIO pins as a workaround. + */ + i2c_ddc: i2c-gpio { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_gpio_bus>; + status = "okay"; + compatible = "i2c-gpio"; + gpios = <&gpa0 6 0 /* sda */ + &gpa0 7 0 /* scl */ + >; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi index 6ff6dea29d44..d31a68672bfa 100644 --- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi @@ -225,6 +225,12 @@ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>; }; + i2c2_gpio_bus: i2c2-gpio-bus { + samsung,pins = "gpa0-6", "gpa0-7"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>; + }; + uart2_data: uart2-data { samsung,pins = "gpa1-0", "gpa1-1"; samsung,pin-function = <EXYNOS_PIN_FUNC_2>; @@ -593,6 +599,11 @@ samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>; }; + + hdmi_hpd: hdmi-hpd { + samsung,pins = "gpx3-7"; + samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>; + }; }; &pinctrl_1 { diff --git a/arch/arm/boot/dts/exynos5250-snow-rev5.dts b/arch/arm/boot/dts/exynos5250-snow-rev5.dts index 0348b1c49a69..7cbfc6f1f4b8 100644 --- a/arch/arm/boot/dts/exynos5250-snow-rev5.dts +++ b/arch/arm/boot/dts/exynos5250-snow-rev5.dts @@ -20,6 +20,14 @@ samsung,model = "Snow-I2S-MAX98090"; samsung,audio-codec = <&max98090>; + + cpu { + sound-dai = <&i2s0 0>; + }; + + codec { + sound-dai = <&max98090 0>, <&hdmi>; + }; }; }; @@ -31,6 +39,9 @@ interrupt-parent = <&gpx0>; pinctrl-names = "default"; pinctrl-0 = <&max98090_irq>; + clocks = <&pmu_system_controller 0>; + clock-names = "mclk"; + #sound-dai-cells = <1>; }; }; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index da163a40af15..5044f754e6e5 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -54,62 +54,109 @@ device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <0>; - clock-frequency = <1700000000>; clocks = <&clock CLK_ARM_CLK>; clock-names = "cpu"; - clock-latency = <140000>; - - operating-points = < - 1700000 1300000 - 1600000 1250000 - 1500000 1225000 - 1400000 1200000 - 1300000 1150000 - 1200000 1125000 - 1100000 1100000 - 1000000 1075000 - 900000 1050000 - 800000 1025000 - 700000 1012500 - 600000 1000000 - 500000 975000 - 400000 950000 - 300000 937500 - 200000 925000 - >; + operating-points-v2 = <&cpu0_opp_table>; #cooling-cells = <2>; /* min followed by max */ }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <1>; - clock-frequency = <1700000000>; clocks = <&clock CLK_ARM_CLK>; clock-names = "cpu"; - clock-latency = <140000>; - - operating-points = < - 1700000 1300000 - 1600000 1250000 - 1500000 1225000 - 1400000 1200000 - 1300000 1150000 - 1200000 1125000 - 1100000 1100000 - 1000000 1075000 - 900000 1050000 - 800000 1025000 - 700000 1012500 - 600000 1000000 - 500000 975000 - 400000 950000 - 300000 937500 - 200000 925000 - >; + operating-points-v2 = <&cpu0_opp_table>; #cooling-cells = <2>; /* min followed by max */ }; }; + cpu0_opp_table: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <925000>; + clock-latency-ns = <140000>; + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <937500>; + clock-latency-ns = <140000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <950000>; + clock-latency-ns = <140000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <975000>; + clock-latency-ns = <140000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1000000>; + clock-latency-ns = <140000>; + }; + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <1012500>; + clock-latency-ns = <140000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1025000>; + clock-latency-ns = <140000>; + }; + opp-900000000 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <1050000>; + clock-latency-ns = <140000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <1075000>; + clock-latency-ns = <140000>; + opp-suspend; + }; + opp-1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <1100000>; + clock-latency-ns = <140000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1125000>; + clock-latency-ns = <140000>; + }; + opp-1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1150000>; + clock-latency-ns = <140000>; + }; + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <1200000>; + clock-latency-ns = <140000>; + }; + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <1225000>; + clock-latency-ns = <140000>; + }; + opp-1600000000 { + opp-hz = /bits/ 64 <1600000000>; + opp-microvolt = <1250000>; + clock-latency-ns = <140000>; + }; + opp-1700000000 { + opp-hz = /bits/ 64 <1700000000>; + opp-microvolt = <1300000>; + clock-latency-ns = <140000>; + }; + }; + soc: soc { sysram@2020000 { compatible = "mmio-sram"; @@ -756,6 +803,27 @@ #phy-cells = <0>; }; + mipi_phy: video-phy@10040710 { + compatible = "samsung,s5pv210-mipi-video-phy"; + reg = <0x10040710 0x100>; + #phy-cells = <1>; + syscon = <&pmu_system_controller>; + }; + + dsi_0: dsi@14500000 { + compatible = "samsung,exynos4210-mipi-dsi"; + reg = <0x14500000 0x10000>; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + samsung,power-domain = <&pd_disp1>; + phys = <&mipi_phy 3>; + phy-names = "dsim"; + clocks = <&clock CLK_DSIM0>, <&clock CLK_SCLK_MIPI1>; + clock-names = "bus_clk", "sclk_mipi"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + adc: adc@12d10000 { compatible = "samsung,exynos-adc-v1"; reg = <0x12D10000 0x100>; diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts index a2046f5f998c..434a7591ff63 100644 --- a/arch/arm/boot/dts/exynos5410-odroidxu.dts +++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts @@ -530,7 +530,7 @@ samsung,dw-mshc-sdr-timing = <0 4>; samsung,dw-mshc-ddr-timing = <0 2>; pinctrl-names = "default"; - pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4 &sd2_wp>; bus-width = <4>; cap-sd-highspeed; vmmc-supply = <&ldo21_reg>; @@ -545,6 +545,14 @@ samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>; }; + sd2_wp: sd2-wp { + samsung,pins = "gpm5-0"; + samsung,pin-function = <EXYNOS_PIN_FUNC_2>; + /* Pin is floating so be sure to disable write-protect */ + samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>; + samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV4>; + }; + pmic_dvs_3: pmic-dvs-3 { samsung,pins = "gpx0-0"; samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>; diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 57c2332bf282..f78db6809cca 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -153,7 +153,7 @@ &clock_audss { assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>; - assigned-clock-parents = <&clock CLK_FOUT_EPLL>; + assigned-clock-parents = <&clock CLK_MAU_EPLL>; }; &cpu0 { @@ -312,6 +312,7 @@ regulator-name = "vdd_1v35"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; @@ -333,6 +334,7 @@ regulator-name = "vdd_2v"; regulator-min-microvolt = <2000000>; regulator-max-microvolt = <2000000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; @@ -343,6 +345,7 @@ regulator-name = "vdd_1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi index 2f4f40882dab..2fac4baf1eb4 100644 --- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi @@ -154,6 +154,13 @@ regulator-always-on; }; + ldo2_reg: LDO2 { + regulator-name = "vdd_ldo2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + ldo3_reg: LDO3 { regulator-name = "vddq_mmc0"; regulator-min-microvolt = <1800000>; @@ -216,10 +223,10 @@ }; ldo12_reg: LDO12 { + /* Unused */ regulator-name = "vdd_ldo12"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <2375000>; }; ldo13_reg: LDO13 { @@ -228,6 +235,13 @@ regulator-max-microvolt = <2800000>; }; + ldo14_reg: LDO14 { + /* Unused */ + regulator-name = "vdd_ldo14"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + ldo15_reg: LDO15 { regulator-name = "vdd_ldo15"; regulator-min-microvolt = <3300000>; @@ -236,10 +250,10 @@ }; ldo16_reg: LDO16 { + /* Unused */ regulator-name = "vdd_ldo16"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <2200000>; - regulator-always-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; }; ldo17_reg: LDO17 { @@ -261,20 +275,139 @@ regulator-max-microvolt = <2800000>; }; - ldo24_reg: LDO24 { - regulator-name = "tsp_io"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; + ldo20_reg: LDO20 { + /* Unused */ + regulator-name = "vdd_ldo20"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo21_reg: LDO21 { + /* Unused */ + regulator-name = "vdd_ldo21"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo22_reg: LDO22 { + /* Unused */ + regulator-name = "vdd_ldo22"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <2375000>; + }; + + ldo23_reg: LDO23 { + regulator-name = "vdd_mifs"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; regulator-always-on; }; + ldo24_reg: LDO24 { + /* Unused */ + regulator-name = "vdd_ldo24"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo25_reg: LDO25 { + /* Unused */ + regulator-name = "vdd_ldo25"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + ldo26_reg: LDO26 { + /* Used on XU3, XU3-Lite and XU4 */ regulator-name = "vdd_ldo26"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo27_reg: LDO27 { + regulator-name = "vdd_g3ds"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; regulator-always-on; }; + ldo28_reg: LDO28 { + /* Used on XU3 */ + regulator-name = "vdd_ldo28"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo29_reg: LDO29 { + /* Unused */ + regulator-name = "vdd_ldo29"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo30_reg: LDO30 { + /* Unused */ + regulator-name = "vdd_ldo30"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo31_reg: LDO31 { + /* Unused */ + regulator-name = "vdd_ldo31"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo32_reg: LDO32 { + /* Unused */ + regulator-name = "vdd_ldo32"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo33_reg: LDO33 { + /* Unused */ + regulator-name = "vdd_ldo33"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo34_reg: LDO34 { + /* Unused */ + regulator-name = "vdd_ldo34"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo35_reg: LDO35 { + /* Unused */ + regulator-name = "vdd_ldo35"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <2375000>; + }; + + ldo36_reg: LDO36 { + /* Unused */ + regulator-name = "vdd_ldo36"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo37_reg: LDO37 { + /* Unused */ + regulator-name = "vdd_ldo37"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + + ldo38_reg: LDO38 { + /* Unused */ + regulator-name = "vdd_ldo38"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3950000>; + }; + buck1_reg: BUCK1 { regulator-name = "vdd_mif"; regulator-min-microvolt = <800000>; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 96e281c0a118..e522edb2bb82 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -367,6 +367,12 @@ status = "okay"; }; +&ldo26_reg { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; +}; + &mixer { status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts index 0322f281912c..db0bc17a667b 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts @@ -49,6 +49,12 @@ }; }; +&ldo28_reg { + regulator-name = "dp_p3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; + &pwm { /* * PWM 0 -- fan diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index d80ab9085da1..e0f470fe54c8 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -153,7 +153,7 @@ &clock_audss { assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>; - assigned-clock-parents = <&clock CLK_FOUT_EPLL>; + assigned-clock-parents = <&clock CLK_MAU_EPLL>; }; &cpu0 { @@ -312,6 +312,7 @@ regulator-name = "vdd_1v35"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; @@ -333,6 +334,7 @@ regulator-name = "vdd_2v"; regulator-min-microvolt = <2000000>; regulator-max-microvolt = <2000000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; @@ -343,6 +345,7 @@ regulator-name = "vdd_1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; regulator-boot-on; regulator-state-mem { regulator-on-in-suspend; diff --git a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi index e31a9e3c18a2..8d77579807ec 100644 --- a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi +++ b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi @@ -69,10 +69,6 @@ port { ceu_in: endpoint { - hsync-active = <1>; - vsync-active = <1>; - bus-width = <8>; - pclk-sample = <1>; remote-endpoint = <&mt9v111_out>; }; }; diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi index 44044f275115..0f917b272ff3 100644 --- a/arch/arm/boot/dts/hip04.dtsi +++ b/arch/arm/boot/dts/hip04.dtsi @@ -277,10 +277,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - port { - etb0_in_port: endpoint@0 { - slave-mode; - remote-endpoint = <&replicator0_out_port0>; + in-ports { + port { + etb0_in_port: endpoint@0 { + remote-endpoint = <&replicator0_out_port0>; + }; }; }; }; @@ -291,10 +292,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - port { - etb1_in_port: endpoint@0 { - slave-mode; - remote-endpoint = <&replicator1_out_port0>; + in-ports { + port { + etb1_in_port: endpoint@0 { + remote-endpoint = <&replicator1_out_port0>; + }; }; }; }; @@ -305,10 +307,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - port { - etb2_in_port: endpoint@0 { - slave-mode; - remote-endpoint = <&replicator2_out_port0>; + in-ports { + port { + etb2_in_port: endpoint@0 { + remote-endpoint = <&replicator2_out_port0>; + }; }; }; }; @@ -319,10 +322,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - port { - etb3_in_port: endpoint@0 { - slave-mode; - remote-endpoint = <&replicator3_out_port0>; + in-ports { + port { + etb3_in_port: endpoint@0 { + remote-endpoint = <&replicator3_out_port0>; + }; }; }; }; @@ -333,10 +337,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - port { - tpiu_in_port: endpoint@0 { - slave-mode; - remote-endpoint = <&funnel4_out_port0>; + in-ports { + port { + tpiu_in_port: endpoint@0 { + remote-endpoint = <&funnel4_out_port0>; + }; }; }; }; @@ -347,7 +352,7 @@ */ compatible = "arm,coresight-replicator"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -365,12 +370,11 @@ remote-endpoint = <&funnel4_in_port0>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator0_in_port0: endpoint { - slave-mode; remote-endpoint = <&funnel0_out_port0>; }; }; @@ -383,7 +387,7 @@ */ compatible = "arm,coresight-replicator"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -401,12 +405,11 @@ remote-endpoint = <&funnel4_in_port1>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator1_in_port0: endpoint { - slave-mode; remote-endpoint = <&funnel1_out_port0>; }; }; @@ -419,11 +422,10 @@ */ compatible = "arm,coresight-replicator"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; - /* replicator output ports */ port@0 { reg = <0>; replicator2_out_port0: endpoint { @@ -437,12 +439,11 @@ remote-endpoint = <&funnel4_in_port2>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator2_in_port0: endpoint { - slave-mode; remote-endpoint = <&funnel2_out_port0>; }; }; @@ -455,11 +456,10 @@ */ compatible = "arm,coresight-replicator"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; - /* replicator output ports */ port@0 { reg = <0>; replicator3_out_port0: endpoint { @@ -473,12 +473,11 @@ remote-endpoint = <&funnel4_in_port3>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator3_in_port0: endpoint { - slave-mode; remote-endpoint = <&funnel3_out_port0>; }; }; @@ -491,48 +490,43 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output port */ - port@0 { - reg = <0>; + out-ports { + port { funnel0_out_port0: endpoint { remote-endpoint = <&replicator0_in_port0>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel0_in_port0: endpoint { - slave-mode; remote-endpoint = <&ptm0_out_port>; }; }; - port@2 { + port@1 { reg = <1>; funnel0_in_port1: endpoint { - slave-mode; remote-endpoint = <&ptm1_out_port>; }; }; - port@3 { + port@2 { reg = <2>; funnel0_in_port2: endpoint { - slave-mode; remote-endpoint = <&ptm2_out_port>; }; }; - port@4 { + port@3 { reg = <3>; funnel0_in_port3: endpoint { - slave-mode; remote-endpoint = <&ptm3_out_port>; }; }; @@ -545,48 +539,43 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output port */ - port@0 { - reg = <0>; + out-ports { + port { funnel1_out_port0: endpoint { remote-endpoint = <&replicator1_in_port0>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel1_in_port0: endpoint { - slave-mode; remote-endpoint = <&ptm4_out_port>; }; }; - port@2 { + port@1 { reg = <1>; funnel1_in_port1: endpoint { - slave-mode; remote-endpoint = <&ptm5_out_port>; }; }; - port@3 { + port@2 { reg = <2>; funnel1_in_port2: endpoint { - slave-mode; remote-endpoint = <&ptm6_out_port>; }; }; - port@4 { + port@3 { reg = <3>; funnel1_in_port3: endpoint { - slave-mode; remote-endpoint = <&ptm7_out_port>; }; }; @@ -599,48 +588,43 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output port */ - port@0 { - reg = <0>; + out-ports { + port { funnel2_out_port0: endpoint { remote-endpoint = <&replicator2_in_port0>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel2_in_port0: endpoint { - slave-mode; remote-endpoint = <&ptm8_out_port>; }; }; - port@2 { + port@1 { reg = <1>; funnel2_in_port1: endpoint { - slave-mode; remote-endpoint = <&ptm9_out_port>; }; }; - port@3 { + port@2 { reg = <2>; funnel2_in_port2: endpoint { - slave-mode; remote-endpoint = <&ptm10_out_port>; }; }; - port@4 { + port@3 { reg = <3>; funnel2_in_port3: endpoint { - slave-mode; remote-endpoint = <&ptm11_out_port>; }; }; @@ -653,48 +637,43 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output port */ - port@0 { - reg = <0>; + out-ports { + port { funnel3_out_port0: endpoint { remote-endpoint = <&replicator3_in_port0>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel3_in_port0: endpoint { - slave-mode; remote-endpoint = <&ptm12_out_port>; }; }; - port@2 { + port@1 { reg = <1>; funnel3_in_port1: endpoint { - slave-mode; remote-endpoint = <&ptm13_out_port>; }; }; - port@3 { + port@2 { reg = <2>; funnel3_in_port2: endpoint { - slave-mode; remote-endpoint = <&ptm14_out_port>; }; }; - port@4 { + port@3 { reg = <3>; funnel3_in_port3: endpoint { - slave-mode; remote-endpoint = <&ptm15_out_port>; }; }; @@ -707,50 +686,45 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output port */ - port@0 { - reg = <0>; + out-ports { + port { funnel4_out_port0: endpoint { remote-endpoint = <&tpiu_in_port>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel4_in_port0: endpoint { - slave-mode; remote-endpoint = <&replicator0_out_port1>; }; }; - port@2 { + port@1 { reg = <1>; funnel4_in_port1: endpoint { - slave-mode; remote-endpoint = <&replicator1_out_port1>; }; }; - port@3 { + port@2 { reg = <2>; funnel4_in_port2: endpoint { - slave-mode; remote-endpoint = <&replicator2_out_port1>; }; }; - port@4 { + port@3 { reg = <3>; funnel4_in_port3: endpoint { - slave-mode; remote-endpoint = <&replicator3_out_port1>; }; @@ -765,9 +739,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU0>; - port { - ptm0_out_port: endpoint { - remote-endpoint = <&funnel0_in_port0>; + out-ports { + port { + ptm0_out_port: endpoint { + remote-endpoint = <&funnel0_in_port0>; + }; }; }; }; @@ -779,9 +755,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU1>; - port { - ptm1_out_port: endpoint { - remote-endpoint = <&funnel0_in_port1>; + out-ports { + port { + ptm1_out_port: endpoint { + remote-endpoint = <&funnel0_in_port1>; + }; }; }; }; @@ -793,9 +771,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU2>; - port { - ptm2_out_port: endpoint { - remote-endpoint = <&funnel0_in_port2>; + out-ports { + port { + ptm2_out_port: endpoint { + remote-endpoint = <&funnel0_in_port2>; + }; }; }; }; @@ -807,9 +787,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU3>; - port { - ptm3_out_port: endpoint { - remote-endpoint = <&funnel0_in_port3>; + out-ports { + port { + ptm3_out_port: endpoint { + remote-endpoint = <&funnel0_in_port3>; + }; }; }; }; @@ -821,9 +803,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU4>; - port { - ptm4_out_port: endpoint { - remote-endpoint = <&funnel1_in_port0>; + out-ports { + port { + ptm4_out_port: endpoint { + remote-endpoint = <&funnel1_in_port0>; + }; }; }; }; @@ -835,9 +819,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU5>; - port { - ptm5_out_port: endpoint { - remote-endpoint = <&funnel1_in_port1>; + out-ports { + port { + ptm5_out_port: endpoint { + remote-endpoint = <&funnel1_in_port1>; + }; }; }; }; @@ -849,9 +835,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU6>; - port { - ptm6_out_port: endpoint { - remote-endpoint = <&funnel1_in_port2>; + out-ports { + port { + ptm6_out_port: endpoint { + remote-endpoint = <&funnel1_in_port2>; + }; }; }; }; @@ -863,9 +851,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU7>; - port { - ptm7_out_port: endpoint { - remote-endpoint = <&funnel1_in_port3>; + out-ports { + port { + ptm7_out_port: endpoint { + remote-endpoint = <&funnel1_in_port3>; + }; }; }; }; @@ -877,9 +867,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU8>; - port { - ptm8_out_port: endpoint { - remote-endpoint = <&funnel2_in_port0>; + out-ports { + port { + ptm8_out_port: endpoint { + remote-endpoint = <&funnel2_in_port0>; + }; }; }; }; @@ -890,9 +882,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU9>; - port { - ptm9_out_port: endpoint { - remote-endpoint = <&funnel2_in_port1>; + out-ports { + port { + ptm9_out_port: endpoint { + remote-endpoint = <&funnel2_in_port1>; + }; }; }; }; @@ -904,9 +898,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU10>; - port { - ptm10_out_port: endpoint { - remote-endpoint = <&funnel2_in_port2>; + out-ports { + port { + ptm10_out_port: endpoint { + remote-endpoint = <&funnel2_in_port2>; + }; }; }; }; @@ -918,9 +914,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU11>; - port { - ptm11_out_port: endpoint { - remote-endpoint = <&funnel2_in_port3>; + out-ports { + port { + ptm11_out_port: endpoint { + remote-endpoint = <&funnel2_in_port3>; + }; }; }; }; @@ -932,9 +930,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU12>; - port { - ptm12_out_port: endpoint { - remote-endpoint = <&funnel3_in_port0>; + out-ports { + port { + ptm12_out_port: endpoint { + remote-endpoint = <&funnel3_in_port0>; + }; }; }; }; @@ -946,9 +946,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU13>; - port { - ptm13_out_port: endpoint { - remote-endpoint = <&funnel3_in_port1>; + out-ports { + port { + ptm13_out_port: endpoint { + remote-endpoint = <&funnel3_in_port1>; + }; }; }; }; @@ -960,9 +962,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU14>; - port { - ptm14_out_port: endpoint { - remote-endpoint = <&funnel3_in_port2>; + out-ports { + port { + ptm14_out_port: endpoint { + remote-endpoint = <&funnel3_in_port2>; + }; }; }; }; @@ -974,9 +978,11 @@ clocks = <&clk_375m>; clock-names = "apb_pclk"; cpu = <&CPU15>; - port { - ptm15_out_port: endpoint { - remote-endpoint = <&funnel3_in_port3>; + out-ports { + port { + ptm15_out_port: endpoint { + remote-endpoint = <&funnel3_in_port3>; + }; }; }; }; diff --git a/arch/arm/boot/dts/imx1.dtsi b/arch/arm/boot/dts/imx1.dtsi index 3edc7b5550d8..b00ece16b853 100644 --- a/arch/arm/boot/dts/imx1.dtsi +++ b/arch/arm/boot/dts/imx1.dtsi @@ -164,7 +164,7 @@ reg = <0x00210000 0x10000>; ranges; - cspi1: cspi@213000 { + cspi1: spi@213000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx1-cspi"; @@ -186,7 +186,7 @@ status = "disabled"; }; - cspi2: cspi@219000 { + cspi2: spi@219000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx1-cspi"; diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts index ad2ae25b7b4d..98efe1aeb26a 100644 --- a/arch/arm/boot/dts/imx23-evk.dts +++ b/arch/arm/boot/dts/imx23-evk.dts @@ -58,7 +58,7 @@ status = "okay"; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts index e9351774c619..31b1e3581ac0 100644 --- a/arch/arm/boot/dts/imx23-olinuxino.dts +++ b/arch/arm/boot/dts/imx23-olinuxino.dts @@ -25,7 +25,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; @@ -59,7 +59,7 @@ }; }; - ssp1: ssp@80034000 { + ssp1: spi@80034000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx23-spi"; diff --git a/arch/arm/boot/dts/imx23-sansa.dts b/arch/arm/boot/dts/imx23-sansa.dts index 67de7863ad79..faf701b2adb2 100644 --- a/arch/arm/boot/dts/imx23-sansa.dts +++ b/arch/arm/boot/dts/imx23-sansa.dts @@ -55,7 +55,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; @@ -65,7 +65,7 @@ status = "okay"; }; - ssp1: ssp@80034000 { + ssp1: spi@80034000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc1_8bit_pins_a>; diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts index 95c7b918f6d6..2ff6cdf71a55 100644 --- a/arch/arm/boot/dts/imx23-stmp378x_devb.dts +++ b/arch/arm/boot/dts/imx23-stmp378x_devb.dts @@ -22,7 +22,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; diff --git a/arch/arm/boot/dts/imx23-xfi3.dts b/arch/arm/boot/dts/imx23-xfi3.dts index 9616e500b996..db53089fb7fb 100644 --- a/arch/arm/boot/dts/imx23-xfi3.dts +++ b/arch/arm/boot/dts/imx23-xfi3.dts @@ -54,7 +54,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; @@ -64,7 +64,7 @@ status = "okay"; }; - ssp1: ssp@80034000 { + ssp1: spi@80034000 { compatible = "fsl,imx23-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc1_4bit_pins_a>; diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index 71bfd2b15609..ea259927eef6 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -93,7 +93,7 @@ status = "disabled"; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { reg = <0x80010000 0x2000>; interrupts = <15>; clocks = <&clks 33>; @@ -457,7 +457,7 @@ status = "disabled"; }; - ssp1: ssp@80034000 { + ssp1: spi@80034000 { reg = <0x80034000 0x2000>; interrupts = <2>; clocks = <&clks 33>; diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi index 85c15ee63272..b25309d26ea5 100644 --- a/arch/arm/boot/dts/imx25.dtsi +++ b/arch/arm/boot/dts/imx25.dtsi @@ -168,7 +168,7 @@ status = "disabled"; }; - spi1: cspi@43fa4000 { + spi1: spi@43fa4000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx25-cspi", "fsl,imx35-cspi"; @@ -209,7 +209,7 @@ reg = <0x50000000 0x40000>; ranges; - spi3: cspi@50004000 { + spi3: spi@50004000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx25-cspi", "fsl,imx35-cspi"; @@ -238,7 +238,7 @@ status = "disabled"; }; - spi2: cspi@50010000 { + spi2: spi@50010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx25-cspi", "fsl,imx35-cspi"; diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 753d88df1627..151b0eb17dda 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -209,7 +209,7 @@ status = "disabled"; }; - cspi1: cspi@1000e000 { + cspi1: spi@1000e000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx27-cspi"; @@ -221,7 +221,7 @@ status = "disabled"; }; - cspi2: cspi@1000f000 { + cspi2: spi@1000f000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx27-cspi"; @@ -373,7 +373,7 @@ status = "disabled"; }; - cspi3: cspi@10017000 { + cspi3: spi@10017000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx27-cspi"; diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts index c4fadbc1b400..8df5ec470376 100644 --- a/arch/arm/boot/dts/imx28-apf28dev.dts +++ b/arch/arm/boot/dts/imx28-apf28dev.dts @@ -18,7 +18,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a @@ -27,7 +27,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-spi"; pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts index 96faa53ba44c..6c9b498305c0 100644 --- a/arch/arm/boot/dts/imx28-apx4devkit.dts +++ b/arch/arm/boot/dts/imx28-apx4devkit.dts @@ -18,7 +18,7 @@ status = "okay"; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_sck_cfg>; @@ -26,7 +26,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc2_4bit_pins_apx4 &mmc2_sck_cfg_apx4>; diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts index e54f5aba7091..8337ca21e281 100644 --- a/arch/arm/boot/dts/imx28-cfa10036.dts +++ b/arch/arm/boot/dts/imx28-cfa10036.dts @@ -66,7 +66,7 @@ }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a diff --git a/arch/arm/boot/dts/imx28-duckbill-2-485.dts b/arch/arm/boot/dts/imx28-duckbill-2-485.dts index 97084e463d7c..f4f2b3d16c8e 100644 --- a/arch/arm/boot/dts/imx28-duckbill-2-485.dts +++ b/arch/arm/boot/dts/imx28-duckbill-2-485.dts @@ -25,7 +25,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -36,7 +36,7 @@ non-removable; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc2_4bit_pins_b diff --git a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts b/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts index 22215337f72a..71d0fcbc2d8c 100644 --- a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts +++ b/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts @@ -26,7 +26,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -37,7 +37,7 @@ non-removable; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc2_4bit_pins_b diff --git a/arch/arm/boot/dts/imx28-duckbill-2-spi.dts b/arch/arm/boot/dts/imx28-duckbill-2-spi.dts index 13e7b134da9e..6580ec6e26ba 100644 --- a/arch/arm/boot/dts/imx28-duckbill-2-spi.dts +++ b/arch/arm/boot/dts/imx28-duckbill-2-spi.dts @@ -29,7 +29,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -40,7 +40,7 @@ non-removable; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-spi"; pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; diff --git a/arch/arm/boot/dts/imx28-duckbill-2.dts b/arch/arm/boot/dts/imx28-duckbill-2.dts index 88556c93b00f..693634edae99 100644 --- a/arch/arm/boot/dts/imx28-duckbill-2.dts +++ b/arch/arm/boot/dts/imx28-duckbill-2.dts @@ -25,7 +25,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -36,7 +36,7 @@ non-removable; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc2_4bit_pins_b diff --git a/arch/arm/boot/dts/imx28-duckbill.dts b/arch/arm/boot/dts/imx28-duckbill.dts index f286bfe699be..16f524428ed7 100644 --- a/arch/arm/boot/dts/imx28-duckbill.dts +++ b/arch/arm/boot/dts/imx28-duckbill.dts @@ -24,7 +24,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a @@ -34,7 +34,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-spi"; pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 93ab5bdfe068..5778300f44e8 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -103,7 +103,7 @@ status = "okay"; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -114,13 +114,13 @@ status = "okay"; }; - ssp1: ssp@80012000 { + ssp1: spi@80012000 { compatible = "fsl,imx28-mmc"; bus-width = <8>; wp-gpios = <&gpio0 28 0>; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-spi"; diff --git a/arch/arm/boot/dts/imx28-m28cu3.dts b/arch/arm/boot/dts/imx28-m28cu3.dts index 3bb5ffc644d6..8883d36a51b5 100644 --- a/arch/arm/boot/dts/imx28-m28cu3.dts +++ b/arch/arm/boot/dts/imx28-m28cu3.dts @@ -41,7 +41,7 @@ }; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a @@ -52,7 +52,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc2_4bit_pins_a diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts index 7d97a0ce74a3..893886d17b2d 100644 --- a/arch/arm/boot/dts/imx28-m28evk.dts +++ b/arch/arm/boot/dts/imx28-m28evk.dts @@ -18,7 +18,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_8bit_pins_a @@ -30,7 +30,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-spi"; diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts index 2393e83979e0..ea9212f6ecda 100644 --- a/arch/arm/boot/dts/imx28-sps1.dts +++ b/arch/arm/boot/dts/imx28-sps1.dts @@ -40,7 +40,7 @@ }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a>; @@ -48,7 +48,7 @@ status = "okay"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx28-spi"; diff --git a/arch/arm/boot/dts/imx28-ts4600.dts b/arch/arm/boot/dts/imx28-ts4600.dts index f8a09a8c2c36..dccdd6bcd0b2 100644 --- a/arch/arm/boot/dts/imx28-ts4600.dts +++ b/arch/arm/boot/dts/imx28-ts4600.dts @@ -25,7 +25,7 @@ apb@80000000 { apbh@80000000 { - ssp0: ssp@80010000 { + ssp0: spi@80010000 { compatible = "fsl,imx28-mmc"; pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 5107fdc482ea..2b7efb659fc0 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -117,7 +117,7 @@ status = "disabled"; }; - ssp0: ssp@80010000 { + ssp0: spi@80010000 { #address-cells = <1>; #size-cells = <0>; reg = <0x80010000 0x2000>; @@ -128,7 +128,7 @@ status = "disabled"; }; - ssp1: ssp@80012000 { + ssp1: spi@80012000 { #address-cells = <1>; #size-cells = <0>; reg = <0x80012000 0x2000>; @@ -139,7 +139,7 @@ status = "disabled"; }; - ssp2: ssp@80014000 { + ssp2: spi@80014000 { #address-cells = <1>; #size-cells = <0>; reg = <0x80014000 0x2000>; @@ -150,7 +150,7 @@ status = "disabled"; }; - ssp3: ssp@80016000 { + ssp3: spi@80016000 { #address-cells = <1>; #size-cells = <0>; reg = <0x80016000 0x2000>; diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi index ca1419ca303c..af7afccf5f2f 100644 --- a/arch/arm/boot/dts/imx31.dtsi +++ b/arch/arm/boot/dts/imx31.dtsi @@ -206,7 +206,7 @@ status = "disabled"; }; - spi2: cspi@50010000 { + spi2: spi@50010000 { compatible = "fsl,imx31-cspi"; reg = <0x50010000 0x4000>; interrupts = <13>; @@ -241,7 +241,7 @@ #clock-cells = <1>; }; - spi3: cspi@53f84000 { + spi3: spi@53f84000 { compatible = "fsl,imx31-cspi"; reg = <0x53f84000 0x4000>; interrupts = <17>; diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi index 1c50b785cad4..a1c3d28e8771 100644 --- a/arch/arm/boot/dts/imx35.dtsi +++ b/arch/arm/boot/dts/imx35.dtsi @@ -133,7 +133,7 @@ status = "disabled"; }; - spi1: cspi@43fa4000 { + spi1: spi@43fa4000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx35-cspi"; @@ -174,7 +174,7 @@ status = "disabled"; }; - spi2: cspi@50010000 { + spi2: spi@50010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx35-cspi"; diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi index 7fae2ffb76fe..95b7fba58300 100644 --- a/arch/arm/boot/dts/imx50.dtsi +++ b/arch/arm/boot/dts/imx50.dtsi @@ -140,7 +140,7 @@ status = "disabled"; }; - ecspi1: ecspi@50010000 { + ecspi1: spi@50010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi"; @@ -403,7 +403,7 @@ status = "disabled"; }; - ecspi2: ecspi@63fac000 { + ecspi2: spi@63fac000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi"; @@ -426,7 +426,7 @@ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx50.bin"; }; - cspi: cspi@63fc0000 { + cspi: spi@63fc0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx50-cspi", "fsl,imx35-cspi"; diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts index ba60b0cb3cc1..35ee1b4247c3 100644 --- a/arch/arm/boot/dts/imx51-babbage.dts +++ b/arch/arm/boot/dts/imx51-babbage.dts @@ -204,6 +204,7 @@ reg = <0>; interrupt-parent = <&gpio1>; interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + fsl,mc13xxx-uses-adc; fsl,mc13xxx-uses-rtc; regulators { diff --git a/arch/arm/boot/dts/imx51-zii-rdu1.dts b/arch/arm/boot/dts/imx51-zii-rdu1.dts index 469cce2c0357..e45a15ceb94b 100644 --- a/arch/arm/boot/dts/imx51-zii-rdu1.dts +++ b/arch/arm/boot/dts/imx51-zii-rdu1.dts @@ -508,7 +508,7 @@ }; ds1341: rtc@68 { - compatible = "maxim,ds1341"; + compatible = "dallas,ds1341"; reg = <0x68>; }; diff --git a/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts b/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts index 26cf08549df4..243d1c8cab0a 100644 --- a/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts +++ b/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts @@ -342,6 +342,14 @@ vcc-supply = <&vusb2_reg>; }; +&vpu { + status = "disabled"; +}; + +&wdog1 { + status = "disabled"; +}; + &iomuxc { pinctrl_ecspi1: ecspi1grp { fsl,pins = < diff --git a/arch/arm/boot/dts/imx51-zii-scu3-esb.dts b/arch/arm/boot/dts/imx51-zii-scu3-esb.dts index e6ebac8f43e4..14b207778114 100644 --- a/arch/arm/boot/dts/imx51-zii-scu3-esb.dts +++ b/arch/arm/boot/dts/imx51-zii-scu3-esb.dts @@ -350,6 +350,10 @@ vcc-supply = <&vusb2_reg>; }; +&vpu { + status = "disabled"; +}; + &wdog1 { status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 5c4ba91e43ba..67d462715048 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -197,7 +197,7 @@ status = "disabled"; }; - ecspi1: ecspi@70010000 { + ecspi1: spi@70010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx51-ecspi"; @@ -464,7 +464,7 @@ status = "disabled"; }; - ecspi2: ecspi@83fac000 { + ecspi2: spi@83fac000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx51-ecspi"; @@ -487,7 +487,7 @@ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin"; }; - cspi: cspi@83fc0000 { + cspi: spi@83fc0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx51-cspi", "fsl,imx35-cspi"; @@ -608,7 +608,7 @@ status = "disabled"; }; - vpu@83ff4000 { + vpu: vpu@83ff4000 { compatible = "fsl,imx51-vpu", "cnm,codahx4"; reg = <0x83ff4000 0x1000>; interrupts = <9>; diff --git a/arch/arm/boot/dts/imx53-ppd.dts b/arch/arm/boot/dts/imx53-ppd.dts index cdb90bee7b4a..b560ff88459b 100644 --- a/arch/arm/boot/dts/imx53-ppd.dts +++ b/arch/arm/boot/dts/imx53-ppd.dts @@ -319,7 +319,6 @@ &ecspi2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; - num-chipselects = <1>; cs-gpios = <&gpio2 26 GPIO_ACTIVE_LOW>; status = "okay"; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index 6386185ae234..207eb557c90e 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -259,7 +259,7 @@ status = "disabled"; }; - ecspi1: ecspi@50010000 { + ecspi1: spi@50010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi"; @@ -684,7 +684,7 @@ status = "disabled"; }; - ecspi2: ecspi@63fac000 { + ecspi2: spi@63fac000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi"; @@ -707,7 +707,7 @@ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin"; }; - cspi: cspi@63fc0000 { + cspi: spi@63fc0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx53-cspi", "fsl,imx35-cspi"; diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts index 9de45a717356..d08e0402793b 100644 --- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts @@ -146,7 +146,7 @@ &ecspi4 { status = "okay"; - mcp251x0: mcp251x@1 { + mcp251x0: mcp251x@0 { compatible = "microchip,mcp2515"; reg = <0>; clocks = <&clk16m>; diff --git a/arch/arm/boot/dts/imx6dl-icore-mipi.dts b/arch/arm/boot/dts/imx6dl-icore-mipi.dts index bf53f0552aa1..e43bccb78ab2 100644 --- a/arch/arm/boot/dts/imx6dl-icore-mipi.dts +++ b/arch/arm/boot/dts/imx6dl-icore-mipi.dts @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2018 Engicam S.r.l. * Copyright (C) 2018 Amarula Solutions B.V. diff --git a/arch/arm/boot/dts/imx6dl-icore-rqs.dts b/arch/arm/boot/dts/imx6dl-icore-rqs.dts index 1281bc39b7ab..73d710d34b9d 100644 --- a/arch/arm/boot/dts/imx6dl-icore-rqs.dts +++ b/arch/arm/boot/dts/imx6dl-icore-rqs.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6dl-icore.dts b/arch/arm/boot/dts/imx6dl-icore.dts index 971f9fc39c66..80fa60607ab1 100644 --- a/arch/arm/boot/dts/imx6dl-icore.dts +++ b/arch/arm/boot/dts/imx6dl-icore.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts index dd3226fe5ecd..8e51491e68cf 100644 --- a/arch/arm/boot/dts/imx6dl-riotboard.dts +++ b/arch/arm/boot/dts/imx6dl-riotboard.dts @@ -84,6 +84,10 @@ status = "okay"; }; +&clks { + fsl,pmic-stby-poweroff; +}; + &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; @@ -164,6 +168,7 @@ reg = <0x08>; interrupt-parent = <&gpio5>; interrupts = <16 8>; + fsl,pmic-stby-poweroff; regulators { reg_vddcore: sw1ab { /* VDDARM_IN */ diff --git a/arch/arm/boot/dts/imx6q-apalis-eval.dts b/arch/arm/boot/dts/imx6q-apalis-eval.dts index 707ac9a46115..0edd3043d9c1 100644 --- a/arch/arm/boot/dts/imx6q-apalis-eval.dts +++ b/arch/arm/boot/dts/imx6q-apalis-eval.dts @@ -196,6 +196,8 @@ }; &pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reset_moci>; /* active-high meaning opposite of regular PERST# active-low polarity */ reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; reset-gpio-active-high; diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts index 4e1c8feaef82..b94bb687be6b 100644 --- a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts +++ b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts @@ -196,6 +196,8 @@ }; &pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reset_moci>; /* active-high meaning opposite of regular PERST# active-low polarity */ reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; reset-gpio-active-high; diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts index 469e3d0e2827..302fd6adc8a7 100644 --- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts +++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts @@ -200,6 +200,8 @@ }; &pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reset_moci>; /* active-high meaning opposite of regular PERST# active-low polarity */ reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; reset-gpio-active-high; diff --git a/arch/arm/boot/dts/imx6q-icore-mipi.dts b/arch/arm/boot/dts/imx6q-icore-mipi.dts index 95b2efda17b4..d51745268dbf 100644 --- a/arch/arm/boot/dts/imx6q-icore-mipi.dts +++ b/arch/arm/boot/dts/imx6q-icore-mipi.dts @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2017 Engicam S.r.l. * Copyright (C) 2017 Amarula Solutions B.V. @@ -8,10 +8,10 @@ /dts-v1/; #include "imx6q.dtsi" -#include "imx6qdl-icore.dtsi" +#include "imx6qdl-icore-1.5.dtsi" / { - model = "Engicam i.CoreM6 Quad/Dual MIPI Starter Kit"; + model = "Engicam i.CoreM6 1.5 Quad/Dual MIPI Starter Kit"; compatible = "engicam,imx6-icore", "fsl,imx6q"; }; diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts b/arch/arm/boot/dts/imx6q-icore-ofcap10.dts index 49b60ca20e6d..81cc346dd149 100644 --- a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts +++ b/arch/arm/boot/dts/imx6q-icore-ofcap10.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts index 6e27c8143f82..241811c52b62 100644 --- a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts +++ b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-icore-rqs.dts b/arch/arm/boot/dts/imx6q-icore-rqs.dts index b81f48c6a8c6..cf6ba724f497 100644 --- a/arch/arm/boot/dts/imx6q-icore-rqs.dts +++ b/arch/arm/boot/dts/imx6q-icore-rqs.dts @@ -1,42 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2015 Amarula Solutions B.V. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright (C) 2015 Engicam S.r.l. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q-icore.dts b/arch/arm/boot/dts/imx6q-icore.dts index 5613dd9dc469..fe28c3cf54c0 100644 --- a/arch/arm/boot/dts/imx6q-icore.dts +++ b/arch/arm/boot/dts/imx6q-icore.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 0193ee6fe964..8381d24eff7d 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -163,7 +163,7 @@ aips-bus@2000000 { /* AIPS1 */ spba-bus@2000000 { - ecspi5: ecspi@2018000 { + ecspi5: spi@2018000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi index 05f07ea3e8c8..3dc99dd8dde1 100644 --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi @@ -482,10 +482,6 @@ }; &iomuxc { - /* pins used on module */ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reset_moci>; - pinctrl_apalis_gpio1: gpio2io04grp { fsl,pins = < MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x130b0 diff --git a/arch/arm/boot/dts/imx6qdl-icore-1.5.dtsi b/arch/arm/boot/dts/imx6qdl-icore-1.5.dtsi new file mode 100644 index 000000000000..d91d46b5898f --- /dev/null +++ b/arch/arm/boot/dts/imx6qdl-icore-1.5.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Jacopo Mondi <jacopo@jmondi.org> + */ + +#include "imx6qdl-icore.dtsi" + +&iomuxc { + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0 + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0b0 + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0 + >; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>; + clocks = <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET_REF>; + phy-mode = "rmii"; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi index acc3b11fba2a..ba93026ecee8 100644 --- a/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi +++ b/arch/arm/boot/dts/imx6qdl-icore-rqs.dtsi @@ -1,42 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2015 Amarula Solutions B.V. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * Copyright (C) 2015 Engicam S.r.l. */ #include <dt-bindings/gpio/gpio.h> @@ -316,7 +281,7 @@ }; &iomuxc { - pinctrl_audmux: audmux { + pinctrl_audmux: audmuxgrp { fsl,pins = < MX6QDL_PAD_DISP0_DAT20__AUD4_TXC 0x130b0 MX6QDL_PAD_DISP0_DAT21__AUD4_TXD 0x110b0 diff --git a/arch/arm/boot/dts/imx6qdl-icore.dtsi b/arch/arm/boot/dts/imx6qdl-icore.dtsi index 9ce993776160..84d03c65f4c8 100644 --- a/arch/arm/boot/dts/imx6qdl-icore.dtsi +++ b/arch/arm/boot/dts/imx6qdl-icore.dtsi @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ #include <dt-bindings/gpio/gpio.h> @@ -310,7 +274,7 @@ }; &iomuxc { - pinctrl_audmux: audmux { + pinctrl_audmux: audmuxgrp { fsl,pins = < MX6QDL_PAD_DISP0_DAT20__AUD4_TXC 0x130b0 MX6QDL_PAD_DISP0_DAT21__AUD4_TXD 0x110b0 @@ -349,7 +313,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/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi index 9f11f1fcc3e6..a6dc5c42c632 100644 --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi @@ -4,6 +4,7 @@ // Copyright 2011 Linaro Ltd. #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> / { chosen { @@ -25,6 +26,47 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_keys>; + + home { + label = "Home"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + linux,code = <KEY_HOME>; + wakeup-source; + }; + + back { + label = "Back"; + gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + linux,code = <KEY_BACK>; + wakeup-source; + }; + + program { + label = "Program"; + gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + linux,code = <KEY_PROGRAM>; + wakeup-source; + }; + + volume-up { + label = "Volume Up"; + gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEUP>; + wakeup-source; + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio5 14 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEDOWN>; + wakeup-source; + }; + }; + clocks { codec_osc: anaclk2 { compatible = "fixed-clock"; @@ -375,6 +417,15 @@ VLC-supply = <®_audio>; }; + touchscreen@4 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_egalax_int>; + interrupt-parent = <&gpio2>; + interrupts = <28 IRQ_TYPE_EDGE_FALLING>; + wakeup-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; + }; }; &i2c3 { @@ -410,6 +461,12 @@ >; }; + pinctrl_egalax_int: egalax-intgrp { + fsl,pins = < + MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0xb0b1 + >; + }; + pinctrl_enet: enetgrp { fsl,pins = < MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0 @@ -446,6 +503,16 @@ >; }; + pinctrl_gpio_keys: gpiokeysgrp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0 + MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0 + MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0 + MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 + MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b0 + >; + }; + pinctrl_gpio_leds: gpioledsgrp { fsl,pins = < MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000 diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi index 381bf61fcd28..b7d5fb421404 100644 --- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi @@ -8,6 +8,10 @@ #include <dt-bindings/gpio/gpio.h> / { + chosen { + stdout-path = &uart1; + }; + sound { compatible = "fsl,imx6-wandboard-sgtl5000", "fsl,imx-audio-sgtl5000"; diff --git a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi index 7fff3717cf7c..85e79a33bcd4 100644 --- a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi +++ b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi @@ -813,6 +813,10 @@ status = "okay"; }; +&snvs_rtc { + status = "disabled"; +}; + &ssi1 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 61d2d26afbf4..e4daf150881a 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -317,7 +317,7 @@ status = "disabled"; }; - ecspi1: ecspi@2008000 { + ecspi1: spi@2008000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; @@ -331,7 +331,7 @@ status = "disabled"; }; - ecspi2: ecspi@200c000 { + ecspi2: spi@200c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; @@ -345,7 +345,7 @@ status = "disabled"; }; - ecspi3: ecspi@2010000 { + ecspi3: spi@2010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; @@ -359,7 +359,7 @@ status = "disabled"; }; - ecspi4: ecspi@2014000 { + ecspi4: spi@2014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 7a4f5dace902..7a3ae7160c12 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -168,7 +168,7 @@ status = "disabled"; }; - ecspi1: ecspi@2008000 { + ecspi1: spi@2008000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; @@ -180,7 +180,7 @@ status = "disabled"; }; - ecspi2: ecspi@200c000 { + ecspi2: spi@200c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; @@ -192,7 +192,7 @@ status = "disabled"; }; - ecspi3: ecspi@2010000 { + ecspi3: spi@2010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; @@ -204,7 +204,7 @@ status = "disabled"; }; - ecspi4: ecspi@2014000 { + ecspi4: spi@2014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index 000e6136a9d6..ed9a980bce85 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -375,10 +375,12 @@ reg = <0x0209c000 0x4000>; interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO1>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 94 7>, <&iomuxc 7 25 25>; }; gpio2: gpio@20a0000 { @@ -386,10 +388,12 @@ reg = <0x020a0000 0x4000>; interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO2>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 50 32>; }; gpio3: gpio@20a4000 { @@ -397,10 +401,14 @@ reg = <0x020a4000 0x4000>; interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO3>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 82 12>, <&iomuxc 12 103 4>, + <&iomuxc 16 101 2>, <&iomuxc 18 5 1>, + <&iomuxc 21 6 11>; }; gpio4: gpio@20a8000 { @@ -408,10 +416,20 @@ reg = <0x020a8000 0x4000>; interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO4>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 17 8>, <&iomuxc 8 107 8>, + <&iomuxc 16 151 1>, <&iomuxc 17 149 1>, + <&iomuxc 18 146 1>, <&iomuxc 19 144 1>, + <&iomuxc 20 142 1>, <&iomuxc 21 143 1>, + <&iomuxc 22 150 1>, <&iomuxc 23 148 1>, + <&iomuxc 24 147 1>, <&iomuxc 25 145 1>, + <&iomuxc 26 152 1>, <&iomuxc 27 125 1>, + <&iomuxc 28 131 1>, <&iomuxc 29 134 1>, + <&iomuxc 30 129 1>, <&iomuxc 31 133 1>; }; gpio5: gpio@20ac000 { @@ -419,10 +437,22 @@ reg = <0x020ac000 0x4000>; interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO5>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; + gpio-ranges = <&iomuxc 0 135 1>, <&iomuxc 1 128 1>, + <&iomuxc 2 132 1>, <&iomuxc 3 130 1>, + <&iomuxc 4 127 1>, <&iomuxc 5 126 1>, + <&iomuxc 6 120 1>, <&iomuxc 7 123 1>, + <&iomuxc 8 118 1>, <&iomuxc 9 122 1>, + <&iomuxc 10 124 1>, <&iomuxc 11 117 1>, + <&iomuxc 12 121 1>, <&iomuxc 13 119 1>, + <&iomuxc 14 116 1>, <&iomuxc 15 115 1>, + <&iomuxc 16 140 2>, <&iomuxc 18 136 1>, + <&iomuxc 19 138 1>, <&iomuxc 20 139 1>, + <&iomuxc 21 137 1>; }; gpio6: gpio@20b0000 { @@ -430,6 +460,7 @@ reg = <0x020b0000 0x4000>; interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SLL_CLK_GPIO6>; gpio-controller; #gpio-cells = <2>; interrupt-controller; diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi index f8f31872fa14..53b3408b5fab 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dtsi +++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi @@ -40,12 +40,14 @@ label = "Volume Up"; gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEUP>; + wakeup-source; }; volume-down { label = "Volume Down"; gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEDOWN>; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 844caa39364f..95a3c1cb877d 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -268,7 +268,7 @@ status = "disabled"; }; - ecspi1: ecspi@2008000 { + ecspi1: spi@2008000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; @@ -280,7 +280,7 @@ status = "disabled"; }; - ecspi2: ecspi@200c000 { + ecspi2: spi@200c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; @@ -292,7 +292,7 @@ status = "disabled"; }; - ecspi3: ecspi@2010000 { + ecspi3: spi@2010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; @@ -304,7 +304,7 @@ status = "disabled"; }; - ecspi4: ecspi@2014000 { + ecspi4: spi@2014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; @@ -1079,7 +1079,7 @@ status = "disabled"; }; - qspi1: qspi@21e0000 { + qspi1: spi@21e0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-qspi"; @@ -1092,7 +1092,7 @@ status = "disabled"; }; - qspi2: qspi@21e4000 { + qspi2: spi@21e4000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-qspi"; @@ -1273,7 +1273,7 @@ status = "disabled"; }; - ecspi5: ecspi@228c000 { + ecspi5: spi@228c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi"; diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts new file mode 100644 index 000000000000..11966d12af76 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcpro.dts @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Digi International's ConnectCore6UL SBC Pro board device tree source + * + * Copyright 2018 Digi International, Inc. + * + */ + +/dts-v1/; +#include <dt-bindings/input/input.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include "imx6ul.dtsi" +#include "imx6ul-ccimx6ulsom.dtsi" + +/ { + model = "Digi International ConnectCore 6UL SBC Pro."; + compatible = "digi,ccimx6ulsbcpro", "digi,ccimx6ulsom", "fsl,imx6ul"; + + lcd_backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm5 0 50000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + status = "okay"; + }; + + reg_usb_otg1_vbus: regulator-usb-otg1 { + compatible = "regulator-fixed"; + regulator-name = "usb_otg1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&adc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc1>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + xceiver-supply = <&ext_3v3>; + status = "okay"; +}; + +/* CAN2 is multiplexed with UART2 RTS/CTS */ +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + xceiver-supply = <&ext_3v3>; + status = "disabled"; +}; + +&ecspi1 { + cs-gpios = <&gpio3 26 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1_master>; + status = "okay"; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet1>; + phy-mode = "rmii"; + phy-handle = <ðphy0>; + status = "okay"; +}; + +&fec2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio>; + phy-mode = "rmii"; + phy-handle = <ðphy1>; + phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>; + phy-reset-duration = <26>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + smsc,disable-energy-detect; + reg = <0>; + }; + + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + smsc,disable-energy-detect; + reg = <1>; + }; + }; +}; + +&gpio5 { + emmc-usd-mux { + gpio-hog; + gpios = <1 GPIO_ACTIVE_LOW>; + output-high; + }; +}; + +&lcdif { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif_dat0_17 + &pinctrl_lcdif_clken + &pinctrl_lcdif_hvsync>; + lcd-supply = <&ldo4_ext>; /* BU90T82 LVDS bridge power */ + status = "okay"; +}; + +&ldo4_ext { + regulator-max-microvolt = <1800000>; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; +}; + +&pwm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm4>; + status = "okay"; +}; + +&pwm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm5>; + status = "okay"; +}; + +&pwm6 { + status = "okay"; +}; + +&pwm7 { + status = "okay"; +}; + +&pwm8 { + status = "okay"; +}; + +&sai2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_sai2>; + pinctrl-1 = <&pinctrl_sai2_sleep>; + assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>, + <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>, + <&clks IMX6UL_CLK_SAI2>; + assigned-clock-rates = <0>, <786432000>, <12288000>; + assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>; + status = "okay"; +}; + +/* UART2 RTS/CTS muxed with CAN2 */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2_4wires>; + uart-has-rtscts; + status = "okay"; +}; + +/* UART3 RTS/CTS muxed with CAN 1 */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_2wires>; + status = "okay"; +}; + +&uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "otg"; + vbus-supply = <®_usb_otg1_vbus>; + pinctrl-0 = <&pinctrl_usbotg1>; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + status = "okay"; +}; + +/* USDHC2 (microSD conflicts with eMMC) */ +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + no-1-8-v; + broken-cd; /* no carrier detect line (use polling) */ + status = "okay"; +}; + +&iomuxc { + pinctrl_adc1: adc1grp { + fsl,pins = < + /* EXP_GPIO_2 -> GPIO1_3/ADC1_IN3 */ + MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0 + >; + }; + + pinctrl_ecspi1_master: ecspi1grp1 { + fsl,pins = < + MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK 0x10b0 + MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI 0x10b0 + MX6UL_PAD_LCD_DATA23__ECSPI1_MISO 0x10b0 + MX6UL_PAD_LCD_DATA21__GPIO3_IO26 0x10b0 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0 + MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0 + MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0 + MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0 + MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x40017051 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0 + MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0 + MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0 + MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0 + MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x40017051 + >; + }; + + pinctrl_enet2_mdio: mdioenet2grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0 + MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0 + >; + }; + + pinctrl_flexcan1: flexcan1grp{ + fsl,pins = < + MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020 + MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020 + >; + }; + pinctrl_flexcan2: flexcan2grp{ + fsl,pins = < + MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX 0x1b020 + MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX 0x1b020 + >; + }; + + pinctrl_lcdif_dat0_17: lcdifdatgrp0-17 { + fsl,pins = < + MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79 + MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79 + MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79 + MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79 + MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79 + MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79 + MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79 + MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79 + MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79 + MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79 + MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79 + MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79 + MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79 + MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79 + MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79 + MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79 + MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79 + MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79 + >; + }; + + pinctrl_lcdif_clken: lcdifctrlgrp1 { + fsl,pins = < + MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x17050 + MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79 + >; + }; + + pinctrl_lcdif_hvsync: lcdifctrlgrp2 { + fsl,pins = < + MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79 + MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79 + >; + }; + + pinctrl_pwm4: pwm4grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO05__PWM4_OUT 0x110b0 + >; + }; + + pinctrl_pwm5: pwm5grp { + fsl,pins = < + MX6UL_PAD_NAND_DQS__PWM5_OUT 0x110b0 + >; + }; + + pinctrl_sai2: sai2grp { + fsl,pins = < + MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA 0x11088 + MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA 0x11088 + MX6UL_PAD_JTAG_TMS__SAI2_MCLK 0x17088 + MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK 0x17088 + MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC 0x17088 + /* Interrupt */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10b0 + >; + }; + + pinctrl_sai2_sleep: sai2grp-sleep { + fsl,pins = < + MX6UL_PAD_JTAG_TRST_B__GPIO1_IO15 0x3000 + MX6UL_PAD_JTAG_TCK__GPIO1_IO14 0x3000 + MX6UL_PAD_JTAG_TMS__GPIO1_IO11 0x3000 + MX6UL_PAD_JTAG_TDO__GPIO1_IO12 0x3000 + /* Interrupt */ + MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x3000 + >; + }; + + pinctrl_uart2_4wires: uart2grp-4wires { + 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 + MX6UL_PAD_UART2_RTS_B__UART2_DCE_RTS 0x1b0b1 + >; + }; + + pinctrl_uart3_2wires: uart3grp-2wires { + fsl,pins = < + MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 + MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX 0x1b0b1 + MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x1b0b1 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_CSI_HSYNC__USDHC2_CMD 0x17059 + MX6UL_PAD_CSI_VSYNC__USDHC2_CLK 0x10039 + MX6UL_PAD_CSI_DATA00__USDHC2_DATA0 0x17059 + MX6UL_PAD_CSI_DATA01__USDHC2_DATA1 0x17059 + MX6UL_PAD_CSI_DATA02__USDHC2_DATA2 0x17059 + MX6UL_PAD_CSI_DATA03__USDHC2_DATA3 0x17059 + /* Mux selector between eMMC/SD# */ + MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x79 + >; + }; + + pinctrl_usbotg1: usbotg1grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 + MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x17059 + MX6UL_PAD_GPIO1_IO01__USB_OTG1_OC 0x17059 + >; + }; +}; diff --git a/arch/arm/boot/dts/imx6ul-geam.dts b/arch/arm/boot/dts/imx6ul-geam.dts index d81d20f8fc8d..e22ec5be2b78 100644 --- a/arch/arm/boot/dts/imx6ul-geam.dts +++ b/arch/arm/boot/dts/imx6ul-geam.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; @@ -328,7 +292,7 @@ >; }; - 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/imx6ul-isiot-emmc.dts b/arch/arm/boot/dts/imx6ul-isiot-emmc.dts index f5b422898e61..1df3e376ae2c 100644 --- a/arch/arm/boot/dts/imx6ul-isiot-emmc.dts +++ b/arch/arm/boot/dts/imx6ul-isiot-emmc.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; @@ -50,28 +14,5 @@ }; &usdhc2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; - bus-width = <8>; - no-1-8-v; status = "okay"; }; - -&iomuxc { - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17070 - MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x10070 - MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17070 - MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17070 - MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17070 - MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17070 - MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17070 - MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17070 - MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17070 - MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17070 - MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x17070 - >; - }; -}; diff --git a/arch/arm/boot/dts/imx6ul-isiot-nand.dts b/arch/arm/boot/dts/imx6ul-isiot-nand.dts index de15e1c75dd1..8c26d4d1a7bf 100644 --- a/arch/arm/boot/dts/imx6ul-isiot-nand.dts +++ b/arch/arm/boot/dts/imx6ul-isiot-nand.dts @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; @@ -50,30 +14,5 @@ }; &gpmi { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpmi_nand>; - nand-on-flash-bbt; status = "okay"; }; - -&iomuxc { - pinctrl_gpmi_nand: gpmi-nand { - fsl,pins = < - MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1 - MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1 - MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1 - MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000 - MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1 - MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1 - MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1 - MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1 - MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1 - MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1 - MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1 - MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1 - MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1 - MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1 - MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1 - >; - }; -}; diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/imx6ul-isiot.dtsi index cd9928551154..b1fa3f0a684d 100644 --- a/arch/arm/boot/dts/imx6ul-isiot.dtsi +++ b/arch/arm/boot/dts/imx6ul-isiot.dtsi @@ -1,43 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 /* * Copyright (C) 2016 Amarula Solutions B.V. * Copyright (C) 2016 Engicam S.r.l. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ #include <dt-bindings/gpio/gpio.h> @@ -133,6 +97,13 @@ }; }; +&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + nand-on-flash-bbt; + status = "disabled"; +}; + &i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; @@ -243,6 +214,15 @@ status = "okay"; }; +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + cd-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; + bus-width = <8>; + no-1-8-v; + status = "disabled"; +}; + &iomuxc { pinctrl_enet1: enet1grp { fsl,pins = < @@ -259,6 +239,26 @@ >; }; + pinctrl_gpmi_nand: gpminandgrp { + fsl,pins = < + MX6UL_PAD_NAND_CLE__RAWNAND_CLE 0xb0b1 + MX6UL_PAD_NAND_ALE__RAWNAND_ALE 0xb0b1 + MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B 0xb0b1 + MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb000 + MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B 0xb0b1 + MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B 0xb0b1 + MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B 0xb0b1 + MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00 0xb0b1 + MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01 0xb0b1 + MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02 0xb0b1 + MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03 0xb0b1 + MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04 0xb0b1 + MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05 0xb0b1 + MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06 0xb0b1 + MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07 0xb0b1 + >; + }; + pinctrl_i2c1: i2c1grp { fsl,pins = < MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0 @@ -366,4 +366,20 @@ MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9 >; }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x17070 + MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x10070 + MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17070 + MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17070 + MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17070 + MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17070 + MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17070 + MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17070 + MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17070 + MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17070 + MX6UL_PAD_NAND_ALE__USDHC2_RESET_B 0x17070 + >; + }; }; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 6dc0b569acdf..083d3446c41d 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -89,6 +89,8 @@ "pll1_sys"; arm-supply = <®_arm>; soc-supply = <®_soc>; + nvmem-cells = <&cpu_speed_grade>; + nvmem-cell-names = "speed_grade"; }; }; @@ -156,7 +158,6 @@ compatible = "arm,cortex-a7-pmu"; interrupt-parent = <&gpc>; interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; }; soc { @@ -218,7 +219,7 @@ reg = <0x02000000 0x40000>; ranges; - ecspi1: ecspi@2008000 { + ecspi1: spi@2008000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi"; @@ -230,7 +231,7 @@ status = "disabled"; }; - ecspi2: ecspi@200c000 { + ecspi2: spi@200c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi"; @@ -242,7 +243,7 @@ status = "disabled"; }; - ecspi3: ecspi@2010000 { + ecspi3: spi@2010000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi"; @@ -254,7 +255,7 @@ status = "disabled"; }; - ecspi4: ecspi@2014000 { + ecspi4: spi@2014000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi"; @@ -918,6 +919,17 @@ reg = <0x021b0000 0x4000>; }; + weim: weim@21b8000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "fsl,imx6ul-weim", "fsl,imx6q-weim"; + reg = <0x021b8000 0x4000>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6UL_CLK_EIM>; + fsl,weim-cs-gpr = <&gpr>; + status = "disabled"; + }; + ocotp: ocotp-ctrl@21bc000 { #address-cells = <1>; #size-cells = <1>; @@ -932,6 +944,10 @@ tempmon_temp_grade: temp-grade@20 { reg = <0x20 4>; }; + + cpu_speed_grade: speed-grade@10 { + reg = <0x10 4>; + }; }; lcdif: lcdif@21c8000 { @@ -945,7 +961,7 @@ status = "disabled"; }; - qspi: qspi@21e0000 { + qspi: spi@21e0000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6ul-qspi", "fsl,imx6sx-qspi"; diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/imx6ull-14x14-evk.dts index 30ef60344af3..0ba64546c13b 100644 --- a/arch/arm/boot/dts/imx6ull-14x14-evk.dts +++ b/arch/arm/boot/dts/imx6ull-14x14-evk.dts @@ -45,7 +45,7 @@ #include "imx6ul-14x14-evk.dtsi" / { - model = "Freescale i.MX6 UlltraLite 14x14 EVK Board"; + model = "Freescale i.MX6 UltraLiteLite 14x14 EVK Board"; compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull"; }; diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h index fdc46bb09cc1..a282a31a4bae 100644 --- a/arch/arm/boot/dts/imx6ull-pinfunc.h +++ b/arch/arm/boot/dts/imx6ull-pinfunc.h @@ -14,14 +14,38 @@ * The pin function ID is a tuple of * <mux_reg conf_reg input_reg mux_mode input_val> */ +/* signals common for i.MX6UL and i.MX6ULL */ +#undef MX6UL_PAD_UART5_TX_DATA__UART5_DTE_RX +#define MX6UL_PAD_UART5_TX_DATA__UART5_DTE_RX 0x00BC 0x0348 0x0644 0x0 0x6 +#undef MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX +#define MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x00C0 0x034C 0x0644 0x0 0x7 +#undef MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS +#define MX6UL_PAD_ENET1_RX_EN__UART5_DCE_RTS 0x00CC 0x0358 0x0640 0x1 0x5 +#undef MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS +#define MX6UL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS 0x00D0 0x035C 0x0640 0x1 0x6 +#undef MX6UL_PAD_CSI_DATA02__UART5_DCE_RTS +#define MX6UL_PAD_CSI_DATA02__UART5_DCE_RTS 0x01EC 0x0478 0x0640 0x8 0x7 + +/* signals for i.MX6ULL only */ +#define MX6ULL_PAD_UART1_TX_DATA__UART5_DCE_TX 0x0084 0x0310 0x0000 0x9 0x0 #define MX6ULL_PAD_UART1_TX_DATA__UART5_DTE_RX 0x0084 0x0310 0x0644 0x9 0x4 #define MX6ULL_PAD_UART1_RX_DATA__UART5_DCE_RX 0x0088 0x0314 0x0644 0x9 0x5 -#define MX6ULL_PAD_UART1_CTS_B__UART5_DCE_RTS 0x008C 0x0318 0x0640 0x9 0x3 -#define MX6ULL_PAD_UART1_RTS_B__UART5_DTE_RTS 0x0090 0x031C 0x0640 0x9 0x4 -#define MX6ULL_PAD_UART5_TX_DATA__UART5_DTE_RX 0x00BC 0x0348 0x0644 0x0 0x6 -#define MX6ULL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x00C0 0x034C 0x0644 0x0 0x7 -#define MX6ULL_PAD_ENET1_RX_EN__UART5_DCE_RTS 0x00CC 0x0358 0x0640 0x1 0x5 -#define MX6ULL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS 0x00D0 0x035C 0x0640 0x1 0x6 +#define MX6ULL_PAD_UART1_RX_DATA__UART5_DTE_TX 0x0088 0x0314 0x0000 0x9 0x0 +#define MX6ULL_PAD_UART1_CTS_B__UART5_DCE_CTS 0x008C 0x0318 0x0000 0x9 0x0 +#define MX6ULL_PAD_UART1_CTS_B__UART5_DTE_RTS 0x008C 0x0318 0x0640 0x9 0x3 +#define MX6ULL_PAD_UART1_RTS_B__UART5_DCE_RTS 0x0090 0x031C 0x0640 0x9 0x4 +#define MX6ULL_PAD_UART1_RTS_B__UART5_DTE_CTS 0x0090 0x031C 0x0000 0x9 0x0 +#define MX6ULL_PAD_UART4_RX_DATA__EPDC_PWRCTRL01 0x00B8 0x0344 0x0000 0x9 0x0 +#define MX6ULL_PAD_UART5_TX_DATA__EPDC_PWRCTRL02 0x00BC 0x0348 0x0000 0x9 0x0 +#define MX6ULL_PAD_UART5_RX_DATA__EPDC_PWRCTRL03 0x00C0 0x034C 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_RX_DATA0__EPDC_SDCE04 0x00C4 0x0350 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_RX_DATA1__EPDC_SDCE05 0x00C8 0x0354 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_RX_EN__EPDC_SDCE06 0x00CC 0x0358 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_TX_DATA0__EPDC_SDCE07 0x00D0 0x035C 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_TX_DATA1__EPDC_SDCE08 0x00D4 0x0360 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_TX_EN__EPDC_SDCE09 0x00D8 0x0364 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_TX_CLK__EPDC_SDOED 0x00DC 0x0368 0x0000 0x9 0x0 +#define MX6ULL_PAD_ENET1_RX_ER__EPDC_SDOEZ 0x00E0 0x036C 0x0000 0x9 0x0 #define MX6ULL_PAD_ENET2_RX_DATA0__EPDC_SDDO08 0x00E4 0x0370 0x0000 0x9 0x0 #define MX6ULL_PAD_ENET2_RX_DATA1__EPDC_SDDO09 0x00E8 0x0374 0x0000 0x9 0x0 #define MX6ULL_PAD_ENET2_RX_EN__EPDC_SDDO10 0x00EC 0x0378 0x0000 0x9 0x0 @@ -48,6 +72,8 @@ #define MX6ULL_PAD_LCD_DATA16__EPDC_GDCLK 0x0158 0x03E4 0x0000 0x9 0x0 #define MX6ULL_PAD_LCD_DATA17__EPDC_GDSP 0x015C 0x03E8 0x0000 0x9 0x0 #define MX6ULL_PAD_LCD_DATA21__EPDC_SDCE1 0x016C 0x03F8 0x0000 0x9 0x0 +#define MX6ULL_PAD_LCD_DATA22__EPDC_SDCE02 0x0170 0x03FC 0x0000 0x9 0x0 +#define MX6ULL_PAD_LCD_DATA23__EPDC_SDCE03 0x0174 0x0400 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_MCLK__ESAI_TX3_RX2 0x01D4 0x0460 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_PIXCLK__ESAI_TX2_RX3 0x01D8 0x0464 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_VSYNC__ESAI_TX4_RX1 0x01DC 0x0468 0x0000 0x9 0x0 @@ -55,7 +81,6 @@ #define MX6ULL_PAD_CSI_DATA00__ESAI_TX_HF_CLK 0x01E4 0x0470 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_DATA01__ESAI_RX_HF_CLK 0x01E8 0x0474 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_DATA02__ESAI_RX_FS 0x01EC 0x0478 0x0000 0x9 0x0 -#define MX6ULL_PAD_CSI_DATA02__UART5_DCE_RTS 0x01EC 0x0478 0x0640 0x8 0x7 #define MX6ULL_PAD_CSI_DATA03__ESAI_RX_CLK 0x01F0 0x047C 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS 0x01F4 0x0480 0x0000 0x9 0x0 #define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK 0x01F8 0x0484 0x0000 0x9 0x0 diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi index cd1776a7015a..796ed35d4ac9 100644 --- a/arch/arm/boot/dts/imx6ull.dtsi +++ b/arch/arm/boot/dts/imx6ull.dtsi @@ -22,7 +22,7 @@ >; fsl,soc-operating-points = < /* KHz uV */ - 900000 1175000 + 900000 1250000 792000 1175000 528000 1175000 396000 1175000 diff --git a/arch/arm/boot/dts/imx6ulz-14x14-evk.dts b/arch/arm/boot/dts/imx6ulz-14x14-evk.dts new file mode 100644 index 000000000000..6f1af240e0ce --- /dev/null +++ b/arch/arm/boot/dts/imx6ulz-14x14-evk.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2018 NXP. + +/dts-v1/; + +#include "imx6ulz.dtsi" +#include "imx6ul-14x14-evk.dtsi" + +/delete-node/ &fec1; +/delete-node/ &fec2; +/delete-node/ &lcdif; +/delete-node/ &tsc; + +/ { + model = "Freescale i.MX6 ULZ 14x14 EVK Board"; + compatible = "fsl,imx6ulz-14x14-evk", "fsl,imx6ull", "fsl,imx6ulz"; + + /delete-node/ panel; +}; diff --git a/arch/arm/boot/dts/imx6ulz.dtsi b/arch/arm/boot/dts/imx6ulz.dtsi new file mode 100644 index 000000000000..ae6d7e593769 --- /dev/null +++ b/arch/arm/boot/dts/imx6ulz.dtsi @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2018 NXP. + +#include "imx6ull.dtsi" + +/ { + aliases { + /delete-property/ ethernet0; + /delete-property/ ethernet1; + /delete-property/ i2c2; + /delete-property/ i2c3; + /delete-property/ serial4; + /delete-property/ serial5; + /delete-property/ serial6; + /delete-property/ serial7; + /delete-property/ spi2; + /delete-property/ spi3; + }; +}; + +/delete-node/ &adc1; +/delete-node/ &can1; +/delete-node/ &can2; +/delete-node/ &ecspi3; +/delete-node/ &ecspi4; +/delete-node/ &epit2; +/delete-node/ &gpt2; +/delete-node/ &i2c3; +/delete-node/ &i2c4; +/delete-node/ &pwm5; +/delete-node/ &pwm6; +/delete-node/ &pwm7; +/delete-node/ &pwm8; +/delete-node/ &uart5; +/delete-node/ &uart6; +/delete-node/ &uart7; +/delete-node/ &uart8; diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts index c9b3c60b0eb2..f1bafdaa7e1a 100644 --- a/arch/arm/boot/dts/imx7d-sdb.dts +++ b/arch/arm/boot/dts/imx7d-sdb.dts @@ -27,12 +27,14 @@ label = "Volume Up"; gpios = <&gpio5 11 GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEUP>; + wakeup-source; }; volume-down { label = "Volume Down"; gpios = <&gpio5 10 GPIO_ACTIVE_LOW>; linux,code = <KEY_VOLUMEDOWN>; + wakeup-source; }; }; diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 7234e8330a57..826224bf7f4f 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -20,6 +20,7 @@ reg = <1>; clock-frequency = <996000000>; operating-points-v2 = <&cpu0_opp_table>; + cpu-idle-states = <&cpu_sleep_wait>; }; }; @@ -63,9 +64,11 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - port { - etm1_out_port: endpoint { - remote-endpoint = <&ca_funnel_in_port1>; + out-ports { + port { + etm1_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port1>; + }; }; }; }; @@ -146,17 +149,20 @@ fsl,max-link-speed = <2>; power-domains = <&pgc_pcie_phy>; resets = <&src IMX7_RESET_PCIEPHY>, - <&src IMX7_RESET_PCIE_CTRL_APPS_EN>; - reset-names = "pciephy", "apps"; + <&src IMX7_RESET_PCIE_CTRL_APPS_EN>, + <&src IMX7_RESET_PCIE_CTRL_APPS_TURNOFF>; + reset-names = "pciephy", "apps", "turnoff"; status = "disabled"; }; }; -&ca_funnel_ports { +&ca_funnel_in_ports { + #address-cells = <1>; + #size-cells = <0>; + port@1 { reg = <1>; ca_funnel_in_port1: endpoint { - slave-mode; remote-endpoint = <&etm1_out_port>; }; }; diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts index fa390da636de..f7ba2c0a24ad 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/imx7s-warp.dts @@ -1,44 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (C) 2016 NXP Semiconductors. * Author: Fabio Estevam <fabio.estevam@nxp.com> - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. */ /dts-v1/; @@ -216,6 +179,13 @@ status = "okay"; }; +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + &i2c4 { clock-frequency = <100000>; pinctrl-names = "default"; @@ -346,6 +316,13 @@ >; }; + 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_I2C4_SCL__I2C4_SCL 0x4000007f diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index a052198f6e96..aa8df7d93b2e 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -54,6 +54,19 @@ #address-cells = <1>; #size-cells = <0>; + idle-states { + entry-method = "psci"; + + cpu_sleep_wait: cpu-sleep-wait { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <100>; + exit-latency-us = <50>; + min-residency-us = <1000>; + }; + }; + cpu0: cpu@0 { compatible = "arm,cortex-a7"; device_type = "cpu"; @@ -61,6 +74,7 @@ clock-frequency = <792000000>; clock-latency = <61036>; /* two CLK32 periods */ clocks = <&clks IMX7D_CLK_ARM>; + cpu-idle-states = <&cpu_sleep_wait>; }; }; @@ -106,7 +120,7 @@ */ compatible = "arm,coresight-replicator"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; /* replicator output ports */ @@ -123,12 +137,11 @@ remote-endpoint = <&etr_in_port>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator_in_port0: endpoint { - slave-mode; remote-endpoint = <&etf_out_port>; }; }; @@ -168,28 +181,23 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - ca_funnel_ports: ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel input ports */ - port@0 { - reg = <0>; + ca_funnel_in_ports: in-ports { + port { ca_funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&etm0_out_port>; }; }; - /* funnel output port */ - port@2 { - reg = <0>; + /* the other input ports are not connect to anything */ + }; + + out-ports { + port { ca_funnel_out_port0: endpoint { remote-endpoint = <&hugo_funnel_in_port0>; }; }; - /* the other input ports are not connect to anything */ }; }; @@ -200,9 +208,11 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - port { - etm0_out_port: endpoint { - remote-endpoint = <&ca_funnel_in_port0>; + out-ports { + port { + etm0_out_port: endpoint { + remote-endpoint = <&ca_funnel_in_port0>; + }; }; }; }; @@ -213,15 +223,13 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; - /* funnel input ports */ port@0 { reg = <0>; hugo_funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&ca_funnel_out_port0>; }; }; @@ -229,18 +237,18 @@ port@1 { reg = <1>; hugo_funnel_in_port1: endpoint { - slave-mode; /* M4 input */ + /* M4 input */ }; }; + /* the other input ports are not connect to anything */ + }; - port@2 { - reg = <0>; + out-ports { + port { hugo_funnel_out_port0: endpoint { remote-endpoint = <&etf_in_port>; }; }; - - /* the other input ports are not connect to anything */ }; }; @@ -250,20 +258,16 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { etf_in_port: endpoint { - slave-mode; remote-endpoint = <&hugo_funnel_out_port0>; }; }; + }; - port@1 { - reg = <0>; + out-ports { + port { etf_out_port: endpoint { remote-endpoint = <&replicator_in_port0>; }; @@ -277,10 +281,11 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - port { - etr_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port1>; + in-ports { + port { + etr_in_port: endpoint { + remote-endpoint = <&replicator_out_port1>; + }; }; }; }; @@ -291,10 +296,11 @@ clocks = <&clks IMX7D_MAIN_AXI_ROOT_CLK>; clock-names = "apb_pclk"; - port { - tpiu_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port0>; + in-ports { + port { + tpiu_in_port: endpoint { + remote-endpoint = <&replicator_out_port0>; + }; }; }; }; @@ -563,14 +569,6 @@ clock-names = "snvs-rtc"; }; - snvs_poweroff: snvs-poweroff { - compatible = "syscon-poweroff"; - regmap = <&snvs>; - offset = <0x38>; - value = <0x60>; - mask = <0x60>; - }; - snvs_pwrkey: snvs-powerkey { compatible = "fsl,sec-v4.0-pwrkey"; regmap = <&snvs>; @@ -644,7 +642,7 @@ status = "disabled"; }; - ecspi4: ecspi@30630000 { + ecspi4: spi@30630000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; @@ -725,7 +723,7 @@ reg = <0x30800000 0x100000>; ranges; - ecspi1: ecspi@30820000 { + ecspi1: spi@30820000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; @@ -737,7 +735,7 @@ status = "disabled"; }; - ecspi2: ecspi@30830000 { + ecspi2: spi@30830000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; @@ -749,7 +747,7 @@ status = "disabled"; }; - ecspi3: ecspi@30840000 { + ecspi3: spi@30840000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx7d-ecspi", "fsl,imx51-ecspi"; @@ -974,6 +972,25 @@ status = "disabled"; }; + mu0a: mailbox@30aa0000 { + compatible = "fsl,imx7s-mu", "fsl,imx6sx-mu"; + reg = <0x30aa0000 0x10000>; + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_MU_ROOT_CLK>; + #mbox-cells = <2>; + status = "disabled"; + }; + + mu0b: mailbox@30ab0000 { + compatible = "fsl,imx7s-mu", "fsl,imx6sx-mu"; + reg = <0x30ab0000 0x10000>; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX7D_MU_ROOT_CLK>; + #mbox-cells = <2>; + fsl,mu-side-b; + status = "disabled"; + }; + usbotg1: usb@30b10000 { compatible = "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x30b10000 0x200>; diff --git a/arch/arm/boot/dts/imx7ulp-pinfunc.h b/arch/arm/boot/dts/imx7ulp-pinfunc.h index fe511775b518..85f6b017803a 100644 --- a/arch/arm/boot/dts/imx7ulp-pinfunc.h +++ b/arch/arm/boot/dts/imx7ulp-pinfunc.h @@ -116,6 +116,7 @@ #define IMX7ULP_PAD_PTC13__LPI2C7_SDA 0x0034 0x030c 0x5 0x1 #define IMX7ULP_PAD_PTC13__TPM7_CLKIN 0x0034 0x02f4 0x6 0x1 #define IMX7ULP_PAD_PTC13__FB_AD13 0x0034 0x0000 0x9 0x0 +#define IMX7ULP_PAD_PTC13__USB0_ID 0x0034 0x0338 0xb 0x1 #define IMX7ULP_PAD_PTC14__PTC14 0x0038 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTC14__TRACE_D1 0x0038 0x0000 0xa 0x0 #define IMX7ULP_PAD_PTC14__FXIO1_D10 0x0038 0x022c 0x2 0x1 @@ -136,6 +137,7 @@ #define IMX7ULP_PAD_PTC16__LPSPI3_SIN 0x0040 0x0324 0x3 0x1 #define IMX7ULP_PAD_PTC16__TPM7_CH2 0x0040 0x02e4 0x6 0x1 #define IMX7ULP_PAD_PTC16__FB_ALE_FB_CS1_B_FB_TS_B 0x0040 0x0000 0x9 0x0 +#define IMX7ULP_PAD_PTC16__USB1_OC2 0x0040 0x0334 0xb 0x1 #define IMX7ULP_PAD_PTC17__PTC17 0x0044 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTC17__FXIO1_D13 0x0044 0x0238 0x2 0x1 #define IMX7ULP_PAD_PTC17__LPSPI3_SOUT 0x0044 0x0328 0x3 0x1 @@ -146,11 +148,16 @@ #define IMX7ULP_PAD_PTC18__LPSPI3_SCK 0x0048 0x0320 0x3 0x1 #define IMX7ULP_PAD_PTC18__TPM6_CH0 0x0048 0x02d0 0x6 0x1 #define IMX7ULP_PAD_PTC18__FB_OE_B 0x0048 0x0000 0x9 0x0 +#define IMX7ULP_PAD_PTC18__USB0_ID 0x0048 0x0338 0xb 0x2 +#define IMX7ULP_PAD_PTC18__VIU_DE 0x0048 0x033c 0xc 0x1 #define IMX7ULP_PAD_PTC19__PTC19 0x004c 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTC19__FXIO1_D15 0x004c 0x0240 0x2 0x1 #define IMX7ULP_PAD_PTC19__LPSPI3_PCS0 0x004c 0x0310 0x3 0x1 #define IMX7ULP_PAD_PTC19__TPM6_CH1 0x004c 0x02d4 0x6 0x1 #define IMX7ULP_PAD_PTC19__FB_A16 0x004c 0x0000 0x9 0x0 +#define IMX7ULP_PAD_PTC19__USB0_ID 0x004c 0x0338 0xa 0x3 +#define IMX7ULP_PAD_PTC19__USB1_PWR2 0x004c 0x0000 0xb 0x0 +#define IMX7ULP_PAD_PTC19__VIU_DE 0x004c 0x033c 0xc 0x3 #define IMX7ULP_PAD_PTD0__PTD0 0x0080 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTD0__SDHC0_RESET_B 0x0080 0x0000 0x8 0x0 #define IMX7ULP_PAD_PTD1__PTD1 0x0084 0x0000 0x1 0x0 @@ -218,6 +225,7 @@ #define IMX7ULP_PAD_PTE5__LPI2C5_SDA 0x0114 0x02c0 0x5 0x2 #define IMX7ULP_PAD_PTE5__TPM5_CH0 0x0114 0x02c4 0x6 0x2 #define IMX7ULP_PAD_PTE5__SDHC1_D2 0x0114 0x0000 0x8 0x0 +#define IMX7ULP_PAD_PTE5__VIU_DE 0x0114 0x033c 0xc 0x2 #define IMX7ULP_PAD_PTE6__PTE6 0x0118 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE6__FXIO1_D25 0x0118 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE6__LPSPI2_SCK 0x0118 0x02ac 0x3 0x2 @@ -226,8 +234,10 @@ #define IMX7ULP_PAD_PTE6__TPM7_CH3 0x0118 0x02e8 0x6 0x2 #define IMX7ULP_PAD_PTE6__SDHC1_D4 0x0118 0x0000 0x8 0x0 #define IMX7ULP_PAD_PTE6__FB_A17 0x0118 0x0000 0x9 0x0 +#define IMX7ULP_PAD_PTE6__USB0_OC 0x0118 0x0330 0xb 0x1 #define IMX7ULP_PAD_PTE7__PTE7 0x011c 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE7__TRACE_D7 0x011c 0x0000 0xa 0x0 +#define IMX7ULP_PAD_PTE7__USB0_PWR 0x011c 0x0000 0xb 0x0 #define IMX7ULP_PAD_PTE7__VIU_FID 0x011c 0x0000 0xc 0x0 #define IMX7ULP_PAD_PTE7__FXIO1_D24 0x011c 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE7__LPSPI2_PCS0 0x011c 0x029c 0x3 0x2 @@ -278,6 +288,7 @@ #define IMX7ULP_PAD_PTE11__FB_A20 0x012c 0x0000 0x9 0x0 #define IMX7ULP_PAD_PTE12__PTE12 0x0130 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE12__TRACE_D2 0x0130 0x0000 0xa 0x0 +#define IMX7ULP_PAD_PTE12__USB1_OC2 0x0130 0x0334 0xb 0x2 #define IMX7ULP_PAD_PTE12__VIU_D20 0x0130 0x0000 0xc 0x0 #define IMX7ULP_PAD_PTE12__FXIO1_D19 0x0130 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE12__LPSPI3_SIN 0x0130 0x0324 0x3 0x2 @@ -288,6 +299,7 @@ #define IMX7ULP_PAD_PTE12__FB_A21 0x0130 0x0000 0x9 0x0 #define IMX7ULP_PAD_PTE13__PTE13 0x0134 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE13__TRACE_D1 0x0134 0x0000 0xa 0x0 +#define IMX7ULP_PAD_PTE13__USB1_PWR2 0x0134 0x0000 0xb 0x0 #define IMX7ULP_PAD_PTE13__VIU_D21 0x0134 0x0000 0xc 0x0 #define IMX7ULP_PAD_PTE13__FXIO1_D18 0x0134 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE13__LPSPI3_SOUT 0x0134 0x0328 0x3 0x2 @@ -298,6 +310,7 @@ #define IMX7ULP_PAD_PTE13__FB_A22 0x0134 0x0000 0x9 0x0 #define IMX7ULP_PAD_PTE14__PTE14 0x0138 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE14__TRACE_D0 0x0138 0x0000 0xa 0x0 +#define IMX7ULP_PAD_PTE14__USB0_OC 0x0138 0x0330 0xb 0x2 #define IMX7ULP_PAD_PTE14__VIU_D22 0x0138 0x0000 0xc 0x0 #define IMX7ULP_PAD_PTE14__FXIO1_D17 0x0138 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE14__LPSPI3_SCK 0x0138 0x0320 0x3 0x2 @@ -308,6 +321,7 @@ #define IMX7ULP_PAD_PTE14__FB_A23 0x0138 0x0000 0x9 0x0 #define IMX7ULP_PAD_PTE15__PTE15 0x013c 0x0000 0x1 0x0 #define IMX7ULP_PAD_PTE15__TRACE_CLKOUT 0x013c 0x0000 0xa 0x0 +#define IMX7ULP_PAD_PTE15__USB0_PWR 0x013c 0x0000 0xb 0x0 #define IMX7ULP_PAD_PTE15__VIU_D23 0x013c 0x0000 0xc 0x0 #define IMX7ULP_PAD_PTE15__FXIO1_D16 0x013c 0x0000 0x2 0x0 #define IMX7ULP_PAD_PTE15__LPSPI3_PCS0 0x013c 0x0310 0x3 0x2 @@ -315,7 +329,7 @@ #define IMX7ULP_PAD_PTE15__TPM6_CH1 0x013c 0x02d4 0x6 0x2 #define IMX7ULP_PAD_PTE15__FB_A24 0x013c 0x0000 0x9 0x0 #define IMX7ULP_PAD_PTF0__PTF0 0x0180 0x0000 0x1 0x0 -#define IMX7ULP_PAD_PTF0__VIU_DE 0x0180 0x0000 0xc 0x0 +#define IMX7ULP_PAD_PTF0__VIU_DE 0x0180 0x033c 0xc 0x0 #define IMX7ULP_PAD_PTF0__LPUART4_CTS_B 0x0180 0x0244 0x4 0x3 #define IMX7ULP_PAD_PTF0__LPI2C4_SCL 0x0180 0x0278 0x5 0x3 #define IMX7ULP_PAD_PTF0__TPM4_CLKIN 0x0180 0x0298 0x6 0x3 diff --git a/arch/arm/boot/dts/iwg20d-q7-common.dtsi b/arch/arm/boot/dts/iwg20d-q7-common.dtsi index 5cae74eb6cdd..ca9154dd8052 100644 --- a/arch/arm/boot/dts/iwg20d-q7-common.dtsi +++ b/arch/arm/boot/dts/iwg20d-q7-common.dtsi @@ -160,10 +160,6 @@ clock-frequency = <100000000>; }; -&pciec { - status = "okay"; -}; - &pfc { can0_pins: can0 { groups = "can0_data_d"; diff --git a/arch/arm/boot/dts/keystone-k2g.dtsi b/arch/arm/boot/dts/keystone-k2g.dtsi index 738b44cf2b0b..1c833105d6c5 100644 --- a/arch/arm/boot/dts/keystone-k2g.dtsi +++ b/arch/arm/boot/dts/keystone-k2g.dtsi @@ -416,7 +416,7 @@ clock-names = "fck", "mmchsdb_fck"; }; - qspi: qspi@2940000 { + qspi: spi@2940000 { compatible = "ti,k2g-qspi", "cdns,qspi-nor"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index abff7ef7c9cd..b7303a4e4236 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -179,7 +179,7 @@ * ssp0 and spi1 are shared pins; * enable one in your board dts, as needed. */ - ssp0: ssp@20084000 { + ssp0: spi@20084000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x20084000 0x1000>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; @@ -199,7 +199,7 @@ * ssp1 and spi2 are shared pins; * enable one in your board dts, as needed. */ - ssp1: ssp@2008c000 { + ssp1: spi@2008c000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x2008c000 0x1000>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts index 499f41a2c6f0..923a25760516 100644 --- a/arch/arm/boot/dts/ls1021a-qds.dts +++ b/arch/arm/boot/dts/ls1021a-qds.dts @@ -1,5 +1,6 @@ /* * Copyright 2013-2014 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * This file is dual-licensed: you can use it either under the terms * of the GPL or the X11 license, at your option. Note that this dual @@ -235,6 +236,7 @@ #size-cells = <1>; compatible = "cfi-flash"; reg = <0x0 0x0 0x8000000>; + big-endian; bank-width = <2>; device-width = <1>; }; diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts index f0c949d74833..8b48c3c7cd21 100644 --- a/arch/arm/boot/dts/ls1021a-twr.dts +++ b/arch/arm/boot/dts/ls1021a-twr.dts @@ -1,5 +1,6 @@ /* * Copyright 2013-2014 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * This file is dual-licensed: you can use it either under the terms * of the GPL or the X11 license, at your option. Note that this dual @@ -203,6 +204,7 @@ #size-cells = <1>; compatible = "cfi-flash"; reg = <0x0 0x0 0x8000000>; + big-endian; bank-width = <2>; device-width = <1>; }; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index f18490548c78..bdd6e66a79ad 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -163,7 +163,7 @@ big-endian; }; - qspi: quadspi@1550000 { + qspi: spi@1550000 { compatible = "fsl,ls1021a-qspi"; #address-cells = <1>; #size-cells = <0>; @@ -330,7 +330,7 @@ }; }; - dspi0: dspi@2100000 { + dspi0: spi@2100000 { compatible = "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; @@ -343,7 +343,7 @@ status = "disabled"; }; - dspi1: dspi@2110000 { + dspi1: spi@2110000 { compatible = "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; @@ -364,6 +364,8 @@ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; clocks = <&clockgen 4 1>; + dma-names = "tx", "rx"; + dmas = <&edma0 1 39>, <&edma0 1 38>; status = "disabled"; }; @@ -375,6 +377,8 @@ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; clocks = <&clockgen 4 1>; + dma-names = "tx", "rx"; + dmas = <&edma0 1 37>, <&edma0 1 36>; status = "disabled"; }; @@ -386,6 +390,8 @@ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>; clock-names = "i2c"; clocks = <&clockgen 4 1>; + dma-names = "tx", "rx"; + dmas = <&edma0 1 35>, <&edma0 1 34>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi index d77dcf890cfc..7162e0ca05b0 100644 --- a/arch/arm/boot/dts/meson8.dtsi +++ b/arch/arm/boot/dts/meson8.dtsi @@ -194,7 +194,7 @@ #clock-cells = <1>; #reset-cells = <1>; compatible = "amlogic,meson8-clkc"; - reg = <0x8000 0x4>, <0x4000 0x460>; + reg = <0x8000 0x4>, <0x4000 0x400>; }; reset: reset-controller@4404 { diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/meson8b-ec100.dts new file mode 100644 index 000000000000..0872f6e3abf5 --- /dev/null +++ b/arch/arm/boot/dts/meson8b-ec100.dts @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>. + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +#include "meson8b.dtsi" + +/ { + model = "Endless Computers Endless Mini"; + compatible = "endless,ec100", "amlogic,meson8b"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0x40000000 0x40000000>; + }; + + gpio-keys { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + pal-switch { + label = "pal"; + linux,input-type = <EV_SW>; + linux,code = <KEY_SWITCHVIDEOMODE>; + gpios = <&gpio GPIOH_7 GPIO_ACTIVE_LOW>; + }; + + ntsc-switch { + label = "ntsc"; + linux,input-type = <EV_SW>; + linux,code = <KEY_SWITCHVIDEOMODE>; + gpios = <&gpio GPIOH_8 GPIO_ACTIVE_HIGH>; + }; + + power-button { + label = "power"; + linux,code = <KEY_POWER>; + gpios = <&gpio GPIOH_9 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + /* + * shutdown is managed by the EC (embedded micro-controller) + * which is configured through GPIOAO_2 (poweroff GPIO) and + * GPIOAO_7 (power LED, which has to go LOW as well). + */ + gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>; + timeout-ms = <20000>; + }; + + leds { + compatible = "gpio-leds"; + + power { + label = "ec100:red:power"; + /* + * Needs to go LOW (together with the poweroff GPIO) + * during shutdown to allow the EC (embedded + * micro-controller) to shutdown the system. Setting + * the output to LOW signals the EC to start a + * "breathing"/pulsing effect until the power is fully + * turned off. + */ + gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + usb_vbus: regulator-usb-vbus { + compatible = "regulator-fixed"; + + regulator-name = "USB_VBUS"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vcc_5v: regulator-vcc5v { + compatible = "regulator-fixed"; + + regulator-name = "VCC5V"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio GPIODV_29 GPIO_ACTIVE_LOW>; + + regulator-boot-on; + regulator-always-on; + }; + + vcck: regulator-vcck { + compatible = "pwm-regulator"; + + regulator-name = "VCCK"; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1140000>; + + pwms = <&pwm_cd 0 1148 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; + + vcc_1v8: regulator-vcc1v8 { + compatible = "regulator-fixed"; + + regulator-name = "VCC1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcc_3v3: regulator-vcc3v3 { + compatible = "regulator-fixed"; + + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&cpu0 { + cpu-supply = <&vcck>; +}; + +ðmac { + status = "okay"; + + pinctrl-0 = <ð_rmii_pins>; + pinctrl-names = "default"; + + phy-handle = <ð_phy0>; + phy-mode = "rmii"; + + snps,reset-gpio = <&gpio GPIOH_4 0>; + snps,reset-delays-us = <0 10000 1000000>; + snps,reset-active-low; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + eth_phy0: ethernet-phy@0 { + /* IC Plus IP101A/G (0x02430c54) */ + reg = <0>; + }; + }; +}; + +&i2c_A { + status = "okay"; + pinctrl-0 = <&i2c_a_pins>; + pinctrl-names = "default"; + + rt5640: codec@1c { + compatible = "realtek,rt5640"; + reg = <0x1c>; + interrupt-parent = <&gpio_intc>; + interrupts = <13 IRQ_TYPE_EDGE_BOTH>; /* GPIOAO_13 */ + realtek,in1-differential; + }; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8>; +}; + +&sdio { + status = "okay"; + + pinctrl-0 = <&sd_b_pins>; + pinctrl-names = "default"; + + /* SD card */ + sd_card_slot: slot@1 { + compatible = "mmc-slot"; + reg = <1>; + status = "okay"; + + bus-width = <4>; + no-sdio; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vcc_3v3>; + }; +}; + +&pwm_cd { + status = "okay"; + pinctrl-0 = <&pwm_c1_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_XTAL>; + clock-names = "clkin0"; +}; + +/* exposed through the pin headers labeled "URDUG1" on the top of the PCB */ +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +/* + * connected to the Bluetooth part of the RTL8723BS SDIO wifi / Bluetooth + * combo chip. This is only available on the variant with 2GB RAM. + */ +&uart_B { + status = "okay"; + pinctrl-0 = <&uart_b0_pins>, <&uart_b0_cts_rts_pins>; + pinctrl-names = "default"; + uart-has-rtscts; +}; + +&usb1 { + status = "okay"; + vbus-supply = <&usb_vbus>; +}; + +&usb1_phy { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts index ef3177d3da3d..58669abda259 100644 --- a/arch/arm/boot/dts/meson8b-odroidc1.dts +++ b/arch/arm/boot/dts/meson8b-odroidc1.dts @@ -57,6 +57,10 @@ mmc0 = &sd_card_slot; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x40000000 0x40000000>; }; @@ -71,6 +75,14 @@ }; }; + p5v0: regulator-p5v0 { + compatible = "regulator-fixed"; + + regulator-name = "P5V0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + tflash_vdd: regulator-tflash_vdd { /* * signal name from schematics: TFLASH_VDD_EN @@ -81,6 +93,8 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3>; + gpio = <&gpio GPIOY_12 GPIO_ACTIVE_HIGH>; enable-active-high; }; @@ -92,6 +106,8 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3>; + /* * signal name from schematics: TF_3V3N_1V8_EN */ @@ -101,6 +117,86 @@ states = <3300000 0 1800000 1>; }; + + vcc_1v8: regulator-vcc-1v8 { + /* + * RICHTEK RT9179 configured for a fixed output voltage of + * 1.8V. This supplies not only VCC1V8 but also IOREF_1V8 and + * VDD1V8 according to the schematics. + */ + compatible = "regulator-fixed"; + + regulator-name = "VCC1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + vin-supply = <&p5v0>; + }; + + vcc_3v3: regulator-vcc-3v3 { + /* + * Monolithic Power Systems MP2161 configured for a fixed + * output voltage of 3.3V. This supplies not only VCC3V3 but + * also VDD3V3 and VDDIO_AO3V3 according to the schematics. + */ + compatible = "regulator-fixed"; + + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + vin-supply = <&p5v0>; + }; + + vcck: regulator-vcck { + /* Monolithic Power Systems MP2161 */ + compatible = "pwm-regulator"; + + regulator-name = "VCCK"; + regulator-min-microvolt = <860000>; + regulator-max-microvolt = <1140000>; + + vin-supply = <&p5v0>; + + pwms = <&pwm_cd 0 12218 0>; + pwm-dutycycle-range = <91 0>; + + regulator-boot-on; + regulator-always-on; + }; + + vddc_ddr: regulator-vddc-ddr { + /* + * Monolithic Power Systems MP2161 configured for a fixed + * output voltage of 1.5V. This supplies not only DDR_VDDC but + * also DDR3_1V5 according to the schematics. + */ + compatible = "regulator-fixed"; + + regulator-name = "DDR_VDDC"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + + vin-supply = <&p5v0>; + }; + + vdd_rtc: regulator-vdd-rtc { + /* + * Torex Semiconductor XC6215 configured for a fixed output of + * 0.9V. + */ + compatible = "regulator-fixed"; + + regulator-name = "VDD_RTC"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + + vin-supply = <&vcc_3v3>; + }; +}; + +&cpu0 { + cpu-supply = <&vcck>; }; ðmac { @@ -154,6 +250,11 @@ pinctrl-names = "default"; }; +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8>; +}; + &sdio { status = "okay"; @@ -180,6 +281,14 @@ }; }; +&pwm_cd { + status = "okay"; + pinctrl-0 = <&pwm_c1_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_XTAL>; + clock-names = "clkin0"; +}; + &uart_AO { status = "okay"; pinctrl-0 = <&uart_ao_a_pins>; diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index 08f7f6be7254..cd1ca9dda126 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -163,7 +163,7 @@ #clock-cells = <1>; #reset-cells = <1>; compatible = "amlogic,meson8b-clkc"; - reg = <0x8000 0x4>, <0x4000 0x460>; + reg = <0x8000 0x4>, <0x4000 0x400>; }; reset: reset-controller@4404 { @@ -223,6 +223,28 @@ }; }; + eth_rmii_pins: eth-rmii { + mux { + groups = "eth_tx_en", + "eth_txd1_0", + "eth_txd0_0", + "eth_rx_clk", + "eth_rx_dv", + "eth_rxd1", + "eth_rxd0", + "eth_mdio_en", + "eth_mdc"; + function = "ethernet"; + }; + }; + + i2c_a_pins: i2c-a { + mux { + groups = "i2c_sda_a", "i2c_sck_a"; + function = "i2c_a"; + }; + }; + sd_b_pins: sd-b { mux { groups = "sd_d0_b", "sd_d1_b", "sd_d2_b", @@ -230,6 +252,29 @@ function = "sd_b"; }; }; + + pwm_c1_pins: pwm-c1 { + mux { + groups = "pwm_c1"; + function = "pwm_c"; + }; + }; + + uart_b0_pins: uart-b0 { + mux { + groups = "uart_tx_b0", + "uart_rx_b0"; + function = "uart_b"; + }; + }; + + uart_b0_cts_rts_pins: uart-b0-cts-rts { + mux { + groups = "uart_cts_b0", + "uart_rts_b0"; + function = "uart_b"; + }; + }; }; }; diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 1cdc346a05e8..d01bdee6f2f3 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -13,6 +13,7 @@ #include <dt-bindings/power/mt2701-power.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/phy/phy.h> +#include <dt-bindings/memory/mt2701-larb-port.h> #include <dt-bindings/reset/mt2701-resets.h> #include <dt-bindings/thermal/thermal.h> @@ -121,6 +122,15 @@ }; }; + pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 5 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + system_clk: dummy13m { compatible = "fixed-clock"; clock-frequency = <13000000>; @@ -277,6 +287,17 @@ clock-names = "system-clk", "rtc-clk"; }; + smi_common: smi@1000c000 { + compatible = "mediatek,mt7623-smi-common", + "mediatek,mt2701-smi-common"; + reg = <0 0x1000c000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_SMI>, + <&mmsys CLK_MM_SMI_COMMON>, + <&infracfg CLK_INFRA_SMI>; + clock-names = "apb", "smi", "async"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + pwrap: pwrap@1000d000 { compatible = "mediatek,mt7623-pwrap", "mediatek,mt2701-pwrap"; @@ -308,6 +329,17 @@ reg = <0 0x10200100 0 0x1c>; }; + iommu: mmsys_iommu@10205000 { + compatible = "mediatek,mt7623-m4u", + "mediatek,mt2701-m4u"; + reg = <0 0x10205000 0 0x1000>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + mediatek,larbs = <&larb0 &larb1 &larb2>; + #iommu-cells = <1>; + }; + efuse: efuse@10206000 { compatible = "mediatek,mt7623-efuse", "mediatek,mt8173-efuse"; @@ -683,6 +715,90 @@ status = "disabled"; }; + g3dsys: syscon@13000000 { + compatible = "mediatek,mt7623-g3dsys", + "mediatek,mt2701-g3dsys", + "syscon"; + reg = <0 0x13000000 0 0x200>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + mmsys: syscon@14000000 { + compatible = "mediatek,mt7623-mmsys", + "mediatek,mt2701-mmsys", + "syscon"; + reg = <0 0x14000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb0: larb@14010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x14010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <0>; + clocks = <&mmsys CLK_MM_SMI_LARB0>, + <&mmsys CLK_MM_SMI_LARB0>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + + imgsys: syscon@15000000 { + compatible = "mediatek,mt7623-imgsys", + "mediatek,mt2701-imgsys", + "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb2: larb@15001000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x15001000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <2>; + clocks = <&imgsys CLK_IMG_SMI_COMM>, + <&imgsys CLK_IMG_SMI_COMM>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; + }; + + jpegdec: jpegdec@15004000 { + compatible = "mediatek,mt7623-jpgdec", + "mediatek,mt2701-jpgdec"; + reg = <0 0x15004000 0 0x1000>; + interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_LOW>; + clocks = <&imgsys CLK_IMG_JPGDEC_SMI>, + <&imgsys CLK_IMG_JPGDEC>; + clock-names = "jpgdec-smi", + "jpgdec"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; + mediatek,larb = <&larb2>; + iommus = <&iommu MT2701_M4U_PORT_JPGDEC_WDMA>, + <&iommu MT2701_M4U_PORT_JPGDEC_BSDMA>; + }; + + vdecsys: syscon@16000000 { + compatible = "mediatek,mt7623-vdecsys", + "mediatek,mt2701-vdecsys", + "syscon"; + reg = <0 0x16000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb1: larb@16010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x16010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <1>; + clocks = <&vdecsys CLK_VDEC_CKGEN>, + <&vdecsys CLK_VDEC_LARB>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>; + }; + hifsys: syscon@1a000000 { compatible = "mediatek,mt7623-hifsys", "mediatek,mt2701-hifsys", @@ -937,6 +1053,14 @@ power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; status = "disabled"; }; + + bdpsys: syscon@1c000000 { + compatible = "mediatek,mt7623-bdpsys", + "mediatek,mt2701-bdpsys", + "syscon"; + reg = <0 0x1c000000 0 0x1000>; + #clock-cells = <1>; + }; }; &pio { diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi index f1d6de8b3c19..000bf16de651 100644 --- a/arch/arm/boot/dts/omap2.dtsi +++ b/arch/arm/boot/dts/omap2.dtsi @@ -114,7 +114,7 @@ dma-names = "tx", "rx"; }; - mcspi1: mcspi@48098000 { + mcspi1: spi@48098000 { compatible = "ti,omap2-mcspi"; ti,hwmods = "mcspi1"; reg = <0x48098000 0x100>; @@ -125,7 +125,7 @@ "tx2", "rx2", "tx3", "rx3"; }; - mcspi2: mcspi@4809a000 { + mcspi2: spi@4809a000 { compatible = "ti,omap2-mcspi"; ti,hwmods = "mcspi2"; reg = <0x4809a000 0x100>; diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index 84635eeb99cd..7f57af2f10ac 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi @@ -285,7 +285,7 @@ ti,timer-alwon; }; - mcspi3: mcspi@480b8000 { + mcspi3: spi@480b8000 { compatible = "ti,omap2-mcspi"; ti,hwmods = "mcspi3"; reg = <0x480b8000 0x100>; diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts index d80587de0bbf..9985ee2aae0c 100644 --- a/arch/arm/boot/dts/omap3-beagle-xm.dts +++ b/arch/arm/boot/dts/omap3-beagle-xm.dts @@ -160,10 +160,11 @@ clocks = <&emu_src_ck>; clock-names = "apb_pclk"; - port { - etb_in: endpoint { - slave-mode; - remote-endpoint = <&etm_out>; + in-ports { + port { + etb_in: endpoint { + remote-endpoint = <&etm_out>; + }; }; }; }; @@ -174,9 +175,11 @@ clocks = <&emu_src_ck>; clock-names = "apb_pclk"; - port { - etm_out: endpoint { - remote-endpoint = <&etb_in>; + out-ports { + port { + etm_out: endpoint { + remote-endpoint = <&etb_in>; + }; }; }; }; diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 3ca8991a6c3e..91bb50ad9a4f 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -147,10 +147,11 @@ clocks = <&emu_src_ck>; clock-names = "apb_pclk"; - port { - etb_in: endpoint { - slave-mode; - remote-endpoint = <&etm_out>; + in-ports { + port { + etb_in: endpoint { + remote-endpoint = <&etm_out>; + }; }; }; }; @@ -161,9 +162,11 @@ clocks = <&emu_src_ck>; clock-names = "apb_pclk"; - port { - etm_out: endpoint { - remote-endpoint = <&etb_in>; + out-ports { + port { + etm_out: endpoint { + remote-endpoint = <&etb_in>; + }; }; }; }; diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi index ac830b917776..d5fe55392230 100644 --- a/arch/arm/boot/dts/omap3-gta04.dtsi +++ b/arch/arm/boot/dts/omap3-gta04.dtsi @@ -10,6 +10,7 @@ /dts-v1/; #include "omap36xx.dtsi" +#include <dt-bindings/input/input.h> / { model = "OMAP3 GTA04"; @@ -28,6 +29,7 @@ aliases { display0 = &lcd; + display1 = &tv0; }; /* fixed 26MHz oscillator */ @@ -42,12 +44,27 @@ aux-button { label = "aux"; - linux,code = <169>; + linux,code = <KEY_PHONE>; gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; wakeup-source; }; }; + antenna-detect { + compatible = "gpio-keys"; + + gps_antenna_button: gps-antenna-button { + label = "GPS_EXT_ANT"; + linux,input-type = <EV_SW>; + linux,code = <SW_LINEIN_INSERT>; + gpios = <&gpio5 16 GPIO_ACTIVE_HIGH>; /* GPIO144 */ + interrupt-parent = <&gpio5>; + interrupts = <16 IRQ_TYPE_EDGE_BOTH>; + debounce-interval = <10>; + wakeup-source; + }; + }; + sound { compatible = "ti,omap-twl4030"; ti,model = "gta04"; @@ -55,7 +72,7 @@ ti,mcbsp = <&mcbsp2>; }; - /* GSM audio */ + /* GSM audio */ sound_telephony { compatible = "simple-audio-card"; simple-audio-card,name = "GTA04 voice"; @@ -78,7 +95,7 @@ #sound-dai-cells = <0>; }; - spi_lcd { + spi_lcd: spi_lcd { compatible = "spi-gpio"; #address-cells = <0x1>; #size-cells = <0x0>; @@ -131,7 +148,7 @@ }; tv0: connector { - compatible = "svideo-connector"; + compatible = "composite-video-connector"; label = "tv"; port { @@ -143,7 +160,7 @@ tv_amp: opa362 { compatible = "ti,opa362"; - enable-gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + enable-gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; /* GPIO_23 to enable video out amplifier */ ports { #address-cells = <1>; @@ -169,6 +186,42 @@ compatible = "mmc-pwrseq-simple"; reset-gpios = <&tca6507 0 GPIO_ACTIVE_LOW>; /* W2CBW003 reset through tca6507 */ }; + + /* devconf0 setup for mcbsp1 clock pins */ + pinmux_mcbsp1@48002274 { + compatible = "pinctrl-single"; + reg = <0x48002274 4>; /* CONTROL_DEVCONF0 */ + #address-cells = <1>; + #size-cells = <0>; + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x7>; /* MCBSP1 CLK pinmux */ + #pinctrl-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp1_devconf0_pins>; + mcbsp1_devconf0_pins: pinmux_mcbsp1_devconf0_pins { + /* offset bits mask */ + pinctrl-single,bits = <0x00 0x08 0x1c>; /* set MCBSP1_CLKR */ + }; + }; + + /* devconf1 setup for tvout pins */ + pinmux_tv_out@480022d8 { + compatible = "pinctrl-single"; + reg = <0x480022d8 4>; /* CONTROL_DEVCONF1 */ + #address-cells = <1>; + #size-cells = <0>; + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x81>; /* TV out pin control */ + #pinctrl-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&tv_acbias_devconf1_pins>; + tv_acbias_devconf1_pins: pinmux_tv_acbias_devconf1_pins { + /* offset bits mask */ + pinctrl-single,bits = <0x00 0x40800 0x40800>; /* set TVOUTBYPASS and TVOUTACEN */ + }; + }; }; &omap3_pmx_core { @@ -220,14 +273,14 @@ >; }; - backlight_pins: backlight_pins_pimnux { + backlight_pins: backlight_pins_pinmux { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20ba, MUX_MODE3) /* gpt11/gpio57 */ >; }; dss_dpi_pins: pinmux_dss_dpi_pins { - pinctrl-single,pins = < + pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */ @@ -265,6 +318,12 @@ >; }; + bmp085_pins: pinmux_bmp085_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2136, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio113 */ + >; + }; + bma180_pins: pinmux_bma180_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x213a, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio115 */ @@ -282,6 +341,78 @@ OMAP3_CORE1_IOPAD(0x2134, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio112 */ >; }; + + penirq_pins: pinmux_penirq_pins { + pinctrl-single,pins = < + /* here we could enable to wakeup the cpu from suspend by a pen touch */ + OMAP3_CORE1_IOPAD(0x2194, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio160 */ + >; + }; + + camera_pins: pinmux_camera_pins { + pinctrl-single,pins = < + /* set up parallel camera interface */ + OMAP3_CORE1_IOPAD(0x210c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_hs */ + OMAP3_CORE1_IOPAD(0x210e, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_vs */ + OMAP3_CORE1_IOPAD(0x2110, PIN_OUTPUT | MUX_MODE0) /* cam_xclka */ + OMAP3_CORE1_IOPAD(0x2112, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_pclk */ + OMAP3_CORE1_IOPAD(0x2114, PIN_OUTPUT | MUX_MODE4) /* cam_fld = gpio_98 */ + OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d0 */ + OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d1 */ + OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d2 */ + OMAP3_CORE1_IOPAD(0x211c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d3 */ + OMAP3_CORE1_IOPAD(0x211e, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d4 */ + OMAP3_CORE1_IOPAD(0x2120, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d5 */ + OMAP3_CORE1_IOPAD(0x2122, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d6 */ + OMAP3_CORE1_IOPAD(0x2124, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d7 */ + OMAP3_CORE1_IOPAD(0x2126, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d8 */ + OMAP3_CORE1_IOPAD(0x2128, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d9 */ + OMAP3_CORE1_IOPAD(0x212a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d10 */ + OMAP3_CORE1_IOPAD(0x212c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* cam_d10 */ + OMAP3_CORE1_IOPAD(0x212e, PIN_OUTPUT | MUX_MODE0) /* cam_xclkb */ + OMAP3_CORE1_IOPAD(0x2130, PIN_OUTPUT | MUX_MODE4) /* cam_wen = gpio_167 */ + OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLDOWN | MUX_MODE4) /* cam_strobe */ + >; + }; + + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x218c, PIN_INPUT | MUX_MODE4) /* mcbsp1_clkr.mcbsp1_clkr - gpio_156 FM interrupt */ + OMAP3_CORE1_IOPAD(0x218e, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_clkr.mcbsp1_fsr */ + OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dx */ + OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dr */ + /* mcbsp_clks is used as PENIRQ */ + /* OMAP3_CORE1_IOPAD(0x2194, PIN_INPUT | MUX_MODE0) /* mcbsp_clks.mcbsp_clks */ + OMAP3_CORE1_IOPAD(0x2196, PIN_INPUT | MUX_MODE0) /* mcbsp_clks.mcbsp1_fsx */ + OMAP3_CORE1_IOPAD(0x2198, PIN_INPUT | MUX_MODE0) /* mcbsp1_clkx.mcbsp1_clkx */ + >; + }; + + mcbsp2_pins: pinmux_mcbsp2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ + OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_clkx */ + OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0) /* mcbsp2_dr.mcbsp2_dr */ + OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dr.mcbsp2_dx */ + >; + }; + + mcbsp3_pins: pinmux_mcbsp3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x216c, PIN_OUTPUT | MUX_MODE0) /* mcbsp3_dx.mcbsp3_dx */ + OMAP3_CORE1_IOPAD(0x216e, PIN_INPUT | MUX_MODE0) /* mcbsp3_dx.mcbsp3_dr */ + OMAP3_CORE1_IOPAD(0x2170, PIN_INPUT | MUX_MODE0) /* mcbsp3_clkx.mcbsp3_clkx */ + OMAP3_CORE1_IOPAD(0x2172, PIN_INPUT | MUX_MODE0) /* mcbsp3_clkx.mcbsp3_fsx */ + >; + }; + + mcbsp4_pins: pinmux_mcbsp4_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcbsp4_clkx.mcbsp4_clkx */ + OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcbsp4_clkx.mcbsp4_dr */ + OMAP3_CORE1_IOPAD(0x218a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcbsp4_dx.mcbsp4_fsx */ + >; + }; }; &omap3_pmx_core2 { @@ -347,6 +478,8 @@ bmp085@77 { compatible = "bosch,bmp085"; reg = <0x77>; + pinctrl-names = "default"; + pinctrl-0 = <&bmp085_pins>; interrupt-parent = <&gpio4>; interrupts = <17 IRQ_TYPE_EDGE_RISING>; /* GPIO_113 */ }; @@ -402,7 +535,7 @@ reg = <0x4>; }; - wifi_reset: wifi_reset@6 { + wifi_reset: wifi_reset@6 { /* reference as <&tca_gpios 0 0> since it is currently the only GPIO */ reg = <0x6>; compatible = "gpio"; }; @@ -422,10 +555,19 @@ tsc2007@48 { compatible = "ti,tsc2007"; reg = <0x48>; + pinctrl-names = "default"; + pinctrl-0 = <&penirq_pins>; interrupt-parent = <&gpio6>; interrupts = <0 IRQ_TYPE_EDGE_FALLING>; /* GPIO_160 */ - gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* GPIO_160 */ ti,x-plate-ohms = <600>; + touchscreen-size-x = <480>; + touchscreen-size-y = <640>; + touchscreen-max-pressure = <1000>; + touchscreen-fuzz-x = <3>; + touchscreen-fuzz-y = <8>; + touchscreen-fuzz-pressure = <10>; + touchscreen-inverted-y; }; /* RFID EEPROM */ @@ -462,6 +604,7 @@ vmmc-supply = <&vmmc1>; bus-width = <4>; ti,non-removable; + broken-cd; /* hardware has no CD */ }; &mmc2 { @@ -476,6 +619,19 @@ status = "disabled"; }; +#define BIT(x) (1 << (x)) +&twl_gpio { + /* pullups: BIT(2) */ + ti,pullups = <BIT(2)>; + /* + * pulldowns: + * BIT(0), BIT(1), BIT(6), BIT(7), BIT(8), BIT(13) + * BIT(15), BIT(16), BIT(17) + */ + ti,pulldowns = <(BIT(0) | BIT(1) | BIT(6) | BIT(7) | BIT(8) | + BIT(13) | BIT(15) | BIT(16) | BIT(17))>; +}; + &twl_keypad { status = "disabled"; }; @@ -493,6 +649,7 @@ &uart3 { pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; + interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>; }; &charger { @@ -510,7 +667,7 @@ &vaux2 { regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-always-on; + regulator-always-on; /* we should never switch off while vio is on! */ }; /* camera */ @@ -531,6 +688,12 @@ regulator-max-microvolt = <3150000>; }; +/* Needed to power the DPI pins */ + +&vpll2 { + regulator-always-on; +}; + &dss { pinctrl-names = "default"; pinctrl-0 = < &dss_dpi_pins >; @@ -551,10 +714,14 @@ vdda-supply = <&vdac>; + #address-cells = <1>; + #size-cells = <0>; + port { + reg = <0>; venc_out: endpoint { remote-endpoint = <&opa_in>; - ti,channels = <2>; + ti,channels = <1>; ti,invert-polarity; }; }; @@ -569,27 +736,27 @@ interrupt-parent = <&gpmc>; interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ <1 IRQ_TYPE_NONE>; /* termcount */ + ti,nand-ecc-opt = "ham1"; + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ nand-bus-width = <16>; - ti,nand-ecc-opt = "bch8"; + #address-cells = <1>; + #size-cells = <1>; - gpmc,sync-clk-ps = <0>; + gpmc,device-width = <2>; gpmc,cs-on-ns = <0>; gpmc,cs-rd-off-ns = <44>; gpmc,cs-wr-off-ns = <44>; gpmc,adv-on-ns = <6>; gpmc,adv-rd-off-ns = <34>; gpmc,adv-wr-off-ns = <44>; - gpmc,we-off-ns = <40>; gpmc,oe-off-ns = <54>; + gpmc,we-off-ns = <40>; gpmc,access-ns = <64>; gpmc,rd-cycle-ns = <82>; gpmc,wr-cycle-ns = <82>; gpmc,wr-access-ns = <40>; gpmc,wr-data-mux-bus-ns = <0>; - gpmc,device-width = <2>; - - #address-cells = <1>; - #size-cells = <1>; + gpmc,sync-clk-ps = <0>; x-loader@0 { label = "X-Loader"; @@ -598,28 +765,51 @@ bootloaders@80000 { label = "U-Boot"; - reg = <0x80000 0x1e0000>; + reg = <0x80000 0x1c0000>; }; - bootloaders_env@260000 { + bootloaders_env@240000 { label = "U-Boot Env"; - reg = <0x260000 0x20000>; + reg = <0x240000 0x40000>; }; kernel@280000 { label = "Kernel"; - reg = <0x280000 0x400000>; + reg = <0x280000 0x600000>; }; - filesystem@680000 { + filesystem@880000 { label = "File System"; - reg = <0x680000 0xf980000>; + reg = <0x880000 0>; /* 0 = MTDPART_SIZ_FULL */ }; }; }; -&mcbsp2 { - status = "okay"; +&mcbsp1 { /* FM Transceiver PCM */ + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp1_pins>; +}; + +&mcbsp2 { /* TPS65950 I2S */ + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp2_pins>; +}; + +&mcbsp3 { /* Bluetooth PCM */ + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp3_pins>; +}; + +&mcbsp4 { /* GSM voice PCM */ + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp4_pins>; }; &hdqw1w { @@ -627,6 +817,22 @@ pinctrl-0 = <&hdq_pins>; }; -&mcbsp4 { - status = "okay"; +/* image signal processor within OMAP3 SoC */ +&isp { + ports { + port@0 { + reg = <0>; + parallel_ep: endpoint { + ti,isp-clock-divisor = <1>; + ti,strobe-mode; + bus-width = <8>;/* Used data lines */ + data-shift = <2>; /* Lines 9:2 are used */ + hsync-active = <0>; /* Active low */ + vsync-active = <1>; /* Active high */ + data-active = <1>;/* Active high */ + pclk-sample = <1>;/* Falling */ + }; + }; + /* port@1 and port@2 are not used by GTA04 */ + }; }; diff --git a/arch/arm/boot/dts/omap3-gta04a3.dts b/arch/arm/boot/dts/omap3-gta04a3.dts index 3099a892cf50..cc9244956679 100644 --- a/arch/arm/boot/dts/omap3-gta04a3.dts +++ b/arch/arm/boot/dts/omap3-gta04a3.dts @@ -9,7 +9,7 @@ #include "omap3-gta04.dtsi" / { - model = "Goldelico GTA04A3"; + model = "Goldelico GTA04A3/Letux 2804"; }; &i2c2 { diff --git a/arch/arm/boot/dts/omap3-gta04a4.dts b/arch/arm/boot/dts/omap3-gta04a4.dts index c918bb1f0529..77afc711fe4f 100644 --- a/arch/arm/boot/dts/omap3-gta04a4.dts +++ b/arch/arm/boot/dts/omap3-gta04a4.dts @@ -9,5 +9,5 @@ #include "omap3-gta04.dtsi" / { - model = "Goldelico GTA04A4"; + model = "Goldelico GTA04A4/Letux 2804"; }; diff --git a/arch/arm/boot/dts/omap3-gta04a5.dts b/arch/arm/boot/dts/omap3-gta04a5.dts index 600b6ca5a1bd..bd232b1b24cb 100644 --- a/arch/arm/boot/dts/omap3-gta04a5.dts +++ b/arch/arm/boot/dts/omap3-gta04a5.dts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 H. Nikolaus Schaller <hns@goldelico.com> + * Copyright (C) 2014-18 H. Nikolaus Schaller <hns@goldelico.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 @@ -9,9 +9,132 @@ #include "omap3-gta04.dtsi" / { - model = "Goldelico GTA04A5"; + model = "Goldelico GTA04A5/Letux 2804"; sound { - ti,jack-det-gpio = <&twl_gpio 2 GPIO_ACTIVE_HIGH>; /* GTA04A5 only */ + ti,jack-det-gpio = <&twl_gpio 2 GPIO_ACTIVE_HIGH>; /* GTA04A5 only */ + }; + + wlan_en: wlan_en_regulator { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&wlan_pins>; + regulator-name = "wlan-en-regulator"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>; /* GPIO_138 */ + + startup-delay-us = <70000>; + enable-active-high; + }; + + pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pps_pins>; + + gpios = <&gpio4 18 GPIO_ACTIVE_HIGH>; /* GPIN_114 */ + }; + +}; + +&gpio5 { + irda_en { + gpio-hog; + gpios = <(175-160) GPIO_ACTIVE_HIGH>; + output-high; /* activate gpio_175 to disable IrDA receiver */ + }; +}; + +&omap3_pmx_core { + bt_pins: pinmux_bt_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* mmc2_dat5 = mmc3_dat1 = gpio137 */ + >; + }; + + wlan_pins: pinmux_wlan_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* mmc2_dat6 = mmc3_dat2 = gpio138 */ + >; + }; + + wlan_irq_pin: pinmux_wlan_irq_pin { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT_PULLUP | MUX_MODE4) /* mmc2_dat7 = mmc3_dat3 = gpio139 */ + >; + }; + + irda_pins: pinmux_irda { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21d0, PIN_OUTPUT_PULLUP | MUX_MODE4) /* mcspi1_cs1 = gpio175 */ + >; + }; + + pps_pins: pinmux_pps_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2138, PIN_INPUT | MUX_MODE4) /* gpin114 */ + >; + }; + +}; + +/* + * for WL183x module see + * http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/net/wireless/ti,wlcore.txt + */ + +&wifi_pwrseq { + /delete-property/ reset-gpios; +}; + +&mmc2 { + vmmc-supply = <&wlan_en>; + bus-width = <4>; + cap-power-off-card; + non-removable; + + pinctrl-names = "default"; + pinctrl-0 = <&wlan_irq_pin>; + + #address-cells = <1>; + #size-cells = <0>; + + /delete-property/ mmc-pwrseq; + + wlcore: wlcore@2 { + compatible = "ti,wl1837"; + reg = <2>; + interrupt-parent = <&gpio5>; + interrupts = <11 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_139 */ + ref-clock-frequency = <26000000>; + }; +}; + +&i2c2 { + /delete-node/ bmp085@77; + /delete-node/ bma180@41; + /delete-node/ itg3200@68; + /delete-node/ hmc5843@1e; + + bmg160@69 { + compatible = "bosch,bmg160"; + reg = <0x69>; + }; + + bmc150@10 { + compatible = "bosch,bmc150_accel"; + reg = <0x10>; + }; + + bmc150@12 { + compatible = "bosch,bmc150_magn"; + reg = <0x12>; + }; + + bme280@76 { + compatible = "bosch,bme280"; + reg = <0x76>; }; }; diff --git a/arch/arm/boot/dts/omap3-gta04a5one.dts b/arch/arm/boot/dts/omap3-gta04a5one.dts new file mode 100644 index 000000000000..9b7bbdc344b3 --- /dev/null +++ b/arch/arm/boot/dts/omap3-gta04a5one.dts @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014-18 H. Nikolaus Schaller <hns@goldelico.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 + * published by the Free Software Foundation. + */ + +#include "omap3-gta04a5.dts" + +&omap3_pmx_core { + model = "Goldelico GTA04A5/Letux 2804 with OneNAND"; + + gpmc_pins: pinmux_gpmc_pins { + pinctrl-single,pins = < + + /* address lines */ + OMAP3_CORE1_IOPAD(0x207a, PIN_OUTPUT | MUX_MODE0) /* gpmc_a1.gpmc_a1 */ + OMAP3_CORE1_IOPAD(0x207c, PIN_OUTPUT | MUX_MODE0) /* gpmc_a2.gpmc_a2 */ + OMAP3_CORE1_IOPAD(0x207e, PIN_OUTPUT | MUX_MODE0) /* gpmc_a3.gpmc_a3 */ + + /* data lines, gpmc_d0..d7 not muxable according to TRM */ + OMAP3_CORE1_IOPAD(0x209e, PIN_INPUT | MUX_MODE0) /* gpmc_d8.gpmc_d8 */ + OMAP3_CORE1_IOPAD(0x20a0, PIN_INPUT | MUX_MODE0) /* gpmc_d9.gpmc_d9 */ + OMAP3_CORE1_IOPAD(0x20a2, PIN_INPUT | MUX_MODE0) /* gpmc_d10.gpmc_d10 */ + OMAP3_CORE1_IOPAD(0x20a4, PIN_INPUT | MUX_MODE0) /* gpmc_d11.gpmc_d11 */ + OMAP3_CORE1_IOPAD(0x20a6, PIN_INPUT | MUX_MODE0) /* gpmc_d12.gpmc_d12 */ + OMAP3_CORE1_IOPAD(0x20a8, PIN_INPUT | MUX_MODE0) /* gpmc_d13.gpmc_d13 */ + OMAP3_CORE1_IOPAD(0x20aa, PIN_INPUT | MUX_MODE0) /* gpmc_d14.gpmc_d14 */ + OMAP3_CORE1_IOPAD(0x20ac, PIN_INPUT | MUX_MODE0) /* gpmc_d15.gpmc_d15 */ + + /* + * gpmc_ncs0, gpmc_nadv_ale, gpmc_noe, gpmc_nwe, gpmc_wait0 not muxable + * according to TRM. OneNAND seems to require PIN_INPUT on clock. + */ + OMAP3_CORE1_IOPAD(0x20b0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ncs1.gpmc_ncs1 */ + OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0) /* gpmc_clk.gpmc_clk */ + >; + }; +}; + +&gpmc { + /* switch inherited setup to OneNAND */ + + ranges = <0 0 0x04000000 0x1000000>; /* CS0: 16MB for OneNAND */ + pinctrl-names = "default"; + pinctrl-0 = <&gpmc_pins>; + + /delete-node/ nand@0,0; + + onenand@0,0 { + + #address-cells = <1>; + #size-cells = <1>; + compatible = "ti,omap2-onenand"; + reg = <0 0 0x20000>; /* CS0, offset 0, IO size 128K */ + + gpmc,sync-read; + gpmc,sync-write; + gpmc,burst-length = <16>; + gpmc,burst-read; + gpmc,burst-wrap; + gpmc,burst-write; + gpmc,device-width = <2>; + gpmc,mux-add-data = <2>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <87>; + gpmc,cs-wr-off-ns = <87>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <10>; + gpmc,adv-wr-off-ns = <10>; + gpmc,oe-on-ns = <15>; + gpmc,oe-off-ns = <87>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <87>; + gpmc,rd-cycle-ns = <112>; + gpmc,wr-cycle-ns = <112>; + gpmc,access-ns = <81>; + gpmc,page-burst-access-ns = <15>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,clk-activation-ns = <5>; + gpmc,wr-data-mux-bus-ns = <30>; + gpmc,wr-access-ns = <81>; + gpmc,sync-clk-ps = <15000>; + + x-loader@0 { + label = "X-Loader"; + reg = <0 0x80000>; + }; + + bootloaders@80000 { + label = "U-Boot"; + reg = <0x80000 0x1c0000>; + }; + + bootloaders_env@240000 { + label = "U-Boot Env"; + reg = <0x240000 0x40000>; + }; + + kernel@280000 { + label = "Kernel"; + reg = <0x280000 0x600000>; + }; + + filesystem@880000 { + label = "File System"; + reg = <0x880000 0>; /* 0 = MTDPART_SIZ_FULL */ + }; + + }; +}; diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts index ded5fcf084eb..1f91646b8951 100644 --- a/arch/arm/boot/dts/omap3-n9.dts +++ b/arch/arm/boot/dts/omap3-n9.dts @@ -40,7 +40,7 @@ }; &i2c3 { - ak8975@0f { + ak8975@f { compatible = "asahi-kasei,ak8975"; reg = <0x0f>; }; diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi index ab6f640b282b..bf7ca00f4c21 100644 --- a/arch/arm/boot/dts/omap5-board-common.dtsi +++ b/arch/arm/boot/dts/omap5-board-common.dtsi @@ -700,6 +700,10 @@ vbus-supply = <&smps10_out1_reg>; }; +&dwc3 { + dr_mode = "otg"; +}; + &mcspi1 { }; diff --git a/arch/arm/boot/dts/orion5x-linkstation.dtsi b/arch/arm/boot/dts/orion5x-linkstation.dtsi index ebd93df5d07a..b6c9b85951ea 100644 --- a/arch/arm/boot/dts/orion5x-linkstation.dtsi +++ b/arch/arm/boot/dts/orion5x-linkstation.dtsi @@ -156,7 +156,7 @@ &i2c { status = "okay"; - rtc { + rtc@32 { compatible = "ricoh,rs5c372a"; reg = <0x32>; }; diff --git a/arch/arm/boot/dts/owl-s500-cubieboard6.dts b/arch/arm/boot/dts/owl-s500-cubieboard6.dts index ea4e01bce8d1..7c96c59b610d 100644 --- a/arch/arm/boot/dts/owl-s500-cubieboard6.dts +++ b/arch/arm/boot/dts/owl-s500-cubieboard6.dts @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Cubietech CubieBoard6 * * Copyright (c) 2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /dts-v1/; diff --git a/arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts b/arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts index 7be1d2eaf3f0..e610d49395d2 100644 --- a/arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts +++ b/arch/arm/boot/dts/owl-s500-guitar-bb-rev-b.dts @@ -1,7 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2016-2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /dts-v1/; diff --git a/arch/arm/boot/dts/owl-s500-guitar.dtsi b/arch/arm/boot/dts/owl-s500-guitar.dtsi index 079b2c02cc13..81cc39871f17 100644 --- a/arch/arm/boot/dts/owl-s500-guitar.dtsi +++ b/arch/arm/boot/dts/owl-s500-guitar.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * LeMaker Guitar SoM * * Copyright (c) 2016-2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ #include "owl-s500.dtsi" diff --git a/arch/arm/boot/dts/owl-s500.dtsi b/arch/arm/boot/dts/owl-s500.dtsi index 43c9980a4260..5ceb6cc4451d 100644 --- a/arch/arm/boot/dts/owl-s500.dtsi +++ b/arch/arm/boot/dts/owl-s500.dtsi @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Actions Semi S500 SoC * * Copyright (c) 2016-2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ #include <dt-bindings/interrupt-controller/arm-gic.h> diff --git a/arch/arm/boot/dts/pxa25x.dtsi b/arch/arm/boot/dts/pxa25x.dtsi index 95d59be97213..8494b5787170 100644 --- a/arch/arm/boot/dts/pxa25x.dtsi +++ b/arch/arm/boot/dts/pxa25x.dtsi @@ -80,6 +80,10 @@ #pwm-cells = <1>; clocks = <&clks CLK_PWM1>; }; + + rtc@40900000 { + clocks = <&clks CLK_OSC32k768>; + }; }; timer@40a00000 { diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi index 747f750f675d..3228ad5fb725 100644 --- a/arch/arm/boot/dts/pxa27x.dtsi +++ b/arch/arm/boot/dts/pxa27x.dtsi @@ -71,7 +71,7 @@ clocks = <&clks CLK_PWM1>; }; - pwri2c: i2c@40f000180 { + pwri2c: i2c@40f00180 { compatible = "mrvl,pxa-i2c"; reg = <0x40f00180 0x24>; interrupts = <6>; @@ -113,6 +113,10 @@ status = "disabled"; }; + + rtc@40900000 { + clocks = <&clks CLK_OSC32k768>; + }; }; clocks { diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi index a520b4c14ea9..080d5c5169b5 100644 --- a/arch/arm/boot/dts/pxa2xx.dtsi +++ b/arch/arm/boot/dts/pxa2xx.dtsi @@ -9,6 +9,25 @@ #include "skeleton.dtsi" #include "dt-bindings/clock/pxa-clock.h" +#define PMGROUP(pin) #pin +#define PMMUX(func, pin, af) \ + mux- ## func { \ + groups = PMGROUP(P ## pin); \ + function = #af; \ + } +#define PMMUX_LPM_LOW(func, pin, af) \ + mux- ## func { \ + groups = PMGROUP(P ## pin); \ + function = #af; \ + low-power-disable; \ + } +#define PMMUX_LPM_HIGH(func, pin, af) \ + mux- ## func { \ + groups = PMGROUP(P ## pin); \ + function = #af; \ + low-power-enable; \ + } + / { model = "Marvell PXA2xx family SoC"; compatible = "marvell,pxa2xx"; @@ -76,7 +95,7 @@ }; }; - ffuart: uart@40100000 { + ffuart: serial@40100000 { compatible = "mrvl,pxa-uart"; reg = <0x40100000 0x30>; interrupts = <22>; @@ -84,7 +103,7 @@ status = "disabled"; }; - btuart: uart@40200000 { + btuart: serial@40200000 { compatible = "mrvl,pxa-uart"; reg = <0x40200000 0x30>; interrupts = <21>; @@ -92,7 +111,7 @@ status = "disabled"; }; - stuart: uart@40700000 { + stuart: serial@40700000 { compatible = "mrvl,pxa-uart"; reg = <0x40700000 0x30>; interrupts = <20>; @@ -100,7 +119,7 @@ status = "disabled"; }; - hwuart: uart@41100000 { + hwuart: serial@41100000 { compatible = "mrvl,pxa-uart"; reg = <0x41100000 0x30>; interrupts = <7>; diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index 4a99c9255104..48c3cf427610 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi @@ -1611,10 +1611,11 @@ clocks = <&rpmcc RPM_QDSS_CLK>; clock-names = "apb_pclk"; - port { - etb_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out0>; + in-ports { + port { + etb_in: endpoint { + remote-endpoint = <&replicator_out0>; + }; }; }; }; @@ -1626,10 +1627,11 @@ clocks = <&rpmcc RPM_QDSS_CLK>; clock-names = "apb_pclk"; - port { - tpiu_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out1>; + in-ports { + port { + tpiu_in: endpoint { + remote-endpoint = <&replicator_out1>; + }; }; }; }; @@ -1640,7 +1642,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>; clock-names = "apb_pclk"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -1656,10 +1658,11 @@ remote-endpoint = <&tpiu_in>; }; }; - port@2 { - reg = <0>; + }; + + in-ports { + port { replicator_in: endpoint { - slave-mode; remote-endpoint = <&funnel_out>; }; }; @@ -1673,7 +1676,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>; clock-names = "apb_pclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; @@ -1687,33 +1690,31 @@ port@0 { reg = <0>; funnel_in0: endpoint { - slave-mode; remote-endpoint = <&etm0_out>; }; }; port@1 { reg = <1>; funnel_in1: endpoint { - slave-mode; remote-endpoint = <&etm1_out>; }; }; port@4 { reg = <4>; funnel_in4: endpoint { - slave-mode; remote-endpoint = <&etm2_out>; }; }; port@5 { reg = <5>; funnel_in5: endpoint { - slave-mode; remote-endpoint = <&etm3_out>; }; }; - port@8 { - reg = <0>; + }; + + out-ports { + port { funnel_out: endpoint { remote-endpoint = <&replicator_in>; }; @@ -1730,9 +1731,11 @@ cpu = <&CPU0>; - port { - etm0_out: endpoint { - remote-endpoint = <&funnel_in0>; + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&funnel_in0>; + }; }; }; }; @@ -1746,9 +1749,11 @@ cpu = <&CPU1>; - port { - etm1_out: endpoint { - remote-endpoint = <&funnel_in1>; + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&funnel_in1>; + }; }; }; }; @@ -1762,9 +1767,11 @@ cpu = <&CPU2>; - port { - etm2_out: endpoint { - remote-endpoint = <&funnel_in4>; + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&funnel_in4>; + }; }; }; }; @@ -1778,9 +1785,11 @@ cpu = <&CPU3>; - port { - etm3_out: endpoint { - remote-endpoint = <&funnel_in5>; + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&funnel_in5>; + }; }; }; }; diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi index 78db67337ed4..2d56008d8d6b 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -52,78 +52,85 @@ cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a7"; - enable-method = "qcom,kpss-acc-v1"; + enable-method = "qcom,kpss-acc-v2"; + next-level-cache = <&L2>; qcom,acc = <&acc0>; qcom,saw = <&saw0>; reg = <0x0>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; - operating-points = < - /* kHz uV (fixed) */ - 48000 1100000 - 200000 1100000 - 500000 1100000 - 716000 1100000 - >; clock-latency = <256000>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a7"; - enable-method = "qcom,kpss-acc-v1"; + enable-method = "qcom,kpss-acc-v2"; + next-level-cache = <&L2>; qcom,acc = <&acc1>; qcom,saw = <&saw1>; reg = <0x1>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; - operating-points = < - /* kHz uV (fixed) */ - 48000 1100000 - 200000 1100000 - 500000 1100000 - 666000 1100000 - >; clock-latency = <256000>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a7"; - enable-method = "qcom,kpss-acc-v1"; + enable-method = "qcom,kpss-acc-v2"; + next-level-cache = <&L2>; qcom,acc = <&acc2>; qcom,saw = <&saw2>; reg = <0x2>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; - operating-points = < - /* kHz uV (fixed) */ - 48000 1100000 - 200000 1100000 - 500000 1100000 - 666000 1100000 - >; clock-latency = <256000>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a7"; - enable-method = "qcom,kpss-acc-v1"; + enable-method = "qcom,kpss-acc-v2"; + next-level-cache = <&L2>; qcom,acc = <&acc3>; qcom,saw = <&saw3>; reg = <0x3>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; - operating-points = < - /* kHz uV (fixed) */ - 48000 1100000 - 200000 1100000 - 500000 1100000 - 666000 1100000 - >; clock-latency = <256000>; + operating-points-v2 = <&cpu0_opp_table>; }; + + L2: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + + cpu0_opp_table: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-48000000 { + opp-hz = /bits/ 64 <48000000>; + clock-latency-ns = <256000>; + }; + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + clock-latency-ns = <256000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + clock-latency-ns = <256000>; + }; + opp-716000000 { + opp-hz = /bits/ 64 <716000000>; + clock-latency-ns = <256000>; + }; }; pmu { @@ -291,49 +298,49 @@ status = "disabled"; }; - acc0: clock-controller@b088000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; - }; + acc0: clock-controller@b088000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; + }; - acc1: clock-controller@b098000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x0b098000 0x1000>, <0xb008000 0x1000>; - }; + acc1: clock-controller@b098000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b098000 0x1000>, <0xb008000 0x1000>; + }; - acc2: clock-controller@b0a8000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x0b0a8000 0x1000>, <0xb008000 0x1000>; - }; + acc2: clock-controller@b0a8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0a8000 0x1000>, <0xb008000 0x1000>; + }; - acc3: clock-controller@b0b8000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>; - }; + acc3: clock-controller@b0b8000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>; + }; - saw0: regulator@b089000 { - compatible = "qcom,saw2"; - reg = <0x02089000 0x1000>, <0x0b009000 0x1000>; + saw0: regulator@b089000 { + compatible = "qcom,saw2"; + reg = <0x0b089000 0x1000>, <0x0b009000 0x1000>; regulator; - }; + }; - saw1: regulator@b099000 { - compatible = "qcom,saw2"; - reg = <0x0b099000 0x1000>, <0x0b009000 0x1000>; - regulator; - }; + saw1: regulator@b099000 { + compatible = "qcom,saw2"; + reg = <0x0b099000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; - saw2: regulator@b0a9000 { - compatible = "qcom,saw2"; - reg = <0x0b0a9000 0x1000>, <0x0b009000 0x1000>; - regulator; - }; + saw2: regulator@b0a9000 { + compatible = "qcom,saw2"; + reg = <0x0b0a9000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; - saw3: regulator@b0b9000 { - compatible = "qcom,saw2"; - reg = <0x0b0b9000 0x1000>, <0x0b009000 0x1000>; - regulator; - }; + saw3: regulator@b0b9000 { + compatible = "qcom,saw2"; + reg = <0x0b0b9000 0x1000>, <0x0b009000 0x1000>; + regulator; + }; blsp1_uart1: serial@78af000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; @@ -387,7 +394,7 @@ #size-cells = <2>; ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000 - 0x82000000 0 0x48000000 0x48000000 0 0x10000000>; + 0x82000000 0 0x40300000 0x40300000 0 0x400000>; interrupts = <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>; interrupt-names = "msi"; diff --git a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts index bcf53e37ed93..554c65e7aa0e 100644 --- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts @@ -2,26 +2,8 @@ #include "qcom-ipq8064-v1.0.dtsi" / { - model = "Qualcomm IPQ8064/AP148"; - compatible = "qcom,ipq8064-ap148", "qcom,ipq8064"; - - aliases { - serial0 = &gsbi4_serial; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; + model = "Qualcomm Technologies, Inc. IPQ8064/AP-148"; + compatible = "qcom,ipq8064-ap148"; soc { pinmux@800000 { @@ -31,73 +13,22 @@ bias-disable; }; - spi_pins: spi_pins { + buttons_pins: buttons_pins { mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - drive-strength = <10>; - bias-none; + pins = "gpio54", "gpio65"; + drive-strength = <2>; + bias-pull-up; }; }; }; gsbi@16300000 { - qcom,mode = <GSBI_PROT_I2C_UART>; - status = "ok"; - serial@16340000 { + i2c@16380000 { status = "ok"; - }; - - i2c4: i2c@16380000 { - status = "ok"; - clock-frequency = <200000>; - pinctrl-0 = <&i2c4_pins>; pinctrl-names = "default"; }; }; - - gsbi5: gsbi@1a200000 { - qcom,mode = <GSBI_PROT_SPI>; - status = "ok"; - - spi4: spi@1a280000 { - status = "ok"; - spi-max-frequency = <50000000>; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 0>; - - flash: m25p80@0 { - compatible = "s25fl256s1"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - partition@0 { - label = "rootfs"; - reg = <0x0 0x1000000>; - }; - - partition@1 { - label = "scratch"; - reg = <0x1000000 0x1000000>; - }; - }; - }; - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - ports-implemented = <0x1>; - status = "ok"; - }; }; }; diff --git a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi index e1181194e8d3..e239a0486936 100644 --- a/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi @@ -1,2 +1,127 @@ // SPDX-License-Identifier: GPL-2.0 #include "qcom-ipq8064.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "Qualcomm Technologies, Inc. IPQ8064-v1.0"; + + aliases { + serial0 = &gsbi4_serial; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + gsbi@16300000 { + qcom,mode = <GSBI_PROT_I2C_UART>; + status = "ok"; + + serial@16340000 { + status = "ok"; + }; + }; + + gsbi5: gsbi@1a200000 { + qcom,mode = <GSBI_PROT_SPI>; + status = "ok"; + + spi4: spi@1a280000 { + status = "ok"; + spi-max-frequency = <50000000>; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 0>; + + flash: m25p80@0 { + compatible = "s25fl256s1"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + + partition@0 { + label = "rootfs"; + reg = <0x0 0x1000000>; + }; + + partition@1 { + label = "scratch"; + reg = <0x1000000 0x1000000>; + }; + }; + }; + }; + + sata-phy@1b400000 { + status = "ok"; + }; + + sata@29000000 { + ports-implemented = <0x1>; + status = "ok"; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&buttons_pins>; + pinctrl-names = "default"; + + button@1 { + label = "reset"; + linux,code = <KEY_RESTART>; + gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + button@2 { + label = "wps"; + linux,code = <KEY_WPS_BUTTON>; + gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&leds_pins>; + pinctrl-names = "default"; + + led@7 { + label = "led_usb1"; + gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "usbdev"; + default-state = "off"; + }; + + led@8 { + label = "led_usb3"; + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "usbdev"; + default-state = "off"; + }; + + led@9 { + label = "status_led_fail"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@26 { + label = "sata_led"; + gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@53 { + label = "status_led_pass"; + gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi index 70790ac242d1..f793cd1ad6d0 100644 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi @@ -2,8 +2,11 @@ /dts-v1/; #include "skeleton.dtsi" +#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/clock/qcom,gcc-ipq806x.h> #include <dt-bindings/clock/qcom,lcc-ipq806x.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/reset/qcom,gcc-ipq806x.h> #include <dt-bindings/soc/qcom,gsbi.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -114,6 +117,61 @@ interrupt-controller; #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; + }; + }; + + pcie1_pins: pcie1_pinmux { + mux { + 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; + }; + }; + + spi_pins: spi_pins { + mux { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + drive-strength = <10>; + bias-none; + }; + }; + + leds_pins: leds_pins { + mux { + 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; + }; + }; }; intc: interrupt-controller@2000000 { @@ -373,5 +431,233 @@ #reset-cells = <1>; }; + pcie0: pci@1b500000 { + compatible = "qcom,pcie-ipq8064"; + reg = <0x1b500000 0x1000 + 0x1b502000 0x80 + 0x1b600000 0x100 + 0x0ff00000 0x100000>; + reg-names = "dbi", "elbi", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <0>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x81000000 0 0x0fe00000 0x0fe00000 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x08000000 0x08000000 0 0x07e00000>; /* non-prefetchable memory */ + + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc PCIE_A_CLK>, + <&gcc PCIE_H_CLK>, + <&gcc PCIE_PHY_CLK>, + <&gcc PCIE_AUX_CLK>, + <&gcc PCIE_ALT_REF_CLK>; + clock-names = "core", "iface", "phy", "aux", "ref"; + + assigned-clocks = <&gcc PCIE_ALT_REF_CLK>; + assigned-clock-rates = <100000000>; + + resets = <&gcc PCIE_ACLK_RESET>, + <&gcc PCIE_HCLK_RESET>, + <&gcc PCIE_POR_RESET>, + <&gcc PCIE_PCI_RESET>, + <&gcc PCIE_PHY_RESET>, + <&gcc PCIE_EXT_RESET>; + reset-names = "axi", "ahb", "por", "pci", "phy", "ext"; + + pinctrl-0 = <&pcie0_pins>; + pinctrl-names = "default"; + + status = "disabled"; + perst-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; + }; + + pcie1: pci@1b700000 { + compatible = "qcom,pcie-ipq8064"; + reg = <0x1b700000 0x1000 + 0x1b702000 0x80 + 0x1b800000 0x100 + 0x31f00000 0x100000>; + reg-names = "dbi", "elbi", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x81000000 0 0x31e00000 0x31e00000 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x2e000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */ + + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 58 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 59 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 60 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 61 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc PCIE_1_A_CLK>, + <&gcc PCIE_1_H_CLK>, + <&gcc PCIE_1_PHY_CLK>, + <&gcc PCIE_1_AUX_CLK>, + <&gcc PCIE_1_ALT_REF_CLK>; + clock-names = "core", "iface", "phy", "aux", "ref"; + + assigned-clocks = <&gcc PCIE_1_ALT_REF_CLK>; + assigned-clock-rates = <100000000>; + + resets = <&gcc PCIE_1_ACLK_RESET>, + <&gcc PCIE_1_HCLK_RESET>, + <&gcc PCIE_1_POR_RESET>, + <&gcc PCIE_1_PCI_RESET>, + <&gcc PCIE_1_PHY_RESET>, + <&gcc PCIE_1_EXT_RESET>; + reset-names = "axi", "ahb", "por", "pci", "phy", "ext"; + + pinctrl-0 = <&pcie1_pins>; + pinctrl-names = "default"; + + status = "disabled"; + perst-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; + }; + + pcie2: pci@1b900000 { + compatible = "qcom,pcie-ipq8064"; + reg = <0x1b900000 0x1000 + 0x1b902000 0x80 + 0x1ba00000 0x100 + 0x35f00000 0x100000>; + reg-names = "dbi", "elbi", "parf", "config"; + device_type = "pci"; + linux,pci-domain = <2>; + bus-range = <0x00 0xff>; + num-lanes = <1>; + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x81000000 0 0x35e00000 0x35e00000 0 0x00100000 /* downstream I/O */ + 0x82000000 0 0x32000000 0x32000000 0 0x03e00000>; /* non-prefetchable memory */ + + interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi"; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 72 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ + <0 0 0 2 &intc 0 73 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ + <0 0 0 3 &intc 0 74 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ + <0 0 0 4 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc PCIE_2_A_CLK>, + <&gcc PCIE_2_H_CLK>, + <&gcc PCIE_2_PHY_CLK>, + <&gcc PCIE_2_AUX_CLK>, + <&gcc PCIE_2_ALT_REF_CLK>; + clock-names = "core", "iface", "phy", "aux", "ref"; + + assigned-clocks = <&gcc PCIE_2_ALT_REF_CLK>; + assigned-clock-rates = <100000000>; + + resets = <&gcc PCIE_2_ACLK_RESET>, + <&gcc PCIE_2_HCLK_RESET>, + <&gcc PCIE_2_POR_RESET>, + <&gcc PCIE_2_PCI_RESET>, + <&gcc PCIE_2_PHY_RESET>, + <&gcc PCIE_2_EXT_RESET>; + reset-names = "axi", "ahb", "por", "pci", "phy", "ext"; + + pinctrl-0 = <&pcie2_pins>; + pinctrl-names = "default"; + + status = "disabled"; + perst-gpio = <&qcom_pinmux 63 GPIO_ACTIVE_LOW>; + }; + + vsdcc_fixed: vsdcc-regulator { + compatible = "regulator-fixed"; + regulator-name = "SDCC Power"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sdcc1bam:dma@12402000 { + compatible = "qcom,bam-v1.3.0"; + reg = <0x12402000 0x8000>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc SDC1_H_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + + sdcc3bam:dma@12182000 { + compatible = "qcom,bam-v1.3.0"; + reg = <0x12182000 0x8000>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc SDC3_H_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; + }; + + amba { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sdcc@12400000 { + status = "disabled"; + compatible = "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00051180>; + reg = <0x12400000 0x2000>; + interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "cmd_irq"; + clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>; + clock-names = "mclk", "apb_pclk"; + bus-width = <8>; + max-frequency = <96000000>; + non-removable; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + vmmc-supply = <&vsdcc_fixed>; + dmas = <&sdcc1bam 2>, <&sdcc1bam 1>; + dma-names = "tx", "rx"; + }; + + sdcc@12180000 { + compatible = "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00051180>; + status = "disabled"; + reg = <0x12180000 0x2000>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "cmd_irq"; + clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>; + clock-names = "mclk", "apb_pclk"; + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <192000000>; + #mmc-ddr-1_8v; + sd-uhs-sdr104; + sd-uhs-ddr50; + vqmmc-supply = <&vsdcc_fixed>; + dmas = <&sdcc3bam 2>, <&sdcc3bam 1>; + dma-names = "tx", "rx"; + }; + }; }; }; diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts index c2dc9d09484a..ed8f064d0895 100644 --- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts +++ b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts @@ -241,6 +241,33 @@ bias-pull-up; }; }; + + i2c3_pins: i2c3 { + mux { + pins = "gpio10", "gpio11"; + function = "blsp_i2c3"; + drive-strength = <2>; + bias-disable; + }; + }; + + i2c12_pins: i2c12 { + mux { + pins = "gpio87", "gpio88"; + function = "blsp_i2c12"; + drive-strength = <2>; + bias-disable; + }; + }; + + mpu6515_pin: mpu6515 { + irq { + pins = "gpio73"; + function = "gpio"; + bias-disable; + input-enable; + }; + }; }; sdhci@f9824900 { @@ -277,6 +304,62 @@ linux,code = <KEY_VOLUMEDOWN>; }; }; + + i2c@f9968000 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c12_pins>; + clock-frequency = <100000>; + qcom,src-freq = <50000000>; + + mpu6515@68 { + compatible = "invensense,mpu6515"; + reg = <0x68>; + interrupts-extended = <&msmgpio 73 IRQ_TYPE_EDGE_FALLING>; + vddio-supply = <&pm8941_lvs1>; + + pinctrl-names = "default"; + pinctrl-0 = <&mpu6515_pin>; + + i2c-gate { + #address-cells = <1>; + #size-cells = <0>; + ak8963@f { + compatible = "asahi-kasei,ak8963"; + reg = <0x0f>; + // Currently only works in polling mode. + // gpios = <&msmgpio 61 0>; + vid-supply = <&pm8941_lvs1>; + vdd-supply = <&pm8941_l17>; + }; + + bmp280@76 { + compatible = "bosch,bmp280"; + reg = <0x76>; + vdda-supply = <&pm8941_lvs1>; + vddd-supply = <&pm8941_l17>; + }; + }; + }; + }; + + i2c@f9925000 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + clock-frequency = <100000>; + qcom,src-freq = <50000000>; + + avago_apds993@39 { + compatible = "avago,apds9930"; + reg = <0x39>; + interrupts-extended = <&msmgpio 61 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&pm8941_l17>; + vddio-supply = <&pm8941_lvs1>; + led-max-microamp = <100000>; + amstaos,proximity-diodes = <0>; + }; + }; }; &spmi_bus { diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index d9019a49b292..aba159d5a95a 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -67,7 +67,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; - interrupts = <1 9 0xf04>; + interrupts = <GIC_PPI 9 0xf04>; CPU0: cpu@0 { compatible = "qcom,krait"; @@ -214,7 +214,7 @@ cpu-pmu { compatible = "qcom,krait-pmu"; - interrupts = <1 7 0xf04>; + interrupts = <GIC_PPI 7 0xf04>; }; clocks { @@ -233,17 +233,17 @@ timer { compatible = "arm,armv7-timer"; - interrupts = <1 2 0xf08>, - <1 3 0xf08>, - <1 4 0xf08>, - <1 1 0xf08>; + interrupts = <GIC_PPI 2 0xf08>, + <GIC_PPI 3 0xf08>, + <GIC_PPI 4 0xf08>, + <GIC_PPI 1 0xf08>; clock-frequency = <19200000>; }; adsp-pil { compatible = "qcom,msm8974-adsp-pil"; - interrupts-extended = <&intc 0 162 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, @@ -275,7 +275,7 @@ qcom,smem = <443>, <429>; interrupt-parent = <&intc>; - interrupts = <0 158 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 10>; @@ -300,7 +300,7 @@ qcom,smem = <435>, <428>; interrupt-parent = <&intc>; - interrupts = <0 27 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 14>; @@ -325,7 +325,7 @@ qcom,smem = <451>, <431>; interrupt-parent = <&intc>; - interrupts = <0 143 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 18>; @@ -364,7 +364,7 @@ modem_smsm: modem@1 { reg = <1>; - interrupts = <0 26 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; interrupt-controller; #interrupt-cells = <2>; @@ -372,7 +372,7 @@ adsp_smsm: adsp@2 { reg = <2>; - interrupts = <0 157 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 157 IRQ_TYPE_EDGE_RISING>; interrupt-controller; #interrupt-cells = <2>; @@ -380,7 +380,7 @@ wcnss_smsm: wcnss@7 { reg = <7>; - interrupts = <0 144 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>; interrupt-controller; #interrupt-cells = <2>; @@ -445,50 +445,50 @@ frame@f9021000 { frame-number = <0>; - interrupts = <0 8 0x4>, - <0 7 0x4>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9021000 0x1000>, <0xf9022000 0x1000>; }; frame@f9023000 { frame-number = <1>; - interrupts = <0 9 0x4>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9023000 0x1000>; status = "disabled"; }; frame@f9024000 { frame-number = <2>; - interrupts = <0 10 0x4>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9024000 0x1000>; status = "disabled"; }; frame@f9025000 { frame-number = <3>; - interrupts = <0 11 0x4>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9025000 0x1000>; status = "disabled"; }; frame@f9026000 { frame-number = <4>; - interrupts = <0 12 0x4>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9026000 0x1000>; status = "disabled"; }; frame@f9027000 { frame-number = <5>; - interrupts = <0 13 0x4>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9027000 0x1000>; status = "disabled"; }; frame@f9028000 { frame-number = <6>; - interrupts = <0 14 0x4>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; reg = <0xf9028000 0x1000>; status = "disabled"; }; @@ -586,7 +586,7 @@ blsp1_uart1: serial@f991d000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0xf991d000 0x1000>; - interrupts = <0 107 0x0>; + interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; status = "disabled"; @@ -595,7 +595,7 @@ blsp1_uart2: serial@f991e000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0xf991e000 0x1000>; - interrupts = <0 108 0x0>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; status = "disabled"; @@ -605,7 +605,8 @@ compatible = "qcom,sdhci-msm-v4"; reg = <0xf9824900 0x11c>, <0xf9824000 0x800>; reg-names = "hc_mem", "core_mem"; - interrupts = <0 123 0>, <0 138 0>; + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>, @@ -618,8 +619,8 @@ compatible = "qcom,sdhci-msm-v4"; reg = <0xf9864900 0x11c>, <0xf9864000 0x800>; reg-names = "hc_mem", "core_mem"; - interrupts = <GIC_SPI 127 IRQ_TYPE_NONE>, - <GIC_SPI 224 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC3_APPS_CLK>, <&gcc GCC_SDCC3_AHB_CLK>, @@ -632,7 +633,8 @@ compatible = "qcom,sdhci-msm-v4"; reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>; reg-names = "hc_mem", "core_mem"; - interrupts = <0 125 0>, <0 221 0>; + interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>, @@ -699,25 +701,36 @@ #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; - interrupts = <0 208 0>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; }; i2c@f9924000 { status = "disabled"; compatible = "qcom,i2c-qup-v2.1.1"; reg = <0xf9924000 0x1000>; - interrupts = <0 96 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; clock-names = "core", "iface"; #address-cells = <1>; #size-cells = <0>; }; + blsp_i2c3: i2c@f9925000 { + status = "disabled"; + compatible = "qcom,i2c-qup-v2.1.1"; + reg = <0xf9925000 0x1000>; + interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + #address-cells = <1>; + #size-cells = <0>; + }; + blsp_i2c8: i2c@f9964000 { status = "disabled"; compatible = "qcom,i2c-qup-v2.1.1"; reg = <0xf9964000 0x1000>; - interrupts = <0 102 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_BLSP2_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; clock-names = "core", "iface"; #address-cells = <1>; @@ -728,7 +741,7 @@ status = "disabled"; compatible = "qcom,i2c-qup-v2.1.1"; reg = <0xf9967000 0x1000>; - interrupts = <0 105 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&gcc GCC_BLSP2_QUP5_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; clock-names = "core", "iface"; #address-cells = <1>; @@ -737,6 +750,17 @@ dma-names = "tx", "rx"; }; + blsp_i2c12: i2c@f9968000 { + status = "disabled"; + compatible = "qcom,i2c-qup-v2.1.1"; + reg = <0xf9968000 0x1000>; + interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc GCC_BLSP2_QUP6_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + #address-cells = <1>; + #size-cells = <0>; + }; + spmi_bus: spmi@fc4cf000 { compatible = "qcom,spmi-pmic-arb"; reg-names = "core", "intr", "cnfg"; @@ -744,7 +768,7 @@ <0xfc4cb000 0x1000>, <0xfc4ca000 0x1000>; interrupt-names = "periph_irq"; - interrupts = <0 190 0>; + interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; qcom,ee = <0>; qcom,channel = <0>; #address-cells = <2>; @@ -770,10 +794,11 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - port { - etr_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out0>; + in-ports { + port { + etr_in: endpoint { + remote-endpoint = <&replicator_out0>; + }; }; }; }; @@ -785,10 +810,11 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - port { - tpiu_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out1>; + in-ports { + port { + tpiu_in: endpoint { + remote-endpoint = <&replicator_out1>; + }; }; }; }; @@ -800,7 +826,7 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -816,10 +842,11 @@ remote-endpoint = <&tpiu_in>; }; }; - port@2 { - reg = <0>; + }; + + in-ports { + port { replicator_in: endpoint { - slave-mode; remote-endpoint = <&etf_out>; }; }; @@ -833,20 +860,17 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + out-ports { + port { etf_out: endpoint { remote-endpoint = <&replicator_in>; }; }; - port@1 { - reg = <0>; + }; + + in-ports { + port { etf_in: endpoint { - slave-mode; remote-endpoint = <&merger_out>; }; }; @@ -860,7 +884,7 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; @@ -873,12 +897,13 @@ port@1 { reg = <1>; merger_in1: endpoint { - slave-mode; remote-endpoint = <&funnel1_out>; }; }; - port@8 { - reg = <0>; + }; + + out-ports { + port { merger_out: endpoint { remote-endpoint = <&etf_in>; }; @@ -893,7 +918,7 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; @@ -910,12 +935,13 @@ port@5 { reg = <5>; funnel1_in5: endpoint { - slave-mode; remote-endpoint = <&kpss_out>; }; }; - port@8 { - reg = <0>; + }; + + out-ports { + port { funnel1_out: endpoint { remote-endpoint = <&merger_in1>; }; @@ -930,40 +956,38 @@ clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; kpss_in0: endpoint { - slave-mode; remote-endpoint = <&etm0_out>; }; }; port@1 { reg = <1>; kpss_in1: endpoint { - slave-mode; remote-endpoint = <&etm1_out>; }; }; port@2 { reg = <2>; kpss_in2: endpoint { - slave-mode; remote-endpoint = <&etm2_out>; }; }; port@3 { reg = <3>; kpss_in3: endpoint { - slave-mode; remote-endpoint = <&etm3_out>; }; }; - port@8 { - reg = <0>; + }; + + out-ports { + port { kpss_out: endpoint { remote-endpoint = <&funnel1_in5>; }; @@ -980,9 +1004,11 @@ cpu = <&CPU0>; - port { - etm0_out: endpoint { - remote-endpoint = <&kpss_in0>; + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&kpss_in0>; + }; }; }; }; @@ -996,9 +1022,11 @@ cpu = <&CPU1>; - port { - etm1_out: endpoint { - remote-endpoint = <&kpss_in1>; + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&kpss_in1>; + }; }; }; }; @@ -1012,9 +1040,11 @@ cpu = <&CPU2>; - port { - etm2_out: endpoint { - remote-endpoint = <&kpss_in2>; + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&kpss_in2>; + }; }; }; }; @@ -1028,9 +1058,11 @@ cpu = <&CPU3>; - port { - etm3_out: endpoint { - remote-endpoint = <&kpss_in3>; + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&kpss_in3>; + }; }; }; }; @@ -1040,21 +1072,21 @@ compatible = "qcom,smd"; adsp { - interrupts = <0 156 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 8>; qcom,smd-edge = <1>; }; modem { - interrupts = <0 25 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 12>; qcom,smd-edge = <0>; }; rpm { - interrupts = <0 168 1>; + interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; qcom,ipc = <&apcs 8 0>; qcom,smd-edge = <15>; diff --git a/arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts b/arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts index 327545119ee3..0d006aea99da 100644 --- a/arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts +++ b/arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts @@ -14,3 +14,7 @@ model = "iW-RainboW-G20D-Q7 RZ/G1M based plus camera daughter board"; compatible = "iwave,g20d", "iwave,g20m", "renesas,r8a7743"; }; + +&pciec { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/r8a7743-iwg20d-q7.dts b/arch/arm/boot/dts/r8a7743-iwg20d-q7.dts index b683db4da8b1..498e223a5f93 100644 --- a/arch/arm/boot/dts/r8a7743-iwg20d-q7.dts +++ b/arch/arm/boot/dts/r8a7743-iwg20d-q7.dts @@ -13,3 +13,7 @@ model = "iWave Systems RainboW-G20D-Qseven board based on RZ/G1M"; compatible = "iwave,g20d", "iwave,g20m", "renesas,r8a7743"; }; + +&pciec { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts index e3585daafdd6..22da819f186b 100644 --- a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts +++ b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts @@ -35,6 +35,8 @@ phy3: ethernet-phy@3 { reg = <3>; + interrupt-parent = <&gpio5>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; micrel,led-mode = <1>; }; }; @@ -43,6 +45,16 @@ clock-frequency = <20000000>; }; +&pfc { + scif1_pins: scif1 { + groups = "scif1_data_b"; + function = "scif1"; + }; +}; + &scif1 { + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; }; diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi index 87d32d3e23de..9ec78d3d0ca8 100644 --- a/arch/arm/boot/dts/r8a77470.dtsi +++ b/arch/arm/boot/dts/r8a77470.dtsi @@ -8,6 +8,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/clock/r8a77470-cpg-mssr.h> +#include <dt-bindings/power/r8a77470-sysc.h> / { compatible = "renesas,r8a77470"; #address-cells = <2>; @@ -16,6 +17,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; + enable-method = "renesas,apmu"; cpu0: cpu@0 { device_type = "cpu"; @@ -23,16 +25,25 @@ reg = <0>; clock-frequency = <1000000000>; clocks = <&cpg CPG_CORE R8A77470_CLK_Z2>; - power-domains = <&sysc 5>; + power-domains = <&sysc R8A77470_PD_CA7_CPU0>; next-level-cache = <&L2_CA7>; }; + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <1>; + clock-frequency = <1000000000>; + clocks = <&cpg CPG_CORE R8A77470_CLK_Z2>; + power-domains = <&sysc R8A77470_PD_CA7_CPU1>; + next-level-cache = <&L2_CA7>; + }; L2_CA7: cache-controller-0 { compatible = "cache"; cache-unified; cache-level = <2>; - power-domains = <&sysc 21>; + power-domains = <&sysc R8A77470_PD_CA7_SCU>; }; }; @@ -60,6 +71,102 @@ #size-cells = <2>; ranges; + gpio0: gpio@e6050000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6050000 0 0x50>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 0 23>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 912>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 912>; + }; + + gpio1: gpio@e6051000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6051000 0 0x50>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 32 23>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 911>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 911>; + }; + + gpio2: gpio@e6052000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6052000 0 0x50>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 64 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 910>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 910>; + }; + + gpio3: gpio@e6053000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6053000 0 0x50>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 96 30>; + gpio-reserved-ranges = <17 10>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 909>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 909>; + }; + + gpio4: gpio@e6054000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6054000 0 0x50>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 128 26>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 908>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 908>; + }; + + gpio5: gpio@e6055000 { + compatible = "renesas,gpio-r8a77470", + "renesas,rcar-gen2-gpio"; + reg = <0 0xe6055000 0 0x50>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 160 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 907>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 907>; + }; + + pfc: pin-controller@e6060000 { + compatible = "renesas,pfc-r8a77470"; + reg = <0 0xe6060000 0 0x118>; + }; + cpg: clock-controller@e6150000 { compatible = "renesas,r8a77470-cpg-mssr"; reg = <0 0xe6150000 0 0x1000>; @@ -70,6 +177,12 @@ #reset-cells = <1>; }; + apmu@e6151000 { + compatible = "renesas,r8a77470-apmu", "renesas,apmu"; + reg = <0 0xe6151000 0 0x188>; + cpus = <&cpu0 &cpu1>; + }; + rst: reset-controller@e6160000 { compatible = "renesas,r8a77470-rst"; reg = <0 0xe6160000 0 0x100>; @@ -97,7 +210,7 @@ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 407>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 407>; }; @@ -124,6 +237,20 @@ reg = <0 0xe6300000 0 0x20000>; }; + i2c4: i2c@e6520000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77470", + "renesas,rcar-gen2-i2c"; + reg = <0 0xe6520000 0 0x40>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 927>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 927>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a77470", "renesas,rcar-dmac"; @@ -151,7 +278,7 @@ "ch12", "ch13", "ch14"; clocks = <&cpg CPG_MOD 219>; clock-names = "fck"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 219>; #dma-cells = <1>; dma-channels = <15>; @@ -184,7 +311,7 @@ "ch12", "ch13", "ch14"; clocks = <&cpg CPG_MOD 218>; clock-names = "fck"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 218>; #dma-cells = <1>; dma-channels = <15>; @@ -196,7 +323,7 @@ reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>; interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 812>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 812>; #address-cells = <1>; #size-cells = <0>; @@ -214,7 +341,7 @@ dmas = <&dmac0 0x29>, <&dmac0 0x2a>, <&dmac1 0x29>, <&dmac1 0x2a>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 721>; status = "disabled"; }; @@ -230,7 +357,7 @@ dmas = <&dmac0 0x2d>, <&dmac0 0x2e>, <&dmac1 0x2d>, <&dmac1 0x2e>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 720>; status = "disabled"; }; @@ -246,7 +373,7 @@ dmas = <&dmac0 0x2b>, <&dmac0 0x2c>, <&dmac1 0x2b>, <&dmac1 0x2c>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 719>; status = "disabled"; }; @@ -262,7 +389,7 @@ dmas = <&dmac0 0x2f>, <&dmac0 0x30>, <&dmac1 0x2f>, <&dmac1 0x30>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 718>; status = "disabled"; }; @@ -278,7 +405,7 @@ dmas = <&dmac0 0xfb>, <&dmac0 0xfc>, <&dmac1 0xfb>, <&dmac1 0xfc>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 715>; status = "disabled"; }; @@ -294,11 +421,26 @@ dmas = <&dmac0 0xfd>, <&dmac0 0xfe>, <&dmac1 0xfd>, <&dmac1 0xfe>; dma-names = "tx", "rx", "tx", "rx"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 714>; status = "disabled"; }; + sdhi2: sd@ee160000 { + compatible = "renesas,sdhi-r8a77470", + "renesas,rcar-gen2-sdhi"; + reg = <0 0xee160000 0 0x328>; + interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 312>; + dmas = <&dmac0 0xd3>, <&dmac0 0xd4>, + <&dmac1 0xd3>, <&dmac1 0xd4>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <97500000>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; + resets = <&cpg 312>; + status = "disabled"; + }; + gic: interrupt-controller@f1001000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; @@ -309,7 +451,7 @@ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; clocks = <&cpg CPG_MOD 408>; clock-names = "clk"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77470_PD_ALWAYS_ON>; resets = <&cpg 408>; }; diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts index de808d2ea856..cecb22924ec4 100644 --- a/arch/arm/boot/dts/r8a7778-bockw.dts +++ b/arch/arm/boot/dts/r8a7778-bockw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Reference Device Tree Source for the Bock-W board + * Reference Device Tree Source for the R-Car M1A (R8A77781) Bock-W board * * Copyright (C) 2013 Renesas Solutions Corp. * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi index 1bce16cc6b20..05db0ccad7a6 100644 --- a/arch/arm/boot/dts/r8a7778.dtsi +++ b/arch/arm/boot/dts/r8a7778.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for Renesas r8a7778 + * Device Tree Source for the R-Car M1A (R8A77781) SoC * * Copyright (C) 2013 Renesas Solutions Corp. * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts index a4d0038363f0..abc14e7a4c93 100644 --- a/arch/arm/boot/dts/r8a7779-marzen.dts +++ b/arch/arm/boot/dts/r8a7779-marzen.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the Marzen board + * Device Tree Source for the R-Car H1 (R8A77790) Marzen board * * Copyright (C) 2013 Renesas Solutions Corp. * Copyright (C) 2013 Simon Horman diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index 6b997bc016ee..3bc133d9489c 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for Renesas r8a7779 + * Device Tree Source for the R-Car H1 (R8A77790) SoC * * Copyright (C) 2013 Renesas Solutions Corp. * Copyright (C) 2013 Simon Horman @@ -344,7 +344,7 @@ sata: sata@fc600000 { compatible = "renesas,sata-r8a7779", "renesas,rcar-sata"; - reg = <0xfc600000 0x2000>; + reg = <0xfc600000 0x200000>; interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7779_CLK_SATA>; power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; diff --git a/arch/arm/boot/dts/r8a7790-stout.dts b/arch/arm/boot/dts/r8a7790-stout.dts index a13a92c26645..629da4cee1b9 100644 --- a/arch/arm/boot/dts/r8a7790-stout.dts +++ b/arch/arm/boot/dts/r8a7790-stout.dts @@ -318,6 +318,10 @@ interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupt-controller; + onkey { + compatible = "dlg,da9063-onkey"; + }; + rtc { compatible = "dlg,da9063-rtc"; }; diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 0925bdca438f..5a2747758f67 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7790 SoC + * Device Tree Source for the R-Car H2 (R8A77900) SoC * * Copyright (C) 2015 Renesas Electronics Corporation * Copyright (C) 2013-2014 Renesas Solutions Corp. @@ -1559,7 +1559,7 @@ sata0: sata@ee300000 { compatible = "renesas,sata-r8a7790", "renesas,rcar-gen2-sata"; - reg = <0 0xee300000 0 0x2000>; + reg = <0 0xee300000 0 0x200000>; interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 815>; power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; @@ -1570,7 +1570,7 @@ sata1: sata@ee500000 { compatible = "renesas,sata-r8a7790", "renesas,rcar-gen2-sata"; - reg = <0 0xee500000 0 0x2000>; + reg = <0 0xee500000 0 0x200000>; interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 814>; power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 991ac6feedd5..6f875502453c 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7791 SoC + * Device Tree Source for the R-Car M2-W (R8A77910) SoC * * Copyright (C) 2013-2015 Renesas Electronics Corporation * Copyright (C) 2013-2014 Renesas Solutions Corp. @@ -1543,7 +1543,7 @@ sata0: sata@ee300000 { compatible = "renesas,sata-r8a7791", "renesas,rcar-gen2-sata"; - reg = <0 0xee300000 0 0x2000>; + reg = <0 0xee300000 0 0x200000>; interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 815>; power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; @@ -1554,7 +1554,7 @@ sata1: sata@ee500000 { compatible = "renesas,sata-r8a7791", "renesas,rcar-gen2-sata"; - reg = <0 0xee500000 0 0x2000>; + reg = <0 0xee500000 0 0x200000>; interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 814>; power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; diff --git a/arch/arm/boot/dts/r8a7792.dtsi b/arch/arm/boot/dts/r8a7792.dtsi index 63a978ec81cc..8e9eb4b704d3 100644 --- a/arch/arm/boot/dts/r8a7792.dtsi +++ b/arch/arm/boot/dts/r8a7792.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7792 SoC + * Device Tree Source for the R-Car V2H (R8A77920) SoC * * Copyright (C) 2016 Cogent Embedded Inc. */ @@ -829,7 +829,6 @@ du: display@feb00000 { compatible = "renesas,du-r8a7792"; reg = <0 0xfeb00000 0 0x40000>; - reg-names = "du"; interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 724>, diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts index 6b2f3a4fd13d..f51601af89a2 100644 --- a/arch/arm/boot/dts/r8a7793-gose.dts +++ b/arch/arm/boot/dts/r8a7793-gose.dts @@ -596,6 +596,10 @@ status = "okay"; }; +&cpu0 { + cpu0-supply = <&vdd_dvfs>; +}; + &rwdt { timeout-sec = <60>; status = "okay"; @@ -725,6 +729,18 @@ compatible = "dlg,da9063-watchdog"; }; }; + + vdd_dvfs: regulator@68 { + compatible = "dlg,da9210"; + reg = <0x68>; + interrupt-parent = <&irqc0>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + }; }; &i2c4 { diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi index 620a570307ff..bf05110fac4e 100644 --- a/arch/arm/boot/dts/r8a7793.dtsi +++ b/arch/arm/boot/dts/r8a7793.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7793 SoC + * Device Tree Source for the R-Car M2-N (R8A77930) SoC * * Copyright (C) 2014-2015 Renesas Electronics Corporation */ diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts index daec965889d3..60e91ebfa65d 100644 --- a/arch/arm/boot/dts/r8a7794-silk.dts +++ b/arch/arm/boot/dts/r8a7794-silk.dts @@ -405,6 +405,31 @@ clock-frequency = <400000>; }; +&i2c7 { + status = "okay"; + clock-frequency = <100000>; + + pmic@58 { + compatible = "dlg,da9063"; + reg = <0x58>; + interrupt-parent = <&gpio3>; + interrupts = <31 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + + onkey { + compatible = "dlg,da9063-onkey"; + }; + + rtc { + compatible = "dlg,da9063-rtc"; + }; + + wdt { + compatible = "dlg,da9063-watchdog"; + }; + }; +}; + &mmcif0 { pinctrl-0 = <&mmcif0_pins>; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index ea2ca4bdaf1c..8d797d34816e 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7794 SoC + * Device Tree Source for the R-Car E2 (R8A77940) SoC * * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2014 Ulrich Hecht @@ -1349,7 +1349,6 @@ du: display@feb00000 { compatible = "renesas,du-r8a7794"; reg = <0 0xfeb00000 0 0x40000>; - reg-names = "du"; interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>; diff --git a/arch/arm/boot/dts/r9a06g032.dtsi b/arch/arm/boot/dts/r9a06g032.dtsi index afe29c95a006..eaf94976ed6d 100644 --- a/arch/arm/boot/dts/r9a06g032.dtsi +++ b/arch/arm/boot/dts/r9a06g032.dtsi @@ -7,6 +7,7 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/r9a06g032-sysctrl.h> / { compatible = "renesas,r9a06g032"; @@ -21,14 +22,14 @@ device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0>; - clocks = <&sysctrl 84>; + clocks = <&sysctrl R9A06G032_CLK_A7MP>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <1>; - clocks = <&sysctrl 84>; + clocks = <&sysctrl R9A06G032_CLK_A7MP>; enable-method = "renesas,r9a06g032-smp"; cpu-release-addr = <0 0x4000c204>; }; @@ -77,13 +78,90 @@ }; uart0: serial@40060000 { - compatible = "snps,dw-apb-uart"; + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart", "snps,dw-apb-uart"; reg = <0x40060000 0x400>; interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&sysctrl 146>; - clock-names = "baudclk"; + clocks = <&sysctrl R9A06G032_CLK_UART0>, <&sysctrl R9A06G032_HCLK_UART0>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart1: serial@40061000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart", "snps,dw-apb-uart"; + reg = <0x40061000 0x400>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART1>, <&sysctrl R9A06G032_HCLK_UART1>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart2: serial@40062000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart", "snps,dw-apb-uart"; + reg = <0x40062000 0x400>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART2>, <&sysctrl R9A06G032_HCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart3: serial@50000000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart"; + reg = <0x50000000 0x400>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART3>, <&sysctrl R9A06G032_HCLK_UART3>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart4: serial@50001000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart"; + reg = <0x50001000 0x400>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART4>, <&sysctrl R9A06G032_HCLK_UART4>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart5: serial@50002000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart"; + reg = <0x50002000 0x400>; + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART5>, <&sysctrl R9A06G032_HCLK_UART5>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart6: serial@50003000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart"; + reg = <0x50003000 0x400>; + interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART6>, <&sysctrl R9A06G032_HCLK_UART6>; + clock-names = "baudclk", "apb_pclk"; + status = "disabled"; + }; + + uart7: serial@50004000 { + compatible = "renesas,r9a06g032-uart", "renesas,rzn1-uart"; + reg = <0x50004000 0x400>; + interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&sysctrl R9A06G032_CLK_UART7>, <&sysctrl R9A06G032_HCLK_UART7>; + clock-names = "baudclk", "apb_pclk"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 67f57200d9a0..d560fc4051c5 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -733,7 +733,7 @@ /* no rts / cts for uart2 */ }; - spi { + spi-pins { spi_txd:spi-txd { rockchip,pins = <1 29 RK_FUNC_3 &pcfg_pull_default>; }; diff --git a/arch/arm/boot/dts/rk3188-radxarock.dts b/arch/arm/boot/dts/rk3188-radxarock.dts index 45fd2b302dda..4a2890618f6f 100644 --- a/arch/arm/boot/dts/rk3188-radxarock.dts +++ b/arch/arm/boot/dts/rk3188-radxarock.dts @@ -93,6 +93,8 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; startup-delay-us = <100000>; vin-supply = <&vcc_io>; }; @@ -315,6 +317,12 @@ }; }; + sd0 { + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <RK_GPIO3 1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb { host_vbus_drv: host-vbus-drv { rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index aa123f93f181..b6f790973736 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -56,6 +56,11 @@ }; }; + display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vop0_out>, <&vop1_out>; + }; + sram: sram@10080000 { compatible = "mmio-sram"; reg = <0x10080000 0x8000>; @@ -69,6 +74,38 @@ }; }; + vop0: vop@1010c000 { + compatible = "rockchip,rk3188-vop"; + reg = <0x1010c000 0x1000>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_LCDC0>, <&cru DCLK_LCDC0>, <&cru HCLK_LCDC0>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; + reset-names = "axi", "ahb", "dclk"; + status = "disabled"; + + vop0_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + vop1: vop@1010e000 { + compatible = "rockchip,rk3188-vop"; + reg = <0x1010e000 0x1000>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_LCDC1>, <&cru DCLK_LCDC1>, <&cru HCLK_LCDC1>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_LCDC1_AXI>, <&cru SRST_LCDC1_AHB>, <&cru SRST_LCDC1_DCLK>; + reset-names = "axi", "ahb", "dclk"; + status = "disabled"; + + vop1_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + timer3: timer@2000e000 { compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; reg = <0x2000e000 0x20>; @@ -309,6 +346,51 @@ }; }; + lcdc1 { + lcdc1_dclk: lcdc1-dclk { + rockchip,pins = <2 RK_PD0 RK_FUNC_1 &pcfg_pull_none>; + }; + + lcdc1_den: lcdc1-den { + rockchip,pins = <2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>; + }; + + lcdc1_hsync: lcdc1-hsync { + rockchip,pins = <2 RK_PD2 RK_FUNC_1 &pcfg_pull_none>; + }; + + lcdc1_vsync: lcdc1-vsync { + rockchip,pins = <2 RK_PD3 RK_FUNC_1 &pcfg_pull_none>; + }; + + lcdc1_rgb24: ldcd1-rgb24 { + rockchip,pins = <2 RK_PA0 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA1 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA2 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA3 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA4 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA5 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA6 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PA7 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB0 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB1 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB2 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB3 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB4 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB5 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB6 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PB7 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC0 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC1 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC2 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC3 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC4 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC5 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC6 RK_FUNC_1 &pcfg_pull_none>, + <2 RK_PC7 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + pwm0 { pwm0_out: pwm0-out { rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_none>; diff --git a/arch/arm/boot/dts/rk3288-tinker-s.dts b/arch/arm/boot/dts/rk3288-tinker-s.dts new file mode 100644 index 000000000000..37093922b482 --- /dev/null +++ b/arch/arm/boot/dts/rk3288-tinker-s.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rk3288-tinker.dtsi" + +/ { + model = "Rockchip RK3288 Asus Tinker Board S"; + compatible = "asus,rk3288-tinker-s", "rockchip,rk3288"; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + disable-wp; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; + max-frequency = <150000000>; + mmc-hs200-1_8v; + mmc-ddr-1_8v; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/rk3288-tinker.dts b/arch/arm/boot/dts/rk3288-tinker.dts index ceade5962899..1e43527aa196 100644 --- a/arch/arm/boot/dts/rk3288-tinker.dts +++ b/arch/arm/boot/dts/rk3288-tinker.dts @@ -5,503 +5,9 @@ /dts-v1/; -#include "rk3288.dtsi" -#include <dt-bindings/input/input.h> +#include "rk3288-tinker.dtsi" / { - model = "Rockchip RK3288 Tinker Board"; + model = "Rockchip RK3288 Asus Tinker Board"; compatible = "asus,rk3288-tinker", "rockchip,rk3288"; - - chosen { - stdout-path = "serial2:115200n8"; - }; - - memory { - reg = <0x0 0x0 0x0 0x80000000>; - device_type = "memory"; - }; - - ext_gmac: external-gmac-clock { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <125000000>; - clock-output-names = "ext_gmac"; - }; - - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - autorepeat; - - pinctrl-names = "default"; - pinctrl-0 = <&pwrbtn>; - - button@0 { - gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; - linux,code = <KEY_POWER>; - label = "GPIO Key Power"; - linux,input-type = <1>; - wakeup-source; - debounce-interval = <100>; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - - act-led { - gpios=<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; - linux,default-trigger="mmc0"; - }; - - heartbeat-led { - gpios=<&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>; - linux,default-trigger="heartbeat"; - }; - - pwr-led { - gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "default-on"; - }; - }; - - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,tinker-codec"; - simple-audio-card,mclk-fs = <512>; - - simple-audio-card,codec { - sound-dai = <&hdmi>; - }; - - simple-audio-card,cpu { - sound-dai = <&i2s>; - }; - }; - - vcc_sys: vsys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - regulator-boot-on; - }; - - vcc_sd: sdmmc-regulator { - compatible = "regulator-fixed"; - gpio = <&gpio7 11 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_pwr>; - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - startup-delay-us = <100000>; - vin-supply = <&vcc_io>; - }; -}; - -&cpu0 { - cpu0-supply = <&vdd_cpu>; -}; - -&gmac { - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; - clock_in_out = "input"; - phy-mode = "rgmii"; - phy-supply = <&vcc33_lan>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - snps,reset-gpio = <&gpio4 7 0>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 1000000>; - tx_delay = <0x30>; - rx_delay = <0x10>; - status = "ok"; -}; - -&gpu { - mali-supply = <&vdd_gpu>; - status = "okay"; -}; - -&hdmi { - ddc-i2c-bus = <&i2c5>; - status = "okay"; -}; - -&i2c0 { - clock-frequency = <400000>; - status = "okay"; - - rk808: pmic@1b { - compatible = "rockchip,rk808"; - reg = <0x1b>; - interrupt-parent = <&gpio0>; - interrupts = <4 IRQ_TYPE_LEVEL_LOW>; - #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; - dvs-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>, - <&gpio0 12 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int &global_pwroff &dvs_1 &dvs_2>; - rockchip,system-power-controller; - wakeup-source; - - vcc1-supply = <&vcc_sys>; - vcc2-supply = <&vcc_sys>; - vcc3-supply = <&vcc_sys>; - vcc4-supply = <&vcc_sys>; - vcc6-supply = <&vcc_sys>; - vcc7-supply = <&vcc_sys>; - vcc8-supply = <&vcc_io>; - vcc9-supply = <&vcc_io>; - vcc10-supply = <&vcc_io>; - vcc11-supply = <&vcc_sys>; - vcc12-supply = <&vcc_io>; - vddio-supply = <&vcc_io>; - - regulators { - vdd_cpu: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-name = "vdd_arm"; - regulator-ramp-delay = <6000>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_gpu: DCDC_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1250000>; - regulator-name = "vdd_gpu"; - regulator-ramp-delay = <6000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_ddr"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_io: DCDC_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_io"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc18_ldo1: LDO_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc18_ldo1"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc33_mipi: LDO_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc33_mipi"; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_10: LDO_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd_10"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc18_codec: LDO_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc18_codec"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vccio_sd: LDO_REG5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vccio_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vdd10_lcd: LDO_REG6 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd10_lcd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc_18: LDO_REG7 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_18"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc18_lcd: LDO_REG8 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc18_lcd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc33_sd: SWITCH_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc33_sd"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc33_lan: SWITCH_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc33_lan"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - }; - }; -}; - -&i2c2 { - status = "okay"; -}; - -&i2c5 { - status = "okay"; -}; - -&i2s { - #sound-dai-cells = <0>; - status = "okay"; -}; - -&io_domains { - status = "okay"; - - sdcard-supply = <&vccio_sd>; -}; - -&pinctrl { - pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { - drive-strength = <8>; - }; - - pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { - bias-pull-up; - drive-strength = <8>; - }; - - backlight { - bl_en: bl-en { - rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - buttons { - pwrbtn: pwrbtn { - rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - eth_phy { - eth_phy_pwr: eth-phy-pwr { - rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - pmic { - pmic_int: pmic-int { - rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO \ - &pcfg_pull_up>; - }; - - dvs_1: dvs-1 { - rockchip,pins = <RK_GPIO0 11 RK_FUNC_GPIO \ - &pcfg_pull_down>; - }; - - dvs_2: dvs-2 { - rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO \ - &pcfg_pull_down>; - }; - }; - - sdmmc { - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, - <6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, - <6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, - <6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; - }; - - sdmmc_clk: sdmmc-clk { - rockchip,pins = <6 20 RK_FUNC_1 \ - &pcfg_pull_none_drv_8ma>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; - }; - - sdmmc_pwr: sdmmc-pwr { - rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - usb { - host_vbus_drv: host-vbus-drv { - rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pwr_3g: pwr-3g { - rockchip,pins = <7 8 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - -&pwm0 { - status = "okay"; -}; - -&saradc { - vref-supply = <&vcc18_ldo1>; - status ="okay"; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - card-detect-delay = <200>; - disable-wp; /* wp not hooked up */ - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; - status = "okay"; - vmmc-supply = <&vcc33_sd>; - vqmmc-supply = <&vccio_sd>; -}; - -&tsadc { - rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */ - rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&uart1 { - status = "okay"; -}; - -&uart2 { - status = "okay"; -}; - -&uart3 { - status = "okay"; -}; - -&uart4 { - status = "okay"; -}; - -&usbphy { - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host1 { - status = "okay"; -}; - -&usb_otg { - status= "okay"; -}; - -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - -&wdt { - status = "okay"; }; diff --git a/arch/arm/boot/dts/rk3288-tinker.dtsi b/arch/arm/boot/dts/rk3288-tinker.dtsi new file mode 100644 index 000000000000..aa107ee41b8b --- /dev/null +++ b/arch/arm/boot/dts/rk3288-tinker.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + */ + +#include "rk3288.dtsi" +#include <dt-bindings/input/input.h> + +/ { + chosen { + stdout-path = "serial2:115200n8"; + }; + + memory { + reg = <0x0 0x0 0x0 0x80000000>; + device_type = "memory"; + }; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + }; + + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + + pinctrl-names = "default"; + pinctrl-0 = <&pwrbtn>; + + button@0 { + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + linux,code = <KEY_POWER>; + label = "GPIO Key Power"; + linux,input-type = <1>; + wakeup-source; + debounce-interval = <100>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + act-led { + gpios=<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; + linux,default-trigger="mmc0"; + }; + + heartbeat-led { + gpios=<&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>; + linux,default-trigger="heartbeat"; + }; + + pwr-led { + gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,tinker-codec"; + simple-audio-card,mclk-fs = <512>; + + simple-audio-card,codec { + sound-dai = <&hdmi>; + }; + + simple-audio-card,cpu { + sound-dai = <&i2s>; + }; + }; + + vcc_sys: vsys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio7 11 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + vin-supply = <&vcc_io>; + }; +}; + +&cpu0 { + cpu0-supply = <&vdd_cpu>; +}; + +&gmac { + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + clock_in_out = "input"; + phy-mode = "rgmii"; + phy-supply = <&vcc33_lan>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 1000000>; + tx_delay = <0x30>; + rx_delay = <0x10>; + status = "ok"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c5>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio0>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + dvs-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>, + <&gpio0 12 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int &global_pwroff &dvs_1 &dvs_2>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc_io>; + vcc9-supply = <&vcc_io>; + vcc10-supply = <&vcc_io>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc_io>; + vddio-supply = <&vcc_io>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-name = "vdd_arm"; + regulator-ramp-delay = <6000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd_gpu"; + regulator-ramp-delay = <6000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc18_ldo1: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_ldo1"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc33_mipi: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33_mipi"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc18_codec: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_codec"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_lcd: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc33_sd: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc33_sd"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc33_lan: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc33_lan"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + }; + }; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&i2s { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&io_domains { + status = "okay"; + + sdcard-supply = <&vccio_sd>; +}; + +&pinctrl { + pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { + drive-strength = <8>; + }; + + pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { + bias-pull-up; + drive-strength = <8>; + }; + + backlight { + bl_en: bl-en { + rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + buttons { + pwrbtn: pwrbtn { + rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + eth_phy { + eth_phy_pwr: eth-phy-pwr { + rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int: pmic-int { + rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO \ + &pcfg_pull_up>; + }; + + dvs_1: dvs-1 { + rockchip,pins = <RK_GPIO0 11 RK_FUNC_GPIO \ + &pcfg_pull_down>; + }; + + dvs_2: dvs-2 { + rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO \ + &pcfg_pull_down>; + }; + }; + + sdmmc { + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + + sdmmc_clk: sdmmc-clk { + rockchip,pins = <6 20 RK_FUNC_1 \ + &pcfg_pull_none_drv_8ma>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pwr_3g: pwr-3g { + rockchip,pins = <7 8 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcc18_ldo1>; + status ="okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + disable-wp; /* wp not hooked up */ + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + status = "okay"; + vmmc-supply = <&vcc33_sd>; + vqmmc-supply = <&vccio_sd>; +}; + +&tsadc { + rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host1 { + status = "okay"; +}; + +&usb_otg { + status= "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/s5pv210.dtsi b/arch/arm/boot/dts/s5pv210.dtsi index 67358562a6ea..75f454a210d6 100644 --- a/arch/arm/boot/dts/s5pv210.dtsi +++ b/arch/arm/boot/dts/s5pv210.dtsi @@ -120,7 +120,7 @@ interrupts = <30>; wakeup-interrupt-controller { - compatible = "samsung,exynos4210-wakeup-eint"; + compatible = "samsung,s5pv210-wakeup-eint"; interrupts = <16>; interrupt-parent = <&vic0>; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 61f68e5c48e9..843052f14f1c 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -47,6 +47,7 @@ #include <dt-bindings/dma/at91.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/clock/at91.h> +#include <dt-bindings/iio/adc/at91-sama5d2_adc.h> / { model = "Atmel SAMA5D2 family SoC"; @@ -58,6 +59,8 @@ serial1 = &uart3; tcb0 = &tcb0; tcb1 = &tcb1; + i2s0 = &i2s0; + i2s1 = &i2s1; }; cpus { @@ -84,10 +87,11 @@ clocks = <&mck>; clock-names = "apb_pclk"; - port { - etb_in: endpoint { - slave-mode; - remote-endpoint = <&etm_out>; + in-ports { + port { + etb_in: endpoint { + remote-endpoint = <&etm_out>; + }; }; }; }; @@ -99,9 +103,11 @@ clocks = <&mck>; clock-names = "apb_pclk"; - port { - etm_out: endpoint { - remote-endpoint = <&etb_in>; + out-ports { + port { + etm_out: endpoint { + remote-endpoint = <&etb_in>; + }; }; }; }; @@ -323,44 +329,6 @@ }; }; - nand0: nand@80000000 { - compatible = "atmel,sama5d2-nand"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - reg = < /* EBI CS3 */ - 0x80000000 0x08000000 - /* SMC PMECC regs */ - 0xf8014070 0x00000490 - /* SMC PMECC Error Location regs */ - 0xf8014500 0x00000200 - /* ROM Galois tables */ - 0x00040000 0x00018000 - >; - interrupts = <17 IRQ_TYPE_LEVEL_HIGH 6>; - atmel,nand-addr-offset = <21>; - atmel,nand-cmd-offset = <22>; - atmel,nand-has-dma; - atmel,has-pmecc; - atmel,pmecc-lookup-table-offset = <0x0 0x8000>; - status = "disabled"; - - nfc@c0000000 { - compatible = "atmel,sama5d3-nfc"; - #address-cells = <1>; - #size-cells = <1>; - reg = < /* NFC Command Registers */ - 0xc0000000 0x08000000 - /* NFC HSMC regs */ - 0xf8014000 0x00000070 - /* NFC SRAM banks */ - 0x00100000 0x00100000 - >; - clocks = <&hsmc_clk>; - atmel,write-by-sram; - }; - }; - sdmmc0: sdio-host@a0000000 { compatible = "atmel,sama5d2-sdhci"; reg = <0xa0000000 0x300>; @@ -992,6 +960,24 @@ atmel,clk-output-range = <0 100000000>; }; }; + + i2s_clkmux { + compatible = "atmel,sama5d2-clk-i2s-mux"; + #address-cells = <1>; + #size-cells = <0>; + + i2s0muxck: i2s0_muxclk { + clocks = <&i2s0_clk>, <&i2s0_gclk>; + #clock-cells = <0>; + reg = <0>; + }; + + i2s1muxck: i2s1_muxclk { + clocks = <&i2s1_clk>, <&i2s1_gclk>; + #clock-cells = <0>; + reg = <1>; + }; + }; }; qspi0: spi@f0020000 { @@ -1295,6 +1281,24 @@ clocks = <&clk32k>; }; + i2s0: i2s@f8050000 { + compatible = "atmel,sama5d2-i2s"; + reg = <0xf8050000 0x100>; + interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(31))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(32))>; + dma-names = "tx", "rx"; + clocks = <&i2s0_clk>, <&i2s0_gclk>; + clock-names = "pclk", "gclk"; + assigned-clocks = <&i2s0muxck>; + assigned-clock-parents = <&i2s0_gclk>; + status = "disabled"; + }; + can0: can@f8054000 { compatible = "bosch,m_can"; reg = <0xf8054000 0x4000>, <0x210000 0x4000>; @@ -1437,6 +1441,17 @@ atmel,max-sample-rate-hz = <20000000>; atmel,startup-time-ms = <4>; atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + resistive_touch: resistive-touch { + compatible = "resistive-adc-touch"; + io-channels = <&adc AT91_SAMA5D2_ADC_X_CHANNEL>, + <&adc AT91_SAMA5D2_ADC_Y_CHANNEL>, + <&adc AT91_SAMA5D2_ADC_P_CHANNEL>; + io-channel-names = "x", "y", "pressure"; + touchscreen-min-pressure = <50000>; status = "disabled"; }; @@ -1488,6 +1503,24 @@ status = "disabled"; }; + i2s1: i2s@fc04c000 { + compatible = "atmel,sama5d2-i2s"; + reg = <0xfc04c000 0x100>; + interrupts = <55 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(33))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(34))>; + dma-names = "tx", "rx"; + clocks = <&i2s1_clk>, <&i2s1_gclk>; + clock-names = "pclk", "gclk"; + assigned-clocks = <&i2s1muxck>; + assigned-parrents = <&i2s1_gclk>; + status = "disabled"; + }; + can1: can@fc050000 { compatible = "bosch,m_can"; reg = <0xfc050000 0x4000>, <0x210000 0x4000>; diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index 92a35a1942b6..7371f2a0460f 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -1323,13 +1323,13 @@ }; }; - rstc@fc068600 { + reset_controller: rstc@fc068600 { compatible = "atmel,sama5d3-rstc", "atmel,at91sam9g45-rstc"; reg = <0xfc068600 0x10>; clocks = <&clk32k>; }; - shdwc@fc068610 { + shutdown_controller: shdwc@fc068610 { compatible = "atmel,at91sam9x5-shdwc"; reg = <0xfc068610 0x10>; clocks = <&clk32k>; @@ -1342,7 +1342,7 @@ clocks = <&h32ck>; }; - watchdog@fc068640 { + watchdog: watchdog@fc068640 { compatible = "atmel,sama5d4-wdt"; reg = <0xfc068640 0x10>; interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>; @@ -1376,7 +1376,7 @@ }; - pinctrl@fc06a000 { + pinctrl: pinctrl@fc06a000 { #address-cells = <1>; #size-cells = <1>; compatible = "atmel,sama5d3-pinctrl", "atmel,at91sam9x5-pinctrl", "simple-bus"; diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index b38f8c240558..2d300396f0ed 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -22,8 +22,6 @@ #size-cells = <1>; aliases { - ethernet0 = &gmac0; - ethernet1 = &gmac1; serial0 = &uart0; serial1 = &uart1; timer0 = &timer0; @@ -483,10 +481,17 @@ clk-gate = <0xa0 9>; }; + nand_ecc_clk: nand_ecc_clk { + #clock-cells = <0>; + compatible = "altr,socfpga-gate-clk"; + clocks = <&nand_x_clk>; + clk-gate = <0xa0 9>; + }; + nand_clk: nand_clk { #clock-cells = <0>; compatible = "altr,socfpga-gate-clk"; - clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>; + clocks = <&nand_x_clk>; clk-gate = <0xa0 10>; fixed-divider = <4>; }; @@ -754,7 +759,8 @@ reg-names = "nand_data", "denali_reg"; interrupts = <0x0 0x90 0x4>; dma-mask = <0xffffffff>; - clocks = <&nand_x_clk>; + clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; + clock-names = "nand", "nand_x", "ecc"; status = "disabled"; }; @@ -841,6 +847,8 @@ reg = <0xffc08000 0x1000>; clocks = <&l4_sp_clk>; clock-names = "timer"; + resets = <&rst SPTIMER0_RESET>; + reset-names = "timer"; }; timer1: timer1@ffc09000 { @@ -849,6 +857,8 @@ reg = <0xffc09000 0x1000>; clocks = <&l4_sp_clk>; clock-names = "timer"; + resets = <&rst SPTIMER1_RESET>; + reset-names = "timer"; }; timer2: timer2@ffd00000 { @@ -857,6 +867,8 @@ reg = <0xffd00000 0x1000>; clocks = <&osc1>; clock-names = "timer"; + resets = <&rst OSC1TIMER0_RESET>; + reset-names = "timer"; }; timer3: timer3@ffd01000 { @@ -865,6 +877,8 @@ reg = <0xffd01000 0x1000>; clocks = <&osc1>; clock-names = "timer"; + resets = <&rst OSC1TIMER1_RESET>; + reset-names = "timer"; }; uart0: serial0@ffc02000 { diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi index a4dcb68f4322..59ef13e37536 100644 --- a/arch/arm/boot/dts/socfpga_arria10.dtsi +++ b/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -377,13 +377,28 @@ clk-gate = <0xC8 11>; }; - nand_clk: nand_clk { + nand_x_clk: nand_x_clk { #clock-cells = <0>; compatible = "altr,socfpga-a10-gate-clk"; clocks = <&l4_mp_clk>; clk-gate = <0xC8 10>; }; + nand_ecc_clk: nand_ecc_clk { + #clock-cells = <0>; + compatible = "altr,socfpga-a10-gate-clk"; + clocks = <&nand_x_clk>; + clk-gate = <0xC8 10>; + }; + + nand_clk: nand_clk { + #clock-cells = <0>; + compatible = "altr,socfpga-a10-gate-clk"; + clocks = <&nand_x_clk>; + fixed-divider = <4>; + clk-gate = <0xC8 10>; + }; + spi_m_clk: spi_m_clk { #clock-cells = <0>; compatible = "altr,socfpga-a10-gate-clk"; @@ -613,7 +628,7 @@ status = "disabled"; }; - sdr: sdr@ffc25000 { + sdr: sdr@ffcfb100 { compatible = "altr,sdr-ctl", "syscon"; reg = <0xffcfb100 0x80>; }; @@ -650,7 +665,8 @@ reg-names = "nand_data", "denali_reg"; interrupts = <0 99 4>; dma-mask = <0xffffffff>; - clocks = <&nand_clk>; + clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; + clock-names = "nand", "nand_x", "ecc"; status = "disabled"; }; @@ -760,7 +776,7 @@ timer@ffffc600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xffffc600 0x100>; - interrupts = <1 13 0xf04>; + interrupts = <1 13 0xf01>; clocks = <&mpu_periph_clk>; }; @@ -770,6 +786,8 @@ reg = <0xffc02700 0x100>; clocks = <&l4_sp_clk>; clock-names = "timer"; + resets = <&rst SPTIMER0_RESET>; + reset-names = "timer"; }; timer1: timer1@ffc02800 { @@ -778,6 +796,8 @@ reg = <0xffc02800 0x100>; clocks = <&l4_sp_clk>; clock-names = "timer"; + resets = <&rst SPTIMER1_RESET>; + reset-names = "timer"; }; timer2: timer2@ffd00000 { @@ -786,6 +806,8 @@ reg = <0xffd00000 0x100>; clocks = <&l4_sys_free_clk>; clock-names = "timer"; + resets = <&rst L4SYSTIMER0_RESET>; + reset-names = "timer"; }; timer3: timer3@ffd00100 { @@ -794,6 +816,8 @@ reg = <0xffd01000 0x100>; clocks = <&l4_sys_free_clk>; clock-names = "timer"; + resets = <&rst L4SYSTIMER1_RESET>; + reset-names = "timer"; }; uart0: serial0@ffc02000 { diff --git a/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts index b280e6494193..31b01a998b2e 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts @@ -88,7 +88,7 @@ status = "okay"; clock-frequency = <100000>; - adxl345: adxl345@0 { + adxl345: adxl345@53 { compatible = "adi,adxl345"; reg = <0x53>; diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts index 53bf99eef66d..031c721441ff 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts @@ -21,8 +21,13 @@ model = "EBV SOCrates"; compatible = "ebv,socrates", "altr,socfpga-cyclone5", "altr,socfpga"; + aliases { + ethernet0 = &gmac1; + }; + chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "earlyprintk"; + stdout-path = "serial0:115200n8"; }; memory@0 { diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts index f50b19447de6..e61efe16e79c 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts @@ -54,7 +54,8 @@ compatible = "samtec,vining", "altr,socfpga-cyclone5", "altr,socfpga"; chosen { - bootargs = "console=ttyS0,115200"; + bootargs = "earlyprintk"; + stdout-path = "serial0:115200n8"; }; memory@0 { diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 2310a4e97768..e6ed7c0354a2 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -15,9 +15,14 @@ #include <dt-bindings/arm/ux500_pm_domains.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/clock/ste-ab8500.h> -#include "skeleton.dtsi" / { + #address-cells = <1>; + #size-cells = <1>; + + chosen { + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -67,9 +72,11 @@ clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; clock-names = "apb_pclk", "atclk"; cpu = <&CPU0>; - port { - ptm0_out_port: endpoint { - remote-endpoint = <&funnel_in_port0>; + out-ports { + port { + ptm0_out_port: endpoint { + remote-endpoint = <&funnel_in_port0>; + }; }; }; }; @@ -81,9 +88,11 @@ clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; clock-names = "apb_pclk", "atclk"; cpu = <&CPU1>; - port { - ptm1_out_port: endpoint { - remote-endpoint = <&funnel_in_port1>; + out-ports { + port { + ptm1_out_port: endpoint { + remote-endpoint = <&funnel_in_port1>; + }; }; }; }; @@ -94,32 +103,29 @@ clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; clock-names = "apb_pclk", "atclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* funnel output ports */ - port@0 { - reg = <0>; + out-ports { + port { funnel_out_port: endpoint { remote-endpoint = <&replicator_in_port0>; }; }; + }; - /* funnel input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&ptm0_out_port>; }; }; - port@2 { + port@1 { reg = <1>; funnel_in_port1: endpoint { - slave-mode; remote-endpoint = <&ptm1_out_port>; }; }; @@ -131,11 +137,10 @@ clocks = <&prcmu_clk PRCMU_APEATCLK>; clock-names = "atclk"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; - /* replicator output ports */ port@0 { reg = <0>; replicator_out_port0: endpoint { @@ -148,12 +153,11 @@ remote-endpoint = <&etb_in_port>; }; }; + }; - /* replicator input port */ - port@2 { - reg = <0>; + in-ports { + port { replicator_in_port0: endpoint { - slave-mode; remote-endpoint = <&funnel_out_port>; }; }; @@ -166,10 +170,11 @@ clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; clock-names = "apb_pclk", "atclk"; - port { - tpiu_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port0>; + in-ports { + port { + tpiu_in_port: endpoint { + remote-endpoint = <&replicator_out_port0>; + }; }; }; }; @@ -180,10 +185,11 @@ clocks = <&prcmu_clk PRCMU_APETRACECLK>, <&prcmu_clk PRCMU_APEATCLK>; clock-names = "apb_pclk", "atclk"; - port { - etb_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port1>; + in-ports { + port { + etb_in_port: endpoint { + remote-endpoint = <&replicator_out_port1>; + }; }; }; }; @@ -197,7 +203,7 @@ <0xa0410100 0x100>; }; - scu@a04100000 { + scu@a0410000 { compatible = "arm,cortex-a9-scu"; reg = <0xa0410000 0x100>; }; @@ -487,7 +493,7 @@ }; prcmu: prcmu@80157000 { - compatible = "stericsson,db8500-prcmu"; + compatible = "stericsson,db8500-prcmu", "syscon"; reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>; reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm"; interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; @@ -878,7 +884,7 @@ power-domains = <&pm_domains DOMAIN_VAPE>; }; - ssp@80002000 { + spi@80002000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80002000 0x1000>; interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; @@ -892,7 +898,7 @@ power-domains = <&pm_domains DOMAIN_VAPE>; }; - ssp@80003000 { + spi@80003000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x80003000 0x1000>; interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi index 5c5cea232743..1ec193b0c506 100644 --- a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi +++ b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi @@ -607,16 +607,20 @@ mcde { lcd_default_mode: lcd_default { - default_mux { + default_mux1 { /* Mux in VSI0 and all the data lines */ function = "lcd"; groups = "lcdvsi0_a_1", /* VSI0 for LCD */ "lcd_d0_d7_a_1", /* Data lines */ "lcd_d8_d11_a_1", /* TV-out */ - "lcdaclk_b_1", /* Clock line for TV-out */ "lcdvsi1_a_1"; /* VSI1 for HDMI */ }; + default_mux2 { + function = "lcda"; + groups = + "lcdaclk_b_1"; /* Clock line for TV-out */ + }; default_cfg1 { pins = "GPIO68_E1", /* VSI0 */ diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index 9e359e4f342e..feb682a3d363 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -15,6 +15,7 @@ / { memory { + device_type = "memory"; reg = <0x00000000 0x20000000>; }; diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/ste-hrefprev60.dtsi index 3f14b4df69b4..94eeb7f1c947 100644 --- a/arch/arm/boot/dts/ste-hrefprev60.dtsi +++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi @@ -57,7 +57,7 @@ }; }; - ssp@80002000 { + spi@80002000 { /* * On the first generation boards, this SSP/SPI port was connected * to the AB8500. diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts index b0b94d053098..2de3ce79e496 100644 --- a/arch/arm/boot/dts/ste-snowball.dts +++ b/arch/arm/boot/dts/ste-snowball.dts @@ -26,6 +26,7 @@ }; memory { + device_type = "memory"; reg = <0x00000000 0x20000000>; }; @@ -376,7 +377,7 @@ pinctrl-1 = <&i2c3_sleep_mode>; }; - ssp@80002000 { + spi@80002000 { pinctrl-names = "default"; pinctrl-0 = <&ssp0_snowball_mode>; }; diff --git a/arch/arm/boot/dts/ste-u300.dts b/arch/arm/boot/dts/ste-u300.dts index 62ecb6a2fa39..1bd1aba3322f 100644 --- a/arch/arm/boot/dts/ste-u300.dts +++ b/arch/arm/boot/dts/ste-u300.dts @@ -442,7 +442,7 @@ dma-names = "rx"; }; - spi: ssp@c0006000 { + spi: spi@c0006000 { compatible = "arm,pl022", "arm,primecell"; reg = <0xc0006000 0x1000>; interrupt-parent = <&vica>; diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/stih410-b2260.dts index 155caa8c002a..4ee6d51d8d1e 100644 --- a/arch/arm/boot/dts/stih410-b2260.dts +++ b/arch/arm/boot/dts/stih410-b2260.dts @@ -61,8 +61,11 @@ compatible = "simple-audio-card"; simple-audio-card,name = "STI-B2260"; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; - simple-audio-card,dai-link0 { + simple-audio-card,dai-link@0 { + reg = <0>; /* DAC */ format = "i2s"; mclk-fs = <128>; diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi index 4dedfcb0fcb3..97e05f55fb6e 100644 --- a/arch/arm/boot/dts/stihxxx-b2120.dtsi +++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi @@ -27,8 +27,11 @@ compatible = "simple-audio-card"; simple-audio-card,name = "STI-B2120"; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; - simple-audio-card,dai-link0 { + simple-audio-card,dai-link@0 { + reg = <0>; /* HDMI */ format = "i2s"; mclk-fs = <128>; @@ -41,7 +44,8 @@ }; }; - simple-audio-card,dai-link1 { + simple-audio-card,dai-link@1 { + reg = <1>; /* DAC */ format = "i2s"; mclk-fs = <256>; @@ -55,7 +59,8 @@ }; }; - simple-audio-card,dai-link2 { + simple-audio-card,dai-link@2 { + reg = <2>; /* SPDIF */ format = "left_j"; mclk-fs = <128>; diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts index 7eb786a2d624..ed7d7f46465e 100644 --- a/arch/arm/boot/dts/stm32429i-eval.dts +++ b/arch/arm/boot/dts/stm32429i-eval.dts @@ -264,8 +264,7 @@ &sdio { status = "okay"; vmmc-supply = <&mmc_vcard>; - cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_LOW>; pinctrl-names = "default", "opendrain"; pinctrl-0 = <&sdio_pins>; pinctrl-1 = <&sdio_pins_od>; diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi index e35d782e7e5f..8d6f028ae285 100644 --- a/arch/arm/boot/dts/stm32f429.dtsi +++ b/arch/arm/boot/dts/stm32f429.dtsi @@ -58,7 +58,7 @@ clock-frequency = <0>; }; - clk-lse { + clk_lse: clk-lse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32768>; diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts index 3ee768cb86fc..7937b43d7788 100644 --- a/arch/arm/boot/dts/stm32f469-disco.dts +++ b/arch/arm/boot/dts/stm32f469-disco.dts @@ -210,8 +210,7 @@ &sdio { status = "okay"; vmmc-supply = <&mmc_vcard>; - cd-gpios = <&gpiog 2 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpiog 2 GPIO_ACTIVE_LOW>; broken-cd; pinctrl-names = "default", "opendrain"; pinctrl-0 = <&sdio_pins>; diff --git a/arch/arm/boot/dts/stm32f746-disco.dts b/arch/arm/boot/dts/stm32f746-disco.dts index f9ad71f7c807..e3a7bd338d61 100644 --- a/arch/arm/boot/dts/stm32f746-disco.dts +++ b/arch/arm/boot/dts/stm32f746-disco.dts @@ -101,8 +101,7 @@ &sdio1 { status = "okay"; vmmc-supply = <&mmc_vcard>; - cd-gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; pinctrl-names = "default", "opendrain"; pinctrl-0 = <&sdio_pins_a>; pinctrl-1 = <&sdio_pins_od_a>; diff --git a/arch/arm/boot/dts/stm32f769-disco.dts b/arch/arm/boot/dts/stm32f769-disco.dts index 677276ba4dbe..483d896e2bc1 100644 --- a/arch/arm/boot/dts/stm32f769-disco.dts +++ b/arch/arm/boot/dts/stm32f769-disco.dts @@ -126,8 +126,7 @@ &sdio2 { status = "okay"; vmmc-supply = <&mmc_vcard>; - cd-gpios = <&gpioi 15 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpioi 15 GPIO_ACTIVE_LOW>; broken-cd; pinctrl-names = "default", "opendrain"; pinctrl-0 = <&sdio_pins_b>; diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi index 637beffe5067..cbdd69ca9e7a 100644 --- a/arch/arm/boot/dts/stm32h743.dtsi +++ b/arch/arm/boot/dts/stm32h743.dtsi @@ -472,7 +472,7 @@ interrupt-parent = <&exti>; interrupts = <17 IRQ_TYPE_EDGE_RISING>; interrupt-names = "alarm"; - st,syscfg = <&pwrcfg>; + st,syscfg = <&pwrcfg 0x00 0x100>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts index 372bc2ea6b92..063ee8ac5dcb 100644 --- a/arch/arm/boot/dts/stm32mp157c-ev1.dts +++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "stm32mp157c-ed1.dts" +#include <dt-bindings/gpio/gpio.h> / { model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; @@ -19,6 +20,58 @@ serial0 = &uart4; ethernet0 = ðernet0; }; + + panel_backlight: panel-backlight { + compatible = "gpio-backlight"; + gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; + default-on; + status = "okay"; + }; +}; + +&cec { + pinctrl-names = "default"; + pinctrl-0 = <&cec_pins_a>; + status = "okay"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep0_out>; + }; + }; + + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&dsi_panel_in>; + }; + }; + }; + + panel-dsi@0 { + compatible = "raydium,rm68200"; + reg = <0>; + reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; + backlight = <&panel_backlight>; + status = "okay"; + + port { + dsi_panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; }; ðernet0 { @@ -40,12 +93,6 @@ }; }; -&cec { - pinctrl-names = "default"; - pinctrl-0 = <&cec_pins_a>; - status = "okay"; -}; - &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; @@ -62,6 +109,20 @@ status = "okay"; }; +<dc { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ltdc_ep0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&dsi_in>; + }; + }; +}; + &m_can1 { pinctrl-names = "default"; pinctrl-0 = <&m_can1_pins_a>; diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi index 185541a5b69f..c50c36baba75 100644 --- a/arch/arm/boot/dts/stm32mp157c.dtsi +++ b/arch/arm/boot/dts/stm32mp157c.dtsi @@ -947,7 +947,7 @@ dma-requests = <48>; }; - qspi: qspi@58003000 { + qspi: spi@58003000 { compatible = "st,stm32f469-qspi"; reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; reg-names = "qspi", "qspi_mm"; diff --git a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi index 8acbaab14fe5..d2a2eb8b3f26 100644 --- a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi +++ b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi @@ -92,7 +92,8 @@ */ clock-frequency = <400000>; - touchscreen: touchscreen { + touchscreen: touchscreen@40 { + reg = <0x40>; interrupt-parent = <&pio>; interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>; /* EINT11 (PG11) */ pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi index 8bfb36651177..9cd65c46720b 100644 --- a/arch/arm/boot/dts/sun5i.dtsi +++ b/arch/arm/boot/dts/sun5i.dtsi @@ -108,6 +108,21 @@ }; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* Address must be kept in the lower 256 MiBs of DRAM for VE. */ + cma_pool: cma@4a000000 { + compatible = "shared-dma-pool"; + size = <0x6000000>; + alloc-ranges = <0x4a000000 0x6000000>; + reusable; + linux,cma-default; + }; + }; + soc@1c00000 { compatible = "simple-bus"; #address-cells = <1>; @@ -294,6 +309,17 @@ }; }; + video-codec@1c0e000 { + compatible = "allwinner,sun5i-a13-video-engine"; + reg = <0x01c0e000 0x1000>; + clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>, + <&ccu CLK_DRAM_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_VE>; + interrupts = <53>; + allwinner,sram = <&ve_sram 1>; + }; + mmc0: mmc@1c0f000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c0f000 0x1000>; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 9c52712af241..02e40da9f028 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -174,6 +174,21 @@ reg = <0x40000000 0x80000000>; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* Address must be kept in the lower 256 MiBs of DRAM for VE. */ + cma_pool: cma@4a000000 { + compatible = "shared-dma-pool"; + size = <0x6000000>; + alloc-ranges = <0x4a000000 0x6000000>; + reusable; + linux,cma-default; + }; + }; + timer { compatible = "arm,armv7-timer"; interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, @@ -479,6 +494,17 @@ }; }; + video-codec@1c0e000 { + compatible = "allwinner,sun7i-a20-video-engine"; + reg = <0x01c0e000 0x1000>; + clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>, + <&ccu CLK_DRAM_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_VE>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; + allwinner,sram = <&ve_sram 1>; + }; + mmc0: mmc@1c0f000 { compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index 4e92741b24a7..c1cc8f09dd9a 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -190,6 +190,21 @@ reg = <0x40000000 0x80000000>; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* Address must be kept in the lower 256 MiBs of DRAM for VE. */ + cma_pool: cma@4a000000 { + compatible = "shared-dma-pool"; + size = <0x6000000>; + alloc-ranges = <0x4a000000 0x6000000>; + reusable; + linux,cma-default; + }; + }; + sound: sound { compatible = "simple-audio-card"; simple-audio-card,name = "sun8i-a33-audio"; @@ -254,6 +269,17 @@ }; }; + video-codec@01c0e000 { + compatible = "allwinner,sun8i-a33-video-engine"; + reg = <0x01c0e000 0x1000>; + clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>, + <&ccu CLK_DRAM_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_BUS_VE>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>; + allwinner,sram = <&ve_sram 1>; + }; + crypto: crypto-engine@1c15000 { compatible = "allwinner,sun4i-a10-crypto"; reg = <0x01c15000 0x1000>; diff --git a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts index c7ce4158d6c8..742d2946b08b 100644 --- a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts +++ b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts @@ -191,6 +191,11 @@ status = "okay"; }; +&r_cir { + clock-frequency = <3000000>; + status = "okay"; +}; + &r_rsb { status = "okay"; diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 00a02b037320..5617dd387fd3 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -990,6 +990,19 @@ reg = <0x1f01c00 0x400>; }; + r_cir: ir@1f02000 { + compatible = "allwinner,sun8i-a83t-ir", + "allwinner,sun5i-a13-ir"; + clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>; + clock-names = "apb", "ir"; + resets = <&r_ccu RST_APB0_IR>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x01f02000 0x400>; + pinctrl-names = "default"; + pinctrl-0 = <&r_cir_pin>; + status = "disabled"; + }; + r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun8i-a83t-r-pinctrl"; reg = <0x01f02c00 0x400>; @@ -1002,6 +1015,11 @@ interrupt-controller; #interrupt-cells = <3>; + r_cir_pin: r-cir-pin { + pins = "PL12"; + function = "s_cir_rx"; + }; + r_rsb_pins: r-rsb-pins { pins = "PL0", "PL1"; function = "s_rsb"; diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus-v1.2.dts b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus-v1.2.dts new file mode 100644 index 000000000000..fc4a8c3d084d --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus-v1.2.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org> + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-bananapi-m2-plus-v1.2.dtsi" + +/ { + model = "Banana Pi BPI-M2-Plus v1.2 H3"; + compatible = "bananapi,bpi-m2-plus-v1.2", "allwinner,sun8i-h3"; +}; diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts index 30540dc8e0c5..195a75da13f1 100644 --- a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts @@ -42,195 +42,9 @@ /dts-v1/; #include "sun8i-h3.dtsi" -#include "sunxi-common-regulators.dtsi" - -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/input/input.h> +#include "sunxi-bananapi-m2-plus.dtsi" / { - model = "Banana Pi BPI-M2-Plus"; + model = "Banana Pi BPI-M2-Plus H3"; compatible = "sinovoip,bpi-m2-plus", "allwinner,sun8i-h3"; - - aliases { - ethernet0 = &emac; - serial0 = &uart0; - serial1 = &uart1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - connector { - compatible = "hdmi-connector"; - type = "a"; - - port { - hdmi_con_in: endpoint { - remote-endpoint = <&hdmi_out_con>; - }; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - - pwr_led { - label = "bananapi-m2-plus:red:pwr"; - gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ - default-state = "on"; - }; - }; - - gpio_keys { - compatible = "gpio-keys"; - pinctrl-names = "default"; - - sw4 { - label = "power"; - linux,code = <BTN_0>; - gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; - }; - }; - - reg_gmac_3v3: gmac-3v3 { - compatible = "regulator-fixed"; - regulator-name = "gmac-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - startup-delay-us = <100000>; - enable-active-high; - gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; - }; - - wifi_pwrseq: wifi_pwrseq { - compatible = "mmc-pwrseq-simple"; - pinctrl-names = "default"; - reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ - }; -}; - -&de { - status = "okay"; -}; - -&ehci0 { - status = "okay"; -}; - -&ehci1 { - status = "okay"; -}; - -&ehci2 { - status = "okay"; -}; - -&emac { - pinctrl-names = "default"; - pinctrl-0 = <&emac_rgmii_pins>; - phy-supply = <®_gmac_3v3>; - phy-handle = <&ext_rgmii_phy>; - phy-mode = "rgmii"; - - status = "okay"; -}; - -&external_mdio { - ext_rgmii_phy: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - }; -}; - -&hdmi { - status = "okay"; -}; - -&hdmi_out { - hdmi_out_con: endpoint { - remote-endpoint = <&hdmi_con_in>; - }; -}; - -&ir { - pinctrl-names = "default"; - pinctrl-0 = <&ir_pins_a>; - status = "okay"; -}; - -&mmc0 { - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ - status = "okay"; -}; - -&mmc1 { - vmmc-supply = <®_vcc3v3>; - vqmmc-supply = <®_vcc3v3>; - mmc-pwrseq = <&wifi_pwrseq>; - bus-width = <4>; - non-removable; - status = "okay"; - - brcmf: wifi@1 { - reg = <1>; - compatible = "brcm,bcm4329-fmac"; - interrupt-parent = <&pio>; - interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */ - interrupt-names = "host-wake"; - }; -}; - -&mmc2 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_8bit_pins>; - vmmc-supply = <®_vcc3v3>; - vqmmc-supply = <®_vcc3v3>; - bus-width = <8>; - non-removable; - status = "okay"; -}; - -&ohci0 { - status = "okay"; -}; - -&ohci1 { - status = "okay"; -}; - -&ohci2 { - status = "okay"; -}; - -®_usb0_vbus { - gpio = <&pio 3 11 GPIO_ACTIVE_HIGH>; /* PD11 */ - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; - status = "okay"; -}; - -&usb_otg { - dr_mode = "otg"; - status = "okay"; -}; - -&usbphy { - usb0_id_det-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ - usb0_vbus-supply = <®_usb0_vbus>; - /* USB host VBUS is on as long as VCC-IO is on */ - status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts new file mode 100644 index 000000000000..c834048c325e --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-zero-plus2.dts @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2017 Jagan Teki <jteki@openedev.com> + * Copyright (C) 2018 Diego Rondini <diego.rondini@kynetics.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "sun8i-h3.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "OrangePi Zero Plus2 H3"; + compatible = "xunlong,orangepi-zero-plus2-h3", "allwinner,sun8i-h3"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + reset-gpios = <&pio 0 9 GPIO_ACTIVE_LOW>; /* PA9 */ + post-power-on-delay-ms = <200>; + }; +}; + +&de { + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mmc0 { + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <®_vcc3v3>; + vqmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&r_pio>; + interrupts = <0 7 IRQ_TYPE_LEVEL_LOW>; /* PL7 */ + interrupt-names = "host-wake"; + }; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_8bit_pins>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index f0096074a467..3ecfabb10151 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -119,6 +119,20 @@ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cma_pool: cma@4a000000 { + compatible = "shared-dma-pool"; + size = <0x6000000>; + alloc-ranges = <0x4a000000 0x6000000>; + reusable; + linux,cma-default; + }; + }; + soc { system-control@1c00000 { compatible = "allwinner,sun8i-h3-system-control"; @@ -142,6 +156,17 @@ }; }; + video-codec@01c0e000 { + compatible = "allwinner,sun8i-h3-video-engine"; + reg = <0x01c0e000 0x1000>; + clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>, + <&ccu CLK_DRAM_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_BUS_VE>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>; + allwinner,sram = <&ve_sram 1>; + }; + mali: gpu@1c40000 { compatible = "allwinner,sun8i-h3-mali", "arm,mali-400"; reg = <0x01c40000 0x10000>; diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts index c39b9169ea64..438b7b44dab3 100644 --- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts +++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts @@ -105,6 +105,12 @@ }; }; +&ahci { + ahci-supply = <®_dldo4>; + phy-supply = <®_eldo3>; + status = "okay"; +}; + &de { status = "okay"; }; @@ -159,8 +165,7 @@ &mmc0 { vmmc-supply = <®_dcdc1>; bus-width = <4>; - cd-gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; /* PH13 */ - cd-inverted; + cd-gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */ status = "okay"; }; @@ -251,6 +256,18 @@ regulator-name = "vcc-wifi"; }; +®_dldo4 { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-name = "vdd2v5-sata"; +}; + +®_eldo3 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vdd1v2-sata"; +}; + &tcon_tv0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 5f547c161baf..6f4c9ca5a3ee 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -529,6 +529,19 @@ #size-cells = <0>; }; + ahci: sata@1c18000 { + compatible = "allwinner,sun8i-r40-ahci"; + reg = <0x01c18000 0x1000>; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>; + resets = <&ccu RST_BUS_SATA>; + resets-name = "ahci"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + }; + gmac: ethernet@1c50000 { compatible = "allwinner,sun8i-r40-gmac"; syscon = <&ccu>; diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi index 880096c7e252..5e8a95af89b8 100644 --- a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi +++ b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi @@ -69,7 +69,8 @@ */ clock-frequency = <400000>; - touchscreen: touchscreen@0 { + touchscreen: touchscreen@40 { + reg = <0x40>; interrupt-parent = <&pio>; interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5 */ pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts index 35859d8f3267..bf97f6244c23 100644 --- a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts +++ b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts @@ -95,7 +95,7 @@ &i2c0 { status = "okay"; - axp22x: pmic@68 { + axp22x: pmic@34 { compatible = "x-powers,axp221"; reg = <0x34>; interrupt-parent = <&nmi_intc>; diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 25591d6883ef..d9532fb1ef65 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -1196,7 +1196,7 @@ }; }; - r_rsb: i2c@8003400 { + r_rsb: rsb@8003400 { compatible = "allwinner,sun8i-a23-rsb"; reg = <0x08003400 0x400>; interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi b/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi new file mode 100644 index 000000000000..53edd1faee99 --- /dev/null +++ b/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org> + */ + +#include "sunxi-bananapi-m2-plus.dtsi" + +/ { + /* + * Bananapi M2+ v1.2 uses a GPIO line to change the effective + * resistance on the CPU regulator's feedback pin. + */ + reg_vdd_cpux: vdd-cpux { + compatible = "regulator-gpio"; + regulator-name = "vdd-cpux"; + regulator-type = "voltage"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-ramp-delay = <50>; /* 4ms */ + gpios = <&r_pio 0 1 GPIO_ACTIVE_HIGH>; /* PL1 */ + gpios-states = <0x1>; + states = <1100000 0x0 + 1300000 0x1>; + }; +}; + +&cpu0 { + cpu-supply = <®_vdd_cpux>; +}; diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi new file mode 100644 index 000000000000..b3283aeb5b7d --- /dev/null +++ b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "sunxi-common-regulators.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + aliases { + ethernet0 = &emac; + serial0 = &uart0; + serial1 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + + pwr_led { + label = "bananapi-m2-plus:red:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ + default-state = "on"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + + sw4 { + label = "power"; + linux,code = <BTN_0>; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ + }; +}; + +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_rgmii_pins>; + phy-supply = <®_gmac_3v3>; + phy-handle = <&ext_rgmii_phy>; + phy-mode = "rgmii"; + + status = "okay"; +}; + +&external_mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <®_vcc3v3>; + vqmmc-supply = <®_vcc3v3>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */ + interrupt-names = "host-wake"; + }; +}; + +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_8bit_pins>; + vmmc-supply = <®_vcc3v3>; + vqmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +®_usb0_vbus { + gpio = <&pio 3 11 GPIO_ACTIVE_HIGH>; /* PD11 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ + usb0_vbus-supply = <®_usb0_vbus>; + /* USB host VBUS is on as long as VCC-IO is on */ + status = "okay"; +}; diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index fc6131315c47..4b1530ebe427 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -816,7 +816,7 @@ clock-names = "apb", "ir"; resets = <&r_ccu RST_APB0_IR>; interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x01f02000 0x40>; + reg = <0x01f02000 0x400>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra124-apalis-eval.dts b/arch/arm/boot/dts/tegra124-apalis-eval.dts index a6ad759dddb4..eaee10ef6512 100644 --- a/arch/arm/boot/dts/tegra124-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra124-apalis-eval.dts @@ -72,6 +72,7 @@ host1x@50000000 { hdmi@54280000 { status = "okay"; + hdmi-supply = <®_5v0>; }; }; @@ -122,7 +123,7 @@ /* * GEN2_I2C: I2C2_SDA/SCL (DDC) on MXM3 pin 205/207 (e.g. display EDID) */ - hdmi_ddc: i2c@7000c400 { + i2c@7000c400 { status = "okay"; }; @@ -141,29 +142,19 @@ spi@7000d400 { status = "okay"; spi-max-frequency = <50000000>; - - spidev0: spidev@0 { - compatible = "spidev"; - reg = <0>; - spi-max-frequency = <50000000>; - }; }; /* SPI4: Apalis SPI2 */ spi@7000da00 { status = "okay"; spi-max-frequency = <50000000>; - - spidev1: spidev@0 { - compatible = "spidev"; - reg = <0>; - spi-max-frequency = <50000000>; - }; }; /* Apalis Serial ATA */ sata@70020000 { status = "okay"; + target-5v-supply = <®_5v0>; + target-12v-supply = <®_12v0>; }; hda@70030000 { @@ -177,18 +168,18 @@ /* Apalis MMC1 */ sdhci@700b0000 { status = "okay"; + bus-width = <4>; /* MMC1_CD# */ cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>; - bus-width = <4>; vqmmc-supply = <&vddio_sdmmc1>; }; /* Apalis SD1 */ sdhci@700b0400 { status = "okay"; + bus-width = <4>; /* SD1_CD# */ cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; - bus-width = <4>; vqmmc-supply = <&vddio_sdmmc3>; }; @@ -225,11 +216,12 @@ backlight: backlight { compatible = "pwm-backlight"; - pwms = <&pwm 3 5000000>; /* BKL1_PWM */ brightness-levels = <255 231 223 207 191 159 127 0>; default-brightness-level = <6>; /* BKL1_ON */ enable-gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 3 5000000>; /* BKL1_PWM */ }; gpio-keys { @@ -244,6 +236,13 @@ }; }; + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + reg_5v0: regulator-5v0 { compatible = "regulator-fixed"; regulator-name = "5V_SW"; @@ -251,6 +250,13 @@ regulator-max-microvolt = <5000000>; }; + reg_12v0: regulator-12v0 { + compatible = "regulator-fixed"; + regulator-name = "12V_SW"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + /* USBO1_EN */ reg_usbo1_vbus: regulator-usbo1-vbus { compatible = "regulator-fixed"; @@ -276,7 +282,7 @@ &gpio { /* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */ - pex_perst_n { + pex-perst-n { gpio-hog; gpios = <TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts b/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts index 8a8d5fa0ecd1..7961eb4bd803 100644 --- a/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts +++ b/arch/arm/boot/dts/tegra124-apalis-v1.2-eval.dts @@ -11,7 +11,8 @@ / { model = "Toradex Apalis TK1 on Apalis Evaluation Board"; compatible = "toradex,apalis-tk1-v1.2-eval", "toradex,apalis-tk1-eval", - "toradex,apalis-tk1", "nvidia,tegra124"; + "toradex,apalis-tk1-v1.2", "toradex,apalis-tk1", + "nvidia,tegra124"; aliases { rtc0 = "/i2c@7000c000/rtc@68"; @@ -36,6 +37,7 @@ host1x@50000000 { hdmi@54280000 { status = "okay"; + hdmi-supply = <®_5v0>; }; }; @@ -98,7 +100,7 @@ * I2C4 (DDC): I2C4_SDA/SCL (DDC) on MXM3 pin 205/207 * (e.g. display EDID) */ - hdmi_ddc: i2c@7000c700 { + i2c@7000c700 { status = "okay"; }; @@ -106,29 +108,19 @@ spi@7000d400 { status = "okay"; spi-max-frequency = <50000000>; - - spidev0: spidev@0 { - compatible = "spidev"; - reg = <0>; - spi-max-frequency = <50000000>; - }; }; /* SPI4: Apalis SPI2 */ spi@7000da00 { status = "okay"; spi-max-frequency = <50000000>; - - spidev1: spidev@0 { - compatible = "spidev"; - reg = <0>; - spi-max-frequency = <50000000>; - }; }; /* Apalis Serial ATA */ sata@70020000 { status = "okay"; + target-5v-supply = <®_5v0>; + target-12v-supply = <®_12v0>; }; hda@70030000 { @@ -142,18 +134,18 @@ /* Apalis MMC1 */ sdhci@700b0000 { status = "okay"; + bus-width = <4>; /* MMC1_CD# */ cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>; - bus-width = <4>; vqmmc-supply = <&vddio_sdmmc1>; }; /* Apalis SD1 */ sdhci@700b0400 { status = "okay"; + bus-width = <4>; /* SD1_CD# */ cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; - bus-width = <4>; vqmmc-supply = <&vddio_sdmmc3>; }; @@ -190,11 +182,12 @@ backlight: backlight { compatible = "pwm-backlight"; - pwms = <&pwm 3 5000000>; /* BKL1_PWM */ brightness-levels = <255 231 223 207 191 159 127 0>; default-brightness-level = <6>; /* BKL1_ON */ enable-gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 3 5000000>; /* BKL1_PWM */ }; gpio-keys { @@ -209,6 +202,13 @@ }; }; + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + reg_5v0: regulator-5v0 { compatible = "regulator-fixed"; regulator-name = "5V_SW"; @@ -216,6 +216,13 @@ regulator-max-microvolt = <5000000>; }; + reg_12v0: regulator-12v0 { + compatible = "regulator-fixed"; + regulator-name = "12V_SW"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + /* USBO1_EN */ reg_usbo1_vbus: regulator-usbo1-vbus { compatible = "regulator-fixed"; @@ -241,7 +248,7 @@ &gpio { /* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */ - pex_perst_n { + pex-perst-n { gpio-hog; gpios = <TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi index 573aaa50fff1..367eb8c86098 100644 --- a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi +++ b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi @@ -11,23 +11,19 @@ * Compatible for Revisions 2GB: V1.2A */ / { - model = "Toradex Apalis TK1"; - compatible = "toradex,apalis-tk1-v1.2", "toradex,apalis-tk1", - "nvidia,tegra124"; - memory@80000000 { reg = <0x0 0x80000000 0x0 0x80000000>; }; pcie@1003000 { status = "okay"; - avddio-pex-supply = <&vdd_1v05>; - avdd-pex-pll-supply = <&vdd_1v05>; - avdd-pll-erefe-supply = <&avdd_1v05>; - dvddio-pex-supply = <&vdd_1v05>; - hvdd-pex-pll-e-supply = <®_3v3>; - hvdd-pex-supply = <®_3v3>; - vddio-pex-ctl-supply = <®_3v3>; + avddio-pex-supply = <®_1v05_vdd>; + avdd-pex-pll-supply = <®_1v05_vdd>; + avdd-pll-erefe-supply = <®_1v05_avdd>; + dvddio-pex-supply = <®_1v05_vdd>; + hvdd-pex-pll-e-supply = <®_module_3v3>; + hvdd-pex-supply = <®_module_3v3>; + vddio-pex-ctl-supply = <®_module_3v3>; /* Apalis PCIe (additional lane Apalis type specific) */ pci@1,0 { @@ -42,16 +38,21 @@ phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>; phy-names = "pcie-0"; status = "okay"; + + pcie@0 { + reg = <0 0 0 0 0>; + local-mac-address = [00 00 00 00 00 00]; + }; }; }; host1x@50000000 { hdmi@54280000 { - pll-supply = <®_1v05_avdd_hdmi_pll>; - vdd-supply = <®_3v3_avdd_hdmi>; nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + pll-supply = <®_1v05_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; }; }; @@ -60,44 +61,44 @@ * Node left disabled on purpose - the bootloader will enable * it after having set the VPR up */ - vdd-supply = <&vdd_gpu>; + vdd-supply = <®_vdd_gpu>; }; - pinmux: pinmux@70000868 { + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; state_default: pinmux { /* Analogue Audio (On-module) */ - dap3_fs_pp0 { + dap3-fs-pp0 { nvidia,pins = "dap3_fs_pp0"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap3_din_pp1 { + dap3-din-pp1 { nvidia,pins = "dap3_din_pp1"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap3_dout_pp2 { + dap3-dout-pp2 { 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>; }; - dap3_sclk_pp3 { + dap3-sclk-pp3 { nvidia,pins = "dap3_sclk_pp3"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap_mclk1_pw4 { + dap-mclk1-pw4 { nvidia,pins = "dap_mclk1_pw4"; nvidia,function = "extperiph1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -124,7 +125,7 @@ }; /* Apalis CAM1_MCLK */ - cam_mclk_pcc0 { + cam-mclk-pcc0 { nvidia,pins = "cam_mclk_pcc0"; nvidia,function = "vi_alt3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -133,28 +134,28 @@ }; /* Apalis Digital Audio */ - dap2_fs_pa2 { + dap2-fs-pa2 { nvidia,pins = "dap2_fs_pa2"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_sclk_pa3 { + dap2-sclk-pa3 { nvidia,pins = "dap2_sclk_pa3"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_din_pa4 { + dap2-din-pa4 { nvidia,pins = "dap2_din_pa4"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_dout_pa5 { + dap2-dout-pa5 { nvidia,pins = "dap2_dout_pa5"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -167,7 +168,7 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - clk3_out_pee0 { + clk3-out-pee0 { nvidia,pins = "clk3_out_pee0"; nvidia,function = "extperiph3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -176,7 +177,7 @@ }; /* Apalis GPIO */ - usb_vbus_en0_pn4 { + usb-vbus-en0-pn4 { nvidia,pins = "usb_vbus_en0_pn4"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -184,7 +185,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_DISABLE>; }; - usb_vbus_en1_pn5 { + usb-vbus-en1-pn5 { nvidia,pins = "usb_vbus_en1_pn5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -192,35 +193,35 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_DISABLE>; }; - pex_l0_rst_n_pdd1 { + pex-l0-rst-n-pdd1 { nvidia,pins = "pex_l0_rst_n_pdd1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l0_clkreq_n_pdd2 { + pex-l0-clkreq-n-pdd2 { nvidia,pins = "pex_l0_clkreq_n_pdd2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l1_rst_n_pdd5 { + pex-l1-rst-n-pdd5 { nvidia,pins = "pex_l1_rst_n_pdd5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l1_clkreq_n_pdd6 { + pex-l1-clkreq-n-pdd6 { nvidia,pins = "pex_l1_clkreq_n_pdd6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dp_hpd_pff0 { + dp-hpd-pff0 { nvidia,pins = "dp_hpd_pff0"; nvidia,function = "dp"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -244,7 +245,7 @@ }; /* Apalis HDMI1_CEC */ - hdmi_cec_pee3 { + hdmi-cec-pee3 { nvidia,pins = "hdmi_cec_pee3"; nvidia,function = "cec"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -254,7 +255,7 @@ }; /* Apalis HDMI1_HPD */ - hdmi_int_pn7 { + hdmi-int-pn7 { nvidia,pins = "hdmi_int_pn7"; nvidia,function = "rsvd1"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -264,7 +265,7 @@ }; /* Apalis I2C1 */ - gen1_i2c_scl_pc4 { + gen1-i2c-scl-pc4 { nvidia,pins = "gen1_i2c_scl_pc4"; nvidia,function = "i2c1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -272,7 +273,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - gen1_i2c_sda_pc5 { + gen1-i2c-sda-pc5 { nvidia,pins = "gen1_i2c_sda_pc5"; nvidia,function = "i2c1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -282,7 +283,7 @@ }; /* Apalis I2C3 (CAM) */ - cam_i2c_scl_pbb1 { + cam-i2c-scl-pbb1 { nvidia,pins = "cam_i2c_scl_pbb1"; nvidia,function = "i2c3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -290,7 +291,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - cam_i2c_sda_pbb2 { + cam-i2c-sda-pbb2 { nvidia,pins = "cam_i2c_sda_pbb2"; nvidia,function = "i2c3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -300,7 +301,7 @@ }; /* Apalis I2C4 (DDC) */ - ddc_scl_pv4 { + ddc-scl-pv4 { nvidia,pins = "ddc_scl_pv4"; nvidia,function = "i2c4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -308,7 +309,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,rcv-sel = <TEGRA_PIN_ENABLE>; }; - ddc_sda_pv5 { + ddc-sda-pv5 { nvidia,pins = "ddc_sda_pv5"; nvidia,function = "i2c4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -318,77 +319,77 @@ }; /* Apalis MMC1 */ - sdmmc1_cd_n_pv3 { /* CD# GPIO */ + sdmmc1-cd-n-pv3 { /* CD# GPIO */ nvidia,pins = "sdmmc1_wp_n_pv3"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - clk2_out_pw5 { /* D5 GPIO */ + clk2-out-pw5 { /* D5 GPIO */ nvidia,pins = "clk2_out_pw5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat3_py4 { + sdmmc1-dat3-py4 { nvidia,pins = "sdmmc1_dat3_py4"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat2_py5 { + sdmmc1-dat2-py5 { nvidia,pins = "sdmmc1_dat2_py5"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat1_py6 { + sdmmc1-dat1-py6 { nvidia,pins = "sdmmc1_dat1_py6"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat0_py7 { + sdmmc1-dat0-py7 { nvidia,pins = "sdmmc1_dat0_py7"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_clk_pz0 { + sdmmc1-clk-pz0 { 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_pz1 { + sdmmc1-cmd-pz1 { nvidia,pins = "sdmmc1_cmd_pz1"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - clk2_req_pcc5 { /* D4 GPIO */ + clk2-req-pcc5 { /* D4 GPIO */ nvidia,pins = "clk2_req_pcc5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_clk_lb_in_pee5 { /* D6 GPIO */ + sdmmc3-clk-lb-in-pee5 { /* D6 GPIO */ nvidia,pins = "sdmmc3_clk_lb_in_pee5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - usb_vbus_en2_pff1 { /* D7 GPIO */ + usb-vbus-en2-pff1 { /* D7 GPIO */ nvidia,pins = "usb_vbus_en2_pff1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -428,7 +429,7 @@ }; /* Apalis SATA1_ACT# */ - dap1_dout_pn2 { + dap1-dout-pn2 { nvidia,pins = "dap1_dout_pn2"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -437,49 +438,49 @@ }; /* Apalis SD1 */ - sdmmc3_clk_pa6 { + sdmmc3-clk-pa6 { 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_cmd_pa7 { + sdmmc3-cmd-pa7 { nvidia,pins = "sdmmc3_cmd_pa7"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat3_pb4 { + sdmmc3-dat3-pb4 { nvidia,pins = "sdmmc3_dat3_pb4"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat2_pb5 { + sdmmc3-dat2-pb5 { nvidia,pins = "sdmmc3_dat2_pb5"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat1_pb6 { + sdmmc3-dat1-pb6 { nvidia,pins = "sdmmc3_dat1_pb6"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat0_pb7 { + sdmmc3-dat0-pb7 { nvidia,pins = "sdmmc3_dat0_pb7"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_cd_n_pv2 { /* CD# GPIO */ + sdmmc3-cd-n-pv2 { /* CD# GPIO */ nvidia,pins = "sdmmc3_cd_n_pv2"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -488,14 +489,14 @@ }; /* Apalis SPDIF */ - spdif_out_pk5 { + spdif-out-pk5 { nvidia,pins = "spdif_out_pk5"; nvidia,function = "spdif"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - spdif_in_pk6 { + spdif-in-pk6 { nvidia,pins = "spdif_in_pk6"; nvidia,function = "spdif"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -504,28 +505,28 @@ }; /* Apalis SPI1 */ - ulpi_clk_py0 { + ulpi-clk-py0 { nvidia,pins = "ulpi_clk_py0"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_dir_py1 { + ulpi-dir-py1 { nvidia,pins = "ulpi_dir_py1"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - ulpi_nxt_py2 { + ulpi-nxt-py2 { nvidia,pins = "ulpi_nxt_py2"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_stp_py3 { + ulpi-stp-py3 { nvidia,pins = "ulpi_stp_py3"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -578,42 +579,42 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_txd_pu0 { + uart1-txd-pu0 { nvidia,pins = "pu0"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart1_rxd_pu1 { + uart1-rxd-pu1 { nvidia,pins = "pu1"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_cts_n_pu2 { + uart1-cts-n-pu2 { nvidia,pins = "pu2"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_rts_n_pu3 { + uart1-rts-n-pu3 { nvidia,pins = "pu3"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart3_cts_n_pa1 { /* DSR GPIO */ + uart3-cts-n-pa1 { /* DSR GPIO */ nvidia,pins = "uart3_cts_n_pa1"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart3_rts_n_pc0 { /* DTR GPIO */ + uart3-rts-n-pc0 { /* DTR GPIO */ nvidia,pins = "uart3_rts_n_pc0"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -622,28 +623,28 @@ }; /* Apalis UART2 */ - uart2_txd_pc2 { + uart2-txd-pc2 { 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>; }; - uart2_rxd_pc3 { + uart2-rxd-pc3 { nvidia,pins = "uart2_rxd_pc3"; nvidia,function = "irda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart2_cts_n_pj5 { + uart2-cts-n-pj5 { nvidia,pins = "uart2_cts_n_pj5"; nvidia,function = "uartb"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart2_rts_n_pj6 { + uart2-rts-n-pj6 { nvidia,pins = "uart2_rts_n_pj6"; nvidia,function = "uartb"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -652,14 +653,14 @@ }; /* Apalis UART3 */ - uart3_txd_pw6 { + uart3-txd-pw6 { nvidia,pins = "uart3_txd_pw6"; nvidia,function = "uartc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart3_rxd_pw7 { + uart3-rxd-pw7 { nvidia,pins = "uart3_rxd_pw7"; nvidia,function = "uartc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -668,14 +669,14 @@ }; /* Apalis UART4 */ - uart4_rxd_pb0 { + uart4-rxd-pb0 { nvidia,pins = "pb0"; nvidia,function = "uartd"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart4_txd_pj7 { + uart4-txd-pj7 { nvidia,pins = "pj7"; nvidia,function = "uartd"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -684,7 +685,7 @@ }; /* Apalis USBH_EN */ - gen2_i2c_sda_pt6 { + gen2-i2c-sda-pt6 { nvidia,pins = "gen2_i2c_sda_pt6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -703,7 +704,7 @@ }; /* Apalis USBO1_EN */ - gen2_i2c_scl_pt5 { + gen2-i2c-scl-pt5 { nvidia,pins = "gen2_i2c_scl_pt5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -722,7 +723,7 @@ }; /* Apalis WAKE1_MICO */ - pex_wake_n_pdd3 { + pex-wake-n-pdd3 { nvidia,pins = "pex_wake_n_pdd3"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -731,7 +732,7 @@ }; /* CORE_PWR_REQ */ - core_pwr_req { + core-pwr-req { nvidia,pins = "core_pwr_req"; nvidia,function = "pwron"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -740,7 +741,7 @@ }; /* CPU_PWR_REQ */ - cpu_pwr_req { + cpu-pwr-req { nvidia,pins = "cpu_pwr_req"; nvidia,function = "cpu"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -749,14 +750,14 @@ }; /* DVFS */ - dvfs_pwm_px0 { + dvfs-pwm-px0 { nvidia,pins = "dvfs_pwm_px0"; nvidia,function = "cldvfs"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dvfs_clk_px2 { + dvfs-clk-px2 { nvidia,pins = "dvfs_clk_px2"; nvidia,function = "cldvfs"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -765,70 +766,70 @@ }; /* eMMC */ - sdmmc4_dat0_paa0 { + sdmmc4-dat0-paa0 { nvidia,pins = "sdmmc4_dat0_paa0"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat1_paa1 { + sdmmc4-dat1-paa1 { nvidia,pins = "sdmmc4_dat1_paa1"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat2_paa2 { + sdmmc4-dat2-paa2 { nvidia,pins = "sdmmc4_dat2_paa2"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat3_paa3 { + sdmmc4-dat3-paa3 { nvidia,pins = "sdmmc4_dat3_paa3"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat4_paa4 { + sdmmc4-dat4-paa4 { nvidia,pins = "sdmmc4_dat4_paa4"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat5_paa5 { + sdmmc4-dat5-paa5 { nvidia,pins = "sdmmc4_dat5_paa5"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat6_paa6 { + sdmmc4-dat6-paa6 { nvidia,pins = "sdmmc4_dat6_paa6"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat7_paa7 { + sdmmc4-dat7-paa7 { nvidia,pins = "sdmmc4_dat7_paa7"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_clk_pcc4 { + sdmmc4-clk-pcc4 { 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_cmd_pt7 { + sdmmc4-cmd-pt7 { nvidia,pins = "sdmmc4_cmd_pt7"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -837,7 +838,7 @@ }; /* JTAG_RTCK */ - jtag_rtck { + jtag-rtck { nvidia,pins = "jtag_rtck"; nvidia,function = "rtck"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -846,7 +847,7 @@ }; /* LAN_DEV_OFF# */ - ulpi_data5_po6 { + ulpi-data5-po6 { nvidia,pins = "ulpi_data5_po6"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -855,7 +856,7 @@ }; /* LAN_RESET# */ - kb_row10_ps2 { + kb-row10-ps2 { nvidia,pins = "kb_row10_ps2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -864,7 +865,7 @@ }; /* LAN_WAKE# */ - ulpi_data4_po5 { + ulpi-data4-po5 { nvidia,pins = "ulpi_data4_po5"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -918,35 +919,35 @@ }; /* MCU SPI */ - gpio_x4_aud_px4 { + gpio-x4-aud-px4 { nvidia,pins = "gpio_x4_aud_px4"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x5_aud_px5 { + gpio-x5-aud-px5 { nvidia,pins = "gpio_x5_aud_px5"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x6_aud_px6 { /* MCU_CS */ + gpio-x6-aud-px6 { /* MCU_CS */ nvidia,pins = "gpio_x6_aud_px6"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x7_aud_px7 { + gpio-x7-aud-px7 { nvidia,pins = "gpio_x7_aud_px7"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - gpio_w2_aud_pw2 { /* MCU_CSEZP */ + gpio-w2-aud-pw2 { /* MCU_CSEZP */ nvidia,pins = "gpio_w2_aud_pw2"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -955,7 +956,7 @@ }; /* PMIC_CLK_32K */ - clk_32k_in { + clk-32k-in { nvidia,pins = "clk_32k_in"; nvidia,function = "clk"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -964,7 +965,7 @@ }; /* PMIC_CPU_OC_INT */ - clk_32k_out_pa0 { + clk-32k-out-pa0 { nvidia,pins = "clk_32k_out_pa0"; nvidia,function = "soc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -973,7 +974,7 @@ }; /* PWR_I2C */ - pwr_i2c_scl_pz6 { + pwr-i2c-scl-pz6 { nvidia,pins = "pwr_i2c_scl_pz6"; nvidia,function = "i2cpwr"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -981,7 +982,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - pwr_i2c_sda_pz7 { + pwr-i2c-sda-pz7 { nvidia,pins = "pwr_i2c_sda_pz7"; nvidia,function = "i2cpwr"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -991,7 +992,7 @@ }; /* PWR_INT_N */ - pwr_int_n { + pwr-int-n { nvidia,pins = "pwr_int_n"; nvidia,function = "pmi"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1009,7 +1010,7 @@ }; /* RESET_OUT_N */ - reset_out_n { + reset-out-n { nvidia,pins = "reset_out_n"; nvidia,function = "reset_out_n"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1018,14 +1019,14 @@ }; /* SHIFT_CTRL_DIR_IN */ - kb_row0_pr0 { + kb-row0-pr0 { nvidia,pins = "kb_row0_pr0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row1_pr1 { + kb-row1-pr1 { nvidia,pins = "kb_row1_pr1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1034,7 +1035,7 @@ }; /* Configure level-shifter as output for HDA */ - kb_row11_ps3 { + kb-row11-ps3 { nvidia,pins = "kb_row11_ps3"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1043,21 +1044,21 @@ }; /* SHIFT_CTRL_DIR_OUT */ - kb_col5_pq5 { + kb-col5-pq5 { nvidia,pins = "kb_col5_pq5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col6_pq6 { + kb-col6-pq6 { nvidia,pins = "kb_col6_pq6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col7_pq7 { + kb-col7-pq7 { nvidia,pins = "kb_col7_pq7"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1066,35 +1067,35 @@ }; /* SHIFT_CTRL_OE */ - kb_col0_pq0 { + kb-col0-pq0 { nvidia,pins = "kb_col0_pq0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col1_pq1 { + kb-col1-pq1 { nvidia,pins = "kb_col1_pq1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col2_pq2 { + kb-col2-pq2 { nvidia,pins = "kb_col2_pq2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col4_pq4 { + kb-col4-pq4 { nvidia,pins = "kb_col4_pq4"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row2_pr2 { + kb-row2-pr2 { nvidia,pins = "kb_row2_pr2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1112,7 +1113,7 @@ }; /* TOUCH_INT */ - gpio_w3_aud_pw3 { + gpio-w3-aud-pw3 { nvidia,pins = "gpio_w3_aud_pw3"; nvidia,function = "spi6"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1253,189 +1254,189 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_fs_pn0 { /* NC */ + dap1-fs-pn0 { /* NC */ nvidia,pins = "dap1_fs_pn0"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_din_pn1 { /* NC */ + dap1-din-pn1 { /* NC */ nvidia,pins = "dap1_din_pn1"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_sclk_pn3 { /* NC */ + dap1-sclk-pn3 { /* NC */ nvidia,pins = "dap1_sclk_pn3"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data7_po0 { /* NC */ + ulpi-data7-po0 { /* NC */ nvidia,pins = "ulpi_data7_po0"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data0_po1 { /* NC */ + ulpi-data0-po1 { /* NC */ nvidia,pins = "ulpi_data0_po1"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data1_po2 { /* NC */ + ulpi-data1-po2 { /* NC */ nvidia,pins = "ulpi_data1_po2"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data2_po3 { /* NC */ + ulpi-data2-po3 { /* NC */ nvidia,pins = "ulpi_data2_po3"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data3_po4 { /* NC */ + ulpi-data3-po4 { /* NC */ nvidia,pins = "ulpi_data3_po4"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data6_po7 { /* NC */ + ulpi-data6-po7 { /* NC */ nvidia,pins = "ulpi_data6_po7"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_fs_pp4 { /* NC */ + dap4-fs-pp4 { /* NC */ nvidia,pins = "dap4_fs_pp4"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_din_pp5 { /* NC */ + dap4-din-pp5 { /* NC */ nvidia,pins = "dap4_din_pp5"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_dout_pp6 { /* NC */ + dap4-dout-pp6 { /* NC */ nvidia,pins = "dap4_dout_pp6"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_sclk_pp7 { /* NC */ + dap4-sclk-pp7 { /* NC */ nvidia,pins = "dap4_sclk_pp7"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col3_pq3 { /* NC */ + kb-col3-pq3 { /* NC */ nvidia,pins = "kb_col3_pq3"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row3_pr3 { /* NC */ + kb-row3-pr3 { /* NC */ nvidia,pins = "kb_row3_pr3"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row4_pr4 { /* NC */ + kb-row4-pr4 { /* NC */ nvidia,pins = "kb_row4_pr4"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row5_pr5 { /* NC */ + kb-row5-pr5 { /* NC */ nvidia,pins = "kb_row5_pr5"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row6_pr6 { /* NC */ + kb-row6-pr6 { /* NC */ nvidia,pins = "kb_row6_pr6"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row7_pr7 { /* NC */ + kb-row7-pr7 { /* NC */ nvidia,pins = "kb_row7_pr7"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row8_ps0 { /* NC */ + kb-row8-ps0 { /* NC */ nvidia,pins = "kb_row8_ps0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row9_ps1 { /* NC */ + kb-row9-ps1 { /* NC */ nvidia,pins = "kb_row9_ps1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row12_ps4 { /* NC */ + kb-row12-ps4 { /* NC */ nvidia,pins = "kb_row12_ps4"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row13_ps5 { /* NC */ + kb-row13-ps5 { /* NC */ nvidia,pins = "kb_row13_ps5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row14_ps6 { /* NC */ + kb-row14-ps6 { /* NC */ nvidia,pins = "kb_row14_ps6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row15_ps7 { /* NC */ + kb-row15-ps7 { /* NC */ nvidia,pins = "kb_row15_ps7"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row16_pt0 { /* NC */ + kb-row16-pt0 { /* NC */ nvidia,pins = "kb_row16_pt0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row17_pt1 { /* NC */ + kb-row17-pt1 { /* NC */ nvidia,pins = "kb_row17_pt1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1467,14 +1468,14 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x1_aud_px1 { /* NC */ + gpio-x1-aud-px1 { /* NC */ nvidia,pins = "gpio_x1_aud_px1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x3_aud_px3 { /* NC */ + gpio-x3-aud-px3 { /* NC */ nvidia,pins = "gpio_x3_aud_px3"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1502,14 +1503,14 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - clk3_req_pee1 { /* NC */ + clk3-req-pee1 { /* NC */ nvidia,pins = "clk3_req_pee1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap_mclk1_req_pee2 { /* NC */ + dap-mclk1-req-pee2 { /* NC */ nvidia,pins = "dap_mclk1_req_pee2"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1525,7 +1526,7 @@ * SDMMC_VENDOR_MISC_CNTRL_0 register's SDMMC_SPARE1 * bits being set to 0xfffd according to the TRM! */ - sdmmc3_clk_lb_out_pee4 { /* NC */ + sdmmc3-clk-lb-out-pee4 { /* NC */ nvidia,pins = "sdmmc3_clk_lb_out_pee4"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1560,8 +1561,9 @@ sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - VDDA-supply = <®_3v3>; - VDDIO-supply = <&vddio_1v8>; + VDDA-supply = <®_module_3v3_audio>; + VDDD-supply = <®_1v8_vddio>; + VDDIO-supply = <®_1v8_vddio>; clocks = <&tegra_car TEGRA124_CLK_EXTERN1>; }; @@ -1578,14 +1580,14 @@ pinctrl-0 = <&as3722_default>; as3722_default: pinmux { - gpio2_7 { + gpio2-7 { pins = "gpio2", /* PWR_EN_+V3.3 */ "gpio7"; /* +V1.6_LPO */ function = "gpio"; bias-pull-up; }; - gpio0_1_3_4_5_6 { + gpio0-1-3-4-5-6 { pins = "gpio0", "gpio1", "gpio3", "gpio4", "gpio5", "gpio6"; bias-high-impedance; @@ -1593,18 +1595,18 @@ }; regulators { - vsup-sd2-supply = <®_3v3>; - vsup-sd3-supply = <®_3v3>; - vsup-sd4-supply = <®_3v3>; - vsup-sd5-supply = <®_3v3>; - vin-ldo0-supply = <&vddio_ddr_1v35>; - vin-ldo1-6-supply = <®_3v3>; - vin-ldo2-5-7-supply = <&vddio_1v8>; - vin-ldo3-4-supply = <®_3v3>; - vin-ldo9-10-supply = <®_3v3>; - vin-ldo11-supply = <®_3v3>; - - vdd_cpu: sd0 { + vsup-sd2-supply = <®_module_3v3>; + vsup-sd3-supply = <®_module_3v3>; + vsup-sd4-supply = <®_module_3v3>; + vsup-sd5-supply = <®_module_3v3>; + vin-ldo0-supply = <®_1v35_vddio_ddr>; + vin-ldo1-6-supply = <®_module_3v3>; + vin-ldo2-5-7-supply = <®_1v8_vddio>; + vin-ldo3-4-supply = <®_module_3v3>; + vin-ldo9-10-supply = <®_module_3v3>; + vin-ldo11-supply = <®_module_3v3>; + + reg_vdd_cpu: sd0 { regulator-name = "+VDD_CPU_AP"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1400000>; @@ -1626,7 +1628,7 @@ ams,ext-control = <1>; }; - vddio_ddr_1v35: sd2 { + reg_1v35_vddio_ddr: sd2 { regulator-name = "+V1.35_VDDIO_DDR(sd2)"; regulator-min-microvolt = <1350000>; @@ -1644,13 +1646,13 @@ regulator-boot-on; }; - vdd_1v05: sd4 { + reg_1v05_vdd: sd4 { regulator-name = "+V1.05"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; }; - vddio_1v8: sd5 { + reg_1v8_vddio: sd5 { regulator-name = "+V1.8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -1658,7 +1660,7 @@ regulator-always-on; }; - vdd_gpu: sd6 { + reg_vdd_gpu: sd6 { regulator-name = "+VDD_GPU_AP"; regulator-min-microvolt = <650000>; regulator-max-microvolt = <1200000>; @@ -1668,7 +1670,7 @@ regulator-always-on; }; - avdd_1v05: ldo0 { + reg_1v05_avdd: ldo0 { regulator-name = "+V1.05_AVDD"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; @@ -1743,12 +1745,13 @@ * TMP451 temperature sensor * Note: THERM_N directly connected to AS3722 PMIC THERM */ - temperature-sensor@4c { + temp-sensor@4c { compatible = "ti,tmp451"; reg = <0x4c>; interrupt-parent = <&gpio>; interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; #thermal-sensor-cells = <1>; + vcc-supply = <®_module_3v3>; }; }; @@ -1780,9 +1783,9 @@ sata@70020000 { phys = <&{/padctl@7009f000/pads/sata/lanes/sata-0}>; phy-names = "sata-0"; - avdd-supply = <&vdd_1v05>; - hvdd-supply = <®_3v3>; - vddio-supply = <&vdd_1v05>; + avdd-supply = <®_1v05_vdd>; + hvdd-supply = <®_module_3v3>; + vddio-supply = <®_1v05_vdd>; }; usb@70090000 { @@ -1793,14 +1796,14 @@ <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>, <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>; phy-names = "usb2-0", "usb3-1", "usb2-1", "usb2-2", "usb3-0"; - avddio-pex-supply = <&vdd_1v05>; - avdd-pll-erefe-supply = <&avdd_1v05>; - avdd-pll-utmip-supply = <&vddio_1v8>; - avdd-usb-ss-pll-supply = <&vdd_1v05>; - avdd-usb-supply = <®_3v3>; - dvddio-pex-supply = <&vdd_1v05>; - hvdd-usb-ss-pll-e-supply = <®_3v3>; - hvdd-usb-ss-supply = <®_3v3>; + avddio-pex-supply = <®_1v05_vdd>; + avdd-pll-erefe-supply = <®_1v05_avdd>; + avdd-pll-utmip-supply = <®_1v8_vddio>; + avdd-usb-ss-pll-supply = <®_1v05_vdd>; + avdd-usb-supply = <®_module_3v3>; + dvddio-pex-supply = <®_1v05_vdd>; + hvdd-usb-ss-pll-e-supply = <®_module_3v3>; + hvdd-usb-ss-supply = <®_module_3v3>; }; padctl@7009f000 { @@ -1810,18 +1813,18 @@ lanes { usb2-0 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; usb2-1 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; usb2-2 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; }; }; @@ -1831,28 +1834,28 @@ lanes { pcie-0 { - nvidia,function = "usb3-ss"; status = "okay"; + nvidia,function = "usb3-ss"; }; pcie-1 { - nvidia,function = "usb3-ss"; status = "okay"; + nvidia,function = "usb3-ss"; }; pcie-2 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; pcie-3 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; pcie-4 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; }; }; @@ -1862,8 +1865,8 @@ lanes { sata-0 { - nvidia,function = "sata"; status = "okay"; + nvidia,function = "sata"; }; }; }; @@ -1874,7 +1877,6 @@ usb2-0 { status = "okay"; mode = "otg"; - vbus-supply = <®_usbo1_vbus>; }; @@ -1882,7 +1884,6 @@ usb2-1 { status = "okay"; mode = "host"; - vbus-supply = <®_usbh_vbus>; }; @@ -1890,18 +1891,19 @@ usb2-2 { status = "okay"; mode = "host"; - vbus-supply = <®_usbh_vbus>; }; usb3-0 { - nvidia,usb2-companion = <2>; status = "okay"; + nvidia,usb2-companion = <2>; + vbus-supply = <®_usbh_vbus>; }; usb3-1 { - nvidia,usb2-companion = <0>; status = "okay"; + nvidia,usb2-companion = <0>; + vbus-supply = <®_usbo1_vbus>; }; }; }; @@ -1911,13 +1913,16 @@ status = "okay"; bus-width = <8>; non-removable; + vmmc-supply = <®_module_3v3>; /* VCC */ + vqmmc-supply = <®_1v8_vddio>; /* VCCQ */ + mmc-ddr-1_8v; }; /* CPU DFLL clock */ clock@70110000 { status = "okay"; - vdd-cpu-supply = <&vdd_cpu>; nvidia,i2c-fs-rate = <400000>; + vdd-cpu-supply = <®_vdd_cpu>; }; ahub@70300000 { @@ -1926,22 +1931,15 @@ }; }; - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - clk32k_in: clock@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; + clk32k_in: osc3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; }; cpus { cpu@0 { - vdd-cpu-supply = <&vdd_cpu>; + vdd-cpu-supply = <®_vdd_cpu>; }; }; @@ -1951,7 +1949,7 @@ regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>; - vin-supply = <&vdd_1v05>; + vin-supply = <®_1v05_vdd>; }; reg_3v3_mxm: regulator-3v3-mxm { @@ -1963,7 +1961,15 @@ regulator-boot-on; }; - reg_3v3: regulator-3v3 { + reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_1v05_vdd>; + }; + + reg_module_3v3: regulator-module-3v3 { compatible = "regulator-fixed"; regulator-name = "+V3.3"; regulator-min-microvolt = <3300000>; @@ -1976,12 +1982,12 @@ vin-supply = <®_3v3_mxm>; }; - reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + reg_module_3v3_audio: regulator-module-3v3-audio { compatible = "regulator-fixed"; - regulator-name = "+V3.3_AVDD_HDMI"; + regulator-name = "+V3.3_AUDIO_AVDD_S"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - vin-supply = <&vdd_1v05>; + regulator-always-on; }; sound { @@ -2035,7 +2041,7 @@ &gpio { /* I210 Gigabit Ethernet Controller Reset */ - lan_reset_n { + lan-reset-n { gpio-hog; gpios = <TEGRA_GPIO(S, 2) GPIO_ACTIVE_HIGH>; output-high; @@ -2043,7 +2049,7 @@ }; /* Control MXM3 pin 26 Reset Module Output Carrier Input */ - reset_moci_ctrl { + reset-moci-ctrl { gpio-hog; gpios = <TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm/boot/dts/tegra124-apalis.dtsi b/arch/arm/boot/dts/tegra124-apalis.dtsi index 0f0d4a4988b9..13c93cd507d8 100644 --- a/arch/arm/boot/dts/tegra124-apalis.dtsi +++ b/arch/arm/boot/dts/tegra124-apalis.dtsi @@ -47,22 +47,19 @@ * Compatible for Revisions 2GB: V1.0A, V1.0B, V1.1A */ / { - model = "Toradex Apalis TK1"; - compatible = "toradex,apalis-tk1", "nvidia,tegra124"; - memory@80000000 { reg = <0x0 0x80000000 0x0 0x80000000>; }; pcie@1003000 { status = "okay"; - avddio-pex-supply = <&vdd_1v05>; - avdd-pex-pll-supply = <&vdd_1v05>; - avdd-pll-erefe-supply = <&avdd_1v05>; - dvddio-pex-supply = <&vdd_1v05>; - hvdd-pex-pll-e-supply = <®_3v3>; - hvdd-pex-supply = <®_3v3>; - vddio-pex-ctl-supply = <®_3v3>; + avddio-pex-supply = <®_1v05_vdd>; + avdd-pex-pll-supply = <®_1v05_vdd>; + avdd-pll-erefe-supply = <®_1v05_avdd>; + dvddio-pex-supply = <®_1v05_vdd>; + hvdd-pex-pll-e-supply = <®_module_3v3>; + hvdd-pex-supply = <®_module_3v3>; + vddio-pex-ctl-supply = <®_module_3v3>; /* Apalis PCIe (additional lane Apalis type specific) */ pci@1,0 { @@ -77,16 +74,21 @@ phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>; phy-names = "pcie-0"; status = "okay"; + + pcie@0 { + reg = <0 0 0 0 0>; + local-mac-address = [00 00 00 00 00 00]; + }; }; }; host1x@50000000 { hdmi@54280000 { - pll-supply = <®_1v05_avdd_hdmi_pll>; - vdd-supply = <®_3v3_avdd_hdmi>; nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + pll-supply = <®_1v05_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; }; }; @@ -95,44 +97,44 @@ * Node left disabled on purpose - the bootloader will enable * it after having set the VPR up */ - vdd-supply = <&vdd_gpu>; + vdd-supply = <®_vdd_gpu>; }; - pinmux: pinmux@70000868 { + pinmux@70000868 { pinctrl-names = "default"; pinctrl-0 = <&state_default>; state_default: pinmux { /* Analogue Audio (On-module) */ - dap3_fs_pp0 { + dap3-fs-pp0 { nvidia,pins = "dap3_fs_pp0"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap3_din_pp1 { + dap3-din-pp1 { nvidia,pins = "dap3_din_pp1"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap3_dout_pp2 { + dap3-dout-pp2 { 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>; }; - dap3_sclk_pp3 { + dap3-sclk-pp3 { nvidia,pins = "dap3_sclk_pp3"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap_mclk1_pw4 { + dap-mclk1-pw4 { nvidia,pins = "dap_mclk1_pw4"; nvidia,function = "extperiph1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -159,7 +161,7 @@ }; /* Apalis CAM1_MCLK */ - cam_mclk_pcc0 { + cam-mclk-pcc0 { nvidia,pins = "cam_mclk_pcc0"; nvidia,function = "vi_alt3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -168,28 +170,28 @@ }; /* Apalis Digital Audio */ - dap2_fs_pa2 { + dap2-fs-pa2 { nvidia,pins = "dap2_fs_pa2"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_sclk_pa3 { + dap2-sclk-pa3 { nvidia,pins = "dap2_sclk_pa3"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_din_pa4 { + dap2-din-pa4 { nvidia,pins = "dap2_din_pa4"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dap2_dout_pa5 { + dap2-dout-pa5 { nvidia,pins = "dap2_dout_pa5"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -202,7 +204,7 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - clk3_out_pee0 { + clk3-out-pee0 { nvidia,pins = "clk3_out_pee0"; nvidia,function = "extperiph3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -211,49 +213,49 @@ }; /* Apalis GPIO */ - ddc_scl_pv4 { + ddc-scl-pv4 { nvidia,pins = "ddc_scl_pv4"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - ddc_sda_pv5 { + ddc-sda-pv5 { nvidia,pins = "ddc_sda_pv5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l0_rst_n_pdd1 { + pex-l0-rst-n-pdd1 { nvidia,pins = "pex_l0_rst_n_pdd1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l0_clkreq_n_pdd2 { + pex-l0-clkreq-n-pdd2 { nvidia,pins = "pex_l0_clkreq_n_pdd2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l1_rst_n_pdd5 { + pex-l1-rst-n-pdd5 { nvidia,pins = "pex_l1_rst_n_pdd5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - pex_l1_clkreq_n_pdd6 { + pex-l1-clkreq-n-pdd6 { nvidia,pins = "pex_l1_clkreq_n_pdd6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - dp_hpd_pff0 { + dp-hpd-pff0 { nvidia,pins = "dp_hpd_pff0"; nvidia,function = "dp"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -277,7 +279,7 @@ }; /* Apalis HDMI1_CEC */ - hdmi_cec_pee3 { + hdmi-cec-pee3 { nvidia,pins = "hdmi_cec_pee3"; nvidia,function = "cec"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -287,7 +289,7 @@ }; /* Apalis HDMI1_HPD */ - hdmi_int_pn7 { + hdmi-int-pn7 { nvidia,pins = "hdmi_int_pn7"; nvidia,function = "rsvd1"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -297,7 +299,7 @@ }; /* Apalis I2C1 */ - gen1_i2c_scl_pc4 { + gen1-i2c-scl-pc4 { nvidia,pins = "gen1_i2c_scl_pc4"; nvidia,function = "i2c1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -305,7 +307,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - gen1_i2c_sda_pc5 { + gen1-i2c-sda-pc5 { nvidia,pins = "gen1_i2c_sda_pc5"; nvidia,function = "i2c1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -315,7 +317,7 @@ }; /* Apalis I2C2 (DDC) */ - gen2_i2c_scl_pt5 { + gen2-i2c-scl-pt5 { nvidia,pins = "gen2_i2c_scl_pt5"; nvidia,function = "i2c2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -323,7 +325,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - gen2_i2c_sda_pt6 { + gen2-i2c-sda-pt6 { nvidia,pins = "gen2_i2c_sda_pt6"; nvidia,function = "i2c2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -333,7 +335,7 @@ }; /* Apalis I2C3 (CAM) */ - cam_i2c_scl_pbb1 { + cam-i2c-scl-pbb1 { nvidia,pins = "cam_i2c_scl_pbb1"; nvidia,function = "i2c3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -341,7 +343,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - cam_i2c_sda_pbb2 { + cam-i2c-sda-pbb2 { nvidia,pins = "cam_i2c_sda_pbb2"; nvidia,function = "i2c3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -351,77 +353,77 @@ }; /* Apalis MMC1 */ - sdmmc1_cd_n_pv3 { /* CD# GPIO */ + sdmmc1-cd-n-pv3 { /* CD# GPIO */ nvidia,pins = "sdmmc1_wp_n_pv3"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - clk2_out_pw5 { /* D5 GPIO */ + clk2-out-pw5 { /* D5 GPIO */ nvidia,pins = "clk2_out_pw5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat3_py4 { + sdmmc1-dat3-py4 { nvidia,pins = "sdmmc1_dat3_py4"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat2_py5 { + sdmmc1-dat2-py5 { nvidia,pins = "sdmmc1_dat2_py5"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat1_py6 { + sdmmc1-dat1-py6 { nvidia,pins = "sdmmc1_dat1_py6"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_dat0_py7 { + sdmmc1-dat0-py7 { nvidia,pins = "sdmmc1_dat0_py7"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc1_clk_pz0 { + sdmmc1-clk-pz0 { 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_pz1 { + sdmmc1-cmd-pz1 { nvidia,pins = "sdmmc1_cmd_pz1"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - clk2_req_pcc5 { /* D4 GPIO */ + clk2-req-pcc5 { /* D4 GPIO */ nvidia,pins = "clk2_req_pcc5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_clk_lb_in_pee5 { /* D6 GPIO */ + sdmmc3-clk-lb-in-pee5 { /* D6 GPIO */ nvidia,pins = "sdmmc3_clk_lb_in_pee5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - usb_vbus_en2_pff1 { /* D7 GPIO */ + usb-vbus-en2-pff1 { /* D7 GPIO */ nvidia,pins = "usb_vbus_en2_pff1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -461,7 +463,7 @@ }; /* Apalis SATA1_ACT# */ - dap1_dout_pn2 { + dap1-dout-pn2 { nvidia,pins = "dap1_dout_pn2"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -470,49 +472,49 @@ }; /* Apalis SD1 */ - sdmmc3_clk_pa6 { + sdmmc3-clk-pa6 { 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_cmd_pa7 { + sdmmc3-cmd-pa7 { nvidia,pins = "sdmmc3_cmd_pa7"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat3_pb4 { + sdmmc3-dat3-pb4 { nvidia,pins = "sdmmc3_dat3_pb4"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat2_pb5 { + sdmmc3-dat2-pb5 { nvidia,pins = "sdmmc3_dat2_pb5"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat1_pb6 { + sdmmc3-dat1-pb6 { nvidia,pins = "sdmmc3_dat1_pb6"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_dat0_pb7 { + sdmmc3-dat0-pb7 { nvidia,pins = "sdmmc3_dat0_pb7"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc3_cd_n_pv2 { /* CD# GPIO */ + sdmmc3-cd-n-pv2 { /* CD# GPIO */ nvidia,pins = "sdmmc3_cd_n_pv2"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -521,14 +523,14 @@ }; /* Apalis SPDIF */ - spdif_out_pk5 { + spdif-out-pk5 { nvidia,pins = "spdif_out_pk5"; nvidia,function = "spdif"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - spdif_in_pk6 { + spdif-in-pk6 { nvidia,pins = "spdif_in_pk6"; nvidia,function = "spdif"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -537,28 +539,28 @@ }; /* Apalis SPI1 */ - ulpi_clk_py0 { + ulpi-clk-py0 { nvidia,pins = "ulpi_clk_py0"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_dir_py1 { + ulpi-dir-py1 { nvidia,pins = "ulpi_dir_py1"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - ulpi_nxt_py2 { + ulpi-nxt-py2 { nvidia,pins = "ulpi_nxt_py2"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_stp_py3 { + ulpi-stp-py3 { nvidia,pins = "ulpi_stp_py3"; nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -611,42 +613,42 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_txd_pu0 { + uart1-txd-pu0 { nvidia,pins = "pu0"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart1_rxd_pu1 { + uart1-rxd-pu1 { nvidia,pins = "pu1"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_cts_n_pu2 { + uart1-cts-n-pu2 { nvidia,pins = "pu2"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart1_rts_n_pu3 { + uart1-rts-n-pu3 { nvidia,pins = "pu3"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart3_cts_n_pa1 { /* DSR GPIO */ + uart3-cts-n-pa1 { /* DSR GPIO */ nvidia,pins = "uart3_cts_n_pa1"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart3_rts_n_pc0 { /* DTR GPIO */ + uart3-rts-n-pc0 { /* DTR GPIO */ nvidia,pins = "uart3_rts_n_pc0"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -655,28 +657,28 @@ }; /* Apalis UART2 */ - uart2_txd_pc2 { + uart2-txd-pc2 { 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>; }; - uart2_rxd_pc3 { + uart2-rxd-pc3 { nvidia,pins = "uart2_rxd_pc3"; nvidia,function = "irda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart2_cts_n_pj5 { + uart2-cts-n-pj5 { nvidia,pins = "uart2_cts_n_pj5"; nvidia,function = "uartb"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart2_rts_n_pj6 { + uart2-rts-n-pj6 { nvidia,pins = "uart2_rts_n_pj6"; nvidia,function = "uartb"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -685,14 +687,14 @@ }; /* Apalis UART3 */ - uart3_txd_pw6 { + uart3-txd-pw6 { nvidia,pins = "uart3_txd_pw6"; nvidia,function = "uartc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - uart3_rxd_pw7 { + uart3-rxd-pw7 { nvidia,pins = "uart3_rxd_pw7"; nvidia,function = "uartc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -701,14 +703,14 @@ }; /* Apalis UART4 */ - uart4_rxd_pb0 { + uart4-rxd-pb0 { nvidia,pins = "pb0"; nvidia,function = "uartd"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - uart4_txd_pj7 { + uart4-txd-pj7 { nvidia,pins = "pj7"; nvidia,function = "uartd"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -717,7 +719,7 @@ }; /* Apalis USBH_EN */ - usb_vbus_en1_pn5 { + usb-vbus-en1-pn5 { nvidia,pins = "usb_vbus_en1_pn5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -736,7 +738,7 @@ }; /* Apalis USBO1_EN */ - usb_vbus_en0_pn4 { + usb-vbus-en0-pn4 { nvidia,pins = "usb_vbus_en0_pn4"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -755,7 +757,7 @@ }; /* Apalis WAKE1_MICO */ - pex_wake_n_pdd3 { + pex-wake-n-pdd3 { nvidia,pins = "pex_wake_n_pdd3"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -764,7 +766,7 @@ }; /* CORE_PWR_REQ */ - core_pwr_req { + core-pwr-req { nvidia,pins = "core_pwr_req"; nvidia,function = "pwron"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -773,7 +775,7 @@ }; /* CPU_PWR_REQ */ - cpu_pwr_req { + cpu-pwr-req { nvidia,pins = "cpu_pwr_req"; nvidia,function = "cpu"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -782,14 +784,14 @@ }; /* DVFS */ - dvfs_pwm_px0 { + dvfs-pwm-px0 { nvidia,pins = "dvfs_pwm_px0"; nvidia,function = "cldvfs"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dvfs_clk_px2 { + dvfs-clk-px2 { nvidia,pins = "dvfs_clk_px2"; nvidia,function = "cldvfs"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -798,70 +800,70 @@ }; /* eMMC */ - sdmmc4_dat0_paa0 { + sdmmc4-dat0-paa0 { nvidia,pins = "sdmmc4_dat0_paa0"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat1_paa1 { + sdmmc4-dat1-paa1 { nvidia,pins = "sdmmc4_dat1_paa1"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat2_paa2 { + sdmmc4-dat2-paa2 { nvidia,pins = "sdmmc4_dat2_paa2"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat3_paa3 { + sdmmc4-dat3-paa3 { nvidia,pins = "sdmmc4_dat3_paa3"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat4_paa4 { + sdmmc4-dat4-paa4 { nvidia,pins = "sdmmc4_dat4_paa4"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat5_paa5 { + sdmmc4-dat5-paa5 { nvidia,pins = "sdmmc4_dat5_paa5"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat6_paa6 { + sdmmc4-dat6-paa6 { nvidia,pins = "sdmmc4_dat6_paa6"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat7_paa7 { + sdmmc4-dat7-paa7 { nvidia,pins = "sdmmc4_dat7_paa7"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_clk_pcc4 { + sdmmc4-clk-pcc4 { 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_cmd_pt7 { + sdmmc4-cmd-pt7 { nvidia,pins = "sdmmc4_cmd_pt7"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -870,7 +872,7 @@ }; /* JTAG_RTCK */ - jtag_rtck { + jtag-rtck { nvidia,pins = "jtag_rtck"; nvidia,function = "rtck"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -879,7 +881,7 @@ }; /* LAN_DEV_OFF# */ - ulpi_data5_po6 { + ulpi-data5-po6 { nvidia,pins = "ulpi_data5_po6"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -888,7 +890,7 @@ }; /* LAN_RESET# */ - kb_row10_ps2 { + kb-row10-ps2 { nvidia,pins = "kb_row10_ps2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -897,7 +899,7 @@ }; /* LAN_WAKE# */ - ulpi_data4_po5 { + ulpi-data4-po5 { nvidia,pins = "ulpi_data4_po5"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -951,35 +953,35 @@ }; /* MCU SPI */ - gpio_x4_aud_px4 { + gpio-x4-aud-px4 { nvidia,pins = "gpio_x4_aud_px4"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x5_aud_px5 { + gpio-x5-aud-px5 { nvidia,pins = "gpio_x5_aud_px5"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x6_aud_px6 { /* MCU_CS */ + gpio-x6-aud-px6 { /* MCU_CS */ nvidia,pins = "gpio_x6_aud_px6"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x7_aud_px7 { + gpio-x7-aud-px7 { nvidia,pins = "gpio_x7_aud_px7"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - gpio_w2_aud_pw2 { /* MCU_CSEZP */ + gpio-w2-aud-pw2 { /* MCU_CSEZP */ nvidia,pins = "gpio_w2_aud_pw2"; nvidia,function = "spi2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -988,7 +990,7 @@ }; /* PMIC_CLK_32K */ - clk_32k_in { + clk-32k-in { nvidia,pins = "clk_32k_in"; nvidia,function = "clk"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -997,7 +999,7 @@ }; /* PMIC_CPU_OC_INT */ - clk_32k_out_pa0 { + clk-32k-out-pa0 { nvidia,pins = "clk_32k_out_pa0"; nvidia,function = "soc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1006,7 +1008,7 @@ }; /* PWR_I2C */ - pwr_i2c_scl_pz6 { + pwr-i2c-scl-pz6 { nvidia,pins = "pwr_i2c_scl_pz6"; nvidia,function = "i2cpwr"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1014,7 +1016,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; - pwr_i2c_sda_pz7 { + pwr-i2c-sda-pz7 { nvidia,pins = "pwr_i2c_sda_pz7"; nvidia,function = "i2cpwr"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1024,7 +1026,7 @@ }; /* PWR_INT_N */ - pwr_int_n { + pwr-int-n { nvidia,pins = "pwr_int_n"; nvidia,function = "pmi"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1042,7 +1044,7 @@ }; /* RESET_OUT_N */ - reset_out_n { + reset-out-n { nvidia,pins = "reset_out_n"; nvidia,function = "reset_out_n"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1051,14 +1053,14 @@ }; /* SHIFT_CTRL_DIR_IN */ - kb_row0_pr0 { + kb-row0-pr0 { nvidia,pins = "kb_row0_pr0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row1_pr1 { + kb-row1-pr1 { nvidia,pins = "kb_row1_pr1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1067,7 +1069,7 @@ }; /* Configure level-shifter as output for HDA */ - kb_row11_ps3 { + kb-row11-ps3 { nvidia,pins = "kb_row11_ps3"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1076,21 +1078,21 @@ }; /* SHIFT_CTRL_DIR_OUT */ - kb_col5_pq5 { + kb-col5-pq5 { nvidia,pins = "kb_col5_pq5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col6_pq6 { + kb-col6-pq6 { nvidia,pins = "kb_col6_pq6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col7_pq7 { + kb-col7-pq7 { nvidia,pins = "kb_col7_pq7"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; @@ -1099,35 +1101,35 @@ }; /* SHIFT_CTRL_OE */ - kb_col0_pq0 { + kb-col0-pq0 { nvidia,pins = "kb_col0_pq0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col1_pq1 { + kb-col1-pq1 { nvidia,pins = "kb_col1_pq1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col2_pq2 { + kb-col2-pq2 { nvidia,pins = "kb_col2_pq2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col4_pq4 { + kb-col4-pq4 { nvidia,pins = "kb_col4_pq4"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row2_pr2 { + kb-row2-pr2 { nvidia,pins = "kb_row2_pr2"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1145,7 +1147,7 @@ }; /* TOUCH_INT */ - gpio_w3_aud_pw3 { + gpio-w3-aud-pw3 { nvidia,pins = "gpio_w3_aud_pw3"; nvidia,function = "spi6"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1286,189 +1288,189 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_fs_pn0 { /* NC */ + dap1-fs-pn0 { /* NC */ nvidia,pins = "dap1_fs_pn0"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_din_pn1 { /* NC */ + dap1-din-pn1 { /* NC */ nvidia,pins = "dap1_din_pn1"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap1_sclk_pn3 { /* NC */ + dap1-sclk-pn3 { /* NC */ nvidia,pins = "dap1_sclk_pn3"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data7_po0 { /* NC */ + ulpi-data7-po0 { /* NC */ nvidia,pins = "ulpi_data7_po0"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data0_po1 { /* NC */ + ulpi-data0-po1 { /* NC */ nvidia,pins = "ulpi_data0_po1"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data1_po2 { /* NC */ + ulpi-data1-po2 { /* NC */ nvidia,pins = "ulpi_data1_po2"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data2_po3 { /* NC */ + ulpi-data2-po3 { /* NC */ nvidia,pins = "ulpi_data2_po3"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data3_po4 { /* NC */ + ulpi-data3-po4 { /* NC */ nvidia,pins = "ulpi_data3_po4"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - ulpi_data6_po7 { /* NC */ + ulpi-data6-po7 { /* NC */ nvidia,pins = "ulpi_data6_po7"; nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_fs_pp4 { /* NC */ + dap4-fs-pp4 { /* NC */ nvidia,pins = "dap4_fs_pp4"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_din_pp5 { /* NC */ + dap4-din-pp5 { /* NC */ nvidia,pins = "dap4_din_pp5"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_dout_pp6 { /* NC */ + dap4-dout-pp6 { /* NC */ nvidia,pins = "dap4_dout_pp6"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap4_sclk_pp7 { /* NC */ + dap4-sclk-pp7 { /* NC */ nvidia,pins = "dap4_sclk_pp7"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_col3_pq3 { /* NC */ + kb-col3-pq3 { /* NC */ nvidia,pins = "kb_col3_pq3"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row3_pr3 { /* NC */ + kb-row3-pr3 { /* NC */ nvidia,pins = "kb_row3_pr3"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row4_pr4 { /* NC */ + kb-row4-pr4 { /* NC */ nvidia,pins = "kb_row4_pr4"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row5_pr5 { /* NC */ + kb-row5-pr5 { /* NC */ nvidia,pins = "kb_row5_pr5"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row6_pr6 { /* NC */ + kb-row6-pr6 { /* NC */ nvidia,pins = "kb_row6_pr6"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row7_pr7 { /* NC */ + kb-row7-pr7 { /* NC */ nvidia,pins = "kb_row7_pr7"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row8_ps0 { /* NC */ + kb-row8-ps0 { /* NC */ nvidia,pins = "kb_row8_ps0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row9_ps1 { /* NC */ + kb-row9-ps1 { /* NC */ nvidia,pins = "kb_row9_ps1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row12_ps4 { /* NC */ + kb-row12-ps4 { /* NC */ nvidia,pins = "kb_row12_ps4"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row13_ps5 { /* NC */ + kb-row13-ps5 { /* NC */ nvidia,pins = "kb_row13_ps5"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row14_ps6 { /* NC */ + kb-row14-ps6 { /* NC */ nvidia,pins = "kb_row14_ps6"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row15_ps7 { /* NC */ + kb-row15-ps7 { /* NC */ nvidia,pins = "kb_row15_ps7"; nvidia,function = "rsvd3"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row16_pt0 { /* NC */ + kb-row16-pt0 { /* NC */ nvidia,pins = "kb_row16_pt0"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - kb_row17_pt1 { /* NC */ + kb-row17-pt1 { /* NC */ nvidia,pins = "kb_row17_pt1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1496,14 +1498,14 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x1_aud_px1 { /* NC */ + gpio-x1-aud-px1 { /* NC */ nvidia,pins = "gpio_x1_aud_px1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - gpio_x3_aud_px3 { /* NC */ + gpio-x3-aud-px3 { /* NC */ nvidia,pins = "gpio_x3_aud_px3"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1531,14 +1533,14 @@ nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - clk3_req_pee1 { /* NC */ + clk3-req-pee1 { /* NC */ nvidia,pins = "clk3_req_pee1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - dap_mclk1_req_pee2 { /* NC */ + dap-mclk1-req-pee2 { /* NC */ nvidia,pins = "dap_mclk1_req_pee2"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_DOWN>; @@ -1554,7 +1556,7 @@ * SDMMC_VENDOR_MISC_CNTRL_0 register's SDMMC_SPARE1 * bits being set to 0xfffd according to the TRM! */ - sdmmc3_clk_lb_out_pee4 { /* NC */ + sdmmc3-clk-lb-out-pee4 { /* NC */ nvidia,pins = "sdmmc3_clk_lb_out_pee4"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -1589,8 +1591,9 @@ sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - VDDA-supply = <®_3v3>; - VDDIO-supply = <&vddio_1v8>; + VDDA-supply = <®_module_3v3_audio>; + VDDD-supply = <®_1v8_vddio>; + VDDIO-supply = <®_1v8_vddio>; clocks = <&tegra_car TEGRA124_CLK_EXTERN1>; }; @@ -1607,14 +1610,14 @@ pinctrl-0 = <&as3722_default>; as3722_default: pinmux { - gpio2_7 { + gpio2-7 { pins = "gpio2", /* PWR_EN_+V3.3 */ "gpio7"; /* +V1.6_LPO */ function = "gpio"; bias-pull-up; }; - gpio0_1_3_4_5_6 { + gpio0-1-3-4-5-6 { pins = "gpio0", "gpio1", "gpio3", "gpio4", "gpio5", "gpio6"; bias-high-impedance; @@ -1622,18 +1625,18 @@ }; regulators { - vsup-sd2-supply = <®_3v3>; - vsup-sd3-supply = <®_3v3>; - vsup-sd4-supply = <®_3v3>; - vsup-sd5-supply = <®_3v3>; - vin-ldo0-supply = <&vddio_ddr_1v35>; - vin-ldo1-6-supply = <®_3v3>; - vin-ldo2-5-7-supply = <&vddio_1v8>; - vin-ldo3-4-supply = <®_3v3>; - vin-ldo9-10-supply = <®_3v3>; - vin-ldo11-supply = <®_3v3>; - - vdd_cpu: sd0 { + vsup-sd2-supply = <®_module_3v3>; + vsup-sd3-supply = <®_module_3v3>; + vsup-sd4-supply = <®_module_3v3>; + vsup-sd5-supply = <®_module_3v3>; + vin-ldo0-supply = <®_1v35_vddio_ddr>; + vin-ldo1-6-supply = <®_module_3v3>; + vin-ldo2-5-7-supply = <®_1v8_vddio>; + vin-ldo3-4-supply = <®_module_3v3>; + vin-ldo9-10-supply = <®_module_3v3>; + vin-ldo11-supply = <®_module_3v3>; + + reg_vdd_cpu: sd0 { regulator-name = "+VDD_CPU_AP"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1400000>; @@ -1655,7 +1658,7 @@ ams,ext-control = <1>; }; - vddio_ddr_1v35: sd2 { + reg_1v35_vddio_ddr: sd2 { regulator-name = "+V1.35_VDDIO_DDR(sd2)"; regulator-min-microvolt = <1350000>; @@ -1673,13 +1676,13 @@ regulator-boot-on; }; - vdd_1v05: sd4 { + reg_1v05_vdd: sd4 { regulator-name = "+V1.05"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; }; - vddio_1v8: sd5 { + reg_1v8_vddio: sd5 { regulator-name = "+V1.8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -1687,7 +1690,7 @@ regulator-always-on; }; - vdd_gpu: sd6 { + reg_vdd_gpu: sd6 { regulator-name = "+VDD_GPU_AP"; regulator-min-microvolt = <650000>; regulator-max-microvolt = <1200000>; @@ -1697,7 +1700,7 @@ regulator-always-on; }; - avdd_1v05: ldo0 { + reg_1v05_avdd: ldo0 { regulator-name = "+V1.05_AVDD"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; @@ -1772,12 +1775,13 @@ * TMP451 temperature sensor * Note: THERM_N directly connected to AS3722 PMIC THERM */ - temperature-sensor@4c { + temp-sensor@4c { compatible = "ti,tmp451"; reg = <0x4c>; interrupt-parent = <&gpio>; interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>; #thermal-sensor-cells = <1>; + vcc-supply = <®_module_3v3>; }; }; @@ -1809,9 +1813,9 @@ sata@70020000 { phys = <&{/padctl@7009f000/pads/sata/lanes/sata-0}>; phy-names = "sata-0"; - avdd-supply = <&vdd_1v05>; - hvdd-supply = <®_3v3>; - vddio-supply = <&vdd_1v05>; + avdd-supply = <®_1v05_vdd>; + hvdd-supply = <®_module_3v3>; + vddio-supply = <®_1v05_vdd>; }; usb@70090000 { @@ -1822,14 +1826,14 @@ <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>, <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>; phy-names = "usb2-0", "usb3-1", "usb2-1", "usb2-2", "usb3-0"; - avddio-pex-supply = <&vdd_1v05>; - avdd-pll-erefe-supply = <&avdd_1v05>; - avdd-pll-utmip-supply = <&vddio_1v8>; - avdd-usb-ss-pll-supply = <&vdd_1v05>; - avdd-usb-supply = <®_3v3>; - dvddio-pex-supply = <&vdd_1v05>; - hvdd-usb-ss-pll-e-supply = <®_3v3>; - hvdd-usb-ss-supply = <®_3v3>; + avddio-pex-supply = <®_1v05_vdd>; + avdd-pll-erefe-supply = <®_1v05_avdd>; + avdd-pll-utmip-supply = <®_1v8_vddio>; + avdd-usb-ss-pll-supply = <®_1v05_vdd>; + avdd-usb-supply = <®_module_3v3>; + dvddio-pex-supply = <®_1v05_vdd>; + hvdd-usb-ss-pll-e-supply = <®_module_3v3>; + hvdd-usb-ss-supply = <®_module_3v3>; }; padctl@7009f000 { @@ -1839,18 +1843,18 @@ lanes { usb2-0 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; usb2-1 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; usb2-2 { - nvidia,function = "xusb"; status = "okay"; + nvidia,function = "xusb"; }; }; }; @@ -1860,28 +1864,28 @@ lanes { pcie-0 { - nvidia,function = "usb3-ss"; status = "okay"; + nvidia,function = "usb3-ss"; }; pcie-1 { - nvidia,function = "usb3-ss"; status = "okay"; + nvidia,function = "usb3-ss"; }; pcie-2 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; pcie-3 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; pcie-4 { - nvidia,function = "pcie"; status = "okay"; + nvidia,function = "pcie"; }; }; }; @@ -1891,8 +1895,8 @@ lanes { sata-0 { - nvidia,function = "sata"; status = "okay"; + nvidia,function = "sata"; }; }; }; @@ -1903,7 +1907,6 @@ usb2-0 { status = "okay"; mode = "otg"; - vbus-supply = <®_usbo1_vbus>; }; @@ -1911,7 +1914,6 @@ usb2-1 { status = "okay"; mode = "host"; - vbus-supply = <®_usbh_vbus>; }; @@ -1919,18 +1921,19 @@ usb2-2 { status = "okay"; mode = "host"; - vbus-supply = <®_usbh_vbus>; }; usb3-0 { - nvidia,usb2-companion = <2>; status = "okay"; + nvidia,usb2-companion = <2>; + vbus-supply = <®_usbh_vbus>; }; usb3-1 { - nvidia,usb2-companion = <0>; status = "okay"; + nvidia,usb2-companion = <0>; + vbus-supply = <®_usbo1_vbus>; }; }; }; @@ -1940,13 +1943,16 @@ status = "okay"; bus-width = <8>; non-removable; + vmmc-supply = <®_module_3v3>; /* VCC */ + vqmmc-supply = <®_1v8_vddio>; /* VCCQ */ + mmc-ddr-1_8v; }; /* CPU DFLL clock */ clock@70110000 { status = "okay"; - vdd-cpu-supply = <&vdd_cpu>; nvidia,i2c-fs-rate = <400000>; + vdd-cpu-supply = <®_vdd_cpu>; }; ahub@70300000 { @@ -1955,22 +1961,15 @@ }; }; - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - clk32k_in: clock@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; + clk32k_in: osc3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; }; cpus { cpu@0 { - vdd-cpu-supply = <&vdd_cpu>; + vdd-cpu-supply = <®_vdd_cpu>; }; }; @@ -1980,7 +1979,7 @@ regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>; - vin-supply = <&vdd_1v05>; + vin-supply = <®_1v05_vdd>; }; reg_3v3_mxm: regulator-3v3-mxm { @@ -1992,7 +1991,15 @@ regulator-boot-on; }; - reg_3v3: regulator-3v3 { + reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_1v05_vdd>; + }; + + reg_module_3v3: regulator-module-3v3 { compatible = "regulator-fixed"; regulator-name = "+V3.3"; regulator-min-microvolt = <3300000>; @@ -2005,12 +2012,12 @@ vin-supply = <®_3v3_mxm>; }; - reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + reg_module_3v3_audio: regulator-module-3v3-audio { compatible = "regulator-fixed"; - regulator-name = "+V3.3_AVDD_HDMI"; + regulator-name = "+V3.3_AUDIO_AVDD_S"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - vin-supply = <&vdd_1v05>; + regulator-always-on; }; sound { @@ -2064,7 +2071,7 @@ &gpio { /* I210 Gigabit Ethernet Controller Reset */ - lan_reset_n { + lan-reset-n { gpio-hog; gpios = <TEGRA_GPIO(S, 2) GPIO_ACTIVE_HIGH>; output-high; @@ -2072,7 +2079,7 @@ }; /* Control MXM3 pin 26 Reset Module Output Carrier Input */ - reset_moci_ctrl { + reset-moci-ctrl { gpio-hog; gpios = <TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>; output-high; diff --git a/arch/arm/boot/dts/tegra20-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra20-colibri-eval-v3.dts new file mode 100644 index 000000000000..3c0f2681fcde --- /dev/null +++ b/arch/arm/boot/dts/tegra20-colibri-eval-v3.dts @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include "tegra20-colibri.dtsi" + +/ { + model = "Toradex Colibri T20 on Colibri Evaluation Board"; + compatible = "toradex,colibri_t20-eval-v3", "toradex,colibri_t20", + "nvidia,tegra20"; + + aliases { + rtc0 = "/i2c@7000c000/rtc@68"; + rtc1 = "/i2c@7000d000/pmic@34"; + rtc2 = "/rtc@7000e000"; + serial0 = &uarta; + serial1 = &uartd; + serial2 = &uartb; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + nvidia,panel = <&panel>; + }; + }; + + hdmi@54280000 { + status = "okay"; + hdmi-supply = <®_5v0>; + }; + }; + + pinmux@70000014 { + state_default: pinmux { + bl-on { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + ddc { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + hotplug-detect { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + i2c { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + lcd { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + lm1 { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + mmc { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + mmccd { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + pwm-a-b { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + pwm-c-d { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + ssp { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + uart-a { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + uart-b { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + uart-c { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + usbh-pen { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + }; + }; + + /* Colibri UART-A */ + serial@70006000 { + status = "okay"; + }; + + /* Colibri UART-C */ + serial@70006040 { + status = "okay"; + }; + + /* Colibri UART-B */ + serial@70006300 { + status = "okay"; + }; + + pwm@7000a000 { + status = "okay"; + }; + + /* + * GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier + * board) + */ + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + /* M41T0M6 real time clock on carrier board */ + rtc@68 { + compatible = "st,m41t0"; + reg = <0x68>; + }; + }; + + /* GEN2_I2C: unused */ + + /* CAM_I2C (I2C3): unused */ + + /* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */ + i2c@7000c400 { + status = "okay"; + }; + + /* EHCI instance 0: USB1_DP/N -> USBC_P/N */ + usb@c5000000 { + status = "okay"; + dr_mode = "otg"; + }; + + usb-phy@c5000000 { + status = "okay"; + vbus-supply = <®_usbc_vbus>; + }; + + /* EHCI instance 2: USB3_DP/N -> USBH_P/N */ + usb@c5008000 { + status = "okay"; + }; + + usb-phy@c5008000 { + status = "okay"; + vbus-supply = <®_usbh_vbus>; + }; + + /* SPI4: Colibri SSP */ + spi@7000da00 { + status = "okay"; + spi-max-frequency = <25000000>; + + can@0 { + compatible = "microchip,mcp2515"; + reg = <0>; + clocks = <&clk16m>; + interrupt-parent = <&gpio>; + /* CAN_INT */ + interrupts = <TEGRA_GPIO(A, 0) IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <10000000>; + vdd-supply = <®_3v3>; + xceiver-supply = <®_5v0>; + }; + }; + + /* SD/MMC */ + sdhci@c8000600 { + status = "okay"; + bus-width = <4>; + cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>; /* MMCD */ + no-1-8-v; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = <255 128 64 32 16 8 4 0>; + default-brightness-level = <6>; + /* BL_ON */ + enable-gpios = <&gpio TEGRA_GPIO(T, 4) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 0 5000000>; /* PWM<A> */ + }; + + clk16m: osc3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + wakeup { + label = "SODIMM pin 45 wakeup"; + gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; + linux,code = <KEY_WAKEUP>; + debounce-interval = <10>; + wakeup-source; + }; + }; + + panel: panel { + /* + * edt,et057090dhu: EDT 5.7" LCD TFT + * edt,et070080dh6: EDT 7.0" LCD TFT + */ + compatible = "edt,et057090dhu", "simple-panel"; + backlight = <&backlight>; + power-supply = <®_3v3>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V_SW"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_usbc_vbus: regulator-usbc-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB5"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_5v0>; + }; + + /* USBH_PEN resp. USB_P_EN */ + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB[1-4]"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>; + vin-supply = <®_5v0>; + }; +}; diff --git a/arch/arm/boot/dts/tegra20-colibri-iris.dts b/arch/arm/boot/dts/tegra20-colibri-iris.dts index 57f16c0e9917..d8004d68efa0 100644 --- a/arch/arm/boot/dts/tegra20-colibri-iris.dts +++ b/arch/arm/boot/dts/tegra20-colibri-iris.dts @@ -1,15 +1,21 @@ // SPDX-License-Identifier: GPL-2.0 /dts-v1/; +#include <dt-bindings/input/input.h> #include "tegra20-colibri.dtsi" / { - model = "Toradex Colibri T20 256/512 MB on Iris"; - compatible = "toradex,iris", "toradex,colibri_t20-512", "nvidia,tegra20"; + model = "Toradex Colibri T20 on Iris"; + compatible = "toradex,colibri_t20-iris", "toradex,colibri_t20", + "nvidia,tegra20"; aliases { + rtc0 = "/i2c@7000c000/rtc@68"; + rtc1 = "/i2c@7000d000/pmic@34"; + rtc2 = "/rtc@7000e000"; serial0 = &uarta; serial1 = &uartd; + serial2 = &uartb; }; chosen { @@ -17,90 +23,222 @@ }; host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + nvidia,panel = <&panel>; + }; + }; + hdmi@54280000 { status = "okay"; + hdmi-supply = <®_5v0>; }; }; pinmux@70000014 { state_default: pinmux { - hdint { + bl-on { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + ddc { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + hotplug-detect { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + i2c { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + lcd { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + lm1 { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + mmc { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + mmccd { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + pwm-a-b { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + pwm-c-d { + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + ssp { nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - i2cddc { + uart-a { nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - sdio4 { + uart-b { nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - uarta { + uart-c { nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - uartd { + usbh-pen { nvidia,tristate = <TEGRA_PIN_DISABLE>; }; }; }; + /* Colibri UART-A */ serial@70006000 { status = "okay"; }; + /* Colibri UART-C */ + serial@70006040 { + status = "okay"; + }; + + /* Colibri UART-B */ serial@70006300 { status = "okay"; }; - i2c_ddc: i2c@7000c400 { + pwm@7000a000 { + status = "okay"; + }; + + /* + * GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier + * board) + */ + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + /* M41T0M6 real time clock on carrier board */ + rtc@68 { + compatible = "st,m41t0"; + reg = <0x68>; + }; + }; + + /* GEN2_I2C: unused */ + + /* CAM_I2C (I2C3): unused */ + + /* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */ + i2c@7000c400 { status = "okay"; }; + /* EHCI instance 0: USB1_DP/N -> USBC_P/N */ usb@c5000000 { status = "okay"; + dr_mode = "otg"; }; usb-phy@c5000000 { status = "okay"; + vbus-supply = <®_usbc_vbus>; }; + /* EHCI instance 2: USB3_DP/N -> USBH_P/N */ usb@c5008000 { status = "okay"; }; usb-phy@c5008000 { status = "okay"; + vbus-supply = <®_usbh_vbus>; + }; + + /* SPI4: Colibri SSP */ + spi@7000da00 { + status = "okay"; + spi-max-frequency = <25000000>; }; + /* SD/MMC */ sdhci@c8000600 { status = "okay"; bus-width = <4>; - vmmc-supply = <&vcc_sd_reg>; - vqmmc-supply = <&vcc_sd_reg>; - }; - - regulators { - regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "usb_host_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - regulator-always-on; - gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_HIGH>; - }; + cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>; /* MMCD */ + no-1-8-v; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = <255 128 64 32 16 8 4 0>; + default-brightness-level = <6>; + /* BL_ON */ + enable-gpios = <&gpio TEGRA_GPIO(T, 4) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 0 5000000>; /* PWM<A> */ + }; + + gpio-keys { + compatible = "gpio-keys"; - vcc_sd_reg: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; + wakeup { + label = "SODIMM pin 45 wakeup"; + gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; + linux,code = <KEY_WAKEUP>; + debounce-interval = <10>; + wakeup-source; }; }; + + panel: panel { + /* + * edt,et057090dhu: EDT 5.7" LCD TFT + * edt,et070080dh6: EDT 7.0" LCD TFT + */ + compatible = "edt,et057090dhu", "simple-panel"; + backlight = <&backlight>; + power-supply = <®_3v3>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_usbc_vbus: regulator-usbc-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB2"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_5v0>; + }; + + /* USBH_PEN resp. USB_P_EN */ + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>; + vin-supply = <®_5v0>; + }; }; diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi b/arch/arm/boot/dts/tegra20-colibri.dtsi index e7b9ab09908a..6162d193e12c 100644 --- a/arch/arm/boot/dts/tegra20-colibri.dtsi +++ b/arch/arm/boot/dts/tegra20-colibri.dtsi @@ -1,15 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 #include "tegra20.dtsi" +/* + * Toradex Colibri T20 Module Device Tree + * Compatible for Revisions Colibri T20 256MB V1.1B, V1.2A; + * Colibri T20 256MB IT V1.2A; Colibri T20 512MB V1.1C, V1.2A; + * Colibri T20 512MB IT V1.2A + */ / { - model = "Toradex Colibri T20 256/512 MB"; - compatible = "toradex,colibri_t20-512", "nvidia,tegra20"; - - aliases { - rtc0 = "/i2c@7000d000/tps6586x@34"; - rtc1 = "/rtc@7000e000"; - }; - memory@0 { /* * Set memory to 256 MB to be safe as this could be used on @@ -21,12 +19,11 @@ host1x@50000000 { hdmi@54280000 { - vdd-supply = <&hdmi_vdd_reg>; - pll-supply = <&hdmi_pll_reg>; - - nvidia,ddc-i2c-bus = <&i2c_ddc>; - nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) - GPIO_ACTIVE_HIGH>; + nvidia,ddc-i2c-bus = <&hdmi_ddc>; + nvidia,hpd-gpio = + <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + pll-supply = <®_1v8_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; }; }; @@ -35,187 +32,406 @@ pinctrl-0 = <&state_default>; state_default: pinmux { - audio_refclk { + /* Analogue Audio AC97 to WM9712 (On-module) */ + audio-refclk { nvidia,pins = "cdev1"; nvidia,function = "plla_out"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - crt { - nvidia,pins = "crtp"; - nvidia,function = "crt"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_ENABLE>; - }; dap3 { nvidia,pins = "dap3"; nvidia,function = "dap3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - displaya { - nvidia,pins = "ld0", "ld1", "ld2", "ld3", - "ld4", "ld5", "ld6", "ld7", "ld8", - "ld9", "ld10", "ld11", "ld12", "ld13", - "ld14", "ld15", "ld16", "ld17", - "lhs", "lpw0", "lpw2", "lsc0", - "lsc1", "lsck", "lsda", "lspi", "lvs"; - nvidia,function = "displaya"; - nvidia,tristate = <TEGRA_PIN_ENABLE>; - }; - gpio_dte { - nvidia,pins = "dte"; - nvidia,function = "rsvd1"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_DISABLE>; - }; - gpio_gmi { - nvidia,pins = "ata", "atc", "atd", "ate", - "dap1", "dap2", "dap4", "gpu", "irrx", - "irtx", "spia", "spib", "spic"; - nvidia,function = "gmi"; + + /* + * AC97_RESET, ULPI_RESET, AC97_INT aka WM9712 GENIRQ + * (All on-module), SODIMM Pin 45 Wakeup + */ + gpio-uac { + nvidia,pins = "uac"; + nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - gpio_pta { + + /* + * Buffer Enables for nPWE and RDnWR (On-module, + * see GPIO hogging further down below) + */ + gpio-pta { nvidia,pins = "pta"; nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - gpio_uac { - nvidia,pins = "uac"; - nvidia,function = "rsvd2"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; + + /* + * CLK_32K_OUT, CORE_PWR_REQ, CPU_PWR_REQ, PWR_INT_N, + * SYS_CLK_REQ (All on-module) + */ + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - hdint { - nvidia,pins = "hdint"; + + /* + * Colibri Address/Data Bus (GMI) + * Note: spid and spie optionally used for SPI1 + */ + gmi { + nvidia,pins = "atc", "atd", "ate", "dap1", + "dap2", "dap4", "gmd", "gpu", + "irrx", "irtx", "spia", "spib", + "spic", "spid", "spie", "uca", + "ucb"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + /* Further pins may be used as GPIOs */ + gmi-gpio1 { + nvidia,pins = "lpw0", "lsc1", "lsck", "lsda"; nvidia,function = "hdmi"; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - i2c1 { - nvidia,pins = "rm"; - nvidia,function = "i2c1"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; + gmi-gpio2 { + nvidia,pins = "lcsn", "ldc", "lm0", "lsdi"; + nvidia,function = "rsvd4"; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - i2c3 { - nvidia,pins = "dtf"; - nvidia,function = "i2c3"; + + /* Colibri BL_ON */ + bl-on { + nvidia,pins = "dta"; + nvidia,function = "rsvd1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - i2cddc { + + /* Colibri Backlight PWM<A>, PWM<B> */ + pwm-a-b { + nvidia,pins = "sdc"; + nvidia,function = "pwm"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri DDC */ + ddc { nvidia,pins = "ddc"; nvidia,function = "i2c2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - i2cp { - nvidia,pins = "i2cp"; - nvidia,function = "i2cp"; + + /* + * Colibri EXT_IO* + * Note: dtf optionally used for I2C3 + */ + ext-io { + nvidia,pins = "dtf", "spdi"; + nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - irda { - nvidia,pins = "uad"; - nvidia,function = "irda"; + + /* + * Colibri Ethernet (On-module) + * ULPI EHCI instance 1 USB2_DP/N -> AX88772B + */ + ulpi { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - nand { - nvidia,pins = "kbca", "kbcc", "kbcd", - "kbce", "kbcf"; - nvidia,function = "nand"; + ulpi-refclk { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - owc { - nvidia,pins = "owc"; - nvidia,function = "owr"; + + /* Colibri HOTPLUG_DETECT (HDMI) */ + hotplug-detect { + nvidia,pins = "hdint"; + nvidia,function = "hdmi"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri I2C */ + i2c { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - pmc { - nvidia,pins = "pmc"; - nvidia,function = "pwr_on"; - nvidia,tristate = <TEGRA_PIN_DISABLE>; + + /* + * Colibri L_BIAS, LCD_M1 is muxed with LCD_DE + * today's display need DE, disable LCD_M1 + */ + lm1 { + nvidia,pins = "lm1"; + nvidia,function = "rsvd3"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - pwm { - nvidia,pins = "sdb", "sdc", "sdd"; - nvidia,function = "pwm"; + + /* Colibri LCD (L_* resp. LDD<*>) */ + lcd { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", + "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", + "ld12", "ld13", "ld14", "ld15", + "ld16", "ld17", "lhs", "lsc0", + "lspi", "lvs"; + nvidia,function = "displaya"; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - sdio4 { - nvidia,pins = "atb", "gma", "gme"; + /* Colibri LCD (Optional 24 BPP Support) */ + lcd-24 { + nvidia,pins = "ldi", "lhp0", "lhp1", "lhp2", + "lpp", "lvp1"; + nvidia,function = "displaya"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri MMC */ + mmc { + nvidia,pins = "atb", "gma"; nvidia,function = "sdio4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - spi1 { - nvidia,pins = "spid", "spie", "spif"; - nvidia,function = "spi1"; + + /* Colibri MMCCD */ + mmccd { + nvidia,pins = "gmb"; + nvidia,function = "gmi_int"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - spi4 { + + /* Colibri MMC (Optional 8-bit) */ + mmc-8bit { + nvidia,pins = "gme"; + nvidia,function = "sdio4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* + * Colibri Parallel Camera (Optional) + * pins multiplexed with others and therefore disabled + * Note: dta used for BL_ON by default + */ + cif-mclk { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + cif { + nvidia,pins = "dtb", "dtc", "dtd"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri PWM<C>, PWM<D> */ + pwm-c-d { + nvidia,pins = "sdb", "sdd"; + nvidia,function = "pwm"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri SSP */ + ssp { nvidia,pins = "slxa", "slxc", "slxd", "slxk"; nvidia,function = "spi4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - uarta { + + /* Colibri UART-A */ + uart-a { nvidia,pins = "sdio1"; nvidia,function = "uarta"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - uartd { + uart-a-dsr { + nvidia,pins = "lpw1"; + nvidia,function = "rsvd3"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + uart-a-dcd { + nvidia,pins = "lpw2"; + nvidia,function = "hdmi"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri UART-B */ + uart-b { nvidia,pins = "gmc"; nvidia,function = "uartd"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - ulpi { - nvidia,pins = "uaa", "uab", "uda"; - nvidia,function = "ulpi"; + + /* Colibri UART-C */ + uart-c { + nvidia,pins = "uad"; + nvidia,function = "irda"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri USB_CDET */ + usb-cdet { + nvidia,pins = "spdo"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri USBH_OC */ + usbh-oc { + nvidia,pins = "spih"; + nvidia,function = "spi2_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri USBH_PEN */ + usbh-pen { + nvidia,pins = "spig"; + nvidia,function = "spi2_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri VGA not supported */ + vga { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* I2C3 (Optional) */ + i2c3 { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* JTAG_RTCK */ + jtag-rtck { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; + + /* + * LAN_RESET, LAN_EXT_WAKEUP and LAN_PME + * (All On-module) + */ + gpio-gpv { + nvidia,pins = "gpv"; + nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - ulpi_refclk { - nvidia,pins = "cdev2"; - nvidia,function = "pllp_out4"; + + /* + * LAN_V_BUS, VDD_FAULT, BATT_FAULT, WM9712 PENDOWN + * (All On-module); Colibri CAN_INT + */ + gpio-dte { + nvidia,pins = "dte"; + nvidia,function = "rsvd1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - usb_gpio { - nvidia,pins = "spig", "spih"; - nvidia,function = "spi2_alt"; + + /* NAND (On-module) */ + nand { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "nand"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - vi { - nvidia,pins = "dta", "dtb", "dtc", "dtd"; - nvidia,function = "vi"; + + /* Onewire (Optional) */ + owr { + nvidia,pins = "owc"; + nvidia,function = "owr"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; - vi_sc { - nvidia,pins = "csus"; - nvidia,function = "vi_sensor_clk"; + + /* Power I2C (On-module) */ + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* RESET_OUT */ + reset-out { + nvidia,pins = "ata"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* + * SPI1 (Optional) + * Note: spid and spie used for Colibri Address/Data + * Bus (GMI) + */ + spi1 { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_ENABLE>; }; + + /* + * THERMD_ALERT# (On-module), unlatched I2C address pin + * of LM95245 temperature sensor therefore requires + * disabling for now + */ + lvp0 { + nvidia,pins = "lvp0"; + nvidia,function = "rsvd3"; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + }; }; }; - ac97: ac97@70002000 { + tegra_ac97: ac97@70002000 { status = "okay"; - nvidia,codec-reset-gpio = <&gpio TEGRA_GPIO(V, 0) - GPIO_ACTIVE_HIGH>; - nvidia,codec-sync-gpio = <&gpio TEGRA_GPIO(P, 0) - GPIO_ACTIVE_HIGH>; + nvidia,codec-reset-gpio = + <&gpio TEGRA_GPIO(V, 0) GPIO_ACTIVE_HIGH>; + nvidia,codec-sync-gpio = + <&gpio TEGRA_GPIO(P, 0) GPIO_ACTIVE_HIGH>; + }; + + serial@70006040 { + compatible = "nvidia,tegra20-hsuart"; + }; + + serial@70006300 { + compatible = "nvidia,tegra20-hsuart"; }; nand-controller@70008000 { @@ -243,7 +459,7 @@ }; /* DDC_SCL/SDA on X3 pin 15/16 (e.g. display EDID) */ - i2c_ddc: i2c@7000c400 { + hdmi_ddc: i2c@7000c400 { clock-frequency = <10000>; }; @@ -256,59 +472,45 @@ status = "okay"; clock-frequency = <100000>; - pmic: tps6586x@34 { + pmic@34 { compatible = "ti,tps6586x"; reg = <0x34>; interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; - ti,system-power-controller; - #gpio-cells = <2>; gpio-controller; - - sys-supply = <&vdd_3v3_reg>; - vin-sm0-supply = <&sys_reg>; - vin-sm1-supply = <&sys_reg>; - vin-sm2-supply = <&sys_reg>; - vinldo01-supply = <&sm2_reg>; - vinldo23-supply = <&vdd_3v3_reg>; - vinldo4-supply = <&vdd_3v3_reg>; - vinldo678-supply = <&vdd_3v3_reg>; - vinldo9-supply = <&vdd_3v3_reg>; + sys-supply = <®_module_3v3>; + vin-sm0-supply = <®_3v3_vsys>; + vin-sm1-supply = <®_3v3_vsys>; + vin-sm2-supply = <®_3v3_vsys>; + vinldo01-supply = <®_1v8_vdd_ddr2>; + vinldo23-supply = <®_module_3v3>; + vinldo4-supply = <®_module_3v3>; + vinldo678-supply = <®_module_3v3>; + vinldo9-supply = <®_module_3v3>; regulators { - #address-cells = <1>; - #size-cells = <0>; - - sys_reg: regulator@0 { - reg = <0>; - regulator-compatible = "sys"; - regulator-name = "vdd_sys"; + reg_3v3_vsys: sys { + regulator-name = "VSYS_3.3V"; regulator-always-on; }; - regulator@1 { - reg = <1>; - regulator-compatible = "sm0"; - regulator-name = "vdd_sm0,vdd_core"; + sm0 { + regulator-name = "VDD_CORE_1.2V"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; }; - regulator@2 { - reg = <2>; - regulator-compatible = "sm1"; - regulator-name = "vdd_sm1,vdd_cpu"; + sm1 { + regulator-name = "VDD_CPU_1.0V"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-always-on; }; - sm2_reg: regulator@3 { - reg = <3>; - regulator-compatible = "sm2"; - regulator-name = "vdd_sm2,vin_ldo*"; + reg_1v8_vdd_ddr2: sm2 { + regulator-name = "VDD_DDR2_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; @@ -316,80 +518,68 @@ /* LDO0 is not connected to anything */ - regulator@5 { - reg = <5>; - regulator-compatible = "ldo1"; - regulator-name = "vdd_ldo1,avdd_pll*"; + /* + * +3.3V_ENABLE_N switching via FET: + * AVDD_AUDIO_S and +3.3V + * see also +3.3V fixed supply + */ + ldo1 { + regulator-name = "AVDD_PLL_1.1V"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; regulator-always-on; }; - regulator@6 { - reg = <6>; - regulator-compatible = "ldo2"; - regulator-name = "vdd_ldo2,vdd_rtc"; + ldo2 { + regulator-name = "VDD_RTC_1.2V"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; /* LDO3 is not connected to anything */ - regulator@8 { - reg = <8>; - regulator-compatible = "ldo4"; - regulator-name = "vdd_ldo4,avdd_osc,vddio_sys"; + ldo4 { + regulator-name = "VDDIO_SYS_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; }; - ldo5_reg: regulator@9 { - reg = <9>; - regulator-compatible = "ldo5"; - regulator-name = "vdd_ldo5,vdd_fuse"; + /* Switched via FET from regular +3.3V */ + ldo5 { + regulator-name = "+3.3V_USB"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; - regulator@10 { - reg = <10>; - regulator-compatible = "ldo6"; - regulator-name = "vdd_ldo6,avdd_vdac,vddio_vi,vddio_cam"; + ldo6 { + regulator-name = "AVDD_VDAC_2.85V"; regulator-min-microvolt = <2850000>; regulator-max-microvolt = <2850000>; }; - hdmi_vdd_reg: regulator@11 { - reg = <11>; - regulator-compatible = "ldo7"; - regulator-name = "vdd_ldo7,avdd_hdmi"; + reg_3v3_avdd_hdmi: ldo7 { + regulator-name = "AVDD_HDMI_3.3V"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - hdmi_pll_reg: regulator@12 { - reg = <12>; - regulator-compatible = "ldo8"; - regulator-name = "vdd_ldo8,avdd_hdmi_pll"; + reg_1v8_avdd_hdmi_pll: ldo8 { + regulator-name = "AVDD_HDMI_PLL_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; - regulator@13 { - reg = <13>; - regulator-compatible = "ldo9"; - regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx"; + ldo9 { + regulator-name = "VDDIO_RX_DDR_2.85V"; regulator-min-microvolt = <2850000>; regulator-max-microvolt = <2850000>; regulator-always-on; }; - regulator@14 { - reg = <14>; - regulator-compatible = "ldo_rtc"; - regulator-name = "vdd_rtc_out,vdd_cell"; + ldo_rtc { + regulator-name = "VCC_BATT"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; @@ -397,7 +587,8 @@ }; }; - temperature-sensor@4c { + /* LM95245 temperature sensor */ + temp-sensor@4c { compatible = "national,lm95245"; reg = <0x4c>; }; @@ -410,6 +601,14 @@ nvidia,core-pwr-good-time = <3845 3845>; nvidia,core-pwr-off-time = <3875>; nvidia,sys-clock-req-active-high; + + /* Set SLEEP MODE bit in SUPPLYENE register of TPS658643 PMIC */ + i2c-thermtrip { + nvidia,i2c-controller-id = <3>; + nvidia,bus-addr = <0x34>; + nvidia,reg-addr = <0x14>; + nvidia,reg-data = <0x8>; + }; }; memory-controller@7000f400 { @@ -483,79 +682,87 @@ }; }; + /* EHCI instance 1: ULPI PHY -> AX88772B (On-module) */ usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) - GPIO_ACTIVE_LOW>; + #address-cells = <1>; + #size-cells = <0>; + + asix@1 { + reg = <1>; + local-mac-address = [00 00 00 00 00 00]; + }; }; usb-phy@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1) - GPIO_ACTIVE_LOW>; + nvidia,phy-reset-gpio = + <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>; + vbus-supply = <®_lan_v_bus>; }; - sdhci@c8000600 { - cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>; + clk32k_in: xtal3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; }; - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - clk32k_in: clock@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; + reg_lan_v_bus: regulator-lan-v-bus { + compatible = "regulator-fixed"; + regulator-name = "LAN_V_BUS"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(BB, 1) GPIO_ACTIVE_HIGH>; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - vdd_3v3_reg: regulator@100 { - compatible = "regulator-fixed"; - reg = <100>; - regulator-name = "vdd_3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - regulator@101 { - compatible = "regulator-fixed"; - reg = <101>; - regulator-name = "internal_usb"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - regulator-boot-on; - regulator-always-on; - gpio = <&gpio TEGRA_GPIO(BB, 1) GPIO_ACTIVE_HIGH>; - }; + reg_module_3v3: regulator-module-3v3 { + compatible = "regulator-fixed"; + regulator-name = "+V3.3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; }; sound { compatible = "nvidia,tegra-audio-wm9712-colibri_t20", - "nvidia,tegra-audio-wm9712"; - nvidia,model = "Colibri T20 AC97 Audio"; - + "nvidia,tegra-audio-wm9712"; + nvidia,model = "Toradex Colibri T20"; nvidia,audio-routing = "Headphone", "HPOUTL", "Headphone", "HPOUTR", "LineIn", "LINEINL", "LineIn", "LINEINR", "Mic", "MIC1"; - - nvidia,ac97-controller = <&ac97>; - + nvidia,ac97-controller = <&tegra_ac97>; clocks = <&tegra_car TEGRA20_CLK_PLL_A>, <&tegra_car TEGRA20_CLK_PLL_A_OUT0>, <&tegra_car TEGRA20_CLK_CDEV1>; clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; + +&gpio { + lan-reset-n { + gpio-hog; + gpios = <TEGRA_GPIO(V, 4) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "LAN_RESET#"; + }; + + /* Tri-stating GMI_WR_N on SODIMM pin 99 nPWE */ + npwe { + gpio-hog; + gpios = <TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "Tri-state nPWE"; + }; + + /* Not tri-stating GMI_WR_N on SODIMM pin 93 RDnWR */ + rdnwr { + gpio-hog; + gpios = <TEGRA_GPIO(T, 6) GPIO_ACTIVE_HIGH>; + output-low; + line-name = "Not tri-state RDnWR"; + }; +}; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index ef245291924f..8861e0976e37 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -303,7 +303,7 @@ request-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; slave-addr = <138>; clocks = <&tegra_car TEGRA20_CLK_I2C3>, - <&tegra_car TEGRA20_CLK_PLL_P_OUT3>; + <&tegra_car TEGRA20_CLK_PLL_P_OUT3>; clock-names = "div-clk", "fast-clk"; resets = <&tegra_car 67>; reset-names = "i2c"; @@ -524,10 +524,10 @@ gpio-keys { compatible = "gpio-keys"; - power { - label = "Power"; + wakeup { + label = "Wakeup"; gpios = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_LOW>; - linux,code = <KEY_POWER>; + linux,code = <KEY_WAKEUP>; wakeup-source; }; }; @@ -599,8 +599,8 @@ GPIO_ACTIVE_HIGH>; clocks = <&tegra_car TEGRA20_CLK_PLL_A>, - <&tegra_car TEGRA20_CLK_PLL_A_OUT0>, - <&tegra_car TEGRA20_CLK_CDEV1>; + <&tegra_car TEGRA20_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA20_CLK_CDEV1>; clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 15b73bd377f0..20869757d32f 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -419,19 +419,6 @@ status = "disabled"; }; - gmi@70009000 { - compatible = "nvidia,tegra20-gmi"; - reg = <0x70009000 0x1000>; - #address-cells = <2>; - #size-cells = <1>; - ranges = <0 0 0xd0000000 0xfffffff>; - clocks = <&tegra_car TEGRA20_CLK_NOR>; - clock-names = "gmi"; - resets = <&tegra_car 42>; - reset-names = "gmi"; - status = "disabled"; - }; - nand-controller@70008000 { compatible = "nvidia,tegra20-nand"; reg = <0x70008000 0x100>; @@ -447,6 +434,19 @@ status = "disabled"; }; + gmi@70009000 { + compatible = "nvidia,tegra20-gmi"; + reg = <0x70009000 0x1000>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0xd0000000 0xfffffff>; + clocks = <&tegra_car TEGRA20_CLK_NOR>; + clock-names = "gmi"; + resets = <&tegra_car 42>; + reset-names = "gmi"; + status = "disabled"; + }; + pwm: pwm@7000a000 { compatible = "nvidia,tegra20-pwm"; reg = <0x7000a000 0x100>; @@ -865,5 +865,7 @@ compatible = "arm,cortex-a9-pmu"; interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&{/cpus/cpu@0}>, + <&{/cpus/cpu@1}>; }; }; diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts index 0dc85a20bd45..749fc6d1ff70 100644 --- a/arch/arm/boot/dts/tegra30-apalis-eval.dts +++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts @@ -6,11 +6,12 @@ / { model = "Toradex Apalis T30 on Apalis Evaluation Board"; - compatible = "toradex,apalis_t30-eval", "toradex,apalis_t30", "nvidia,tegra30"; + compatible = "toradex,apalis_t30-eval", "toradex,apalis_t30", + "nvidia,tegra30"; aliases { rtc0 = "/i2c@7000c000/rtc@68"; - rtc1 = "/i2c@7000d000/tps65911@2d"; + rtc1 = "/i2c@7000d000/pmic@2d"; rtc2 = "/rtc@7000e000"; serial0 = &uarta; serial1 = &uartb; @@ -23,8 +24,6 @@ }; pcie@3000 { - status = "okay"; - pci@1,0 { status = "okay"; }; @@ -32,10 +31,6 @@ pci@2,0 { status = "okay"; }; - - pci@3,0 { - status = "okay"; - }; }; host1x@50000000 { @@ -45,27 +40,30 @@ nvidia,panel = <&panel>; }; }; + hdmi@54280000 { status = "okay"; + hdmi-supply = <®_5v0>; }; }; + /* Apalis UART1 */ serial@70006000 { status = "okay"; }; + /* Apalis UART2 */ serial@70006040 { - compatible = "nvidia,tegra30-hsuart"; status = "okay"; }; + /* Apalis UART3 */ serial@70006200 { - compatible = "nvidia,tegra30-hsuart"; status = "okay"; }; + /* Apalis UART4 */ serial@70006300 { - compatible = "nvidia,tegra30-hsuart"; status = "okay"; }; @@ -99,13 +97,13 @@ * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on * carrier board) */ - cami2c: i2c@7000c500 { + i2c@7000c500 { status = "okay"; clock-frequency = <400000>; }; /* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */ - hdmiddc: i2c@7000c700 { + i2c@7000c700 { status = "okay"; }; @@ -113,29 +111,16 @@ spi@7000d400 { status = "okay"; spi-max-frequency = <25000000>; - spidev0: spidev@1 { - compatible = "spidev"; - reg = <1>; - spi-max-frequency = <25000000>; - }; }; /* SPI5: Apalis SPI2 */ spi@7000dc00 { status = "okay"; spi-max-frequency = <25000000>; - spidev1: spidev@2 { - compatible = "spidev"; - reg = <2>; - spi-max-frequency = <25000000>; - }; - }; - - hda@70030000 { - status = "okay"; }; - sd1: sdhci@78000000 { + /* Apalis SD1 */ + sdhci@78000000 { status = "okay"; bus-width = <4>; /* SD1_CD# */ @@ -143,7 +128,8 @@ no-1-8-v; }; - mmc1: sdhci@78000400 { + /* Apalis MMC1 */ + sdhci@78000400 { status = "okay"; bus-width = <8>; /* MMC1_CD# */ @@ -154,12 +140,12 @@ /* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */ usb@7d000000 { status = "okay"; + dr_mode = "otg"; }; usb-phy@7d000000 { status = "okay"; - dr_mode = "otg"; - vbus-supply = <&usbo1_vbus_reg>; + vbus-supply = <®_usbo1_vbus>; }; /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */ @@ -169,7 +155,7 @@ usb-phy@7d004000 { status = "okay"; - vbus-supply = <&usbh_vbus_reg>; + vbus-supply = <®_usbh_vbus>; }; /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */ @@ -179,18 +165,17 @@ usb-phy@7d008000 { status = "okay"; - vbus-supply = <&usbh_vbus_reg>; + vbus-supply = <®_usbh_vbus>; }; backlight: backlight { compatible = "pwm-backlight"; - - /* PWM_BKL1 */ - pwms = <&pwm 0 5000000>; brightness-levels = <255 231 223 207 191 159 127 0>; default-brightness-level = <6>; /* BKL1_ON */ enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 0 5000000>; /* BKL1_PWM */ }; gpio-keys { @@ -211,64 +196,53 @@ * edt,et070080dh6: EDT 7.0" LCD TFT */ compatible = "edt,et057090dhu", "simple-panel"; - backlight = <&backlight>; + power-supply = <®_3v3>; }; - pwmleds { - compatible = "pwm-leds"; - - pwm1 { - label = "PWM1"; - pwms = <&pwm 3 19600>; - max-brightness = <255>; - }; - - pwm2 { - label = "PWM2"; - pwms = <&pwm 2 19600>; - max-brightness = <255>; - }; + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; - pwm3 { - label = "PWM3"; - pwms = <&pwm 1 19600>; - max-brightness = <255>; - }; + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V_SW"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; }; - regulators { - sys_5v0_reg: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - }; + /* USBO1_EN */ + reg_usbo1_vbus: regulator-usbo1-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USBO1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_5v0>; + }; - /* USBO1_EN */ - usbo1_vbus_reg: regulator@2 { - compatible = "regulator-fixed"; - reg = <2>; - regulator-name = "usbo1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&sys_5v0_reg>; - }; + /* USBH_EN */ + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USBH(2A|2C|2D|3|4)"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_5v0>; + }; +}; - /* USBH_EN */ - usbh_vbus_reg: regulator@3 { - compatible = "regulator-fixed"; - reg = <3>; - regulator-name = "usbh_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&sys_5v0_reg>; - }; +&gpio { + /* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */ + pex-perst-n { + gpio-hog; + gpios = <TEGRA_GPIO(S, 7) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "PEX_PERST_N"; }; }; diff --git a/arch/arm/boot/dts/tegra30-apalis-v1.1-eval.dts b/arch/arm/boot/dts/tegra30-apalis-v1.1-eval.dts new file mode 100644 index 000000000000..0be50e881684 --- /dev/null +++ b/arch/arm/boot/dts/tegra30-apalis-v1.1-eval.dts @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include "tegra30-apalis-v1.1.dtsi" + +/ { + model = "Toradex Apalis T30 on Apalis Evaluation Board"; + compatible = "toradex,apalis_t30-v1.1-eval", "toradex,apalis_t30-eval", + "toradex,apalis_t30-v1.1", "toradex,apalis_t30", + "nvidia,tegra30"; + + aliases { + rtc0 = "/i2c@7000c000/rtc@68"; + rtc1 = "/i2c@7000d000/pmic@2d"; + rtc2 = "/rtc@7000e000"; + serial0 = &uarta; + serial1 = &uartb; + serial2 = &uartc; + serial3 = &uartd; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + pcie@3000 { + pci@1,0 { + status = "okay"; + }; + + pci@2,0 { + status = "okay"; + }; + }; + + host1x@50000000 { + dc@54200000 { + rgb { + status = "okay"; + nvidia,panel = <&panel>; + }; + }; + + hdmi@54280000 { + status = "okay"; + hdmi-supply = <®_5v0>; + }; + }; + + /* Apalis UART1 */ + serial@70006000 { + status = "okay"; + }; + + /* Apalis UART2 */ + serial@70006040 { + status = "okay"; + }; + + /* Apalis UART3 */ + serial@70006200 { + status = "okay"; + }; + + /* Apalis UART4 */ + serial@70006300 { + status = "okay"; + }; + + pwm@7000a000 { + status = "okay"; + }; + + /* + * GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier + * board) + */ + i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + pcie-switch@58 { + compatible = "plx,pex8605"; + reg = <0x58>; + }; + + /* M41T0M6 real time clock on carrier board */ + rtc@68 { + compatible = "st,m41t0"; + reg = <0x68>; + }; + }; + + /* GEN2_I2C: unused */ + + /* + * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on + * carrier board) + */ + i2c@7000c500 { + status = "okay"; + clock-frequency = <400000>; + }; + + /* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */ + i2c@7000c700 { + status = "okay"; + }; + + /* SPI1: Apalis SPI1 */ + spi@7000d400 { + status = "okay"; + spi-max-frequency = <25000000>; + }; + + /* SPI5: Apalis SPI2 */ + spi@7000dc00 { + status = "okay"; + spi-max-frequency = <25000000>; + }; + + /* Apalis SD1 */ + sdhci@78000000 { + status = "okay"; + bus-width = <4>; + /* SD1_CD# */ + cd-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_LOW>; + no-1-8-v; + }; + + /* Apalis MMC1 */ + sdhci@78000400 { + status = "okay"; + bus-width = <8>; + /* MMC1_CD# */ + cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>; + vqmmc-supply = <®_vddio_sdmmc3>; + }; + + /* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */ + usb@7d000000 { + status = "okay"; + dr_mode = "otg"; + }; + + usb-phy@7d000000 { + status = "okay"; + vbus-supply = <®_usbo1_vbus>; + }; + + /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */ + usb@7d004000 { + status = "okay"; + }; + + usb-phy@7d004000 { + status = "okay"; + vbus-supply = <®_usbh_vbus>; + }; + + /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */ + usb@7d008000 { + status = "okay"; + }; + + usb-phy@7d008000 { + status = "okay"; + vbus-supply = <®_usbh_vbus>; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = <255 231 223 207 191 159 127 0>; + default-brightness-level = <6>; + /* BKL1_ON */ + enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 0 5000000>; /* BKL1_PWM */ + }; + + gpio-keys { + compatible = "gpio-keys"; + + wakeup { + label = "WAKE1_MICO"; + gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>; + linux,code = <KEY_WAKEUP>; + debounce-interval = <10>; + wakeup-source; + }; + }; + + panel: panel { + /* + * edt,et057090dhu: EDT 5.7" LCD TFT + * edt,et070080dh6: EDT 7.0" LCD TFT + */ + compatible = "edt,et057090dhu", "simple-panel"; + backlight = <&backlight>; + power-supply = <®_3v3>; + }; + + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V_SW"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + /* USBO1_EN */ + reg_usbo1_vbus: regulator-usbo1-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USBO1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_5v0>; + }; + + /* USBH_EN */ + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USBH(2A|2C|2D|3|4)"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <®_5v0>; + }; + + /* + * 1.8 volt resp. 3.3 volt VDDIO_SDMMC3 depending on + * EN_+3.3_SDMMC3 GPIO + */ + reg_vddio_sdmmc3: regulator-vddio-sdmmc3 { + compatible = "regulator-gpio"; + regulator-name = "VDDIO_SDMMC3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-type = "voltage"; + gpios = <&gpio TEGRA_GPIO(J, 5) GPIO_ACTIVE_HIGH>; + states = <1800000 0x0 + 3300000 0x1>; + startup-delay-us = <100000>; + vin-supply = <&vddio_sdmmc_1v8_reg>; + }; +}; + +&gpio { + /* Apalis GPIO7 MXM3 pin 15 PLX PEX 8605 PCIe Switch Reset */ + pex-perst-n { + gpio-hog; + gpios = <TEGRA_GPIO(S, 7) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "PEX_PERST_N"; + }; +}; diff --git a/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi b/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi new file mode 100644 index 000000000000..02f8126481a2 --- /dev/null +++ b/arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi @@ -0,0 +1,1189 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +#include "tegra30.dtsi" + +/* + * Toradex Apalis T30 Module Device Tree + * Compatible for Revisions 1GB: V1.1A, V1.1B; 1GB IT: V1.1A, V1.1B; + * 2GB: V1.1A, V1.1B + */ +/ { + memory@80000000 { + reg = <0x80000000 0x40000000>; + }; + + pcie@3000 { + status = "okay"; + avdd-pexa-supply = <&vdd2_reg>; + avdd-pexb-supply = <&vdd2_reg>; + avdd-pex-pll-supply = <&vdd2_reg>; + avdd-plle-supply = <&ldo6_reg>; + hvdd-pex-supply = <®_module_3v3>; + vddio-pex-ctl-supply = <®_module_3v3>; + vdd-pexa-supply = <&vdd2_reg>; + vdd-pexb-supply = <&vdd2_reg>; + + /* Apalis type specific */ + pci@1,0 { + nvidia,num-lanes = <4>; + }; + + /* Apalis PCIe */ + pci@2,0 { + nvidia,num-lanes = <1>; + }; + + /* I210/I211 Gigabit Ethernet Controller (on-module) */ + pci@3,0 { + status = "okay"; + nvidia,num-lanes = <1>; + + pcie@0 { + reg = <0 0 0 0 0>; + local-mac-address = [00 00 00 00 00 00]; + }; + }; + }; + + host1x@50000000 { + hdmi@54280000 { + nvidia,ddc-i2c-bus = <&hdmi_ddc>; + nvidia,hpd-gpio = + <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; + pll-supply = <®_1v8_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; + }; + }; + + pinmux@70000868 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + /* Analogue Audio (On-module) */ + clk1-out-pw4 { + 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>; + }; + dap3-fs-pp0 { + nvidia,pins = "dap3_fs_pp0", + "dap3_sclk_pp3", + "dap3_din_pp1", + "dap3_dout_pp2"; + nvidia,function = "i2s2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis BKL1_ON */ + pv2 { + nvidia,pins = "pv2"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis BKL1_PWM */ + uart3-rts-n-pc0 { + nvidia,pins = "uart3_rts_n_pc0"; + nvidia,function = "pwm0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */ + uart3-cts-n-pa1 { + nvidia,pins = "uart3_cts_n_pa1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis CAN1 on SPI6 */ + spi2-cs0-n-px3 { + nvidia,pins = "spi2_cs0_n_px3", + "spi2_miso_px1", + "spi2_mosi_px0", + "spi2_sck_px2"; + nvidia,function = "spi6"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + /* CAN_INT1 */ + spi2-cs1-n-pw2 { + nvidia,pins = "spi2_cs1_n_pw2"; + nvidia,function = "spi3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis CAN2 on SPI4 */ + gmi-a16-pj7 { + nvidia,pins = "gmi_a16_pj7", + "gmi_a17_pb0", + "gmi_a18_pb1", + "gmi_a19_pk7"; + nvidia,function = "spi4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* CAN_INT2 */ + spi2-cs2-n-pw3 { + nvidia,pins = "spi2_cs2_n_pw3"; + nvidia,function = "spi3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis Digital Audio */ + clk1-req-pee2 { + nvidia,pins = "clk1_req_pee2"; + nvidia,function = "hda"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + clk2-out-pw5 { + 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>; + }; + dap1-fs-pn0 { + nvidia,pins = "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3"; + nvidia,function = "hda"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis GPIO */ + kb-col0-pq0 { + nvidia,pins = "kb_col0_pq0", + "kb_col1_pq1", + "kb_row10_ps2", + "kb_row11_ps3", + "kb_row12_ps4", + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Multiplexed and therefore disabled */ + owr { + nvidia,pins = "owr"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis HDMI1 */ + hdmi-cec-pee3 { + 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>; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + }; + hdmi-int-pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "hdmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis I2C1 */ + gen1-i2c-scl-pc4 { + 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>; + }; + + /* Apalis I2C2 (DDC) */ + ddc-scl-pv4 { + 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>; + }; + + /* Apalis I2C3 (CAM) */ + cam-i2c-scl-pbb1 { + 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>; + }; + + /* Apalis LCD1 */ + lcd-d0-pe0 { + nvidia,pins = "lcd_d0_pe0", + "lcd_d1_pe1", + "lcd_d2_pe2", + "lcd_d3_pe3", + "lcd_d4_pe4", + "lcd_d5_pe5", + "lcd_d6_pe6", + "lcd_d7_pe7", + "lcd_d8_pf0", + "lcd_d9_pf1", + "lcd_d10_pf2", + "lcd_d11_pf3", + "lcd_d12_pf4", + "lcd_d13_pf5", + "lcd_d14_pf6", + "lcd_d15_pf7", + "lcd_d16_pm0", + "lcd_d17_pm1", + "lcd_d18_pm2", + "lcd_d19_pm3", + "lcd_d20_pm4", + "lcd_d21_pm5", + "lcd_d22_pm6", + "lcd_d23_pm7", + "lcd_de_pj1", + "lcd_hsync_pj3", + "lcd_pclk_pb3", + "lcd_vsync_pj4"; + nvidia,function = "displaya"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis MMC1 */ + sdmmc3-clk-pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + sdmmc3-dat0-pb7 { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "sdmmc3_dat4_pd1", + "sdmmc3_dat5_pd0", + "sdmmc3_dat6_pd3", + "sdmmc3_dat7_pd4"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + /* Apalis MMC1_CD# */ + pv3 { + nvidia,pins = "pv3"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis Parallel Camera */ + cam-mclk-pcc0 { + nvidia,pins = "cam_mclk_pcc0"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + vi-vsync-pd6 { + nvidia,pins = "vi_d0_pt4", + "vi_d1_pd5", + "vi_d2_pl0", + "vi_d3_pl1", + "vi_d4_pl2", + "vi_d5_pl3", + "vi_d6_pl4", + "vi_d7_pl5", + "vi_d8_pl6", + "vi_d9_pl7", + "vi_d10_pt2", + "vi_d11_pt3", + "vi_hsync_pd7", + "vi_pclk_pt0", + "vi_vsync_pd6"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Multiplexed and therefore disabled */ + kb-col2-pq2 { + nvidia,pins = "kb_col2_pq2", + "kb_col3_pq3", + "kb_col4_pq4", + "kb_row4_pr4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-row0-pr0 { + nvidia,pins = "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row3_pr3"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-row5-pr5 { + nvidia,pins = "kb_row5_pr5", + "kb_row6_pr6", + "kb_row7_pr7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* + * VI level-shifter direction + * (pull-down => default direction input) + */ + vi-mclk-pt1 { + nvidia,pins = "vi_mclk_pt1"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis PWM1 */ + pu6 { + nvidia,pins = "pu6"; + nvidia,function = "pwm3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis PWM2 */ + pu5 { + nvidia,pins = "pu5"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis PWM3 */ + pu4 { + nvidia,pins = "pu4"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis PWM4 */ + pu3 { + nvidia,pins = "pu3"; + nvidia,function = "pwm0"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis RESET_MOCI# */ + gmi-rst-n-pi4 { + nvidia,pins = "gmi_rst_n_pi4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis SATA1_ACT# */ + pex-l0-prsnt-n-pdd0 { + nvidia,pins = "pex_l0_prsnt_n_pdd0"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis SD1 */ + sdmmc1-clk-pz0 { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + sdmmc1-cmd-pz1 { + 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>; + }; + /* Apalis SD1_CD# */ + clk2-req-pcc5 { + nvidia,pins = "clk2_req_pcc5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis SPDIF1 */ + spdif-out-pk5 { + nvidia,pins = "spdif_out_pk5", + "spdif_in_pk6"; + nvidia,function = "spdif"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis SPI1 */ + spi1-sck-px5 { + nvidia,pins = "spi1_sck_px5", + "spi1_mosi_px4", + "spi1_miso_px7", + "spi1_cs0_n_px6"; + nvidia,function = "spi1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis SPI2 */ + lcd-sck-pz4 { + nvidia,pins = "lcd_sck_pz4", + "lcd_sdout_pn5", + "lcd_sdin_pz2", + "lcd_cs0_n_pn4"; + nvidia,function = "spi5"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* + * Apalis TS (Low-speed type specific) + * pins may be used as GPIOs + */ + kb-col5-pq5 { + nvidia,pins = "kb_col5_pq5"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + kb-col6-pq6 { + nvidia,pins = "kb_col6_pq6", + "kb_col7_pq7", + "kb_row8_ps0", + "kb_row9_ps1"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis UART1 */ + ulpi-data0 { + nvidia,pins = "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0"; + nvidia,function = "uarta"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis UART2 */ + ulpi-clk-py0 { + nvidia,pins = "ulpi_clk_py0", + "ulpi_dir_py1", + "ulpi_nxt_py2", + "ulpi_stp_py3"; + nvidia,function = "uartd"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis UART3 */ + uart2-rxd-pc3 { + nvidia,pins = "uart2_rxd_pc3", + "uart2_txd_pc2"; + nvidia,function = "uartb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis UART4 */ + uart3-rxd-pw7 { + nvidia,pins = "uart3_rxd_pw7", + "uart3_txd_pw6"; + nvidia,function = "uartc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis USBH_EN */ + pex-l0-rst-n-pdd1 { + nvidia,pins = "pex_l0_rst_n_pdd1"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis USBH_OC# */ + pex-l0-clkreq-n-pdd2 { + nvidia,pins = "pex_l0_clkreq_n_pdd2"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis USBO1_EN */ + gen2-i2c-scl-pt5 { + nvidia,pins = "gen2_i2c_scl_pt5"; + nvidia,function = "rsvd4"; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis USBO1_OC# */ + gen2-i2c-sda-pt6 { + nvidia,pins = "gen2_i2c_sda_pt6"; + nvidia,function = "rsvd4"; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis VGA1 not supported and therefore disabled */ + crt-hsync-pv6 { + nvidia,pins = "crt_hsync_pv6", + "crt_vsync_pv7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis WAKE1_MICO */ + pv1 { + nvidia,pins = "pv1"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* eMMC (On-module) */ + sdmmc4-clk-pcc4 { + nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", + "sdmmc4_rst_n_pcc3"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc4-dat0-paa0 { + nvidia,pins = "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>; + }; + + /* EN_+3.3_SDMMC3 */ + uart2-cts-n-pj5 { + nvidia,pins = "uart2_cts_n_pj5"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* LAN i210/i211 DEV_OFF_N, PE_RST_N (On-module) */ + pex-l2-prsnt-n-pdd7 { + nvidia,pins = "pex_l2_prsnt_n_pdd7", + "pex_l2_rst_n_pcc6"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* LAN i210/i211 PE_WAKE_N, SDP3 (On-module) */ + pex-wake-n-pdd3 { + nvidia,pins = "pex_wake_n_pdd3", + "pex_l2_clkreq_n_pcc7"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* LAN i210/i211 SMB_ALERT_N (On-module) */ + sys-clk-req-pz5 { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* LVDS Transceiver Configuration */ + pbb0 { + nvidia,pins = "pbb0", + "pbb7", + "pcc1", + "pcc2"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + pbb3 { + nvidia,pins = "pbb3", + "pbb4", + "pbb5", + "pbb6"; + nvidia,function = "displayb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Not connected and therefore disabled */ + clk-32k-out-pa0 { + nvidia,pins = "clk3_out_pee0", + "clk3_req_pee1", + "clk_32k_out_pa0", + "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_fs_pp4", + "dap4_sclk_pp7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + dap2-fs-pa2 { + nvidia,pins = "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5", + "lcd_dc0_pn6", + "lcd_m1_pw1", + "lcd_pwr1_pc1", + "pex_l1_clkreq_n_pdd6", + "pex_l1_prsnt_n_pdd4", + "pex_l1_rst_n_pdd5"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-ad0-pg0 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad2_pg2", + "gmi_ad3_pg3", + "gmi_ad4_pg4", + "gmi_ad5_pg5", + "gmi_ad6_pg6", + "gmi_ad7_pg7", + "gmi_ad8_ph0", + "gmi_ad9_ph1", + "gmi_ad10_ph2", + "gmi_ad11_ph3", + "gmi_ad12_ph4", + "gmi_ad13_ph5", + "gmi_ad14_ph6", + "gmi_ad15_ph7", + "gmi_adv_n_pk0", + "gmi_clk_pk1", + "gmi_cs4_n_pk2", + "gmi_cs2_n_pk3", + "gmi_dqs_pi2", + "gmi_iordy_pi5", + "gmi_oe_n_pi1", + "gmi_wait_pi7", + "gmi_wr_n_pi0", + "lcd_cs1_n_pw0", + "pu0", + "pu1", + "pu2"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs0-n-pj0 { + nvidia,pins = "gmi_cs0_n_pj0", + "gmi_cs1_n_pj2", + "gmi_cs3_n_pk4"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs6-n-pi3 { + nvidia,pins = "gmi_cs6_n_pi3"; + nvidia,function = "sata"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs7-n-pi6 { + nvidia,pins = "gmi_cs7_n_pi6"; + nvidia,function = "gmi_alt"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-pwr0-pb2 { + nvidia,pins = "lcd_pwr0_pb2", + "lcd_pwr2_pc6", + "lcd_wr_n_pz3"; + nvidia,function = "hdcp"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + uart2-rts-n-pj6 { + nvidia,pins = "uart2_rts_n_pj6"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Power I2C (On-module) */ + pwr-i2c-scl-pz6 { + 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>; + }; + + /* + * THERMD_ALERT#, unlatched I2C address pin of LM95245 + * temperature sensor therefore requires disabling for + * now + */ + lcd-dc1-pd2 { + nvidia,pins = "lcd_dc1_pd2"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* TOUCH_PEN_INT# (On-module) */ + pv0 { + nvidia,pins = "pv0"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + }; + }; + + serial@70006040 { + compatible = "nvidia,tegra30-hsuart"; + }; + + serial@70006200 { + compatible = "nvidia,tegra30-hsuart"; + }; + + serial@70006300 { + compatible = "nvidia,tegra30-hsuart"; + }; + + hdmi_ddc: i2c@7000c700 { + clock-frequency = <10000>; + }; + + /* + * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and + * touch screen controller + */ + i2c@7000d000 { + status = "okay"; + clock-frequency = <100000>; + + /* SGTL5000 audio codec */ + sgtl5000: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_module_3v3_audio>; + VDDD-supply = <®_1v8_vio>; + VDDIO-supply = <®_module_3v3>; + clocks = <&tegra_car TEGRA30_CLK_EXTERN1>; + }; + + pmic: pmic@2d { + compatible = "ti,tps65911"; + reg = <0x2d>; + + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + + #gpio-cells = <2>; + gpio-controller; + + vcc1-supply = <®_module_3v3>; + vcc2-supply = <®_module_3v3>; + vcc3-supply = <®_1v8_vio>; + vcc4-supply = <®_module_3v3>; + vcc5-supply = <®_module_3v3>; + vcc6-supply = <®_1v8_vio>; + vcc7-supply = <®_5v0_charge_pump>; + vccio-supply = <®_module_3v3>; + + regulators { + vdd1_reg: vdd1 { + regulator-name = "+V1.35_VDDIO_DDR"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + + vdd2_reg: vdd2 { + regulator-name = "+V1.05"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + }; + + vddctrl_reg: vddctrl { + regulator-name = "+V1.0_VDD_CPU"; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1150000>; + regulator-always-on; + }; + + reg_1v8_vio: vio { + regulator-name = "+V1.8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + /* + * 1.8 volt +VDDIO_SDMMC3 in case EN_+3.3_SDMMC3 + * is off + */ + vddio_sdmmc_1v8_reg: ldo1 { + regulator-name = "+VDDIO_SDMMC3_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + /* + * EN_+V3.3 switching via FET: + * +V3.3_AUDIO_AVDD_S, +V3.3 + * see also +V3.3 fixed supply + */ + ldo2_reg: ldo2 { + regulator-name = "EN_+V3.3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ldo3_reg: ldo3 { + regulator-name = "+V1.2_CSI"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo4_reg: ldo4 { + regulator-name = "+V1.2_VDD_RTC"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + /* + * +V2.8_AVDD_VDAC: + * only required for (unsupported) analog RGB + */ + ldo5_reg: ldo5 { + regulator-name = "+V2.8_AVDD_VDAC"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + /* + * +V1.05_AVDD_PLLE: avdd_plle should be 1.05V + * but LDO6 can't set voltage in 50mV + * granularity + */ + ldo6_reg: ldo6 { + regulator-name = "+V1.05_AVDD_PLLE"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + ldo7_reg: ldo7 { + regulator-name = "+V1.2_AVDD_PLL"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + ldo8_reg: ldo8 { + regulator-name = "+V1.0_VDD_DDR_HS"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + }; + }; + + /* STMPE811 touch screen controller */ + touchscreen@41 { + compatible = "st,stmpe811"; + reg = <0x41>; + irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + id = <0>; + blocks = <0x5>; + irq-trigger = <0x1>; + + stmpe_touchscreen { + compatible = "st,stmpe-ts"; + /* 3.25 MHz ADC clock speed */ + st,adc-freq = <1>; + /* 8 sample average control */ + st,ave-ctrl = <3>; + /* 7 length fractional part in z */ + st,fraction-z = <7>; + /* + * 50 mA typical 80 mA max touchscreen drivers + * current limit value + */ + st,i-drive = <1>; + /* 12-bit ADC */ + st,mod-12b = <1>; + /* internal ADC reference */ + st,ref-sel = <0>; + /* ADC converstion time: 80 clocks */ + st,sample-time = <4>; + /* 1 ms panel driver settling time */ + st,settling = <3>; + /* 5 ms touch detect interrupt delay */ + st,touch-det-delay = <5>; + }; + }; + + /* + * LM95245 temperature sensor + * Note: OVERT1# directly connected to TPS65911 PMIC PWRDN + */ + temp-sensor@4c { + compatible = "national,lm95245"; + reg = <0x4c>; + }; + + /* SW: +V1.2_VDD_CORE */ + regulator@60 { + compatible = "ti,tps62362"; + reg = <0x60>; + + regulator-name = "tps62362-vout"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + regulator-always-on; + ti,vsel0-state-low; + /* VSEL1: EN_CORE_DVFS_N low for DVFS */ + ti,vsel1-state-low; + }; + }; + + /* SPI4: CAN2 */ + spi@7000da00 { + status = "okay"; + spi-max-frequency = <10000000>; + + can@1 { + compatible = "microchip,mcp2515"; + reg = <1>; + clocks = <&clk16m>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <10000000>; + }; + }; + + /* SPI6: CAN1 */ + spi@7000de00 { + status = "okay"; + spi-max-frequency = <10000000>; + + can@0 { + compatible = "microchip,mcp2515"; + reg = <0>; + clocks = <&clk16m>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(W, 2) IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <10000000>; + }; + }; + + pmc@7000e400 { + nvidia,invert-interrupt; + nvidia,suspend-mode = <1>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <0>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + + /* Set DEV_OFF bit in DCDC control register of TPS65911 PMIC */ + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x2d>; + nvidia,reg-addr = <0x3f>; + nvidia,reg-data = <0x1>; + }; + }; + + hda@70030000 { + status = "okay"; + }; + + ahub@70080000 { + i2s@70080500 { + status = "okay"; + }; + }; + + /* eMMC */ + sdhci@78000600 { + status = "okay"; + bus-width = <8>; + non-removable; + vmmc-supply = <®_module_3v3>; /* VCC */ + vqmmc-supply = <®_1v8_vio>; /* VCCQ */ + mmc-ddr-1_8v; + }; + + clk32k_in: xtal1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + clk16m: osc4 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; + }; + + reg_1v8_avdd_hdmi_pll: regulator-1v8-avdd-hdmi-pll { + compatible = "regulator-fixed"; + regulator-name = "+V1.8_AVDD_HDMI_PLL"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_1v8_vio>; + }; + + reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_module_3v3>; + }; + + reg_5v0_charge_pump: regulator-5v0-charge-pump { + compatible = "regulator-fixed"; + regulator-name = "+V5.0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + reg_module_3v3: regulator-module-3v3 { + compatible = "regulator-fixed"; + regulator-name = "+V3.3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_module_3v3_audio: regulator-module-3v3-audio { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AUDIO_AVDD_S"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sound { + compatible = "toradex,tegra-audio-sgtl5000-apalis_t30", + "nvidia,tegra-audio-sgtl5000"; + nvidia,model = "Toradex Apalis T30"; + nvidia,audio-routing = + "Headphone Jack", "HP_OUT", + "LINE_IN", "Line In Jack", + "MIC_IN", "Mic Jack"; + nvidia,i2s-controller = <&tegra_i2s2>; + nvidia,audio-codec = <&sgtl5000>; + clocks = <&tegra_car TEGRA30_CLK_PLL_A>, + <&tegra_car TEGRA30_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA30_CLK_EXTERN1>; + clock-names = "pll_a", "pll_a_out0", "mclk"; + }; +}; diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi index 2f807d40c1b7..7f112f192fe9 100644 --- a/arch/arm/boot/dts/tegra30-apalis.dtsi +++ b/arch/arm/boot/dts/tegra30-apalis.dtsi @@ -3,48 +3,53 @@ /* * Toradex Apalis T30 Module Device Tree - * Compatible for Revisions 1GB: V1.0A, V1.1A; 1GB IT: V1.1A; - * 2GB: V1.0B, V1.0C, V1.0E, V1.1A + * Compatible for Revisions 1GB: V1.0A; 2GB: V1.0B, V1.0C, V1.0E */ / { - model = "Toradex Apalis T30"; - compatible = "toradex,apalis_t30", "nvidia,tegra30"; - memory@80000000 { reg = <0x80000000 0x40000000>; }; pcie@3000 { + status = "okay"; avdd-pexa-supply = <&vdd2_reg>; - vdd-pexa-supply = <&vdd2_reg>; avdd-pexb-supply = <&vdd2_reg>; - vdd-pexb-supply = <&vdd2_reg>; avdd-pex-pll-supply = <&vdd2_reg>; avdd-plle-supply = <&ldo6_reg>; - vddio-pex-ctl-supply = <&sys_3v3_reg>; - hvdd-pex-supply = <&sys_3v3_reg>; + hvdd-pex-supply = <®_module_3v3>; + vddio-pex-ctl-supply = <®_module_3v3>; + vdd-pexa-supply = <&vdd2_reg>; + vdd-pexb-supply = <&vdd2_reg>; + /* Apalis type specific */ pci@1,0 { nvidia,num-lanes = <4>; }; + /* Apalis PCIe */ pci@2,0 { nvidia,num-lanes = <1>; }; + /* I210/I211 Gigabit Ethernet Controller (on-module) */ pci@3,0 { + status = "okay"; nvidia,num-lanes = <1>; + + pcie@0 { + reg = <0 0 0 0 0>; + local-mac-address = [00 00 00 00 00 00]; + }; }; }; host1x@50000000 { hdmi@54280000 { - vdd-supply = <&avdd_hdmi_3v3_reg>; - pll-supply = <&avdd_hdmi_pll_1v8_reg>; - + nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; - nvidia,ddc-i2c-bus = <&hdmiddc>; + pll-supply = <®_1v8_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; }; }; @@ -54,18 +59,18 @@ state_default: pinmux { /* Analogue Audio (On-module) */ - clk1_out_pw4 { + clk1-out-pw4 { 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>; }; - dap3_fs_pp0 { - nvidia,pins = "dap3_fs_pp0", - "dap3_sclk_pp3", - "dap3_din_pp1", - "dap3_dout_pp2"; + dap3-fs-pp0 { + nvidia,pins = "dap3_fs_pp0", + "dap3_sclk_pp3", + "dap3_din_pp1", + "dap3_dout_pp2"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; @@ -77,25 +82,28 @@ nvidia,function = "rsvd4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* Apalis BKL1_PWM */ - uart3_rts_n_pc0 { + uart3-rts-n-pc0 { nvidia,pins = "uart3_rts_n_pc0"; nvidia,function = "pwm0"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */ - uart3_cts_n_pa1 { + uart3-cts-n-pa1 { nvidia,pins = "uart3_cts_n_pa1"; nvidia,function = "rsvd2"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* Apalis CAN1 on SPI6 */ - spi2_cs0_n_px3 { + spi2-cs0-n-px3 { nvidia,pins = "spi2_cs0_n_px3", "spi2_miso_px1", "spi2_mosi_px0", @@ -105,7 +113,7 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; /* CAN_INT1 */ - spi2_cs1_n_pw2 { + spi2-cs1-n-pw2 { nvidia,pins = "spi2_cs1_n_pw2"; nvidia,function = "spi3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -114,7 +122,7 @@ }; /* Apalis CAN2 on SPI4 */ - gmi_a16_pj7 { + gmi-a16-pj7 { nvidia,pins = "gmi_a16_pj7", "gmi_a17_pb0", "gmi_a18_pb1", @@ -125,7 +133,7 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; /* CAN_INT2 */ - spi2_cs2_n_pw3 { + spi2-cs2-n-pw3 { nvidia,pins = "spi2_cs2_n_pw3"; nvidia,function = "spi3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -134,20 +142,20 @@ }; /* Apalis Digital Audio */ - clk1_req_pee2 { + clk1-req-pee2 { nvidia,pins = "clk1_req_pee2"; nvidia,function = "hda"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - clk2_out_pw5 { + clk2-out-pw5 { 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>; }; - dap1_fs_pn0 { + dap1-fs-pn0 { nvidia,pins = "dap1_fs_pn0", "dap1_din_pn1", "dap1_dout_pn2", @@ -157,28 +165,125 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - /* Apalis I2C3 */ - cam_i2c_scl_pbb1 { + /* Apalis GPIO */ + kb-col0-pq0 { + nvidia,pins = "kb_col0_pq0", + "kb_col1_pq1", + "kb_row10_ps2", + "kb_row11_ps3", + "kb_row12_ps4", + "kb_row13_ps5", + "kb_row14_ps6", + "kb_row15_ps7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Multiplexed and therefore disabled */ + owr { + nvidia,pins = "owr"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis HDMI1 */ + hdmi-cec-pee3 { + 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>; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + }; + hdmi-int-pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "hdmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis I2C1 */ + gen1-i2c-scl-pc4 { + 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>; + }; + + /* Apalis I2C2 (DDC) */ + ddc-scl-pv4 { + 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>; + }; + + /* Apalis I2C3 (CAM) */ + cam-i2c-scl-pbb1 { 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,lock = <TEGRA_PIN_DISABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; + /* Apalis LCD1 */ + lcd-d0-pe0 { + nvidia,pins = "lcd_d0_pe0", + "lcd_d1_pe1", + "lcd_d2_pe2", + "lcd_d3_pe3", + "lcd_d4_pe4", + "lcd_d5_pe5", + "lcd_d6_pe6", + "lcd_d7_pe7", + "lcd_d8_pf0", + "lcd_d9_pf1", + "lcd_d10_pf2", + "lcd_d11_pf3", + "lcd_d12_pf4", + "lcd_d13_pf5", + "lcd_d14_pf6", + "lcd_d15_pf7", + "lcd_d16_pm0", + "lcd_d17_pm1", + "lcd_d18_pm2", + "lcd_d19_pm3", + "lcd_d20_pm4", + "lcd_d21_pm5", + "lcd_d22_pm6", + "lcd_d23_pm7", + "lcd_de_pj1", + "lcd_hsync_pj3", + "lcd_pclk_pb3", + "lcd_vsync_pj4"; + nvidia,function = "displaya"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Apalis MMC1 */ - sdmmc3_clk_pa6 { - nvidia,pins = "sdmmc3_clk_pa6", - "sdmmc3_cmd_pa7"; + sdmmc3-clk-pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; nvidia,function = "sdmmc3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - sdmmc3_dat0_pb7 { - nvidia,pins = "sdmmc3_dat0_pb7", + sdmmc3-dat0-pb7 { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", "sdmmc3_dat1_pb6", "sdmmc3_dat2_pb5", "sdmmc3_dat3_pb4", @@ -194,10 +299,81 @@ pv3 { nvidia,pins = "pv3"; nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis Parallel Camera */ + cam-mclk-pcc0 { + nvidia,pins = "cam_mclk_pcc0"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + vi-vsync-pd6 { + nvidia,pins = "vi_d0_pt4", + "vi_d1_pd5", + "vi_d2_pl0", + "vi_d3_pl1", + "vi_d4_pl2", + "vi_d5_pl3", + "vi_d6_pl4", + "vi_d7_pl5", + "vi_d8_pl6", + "vi_d9_pl7", + "vi_d10_pt2", + "vi_d11_pt3", + "vi_hsync_pd7", + "vi_pclk_pt0", + "vi_vsync_pd6"; + nvidia,function = "vi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; + /* Multiplexed and therefore disabled */ + kb-col2-pq2 { + nvidia,pins = "kb_col2_pq2", + "kb_col3_pq3", + "kb_col4_pq4", + "kb_row4_pr4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-row0-pr0 { + nvidia,pins = "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row3_pr3"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-row5-pr5 { + nvidia,pins = "kb_row5_pr5", + "kb_row6_pr6", + "kb_row7_pr7"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* + * VI level-shifter direction + * (pull-down => default direction input) + */ + vi-mclk-pt1 { + nvidia,pins = "vi_mclk_pt1"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; /* Apalis PWM1 */ pu6 { @@ -232,21 +408,30 @@ }; /* Apalis RESET_MOCI# */ - gmi_rst_n_pi4 { + gmi-rst-n-pi4 { nvidia,pins = "gmi_rst_n_pi4"; nvidia,function = "gmi"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; + /* Apalis SATA1_ACT# */ + pex-l0-prsnt-n-pdd0 { + nvidia,pins = "pex_l0_prsnt_n_pdd0"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Apalis SD1 */ - sdmmc1_clk_pz0 { + sdmmc1-clk-pz0 { nvidia,pins = "sdmmc1_clk_pz0"; nvidia,function = "sdmmc1"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - sdmmc1_cmd_pz1 { + sdmmc1-cmd-pz1 { nvidia,pins = "sdmmc1_cmd_pz1", "sdmmc1_dat0_py7", "sdmmc1_dat1_py6", @@ -257,16 +442,26 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; /* Apalis SD1_CD# */ - clk2_req_pcc5 { + clk2-req-pcc5 { nvidia,pins = "clk2_req_pcc5"; nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Apalis SPDIF1 */ + spdif-out-pk5 { + nvidia,pins = "spdif_out_pk5", + "spdif_in_pk6"; + nvidia,function = "spdif"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; /* Apalis SPI1 */ - spi1_sck_px5 { + spi1-sck-px5 { nvidia,pins = "spi1_sck_px5", "spi1_mosi_px4", "spi1_miso_px7", @@ -277,7 +472,7 @@ }; /* Apalis SPI2 */ - lcd_sck_pz4 { + lcd-sck-pz4 { nvidia,pins = "lcd_sck_pz4", "lcd_sdout_pn5", "lcd_sdin_pz2", @@ -287,8 +482,30 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; + /* + * Apalis TS (Low-speed type specific) + * pins may be used as GPIOs + */ + kb-col5-pq5 { + nvidia,pins = "kb_col5_pq5"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + kb-col6-pq6 { + nvidia,pins = "kb_col6_pq6", + "kb_col7_pq7", + "kb_row8_ps0", + "kb_row9_ps1"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Apalis UART1 */ - ulpi_data0 { + ulpi-data0 { nvidia,pins = "ulpi_data0_po1", "ulpi_data1_po2", "ulpi_data2_po3", @@ -303,7 +520,7 @@ }; /* Apalis UART2 */ - ulpi_clk_py0 { + ulpi-clk-py0 { nvidia,pins = "ulpi_clk_py0", "ulpi_dir_py1", "ulpi_nxt_py2", @@ -314,7 +531,7 @@ }; /* Apalis UART3 */ - uart2_rxd_pc3 { + uart2-rxd-pc3 { nvidia,pins = "uart2_rxd_pc3", "uart2_txd_pc2"; nvidia,function = "uartb"; @@ -323,7 +540,7 @@ }; /* Apalis UART4 */ - uart3_rxd_pw7 { + uart3-rxd-pw7 { nvidia,pins = "uart3_rxd_pw7", "uart3_txd_pw6"; nvidia,function = "uartc"; @@ -331,8 +548,26 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; + /* Apalis USBH_EN */ + pex-l0-rst-n-pdd1 { + nvidia,pins = "pex_l0_rst_n_pdd1"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Apalis USBH_OC# */ + pex-l0-clkreq-n-pdd2 { + nvidia,pins = "pex_l0_clkreq_n_pdd2"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Apalis USBO1_EN */ - gen2_i2c_scl_pt5 { + gen2-i2c-scl-pt5 { nvidia,pins = "gen2_i2c_scl_pt5"; nvidia,function = "rsvd4"; nvidia,open-drain = <TEGRA_PIN_DISABLE>; @@ -341,7 +576,7 @@ }; /* Apalis USBO1_OC# */ - gen2_i2c_sda_pt6 { + gen2-i2c-sda-pt6 { nvidia,pins = "gen2_i2c_sda_pt6"; nvidia,function = "rsvd4"; nvidia,open-drain = <TEGRA_PIN_DISABLE>; @@ -350,6 +585,16 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; + /* Apalis VGA1 not supported and therefore disabled */ + crt-hsync-pv6 { + nvidia,pins = "crt_hsync_pv6", + "crt_vsync_pv7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Apalis WAKE1_MICO */ pv1 { nvidia,pins = "pv1"; @@ -360,14 +605,16 @@ }; /* eMMC (On-module) */ - sdmmc4_clk_pcc4 { + sdmmc4-clk-pcc4 { nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", "sdmmc4_rst_n_pcc3"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat0_paa0 { + sdmmc4-dat0-paa0 { nvidia,pins = "sdmmc4_dat0_paa0", "sdmmc4_dat1_paa1", "sdmmc4_dat2_paa2", @@ -379,6 +626,34 @@ nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* LAN i210/i211 DEV_OFF_N, PE_RST_N (On-module) */ + pex-l2-prsnt-n-pdd7 { + nvidia,pins = "pex_l2_prsnt_n_pdd7", + "pex_l2_rst_n_pcc6"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* LAN i210/i211 PE_WAKE_N, SDP3 (On-module) */ + pex-wake-n-pdd3 { + nvidia,pins = "pex_wake_n_pdd3", + "pex_l2_clkreq_n_pcc7"; + nvidia,function = "pcie"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* LAN i210/i211 SMB_ALERT_N (On-module) */ + sys-clk-req-pz5 { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; /* LVDS Transceiver Configuration */ @@ -391,7 +666,6 @@ nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; - nvidia,lock = <TEGRA_PIN_DISABLE>; }; pbb3 { nvidia,pins = "pbb3", @@ -402,18 +676,121 @@ nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; nvidia,enable-input = <TEGRA_PIN_DISABLE>; - nvidia,lock = <TEGRA_PIN_DISABLE>; + }; + + /* Not connected and therefore disabled */ + clk-32k-out-pa0 { + nvidia,pins = "clk3_out_pee0", + "clk3_req_pee1", + "clk_32k_out_pa0", + "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_fs_pp4", + "dap4_sclk_pp7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + dap2-fs-pa2 { + nvidia,pins = "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5", + "lcd_dc0_pn6", + "lcd_m1_pw1", + "lcd_pwr1_pc1", + "pex_l1_clkreq_n_pdd6", + "pex_l1_prsnt_n_pdd4", + "pex_l1_rst_n_pdd5"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-ad0-pg0 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad2_pg2", + "gmi_ad3_pg3", + "gmi_ad4_pg4", + "gmi_ad5_pg5", + "gmi_ad6_pg6", + "gmi_ad7_pg7", + "gmi_ad8_ph0", + "gmi_ad9_ph1", + "gmi_ad10_ph2", + "gmi_ad11_ph3", + "gmi_ad12_ph4", + "gmi_ad13_ph5", + "gmi_ad14_ph6", + "gmi_ad15_ph7", + "gmi_adv_n_pk0", + "gmi_clk_pk1", + "gmi_cs4_n_pk2", + "gmi_cs2_n_pk3", + "gmi_dqs_pi2", + "gmi_iordy_pi5", + "gmi_oe_n_pi1", + "gmi_wait_pi7", + "gmi_wr_n_pi0", + "lcd_cs1_n_pw0", + "pu0", + "pu1", + "pu2"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs0-n-pj0 { + nvidia,pins = "gmi_cs0_n_pj0", + "gmi_cs1_n_pj2", + "gmi_cs3_n_pk4"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs6-n-pi3 { + nvidia,pins = "gmi_cs6_n_pi3"; + nvidia,function = "sata"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-cs7-n-pi6 { + nvidia,pins = "gmi_cs7_n_pi6"; + nvidia,function = "gmi_alt"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-pwr0-pb2 { + nvidia,pins = "lcd_pwr0_pb2", + "lcd_pwr2_pc6", + "lcd_wr_n_pz3"; + nvidia,function = "hdcp"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + uart2-cts-n-pj5 { + nvidia,pins = "uart2_cts_n_pj5", + "uart2_rts_n_pj6"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* Power I2C (On-module) */ - pwr_i2c_scl_pz6 { + pwr-i2c-scl-pz6 { 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,lock = <TEGRA_PIN_DISABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; @@ -422,15 +799,15 @@ * temperature sensor therefore requires disabling for * now */ - lcd_dc1_pd2 { + lcd-dc1-pd2 { nvidia,pins = "lcd_dc1_pd2"; nvidia,function = "rsvd3"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_DISABLE>; - nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - /* TOUCH_PEN_INT# */ + /* TOUCH_PEN_INT# (On-module) */ pv0 { nvidia,pins = "pv0"; nvidia,function = "rsvd1"; @@ -441,7 +818,19 @@ }; }; - hdmiddc: i2c@7000c700 { + serial@70006040 { + compatible = "nvidia,tegra30-hsuart"; + }; + + serial@70006200 { + compatible = "nvidia,tegra30-hsuart"; + }; + + serial@70006300 { + compatible = "nvidia,tegra30-hsuart"; + }; + + hdmi_ddc: i2c@7000c700 { clock-frequency = <10000>; }; @@ -457,12 +846,13 @@ sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - VDDA-supply = <&sys_3v3_reg>; - VDDIO-supply = <&sys_3v3_reg>; + VDDA-supply = <®_module_3v3_audio>; + VDDD-supply = <®_1v8_vio>; + VDDIO-supply = <®_module_3v3>; clocks = <&tegra_car TEGRA30_CLK_EXTERN1>; }; - pmic: tps65911@2d { + pmic: pmic@2d { compatible = "ti,tps65911"; reg = <0x2d>; @@ -475,43 +865,38 @@ #gpio-cells = <2>; gpio-controller; - vcc1-supply = <&sys_3v3_reg>; - vcc2-supply = <&sys_3v3_reg>; - vcc3-supply = <&vio_reg>; - vcc4-supply = <&sys_3v3_reg>; - vcc5-supply = <&sys_3v3_reg>; - vcc6-supply = <&vio_reg>; - vcc7-supply = <&charge_pump_5v0_reg>; - vccio-supply = <&sys_3v3_reg>; + vcc1-supply = <®_module_3v3>; + vcc2-supply = <®_module_3v3>; + vcc3-supply = <®_1v8_vio>; + vcc4-supply = <®_module_3v3>; + vcc5-supply = <®_module_3v3>; + vcc6-supply = <®_1v8_vio>; + vcc7-supply = <®_5v0_charge_pump>; + vccio-supply = <®_module_3v3>; regulators { - /* SW1: +V1.35_VDDIO_DDR */ vdd1_reg: vdd1 { - regulator-name = "vddio_ddr_1v35"; + regulator-name = "+V1.35_VDDIO_DDR"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; }; - /* SW2: +V1.05 */ vdd2_reg: vdd2 { - regulator-name = - "vdd_pexa,vdd_pexb,vdd_sata"; + regulator-name = "+V1.05"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; }; - /* SW CTRL: +V1.0_VDD_CPU */ vddctrl_reg: vddctrl { - regulator-name = "vdd_cpu,vdd_sys"; + regulator-name = "+V1.0_VDD_CPU"; regulator-min-microvolt = <1150000>; regulator-max-microvolt = <1150000>; regulator-always-on; }; - /* SWIO: +V1.8 */ - vio_reg: vio { - regulator-name = "vdd_1v8_gen"; + reg_1v8_vio: vio { + regulator-name = "+V1.8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; @@ -521,27 +906,24 @@ /* * EN_+V3.3 switching via FET: - * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN - * see also v3_3 fixed supply + * +V3.3_AUDIO_AVDD_S, +V3.3 + * see also +V3.3 fixed supply */ ldo2_reg: ldo2 { - regulator-name = "en_3v3"; + regulator-name = "EN_+V3.3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; - /* +V1.2_CSI */ ldo3_reg: ldo3 { - regulator-name = - "avdd_dsi_csi,pwrdet_mipi"; + regulator-name = "+V1.2_CSI"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; - /* +V1.2_VDD_RTC */ ldo4_reg: ldo4 { - regulator-name = "vdd_rtc"; + regulator-name = "+V1.2_VDD_RTC"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; @@ -549,10 +931,10 @@ /* * +V2.8_AVDD_VDAC: - * only required for analog RGB + * only required for (unsupported) analog RGB */ ldo5_reg: ldo5 { - regulator-name = "avdd_vdac"; + regulator-name = "+V2.8_AVDD_VDAC"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; regulator-always-on; @@ -564,22 +946,20 @@ * granularity */ ldo6_reg: ldo6 { - regulator-name = "avdd_plle"; + regulator-name = "+V1.05_AVDD_PLLE"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; }; - /* +V1.2_AVDD_PLL */ ldo7_reg: ldo7 { - regulator-name = "avdd_pll"; + regulator-name = "+V1.2_AVDD_PLL"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; }; - /* +V1.0_VDD_DDR_HS */ ldo8_reg: ldo8 { - regulator-name = "vdd_ddr_hs"; + regulator-name = "+V1.0_VDD_DDR_HS"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-always-on; @@ -588,11 +968,10 @@ }; /* STMPE811 touch screen controller */ - stmpe811@41 { + touchscreen@41 { compatible = "st,stmpe811"; reg = <0x41>; - interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>; - interrupt-parent = <&gpio>; + irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>; interrupt-controller; id = <0>; blocks = <0x5>; @@ -626,7 +1005,7 @@ /* * LM95245 temperature sensor - * Note: OVERT_N directly connected to PMIC PWRDN + * Note: OVERT1# directly connected to TPS65911 PMIC PWRDN */ temp-sensor@4c { compatible = "national,lm95245"; @@ -634,7 +1013,7 @@ }; /* SW: +V1.2_VDD_CORE */ - tps62362@60 { + regulator@60 { compatible = "ti,tps62362"; reg = <0x60>; @@ -659,7 +1038,7 @@ reg = <1>; clocks = <&clk16m>; interrupt-parent = <&gpio>; - interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_EDGE_RISING>; + interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_EDGE_FALLING>; spi-max-frequency = <10000000>; }; }; @@ -674,7 +1053,7 @@ reg = <0>; clocks = <&clk16m>; interrupt-parent = <&gpio>; - interrupts = <TEGRA_GPIO(W, 2) IRQ_TYPE_EDGE_RISING>; + interrupts = <TEGRA_GPIO(W, 2) IRQ_TYPE_EDGE_FALLING>; spi-max-frequency = <10000000>; }; }; @@ -688,6 +1067,18 @@ nvidia,core-pwr-off-time = <0>; nvidia,core-power-req-active-high; nvidia,sys-clock-req-active-high; + + /* Set DEV_OFF bit in DCDC control register of TPS65911 PMIC */ + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x2d>; + nvidia,reg-addr = <0x3f>; + nvidia,reg-data = <0x1>; + }; + }; + + hda@70030000 { + status = "okay"; }; ahub@70080000 { @@ -701,73 +1092,65 @@ status = "okay"; bus-width = <8>; non-removable; + vmmc-supply = <®_module_3v3>; /* VCC */ + vqmmc-supply = <®_1v8_vio>; /* VCCQ */ + mmc-ddr-1_8v; }; - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; + clk32k_in: xtal1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; - clk32k_in: clk@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; + clk16m: osc4 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; + }; - clk16m: clk@1 { - compatible = "fixed-clock"; - reg = <1>; - #clock-cells = <0>; - clock-frequency = <16000000>; - clock-output-names = "clk16m"; - }; + reg_1v8_avdd_hdmi_pll: regulator-1v8-avdd-hdmi-pll { + compatible = "regulator-fixed"; + regulator-name = "+V1.8_AVDD_HDMI_PLL"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_1v8_vio>; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - avdd_hdmi_pll_1v8_reg: regulator@100 { - compatible = "regulator-fixed"; - reg = <100>; - regulator-name = "+V1.8_AVDD_HDMI_PLL"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - enable-active-high; - gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; - vin-supply = <&vio_reg>; - }; + reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_module_3v3>; + }; - sys_3v3_reg: regulator@101 { - compatible = "regulator-fixed"; - reg = <101>; - regulator-name = "3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; + reg_5v0_charge_pump: regulator-5v0-charge-pump { + compatible = "regulator-fixed"; + regulator-name = "+V5.0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; - avdd_hdmi_3v3_reg: regulator@102 { - compatible = "regulator-fixed"; - reg = <102>; - regulator-name = "+V3.3_AVDD_HDMI"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - enable-active-high; - gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; - vin-supply = <&sys_3v3_reg>; - }; + reg_module_3v3: regulator-module-3v3 { + compatible = "regulator-fixed"; + regulator-name = "+V3.3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; - charge_pump_5v0_reg: regulator@103 { - compatible = "regulator-fixed"; - reg = <103>; - regulator-name = "5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - }; + reg_module_3v3_audio: regulator-module-3v3-audio { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AUDIO_AVDD_S"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; }; sound { diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 16e1f387aa6d..5965150ecdd2 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -1,15 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 /dts-v1/; +#include <dt-bindings/input/input.h> #include "tegra30-colibri.dtsi" / { model = "Toradex Colibri T30 on Colibri Evaluation Board"; - compatible = "toradex,colibri_t30-eval-v3", "toradex,colibri_t30", "nvidia,tegra30"; + compatible = "toradex,colibri_t30-eval-v3", "toradex,colibri_t30", + "nvidia,tegra30"; aliases { rtc0 = "/i2c@7000c000/rtc@68"; - rtc1 = "/i2c@7000d000/tps65911@2d"; + rtc1 = "/i2c@7000d000/pmic@2d"; rtc2 = "/rtc@7000e000"; serial0 = &uarta; serial1 = &uartb; @@ -27,22 +29,25 @@ nvidia,panel = <&panel>; }; }; + hdmi@54280000 { status = "okay"; + hdmi-supply = <®_5v0>; }; }; + /* Colibri UART-A */ serial@70006000 { status = "okay"; }; + /* Colibri UART-C */ serial@70006040 { - compatible = "nvidia,tegra30-hsuart"; status = "okay"; }; + /* Colibri UART-B */ serial@70006300 { - compatible = "nvidia,tegra30-hsuart"; status = "okay"; }; @@ -65,8 +70,12 @@ }; }; + /* GEN2_I2C: unused */ + + /* CAM_I2C (I2C3): unused */ + /* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */ - hdmiddc: i2c@7000c700 { + i2c@7000c700 { status = "okay"; }; @@ -74,18 +83,17 @@ spi@7000d400 { status = "okay"; spi-max-frequency = <25000000>; - can0: can@0 { + + can@0 { compatible = "microchip,mcp2515"; reg = <0>; clocks = <&clk16m>; interrupt-parent = <&gpio>; - interrupts = <TEGRA_GPIO(S, 0) IRQ_TYPE_EDGE_RISING>; + /* CAN_INT */ + interrupts = <TEGRA_GPIO(S, 0) IRQ_TYPE_EDGE_FALLING>; spi-max-frequency = <10000000>; - }; - spidev0: spi@1 { - compatible = "spidev"; - reg = <1>; - spi-max-frequency = <25000000>; + vdd-supply = <®_3v3>; + xceiver-supply = <®_5v0>; }; }; @@ -93,19 +101,19 @@ sdhci@78000200 { status = "okay"; bus-width = <4>; - cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>; + cd-gpios = <&gpio TEGRA_GPIO(C, 7) GPIO_ACTIVE_LOW>; /* MMCD */ no-1-8-v; }; /* EHCI instance 0: USB1_DP/N -> USBC_P/N */ usb@7d000000 { status = "okay"; + dr_mode = "otg"; }; usb-phy@7d000000 { status = "okay"; - dr_mode = "otg"; - vbus-supply = <&usbc_vbus_reg>; + vbus-supply = <®_usbc_vbus>; }; /* EHCI instance 2: USB3_DP/N -> USBH_P/N */ @@ -115,28 +123,23 @@ usb-phy@7d008000 { status = "okay"; - vbus-supply = <&usbh_vbus_reg>; + vbus-supply = <®_usbh_vbus>; }; backlight: backlight { compatible = "pwm-backlight"; - - /* PWM<A> */ - pwms = <&pwm 0 5000000>; brightness-levels = <255 128 64 32 16 8 4 0>; default-brightness-level = <6>; /* BL_ON */ enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + power-supply = <®_3v3>; + pwms = <&pwm 0 5000000>; /* PWM<A> */ }; - clocks { - clk16m: clk@1 { - compatible = "fixed-clock"; - reg = <1>; - #clock-cells = <0>; - clock-frequency = <16000000>; - clock-output-names = "clk16m"; - }; + clk16m: osc3 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; }; gpio-keys { @@ -157,58 +160,39 @@ * edt,et070080dh6: EDT 7.0" LCD TFT */ compatible = "edt,et057090dhu", "simple-panel"; - backlight = <&backlight>; + power-supply = <®_3v3>; }; - pwmleds { - compatible = "pwm-leds"; - - pwmb { - label = "PWM<B>"; - pwms = <&pwm 1 19600>; - max-brightness = <255>; - }; - pwmc { - label = "PWM<C>"; - pwms = <&pwm 2 19600>; - max-brightness = <255>; - }; - pwmd { - label = "PWM<D>"; - pwms = <&pwm 3 19600>; - max-brightness = <255>; - }; + reg_3v3: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3.3V_SW"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; }; - regulators { - sys_5v0_reg: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - }; + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + regulator-name = "5V_SW"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; - usbc_vbus_reg: regulator@2 { - compatible = "regulator-fixed"; - reg = <2>; - regulator-name = "usbc_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&sys_5v0_reg>; - }; + reg_usbc_vbus: regulator-usbc-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB5"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_5v0>; + }; - /* USBH_PEN */ - usbh_vbus_reg: regulator@3 { - compatible = "regulator-fixed"; - reg = <3>; - regulator-name = "usbh_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>; - vin-supply = <&sys_5v0_reg>; - }; + /* USBH_PEN resp. USB_P_EN */ + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + regulator-name = "VCC_USB[1-4]"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>; + vin-supply = <®_5v0>; }; }; diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi index 526ed71cf7a3..35af03ca9e90 100644 --- a/arch/arm/boot/dts/tegra30-colibri.dtsi +++ b/arch/arm/boot/dts/tegra30-colibri.dtsi @@ -1,27 +1,22 @@ // SPDX-License-Identifier: GPL-2.0 -#include <dt-bindings/input/input.h> #include "tegra30.dtsi" /* * Toradex Colibri T30 Module Device Tree - * Compatible for Revisions V1.1B, V1.1C, V1.1D, V1.1E; IT: V1.1A + * Compatible for Revisions V1.1B, V1.1C, V1.1D, V1.1E, V1.1F; IT: V1.1A, V1.1B */ / { - model = "Toradex Colibri T30"; - compatible = "toradex,colibri_t30", "nvidia,tegra30"; - memory@80000000 { reg = <0x80000000 0x40000000>; }; host1x@50000000 { hdmi@54280000 { - vdd-supply = <&avdd_hdmi_3v3_reg>; - pll-supply = <&avdd_hdmi_pll_1v8_reg>; - + nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; - nvidia,ddc-i2c-bus = <&hdmiddc>; + pll-supply = <®_1v8_avdd_hdmi_pll>; + vdd-supply = <®_3v3_avdd_hdmi>; }; }; @@ -31,23 +26,173 @@ state_default: pinmux { /* Analogue Audio (On-module) */ - clk1_out_pw4 { + clk1-out-pw4 { 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>; }; - dap3_fs_pp0 { - nvidia,pins = "dap3_fs_pp0", - "dap3_sclk_pp3", - "dap3_din_pp1", - "dap3_dout_pp2"; + dap3-fs-pp0 { + nvidia,pins = "dap3_fs_pp0", + "dap3_sclk_pp3", + "dap3_din_pp1", + "dap3_dout_pp2"; nvidia,function = "i2s2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; + /* Colibri Address/Data Bus (GMI) */ + gmi-ad0-pg0 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad2_pg2", + "gmi_ad3_pg3", + "gmi_ad4_pg4", + "gmi_ad5_pg5", + "gmi_ad6_pg6", + "gmi_ad7_pg7", + "gmi_ad8_ph0", + "gmi_ad9_ph1", + "gmi_ad10_ph2", + "gmi_ad11_ph3", + "gmi_ad12_ph4", + "gmi_ad13_ph5", + "gmi_ad14_ph6", + "gmi_ad15_ph7", + "gmi_adv_n_pk0", + "gmi_clk_pk1", + "gmi_cs4_n_pk2", + "gmi_cs2_n_pk3", + "gmi_iordy_pi5", + "gmi_oe_n_pi1", + "gmi_wait_pi7", + "gmi_wr_n_pi0", + "dap1_fs_pn0", + "dap1_din_pn1", + "dap1_dout_pn2", + "dap1_sclk_pn3", + "dap2_fs_pa2", + "dap2_sclk_pa3", + "dap2_din_pa4", + "dap2_dout_pa5", + "spi1_sck_px5", + "spi1_mosi_px4", + "spi1_cs0_n_px6", + "spi2_cs0_n_px3", + "spi2_miso_px1", + "spi2_mosi_px0", + "spi2_sck_px2", + "uart2_cts_n_pj5", + "uart2_rts_n_pj6"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Further pins may be used as GPIOs */ + dap4-din-pp5 { + nvidia,pins = "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_fs_pp4", + "dap4_sclk_pp7", + "pbb7", + "sdmmc1_clk_pz0", + "sdmmc1_cmd_pz1", + "sdmmc1_dat0_py7", + "sdmmc1_dat1_py6", + "sdmmc1_dat3_py4", + "uart3_cts_n_pa1", + "uart3_txd_pw6", + "uart3_rxd_pw7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-d18-pm2 { + nvidia,pins = "lcd_d18_pm2", + "lcd_d19_pm3", + "lcd_d20_pm4", + "lcd_d21_pm5", + "lcd_d22_pm6", + "lcd_d23_pm7", + "lcd_dc0_pn6", + "pex_l2_clkreq_n_pcc7"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-cs0-n-pn4 { + nvidia,pins = "lcd_cs0_n_pn4", + "lcd_sdin_pz2", + "pu0", + "pu1", + "pu2", + "pu3", + "pu4", + "pu5", + "pu6", + "spi1_miso_px7", + "uart3_rts_n_pc0"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-pwr0-pb2 { + nvidia,pins = "lcd_pwr0_pb2", + "lcd_sck_pz4", + "lcd_sdout_pn5", + "lcd_wr_n_pz3"; + nvidia,function = "hdcp"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + pbb4 { + nvidia,pins = "pbb4", + "pbb5", + "pbb6"; + nvidia,function = "displayb"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Multiplexed RDnWR and therefore disabled */ + lcd-cs1-n-pw0 { + nvidia,pins = "lcd_cs1_n_pw0"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Multiplexed GMI_CLK and therefore disabled */ + owr { + nvidia,pins = "owr"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Tri-stating GMI_WR_N on nPWE SODIMM pin 99 */ + sdmmc3-dat4-pd1 { + nvidia,pins = "sdmmc3_dat4_pd1"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Not tri-stating GMI_WR_N on RDnWR SODIMM pin 93 */ + sdmmc3-dat5-pd0 { + nvidia,pins = "sdmmc3_dat5_pd0"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + /* Colibri BL_ON */ pv2 { nvidia,pins = "pv2"; @@ -57,7 +202,7 @@ }; /* Colibri Backlight PWM<A> */ - sdmmc3_dat3_pb4 { + sdmmc3-dat3-pb4 { nvidia,pins = "sdmmc3_dat3_pb4"; nvidia,function = "pwm0"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -65,7 +210,7 @@ }; /* Colibri CAN_INT */ - kb_row8_ps0 { + kb-row8-ps0 { nvidia,pins = "kb_row8_ps0"; nvidia,function = "kbc"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; @@ -73,26 +218,133 @@ nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; + /* Colibri DDC */ + ddc-scl-pv4 { + 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>; + }; + + /* Colibri EXT_IO* */ + gen2-i2c-scl-pt5 { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "rsvd4"; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + spdif-in-pk6 { + nvidia,pins = "spdif_in_pk6"; + nvidia,function = "hda"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri GPIO */ + clk2-out-pw5 { + nvidia,pins = "clk2_out_pw5", + "pcc2", + "pv3", + "sdmmc1_dat2_py5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-pwr1-pc1 { + nvidia,pins = "lcd_pwr1_pc1", + "pex_l1_clkreq_n_pdd6", + "pex_l1_rst_n_pdd5"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + pv1 { + nvidia,pins = "pv1", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri HOTPLUG_DETECT (HDMI) */ + hdmi-int-pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "hdmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri I2C */ + gen1-i2c-scl-pc4 { + 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>; + }; + + /* Colibri LCD (L_* resp. LDD<*>) */ + lcd-d0-pe0 { + nvidia,pins = "lcd_d0_pe0", + "lcd_d1_pe1", + "lcd_d2_pe2", + "lcd_d3_pe3", + "lcd_d4_pe4", + "lcd_d5_pe5", + "lcd_d6_pe6", + "lcd_d7_pe7", + "lcd_d8_pf0", + "lcd_d9_pf1", + "lcd_d10_pf2", + "lcd_d11_pf3", + "lcd_d12_pf4", + "lcd_d13_pf5", + "lcd_d14_pf6", + "lcd_d15_pf7", + "lcd_d16_pm0", + "lcd_d17_pm1", + "lcd_de_pj1", + "lcd_hsync_pj3", + "lcd_pclk_pb3", + "lcd_vsync_pj4"; + nvidia,function = "displaya"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; /* * Colibri L_BIAS, LCD_M1 is muxed with LCD_DE - * todays display need DE, disable LCD_M1 + * today's display need DE, disable LCD_M1 */ - lcd_m1_pw1 { + lcd-m1-pw1 { nvidia,pins = "lcd_m1_pw1"; nvidia,function = "rsvd3"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_DISABLE>; - nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* Colibri MMC */ - kb_row10_ps2 { + kb-row10-ps2 { nvidia,pins = "kb_row10_ps2"; nvidia,function = "sdmmc2"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - kb_row11_ps3 { + kb-row11-ps3 { nvidia,pins = "kb_row11_ps3", "kb_row12_ps4", "kb_row13_ps5", @@ -102,9 +354,108 @@ nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; + /* Colibri MMC_CD */ + gmi-wp-n-pc7 { + nvidia,pins = "gmi_wp_n_pc7"; + nvidia,function = "rsvd1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* Multiplexed and therefore disabled */ + cam-mclk-pcc0 { + nvidia,pins = "cam_mclk_pcc0"; + nvidia,function = "vi_alt3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + cam-i2c-scl-pbb1 { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + nvidia,open-drain = <TEGRA_PIN_DISABLE>; + }; + pbb0 { + nvidia,pins = "pbb0", + "pcc1"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + pbb3 { + nvidia,pins = "pbb3"; + nvidia,function = "displayb"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Colibri nRESET_OUT */ + gmi-rst-n-pi4 { + nvidia,pins = "gmi_rst_n_pi4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* + * Colibri Parallel Camera (Optional) + * pins multiplexed with others and therefore disabled + */ + vi-vsync-pd6 { + nvidia,pins = "vi_d0_pt4", + "vi_d1_pd5", + "vi_d2_pl0", + "vi_d3_pl1", + "vi_d4_pl2", + "vi_d5_pl3", + "vi_d6_pl4", + "vi_d7_pl5", + "vi_d8_pl6", + "vi_d9_pl7", + "vi_d10_pt2", + "vi_d11_pt3", + "vi_hsync_pd7", + "vi_mclk_pt1", + "vi_pclk_pt0", + "vi_vsync_pd6"; + nvidia,function = "vi"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Colibri PWM<B> */ + sdmmc3-dat2-pb5 { + nvidia,pins = "sdmmc3_dat2_pb5"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Colibri PWM<C> */ + sdmmc3-clk-pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Colibri PWM<D> */ + sdmmc3-cmd-pa7 { + nvidia,pins = "sdmmc3_cmd_pa7"; + nvidia,function = "pwm3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; /* Colibri SSP */ - ulpi_clk_py0 { + ulpi-clk-py0 { nvidia,pins = "ulpi_clk_py0", "ulpi_dir_py1", "ulpi_nxt_py2", @@ -113,16 +464,18 @@ nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - sdmmc3_dat6_pd3 { + /* Multiplexed SSPFRM, SSPTXD and therefore disabled */ + sdmmc3-dat6-pd3 { nvidia,pins = "sdmmc3_dat6_pd3", "sdmmc3_dat7_pd4"; nvidia,function = "spdif"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - /* Colibri UART_A */ - ulpi_data0 { + /* Colibri UART-A */ + ulpi-data0 { nvidia,pins = "ulpi_data0_po1", "ulpi_data1_po2", "ulpi_data2_po3", @@ -136,8 +489,8 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - /* Colibri UART_B */ - gmi_a16_pj7 { + /* Colibri UART-B */ + gmi-a16-pj7 { nvidia,pins = "gmi_a16_pj7", "gmi_a17_pb0", "gmi_a18_pb1", @@ -147,8 +500,8 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - /* Colibri UART_C */ - uart2_rxd { + /* Colibri UART-C */ + uart2-rxd { nvidia,pins = "uart2_rxd_pc3", "uart2_txd_pc2"; nvidia,function = "uartb"; @@ -156,15 +509,53 @@ nvidia,tristate = <TEGRA_PIN_DISABLE>; }; - /* eMMC */ - sdmmc4_clk_pcc4 { + /* Colibri USBC_DET */ + spdif-out-pk5 { + nvidia,pins = "spdif_out_pk5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri USBH_PEN */ + spi2-cs1-n-pw2 { + nvidia,pins = "spi2_cs1_n_pw2"; + nvidia,function = "spi2_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + }; + + /* Colibri USBH_OC */ + spi2-cs2-n-pw3, { + nvidia,pins = "spi2_cs2_n_pw3"; + nvidia,function = "spi2_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Colibri VGA not supported and therefore disabled */ + crt-hsync-pv6 { + nvidia,pins = "crt_hsync_pv6", + "crt_vsync_pv7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* eMMC (On-module) */ + sdmmc4-clk-pcc4 { nvidia,pins = "sdmmc4_clk_pcc4", + "sdmmc4_cmd_pt7", "sdmmc4_rst_n_pcc3"; nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; - sdmmc4_dat0_paa0 { + sdmmc4-dat0-paa0 { nvidia,pins = "sdmmc4_dat0_paa0", "sdmmc4_dat1_paa1", "sdmmc4_dat2_paa2", @@ -176,17 +567,111 @@ nvidia,function = "sdmmc4"; nvidia,pull = <TEGRA_PIN_PULL_UP>; nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* LAN_EXT_WAKEUP#, LAN_PME (On-module) */ + pex-l0-rst-n-pdd1 { + nvidia,pins = "pex_l0_rst_n_pdd1", + "pex_wake_n_pdd3"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + /* LAN_V_BUS, LAN_RESET# (On-module) */ + pex-l0-clkreq-n-pdd2 { + nvidia,pins = "pex_l0_clkreq_n_pdd2", + "pex_l0_prsnt_n_pdd0"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* nBATT_FAULT(SENSE), nVDD_FAULT(SENSE) */ + pex-l2-rst-n-pcc6 { + nvidia,pins = "pex_l2_rst_n_pcc6", + "pex_l2_prsnt_n_pdd7"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Not connected and therefore disabled */ + clk1-req-pee2 { + nvidia,pins = "clk1_req_pee2", + "pex_l1_prsnt_n_pdd4"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + clk2-req-pcc5 { + nvidia,pins = "clk2_req_pcc5", + "clk3_out_pee0", + "clk3_req_pee1", + "clk_32k_out_pa0", + "hdmi_cec_pee3", + "sys_clk_req_pz5"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + gmi-dqs-pi2 { + nvidia,pins = "gmi_dqs_pi2", + "kb_col2_pq2", + "kb_col3_pq3", + "kb_col4_pq4", + "kb_col5_pq5", + "kb_row4_pr4"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-col0-pq0 { + nvidia,pins = "kb_col0_pq0", + "kb_col1_pq1", + "kb_col6_pq6", + "kb_col7_pq7", + "kb_row5_pr5", + "kb_row6_pr6", + "kb_row7_pr7", + "kb_row9_ps1"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + kb-row0-pr0 { + nvidia,pins = "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2", + "kb_row3_pr3"; + nvidia,function = "rsvd3"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-pwr2-pc6 { + nvidia,pins = "lcd_pwr2_pc6"; + nvidia,function = "hdcp"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; /* Power I2C (On-module) */ - pwr_i2c_scl_pz6 { + pwr-i2c-scl-pz6 { 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,lock = <TEGRA_PIN_DISABLE>; nvidia,open-drain = <TEGRA_PIN_ENABLE>; }; @@ -195,15 +680,15 @@ * temperature sensor therefore requires disabling for * now */ - lcd_dc1_pd2 { + lcd-dc1-pd2 { nvidia,pins = "lcd_dc1_pd2"; nvidia,function = "rsvd3"; - nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_DISABLE>; - nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_ENABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; }; - /* TOUCH_PEN_INT# */ + /* TOUCH_PEN_INT# (On-module) */ pv0 { nvidia,pins = "pv0"; nvidia,function = "rsvd1"; @@ -214,13 +699,21 @@ }; }; - hdmiddc: i2c@7000c700 { + serial@70006040 { + compatible = "nvidia,tegra30-hsuart"; + }; + + serial@70006300 { + compatible = "nvidia,tegra30-hsuart"; + }; + + hdmi_ddc: i2c@7000c700 { clock-frequency = <10000>; }; /* * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and - * touch screen controller + * touch screen controller (On-module) */ i2c@7000d000 { status = "okay"; @@ -230,12 +723,13 @@ sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - VDDA-supply = <&sys_3v3_reg>; - VDDIO-supply = <&sys_3v3_reg>; + VDDA-supply = <®_module_3v3_audio>; + VDDD-supply = <®_1v8_vio>; + VDDIO-supply = <®_module_3v3>; clocks = <&tegra_car TEGRA30_CLK_EXTERN1>; }; - pmic: tps65911@2d { + pmic: pmic@2d { compatible = "ti,tps65911"; reg = <0x2d>; @@ -248,19 +742,18 @@ #gpio-cells = <2>; gpio-controller; - vcc1-supply = <&sys_3v3_reg>; - vcc2-supply = <&sys_3v3_reg>; - vcc3-supply = <&vio_reg>; - vcc4-supply = <&sys_3v3_reg>; - vcc5-supply = <&sys_3v3_reg>; - vcc6-supply = <&vio_reg>; - vcc7-supply = <&charge_pump_5v0_reg>; - vccio-supply = <&sys_3v3_reg>; + vcc1-supply = <®_module_3v3>; + vcc2-supply = <®_module_3v3>; + vcc3-supply = <®_1v8_vio>; + vcc4-supply = <®_module_3v3>; + vcc5-supply = <®_module_3v3>; + vcc6-supply = <®_1v8_vio>; + vcc7-supply = <®_5v0_charge_pump>; + vccio-supply = <®_module_3v3>; regulators { - /* SW1: +V1.35_VDDIO_DDR */ vdd1_reg: vdd1 { - regulator-name = "vddio_ddr_1v35"; + regulator-name = "+V1.35_VDDIO_DDR"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; @@ -268,17 +761,15 @@ /* SW2: unused */ - /* SW CTRL: +V1.0_VDD_CPU */ vddctrl_reg: vddctrl { - regulator-name = "vdd_cpu,vdd_sys"; + regulator-name = "+V1.0_VDD_CPU"; regulator-min-microvolt = <1150000>; regulator-max-microvolt = <1150000>; regulator-always-on; }; - /* SWIO: +V1.8 */ - vio_reg: vio { - regulator-name = "vdd_1v8_gen"; + reg_1v8_vio: vio { + regulator-name = "+V1.8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; @@ -289,10 +780,10 @@ /* * EN_+V3.3 switching via FET: * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN - * see also 3v3 fixed supply + * see also +V3.3 fixed supply */ ldo2_reg: ldo2 { - regulator-name = "en_3v3"; + regulator-name = "EN_+V3.3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; @@ -300,9 +791,8 @@ /* LDO3: unused */ - /* +V1.2_VDD_RTC */ ldo4_reg: ldo4 { - regulator-name = "vdd_rtc"; + regulator-name = "+V1.2_VDD_RTC"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; @@ -310,10 +800,10 @@ /* * +V2.8_AVDD_VDAC: - * only required for analog RGB + * only required for (unsupported) analog RGB */ ldo5_reg: ldo5 { - regulator-name = "avdd_vdac"; + regulator-name = "+V2.8_AVDD_VDAC"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; regulator-always-on; @@ -325,22 +815,20 @@ * granularity */ ldo6_reg: ldo6 { - regulator-name = "avdd_plle"; + regulator-name = "+V1.05_AVDD_PLLE"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; }; - /* +V1.2_AVDD_PLL */ ldo7_reg: ldo7 { - regulator-name = "avdd_pll"; + regulator-name = "+V1.2_AVDD_PLL"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; }; - /* +V1.0_VDD_DDR_HS */ ldo8_reg: ldo8 { - regulator-name = "vdd_ddr_hs"; + regulator-name = "+V1.0_VDD_DDR_HS"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-always-on; @@ -349,11 +837,10 @@ }; /* STMPE811 touch screen controller */ - stmpe811@41 { + touchscreen@41 { compatible = "st,stmpe811"; reg = <0x41>; - interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>; - interrupt-parent = <&gpio>; + irq-gpio = <&gpio TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>; interrupt-controller; id = <0>; blocks = <0x5>; @@ -387,7 +874,7 @@ /* * LM95245 temperature sensor - * Note: OVERT_N directly connected to PMIC PWRDN + * Note: OVERT1# directly connected to TPS65911 PMIC PWRDN */ temp-sensor@4c { compatible = "national,lm95245"; @@ -395,7 +882,7 @@ }; /* SW: +V1.2_VDD_CORE */ - tps62362@60 { + regulator@60 { compatible = "ti,tps62362"; reg = <0x60>; @@ -419,6 +906,18 @@ nvidia,core-pwr-off-time = <0>; nvidia,core-power-req-active-high; nvidia,sys-clock-req-active-high; + + /* Set DEV_OFF bit in DCDC control register of TPS65911 PMIC */ + i2c-thermtrip { + nvidia,i2c-controller-id = <4>; + nvidia,bus-addr = <0x2d>; + nvidia,reg-addr = <0x3f>; + nvidia,reg-data = <0x1>; + }; + }; + + hda@70030000 { + status = "okay"; }; ahub@70080000 { @@ -432,75 +931,85 @@ status = "okay"; bus-width = <8>; non-removable; + vmmc-supply = <®_module_3v3>; /* VCC */ + vqmmc-supply = <®_1v8_vio>; /* VCCQ */ + mmc-ddr-1_8v; }; - /* EHCI instance 1: USB2_DP/N -> AX88772B */ + /* EHCI instance 1: USB2_DP/N -> AX88772B (On-module) */ usb@7d004000 { status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + asix@1 { + reg = <1>; + local-mac-address = [00 00 00 00 00 00]; + }; }; usb-phy@7d004000 { status = "okay"; - nvidia,is-wired = <1>; + vbus-supply = <®_lan_v_bus>; }; - clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; + clk32k_in: xtal1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; - clk32k_in: clk@0 { - compatible = "fixed-clock"; - reg = <0>; - #clock-cells = <0>; - clock-frequency = <32768>; - }; + reg_1v8_avdd_hdmi_pll: regulator-1v8-avdd-hdmi-pll { + compatible = "regulator-fixed"; + regulator-name = "+V1.8_AVDD_HDMI_PLL"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_1v8_vio>; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; + reg_3v3_avdd_hdmi: regulator-3v3-avdd-hdmi { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AVDD_HDMI"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_module_3v3>; + }; - avdd_hdmi_pll_1v8_reg: regulator@100 { - compatible = "regulator-fixed"; - reg = <100>; - regulator-name = "+V1.8_AVDD_HDMI_PLL"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - enable-active-high; - gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; - vin-supply = <&vio_reg>; - }; + reg_5v0_charge_pump: regulator-5v0-charge-pump { + compatible = "regulator-fixed"; + regulator-name = "+V5.0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; - sys_3v3_reg: regulator@101 { - compatible = "regulator-fixed"; - reg = <101>; - regulator-name = "3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; + reg_lan_v_bus: regulator-lan-v-bus { + compatible = "regulator-fixed"; + regulator-name = "LAN_V_BUS"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>; + }; - avdd_hdmi_3v3_reg: regulator@102 { - compatible = "regulator-fixed"; - reg = <102>; - regulator-name = "+V3.3_AVDD_HDMI"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - enable-active-high; - gpio = <&pmic 6 GPIO_ACTIVE_HIGH>; - vin-supply = <&sys_3v3_reg>; - }; + reg_module_3v3: regulator-module-3v3 { + compatible = "regulator-fixed"; + regulator-name = "+V3.3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; - charge_pump_5v0_reg: regulator@103 { - compatible = "regulator-fixed"; - reg = <103>; - regulator-name = "5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - }; + reg_module_3v3_audio: regulator-module-3v3-audio { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_AUDIO_AVDD_S"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; }; sound { @@ -519,3 +1028,12 @@ clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; + +&gpio { + lan-reset-n { + gpio-hog; + gpios = <TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>; + output-high; + line-name = "LAN_RESET#"; + }; +}; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index a6781f653310..d2b553f76719 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -896,7 +896,7 @@ nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <51>; - nvidia.xcvr-setup-use-fuses; + nvidia,xcvr-setup-use-fuses; nvidia,xcvr-lsfslew = <1>; nvidia,xcvr-lsrslew = <1>; nvidia,xcvr-hsslew = <32>; @@ -933,7 +933,7 @@ nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <51>; - nvidia.xcvr-setup-use-fuses; + nvidia,xcvr-setup-use-fuses; nvidia,xcvr-lsfslew = <2>; nvidia,xcvr-lsrslew = <2>; nvidia,xcvr-hsslew = <32>; @@ -969,7 +969,7 @@ nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <51>; - nvidia.xcvr-setup-use-fuses; + nvidia,xcvr-setup-use-fuses; nvidia,xcvr-lsfslew = <2>; nvidia,xcvr-lsrslew = <2>; nvidia,xcvr-hsslew = <32>; @@ -1013,5 +1013,9 @@ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&{/cpus/cpu@0}>, + <&{/cpus/cpu@1}>, + <&{/cpus/cpu@2}>, + <&{/cpus/cpu@3}>; }; }; diff --git a/arch/arm/boot/dts/uniphier-ld4-ref.dts b/arch/arm/boot/dts/uniphier-ld4-ref.dts index 21407e159bf7..3aaca10f6644 100644 --- a/arch/arm/boot/dts/uniphier-ld4-ref.dts +++ b/arch/arm/boot/dts/uniphier-ld4-ref.dts @@ -63,6 +63,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/uniphier-ld4.dtsi b/arch/arm/boot/dts/uniphier-ld4.dtsi index 37950ad2de7c..b73d594b6dcd 100644 --- a/arch/arm/boot/dts/uniphier-ld4.dtsi +++ b/arch/arm/boot/dts/uniphier-ld4.dtsi @@ -63,6 +63,17 @@ cache-level = <2>; }; + spi: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -224,6 +235,40 @@ }; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&mio_clk 0>; + reset-names = "host", "bridge"; + resets = <&mio_rst 0>, <&mio_rst 3>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&mio_clk 1>; + reset-names = "host", "bridge", "hw"; + resets = <&mio_rst 1>, <&mio_rst 4>, <&mio_rst 6>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + non-removable; + }; + usb0: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; @@ -347,7 +392,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand2cs>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm/boot/dts/uniphier-ld6b-ref.dts b/arch/arm/boot/dts/uniphier-ld6b-ref.dts index a0a44a422e12..3d9080ee7aef 100644 --- a/arch/arm/boot/dts/uniphier-ld6b-ref.dts +++ b/arch/arm/boot/dts/uniphier-ld6b-ref.dts @@ -65,6 +65,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + ð { status = "okay"; phy-handle = <ðphy>; @@ -76,6 +80,14 @@ }; }; +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + &nand { status = "okay"; }; diff --git a/arch/arm/boot/dts/uniphier-pinctrl.dtsi b/arch/arm/boot/dts/uniphier-pinctrl.dtsi index 51f0e69f49fd..1fee5ffbfb9c 100644 --- a/arch/arm/boot/dts/uniphier-pinctrl.dtsi +++ b/arch/arm/boot/dts/uniphier-pinctrl.dtsi @@ -121,11 +121,36 @@ function = "sd"; }; + pinctrl_sd_uhs: sd-uhs { + groups = "sd"; + function = "sd"; + }; + pinctrl_sd1: sd1 { groups = "sd1"; function = "sd1"; }; + pinctrl_spi0: spi0 { + groups = "spi0"; + function = "spi0"; + }; + + pinctrl_spi1: spi1 { + groups = "spi1"; + function = "spi1"; + }; + + pinctrl_spi2: spi2 { + groups = "spi2"; + function = "spi2"; + }; + + pinctrl_spi3: spi3 { + groups = "spi3"; + function = "spi3"; + }; + pinctrl_system_bus: system-bus { groups = "system_bus", "system_bus_cs1"; function = "system_bus"; diff --git a/arch/arm/boot/dts/uniphier-pro4-ace.dts b/arch/arm/boot/dts/uniphier-pro4-ace.dts index db1b08935ae5..92cc48dd86d0 100644 --- a/arch/arm/boot/dts/uniphier-pro4-ace.dts +++ b/arch/arm/boot/dts/uniphier-pro4-ace.dts @@ -68,6 +68,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb2 { status = "okay"; }; @@ -86,3 +90,11 @@ reg = <1>; }; }; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/uniphier-pro4-ref.dts b/arch/arm/boot/dts/uniphier-pro4-ref.dts index efb084983b82..28038b17bbb3 100644 --- a/arch/arm/boot/dts/uniphier-pro4-ref.dts +++ b/arch/arm/boot/dts/uniphier-pro4-ref.dts @@ -65,6 +65,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb2 { status = "okay"; }; @@ -84,6 +88,14 @@ }; }; +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + &nand { status = "okay"; }; diff --git a/arch/arm/boot/dts/uniphier-pro4-sanji.dts b/arch/arm/boot/dts/uniphier-pro4-sanji.dts index dac4d6679a32..dda1a2f214a8 100644 --- a/arch/arm/boot/dts/uniphier-pro4-sanji.dts +++ b/arch/arm/boot/dts/uniphier-pro4-sanji.dts @@ -71,6 +71,10 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + ð { status = "okay"; phy-handle = <ðphy>; @@ -81,3 +85,11 @@ reg = <1>; }; }; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi index 49539f035219..0beb606cf3c8 100644 --- a/arch/arm/boot/dts/uniphier-pro4.dtsi +++ b/arch/arm/boot/dts/uniphier-pro4.dtsi @@ -71,6 +71,17 @@ cache-level = <2>; }; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -258,6 +269,54 @@ }; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&mio_clk 0>; + reset-names = "host", "bridge"; + resets = <&mio_rst 0>, <&mio_rst 3>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&mio_clk 1>; + reset-names = "host", "bridge", "hw"; + resets = <&mio_rst 1>, <&mio_rst 4>, <&mio_rst 6>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + non-removable; + }; + + sd1: sdhc@5a600000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a600000 0x200>; + interrupts = <0 85 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1>; + clocks = <&mio_clk 2>; + reset-names = "host", "bridge"; + resets = <&mio_rst 2>, <&mio_rst 5>; + bus-width = <4>; + cap-sd-highspeed; + }; + usb2: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; @@ -269,6 +328,8 @@ <&mio_clk 12>; resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>; + phy-names = "usb"; + phys = <&usb_phy0>; has-transaction-translator; }; @@ -283,6 +344,8 @@ <&mio_clk 13>; resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>; + phy-names = "usb"; + phys = <&usb_phy1>; has-transaction-translator; }; @@ -294,6 +357,34 @@ pinctrl: pinctrl { compatible = "socionext,uniphier-pro4-pinctrl"; }; + + usb-phy { + compatible = "socionext,uniphier-pro4-usb2-phy"; + #address-cells = <1>; + #size-cells = <0>; + + usb_phy0: phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + usb_phy1: phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + + usb_phy2: phy@2 { + reg = <2>; + #phy-cells = <0>; + vbus-supply = <&usb0_vbus>; + }; + + usb_phy3: phy@3 { + reg = <3>; + #phy-cells = <0>; + vbus-supply = <&usb1_vbus>; + }; + }; }; soc-glue@5f900000 { @@ -386,6 +477,101 @@ }; }; + usb0: usb@65a00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 134 4>, <0 135 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 12>, <&sys_clk 12>, <&sys_clk 12>; + resets = <&usb0_rst 4>; + phys = <&usb_phy2>, <&usb0_ssphy>; + dr_mode = "host"; + }; + + usb-glue@65b00000 { + compatible = "socionext,uniphier-pro4-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65b00000 0x100>; + + usb0_vbus: regulator@0 { + compatible = "socionext,uniphier-pro4-usb3-regulator"; + reg = <0 0x10>; + clock-names = "gio", "link"; + clocks = <&sys_clk 12>, <&sys_clk 14>; + reset-names = "gio", "link"; + resets = <&sys_rst 12>, <&sys_rst 14>; + }; + + usb0_ssphy: ss-phy@10 { + compatible = "socionext,uniphier-pro4-usb3-ssphy"; + reg = <0x10 0x10>; + #phy-cells = <0>; + clock-names = "gio", "link"; + clocks = <&sys_clk 12>, <&sys_clk 14>; + reset-names = "gio", "link"; + resets = <&sys_rst 12>, <&sys_rst 14>; + vbus-supply = <&usb0_vbus>; + }; + + usb0_rst: reset@40 { + compatible = "socionext,uniphier-pro4-usb3-reset"; + reg = <0x40 0x4>; + #reset-cells = <1>; + clock-names = "gio", "link"; + clocks = <&sys_clk 12>, <&sys_clk 14>; + reset-names = "gio", "link"; + resets = <&sys_rst 12>, <&sys_rst 14>; + }; + }; + + usb1: usb@65c00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65c00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 137 4>, <0 138 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 12>, <&sys_clk 12>, <&sys_clk 12>; + resets = <&usb1_rst 4>; + phys = <&usb_phy3>; + dr_mode = "host"; + }; + + usb-glue@65d00000 { + compatible = "socionext,uniphier-pro4-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65d00000 0x100>; + + usb1_vbus: regulator@0 { + compatible = "socionext,uniphier-pro4-usb3-regulator"; + reg = <0 0x10>; + clock-names = "gio", "link"; + clocks = <&sys_clk 12>, <&sys_clk 15>; + reset-names = "gio", "link"; + resets = <&sys_rst 12>, <&sys_rst 15>; + }; + + usb1_rst: reset@40 { + compatible = "socionext,uniphier-pro4-usb3-reset"; + reg = <0x40 0x4>; + #reset-cells = <1>; + clock-names = "gio", "link"; + clocks = <&sys_clk 12>, <&sys_clk 15>; + reset-names = "gio", "link"; + resets = <&sys_rst 12>, <&sys_rst 15>; + }; + }; + nand: nand@68000000 { compatible = "socionext,uniphier-denali-nand-v5a"; status = "disabled"; @@ -394,7 +580,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm/boot/dts/uniphier-pro5.dtsi b/arch/arm/boot/dts/uniphier-pro5.dtsi index 06c2cef91ec7..365738739412 100644 --- a/arch/arm/boot/dts/uniphier-pro5.dtsi +++ b/arch/arm/boot/dts/uniphier-pro5.dtsi @@ -156,6 +156,28 @@ cache-level = <3>; }; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi1: spi@54006100 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006100 0x100>; + interrupts = <0 216 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -439,9 +461,44 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand2cs>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; + + emmc: sdhc@68400000 { + compatible = "socionext,uniphier-sd-v3.1"; + status = "disabled"; + reg = <0x68400000 0x800>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&sd_clk 1>; + reset-names = "host", "hw"; + resets = <&sd_rst 1>, <&sd_rst 6>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + non-removable; + }; + + sd: sdhc@68800000 { + compatible = "socionext,uniphier-sd-v3.1"; + status = "disabled"; + reg = <0x68800000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&sd_clk 0>; + reset-names = "host"; + resets = <&sd_rst 0>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; }; }; diff --git a/arch/arm/boot/dts/uniphier-pxs2-gentil.dts b/arch/arm/boot/dts/uniphier-pxs2-gentil.dts index bed26b8ed9a3..e27fd4f2a569 100644 --- a/arch/arm/boot/dts/uniphier-pxs2-gentil.dts +++ b/arch/arm/boot/dts/uniphier-pxs2-gentil.dts @@ -76,6 +76,10 @@ }; }; +&emmc { + status = "okay"; +}; + ð { status = "okay"; phy-handle = <ðphy>; @@ -86,3 +90,11 @@ reg = <1>; }; }; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/uniphier-pxs2-vodka.dts b/arch/arm/boot/dts/uniphier-pxs2-vodka.dts index b13d2d16ddad..23fe42b7408b 100644 --- a/arch/arm/boot/dts/uniphier-pxs2-vodka.dts +++ b/arch/arm/boot/dts/uniphier-pxs2-vodka.dts @@ -77,6 +77,10 @@ status = "okay"; }; +&emmc { + status = "okay"; +}; + ð { status = "okay"; phy-handle = <ðphy>; @@ -87,3 +91,7 @@ reg = <1>; }; }; + +&usb0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi index e2d1a22c5950..8d20e9548e39 100644 --- a/arch/arm/boot/dts/uniphier-pxs2.dtsi +++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi @@ -167,6 +167,28 @@ cache-level = <2>; }; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi1: spi@54006100 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006100 0x100>; + interrupts = <0 216 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -422,6 +444,40 @@ }; }; + emmc: sdhc@5a000000 { + compatible = "socionext,uniphier-sd-v3.1.1"; + status = "disabled"; + reg = <0x5a000000 0x800>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&sd_clk 1>; + reset-names = "host", "hw"; + resets = <&sd_rst 1>, <&sd_rst 6>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + non-removable; + }; + + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v3.1.1"; + status = "disabled"; + reg = <0x5a400000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&sd_clk 0>; + reset-names = "host"; + resets = <&sd_rst 0>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; + soc_glue: soc-glue@5f800000 { compatible = "socionext,uniphier-pxs2-soc-glue", "simple-mfd", "syscon"; @@ -523,6 +579,186 @@ }; }; + usb0: usb@65a00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 134 4>, <0 135 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 14>, <&sys_clk 14>, <&sys_clk 14>; + resets = <&usb0_rst 15>; + phys = <&usb0_hsphy0>, <&usb0_hsphy1>, + <&usb0_ssphy0>, <&usb0_ssphy1>; + dr_mode = "host"; + }; + + usb-glue@65b00000 { + compatible = "socionext,uniphier-pxs2-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65b00000 0x400>; + + usb0_rst: reset@0 { + compatible = "socionext,uniphier-pxs2-usb3-reset"; + reg = <0x0 0x4>; + #reset-cells = <1>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb0_vbus0: regulator@100 { + compatible = "socionext,uniphier-pxs2-usb3-regulator"; + reg = <0x100 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb0_vbus1: regulator@110 { + compatible = "socionext,uniphier-pxs2-usb3-regulator"; + reg = <0x110 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb0_hsphy0: hs-phy@200 { + compatible = "socionext,uniphier-pxs2-usb3-hsphy"; + reg = <0x200 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 16>; + vbus-supply = <&usb0_vbus0>; + }; + + usb0_hsphy1: hs-phy@210 { + compatible = "socionext,uniphier-pxs2-usb3-hsphy"; + reg = <0x210 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 16>; + vbus-supply = <&usb0_vbus1>; + }; + + usb0_ssphy0: ss-phy@300 { + compatible = "socionext,uniphier-pxs2-usb3-ssphy"; + reg = <0x300 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 17>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 17>; + vbus-supply = <&usb0_vbus0>; + }; + + usb0_ssphy1: ss-phy@310 { + compatible = "socionext,uniphier-pxs2-usb3-ssphy"; + reg = <0x310 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 18>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 18>; + vbus-supply = <&usb0_vbus1>; + }; + }; + + usb1: usb@65c00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65c00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 137 4>, <0 138 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 15>, <&sys_clk 15>, <&sys_clk 15>; + resets = <&usb1_rst 15>; + phys = <&usb1_hsphy0>, <&usb1_hsphy1>, <&usb1_ssphy0>; + dr_mode = "host"; + }; + + usb-glue@65d00000 { + compatible = "socionext,uniphier-pxs2-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65d00000 0x400>; + + usb1_rst: reset@0 { + compatible = "socionext,uniphier-pxs2-usb3-reset"; + reg = <0x0 0x4>; + #reset-cells = <1>; + clock-names = "link"; + clocks = <&sys_clk 15>; + reset-names = "link"; + resets = <&sys_rst 15>; + }; + + usb1_vbus0: regulator@100 { + compatible = "socionext,uniphier-pxs2-usb3-regulator"; + reg = <0x100 0x10>; + clock-names = "link"; + clocks = <&sys_clk 15>; + reset-names = "link"; + resets = <&sys_rst 15>; + }; + + usb1_vbus1: regulator@110 { + compatible = "socionext,uniphier-pxs2-usb3-regulator"; + reg = <0x110 0x10>; + clock-names = "link"; + clocks = <&sys_clk 15>; + reset-names = "link"; + resets = <&sys_rst 15>; + }; + + usb1_hsphy0: hs-phy@200 { + compatible = "socionext,uniphier-pxs2-usb3-hsphy"; + reg = <0x200 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 15>, <&sys_clk 20>; + reset-names = "link", "phy"; + resets = <&sys_rst 15>, <&sys_rst 20>; + vbus-supply = <&usb1_vbus0>; + }; + + usb1_hsphy1: hs-phy@210 { + compatible = "socionext,uniphier-pxs2-usb3-hsphy"; + reg = <0x210 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 15>, <&sys_clk 20>; + reset-names = "link", "phy"; + resets = <&sys_rst 15>, <&sys_rst 20>; + vbus-supply = <&usb1_vbus1>; + }; + + usb1_ssphy0: ss-phy@300 { + compatible = "socionext,uniphier-pxs2-usb3-ssphy"; + reg = <0x300 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 15>, <&sys_clk 21>; + reset-names = "link", "phy"; + resets = <&sys_rst 15>, <&sys_rst 21>; + vbus-supply = <&usb1_vbus0>; + }; + }; + nand: nand@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; @@ -531,7 +767,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand2cs>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm/boot/dts/uniphier-sld8-ref.dts b/arch/arm/boot/dts/uniphier-sld8-ref.dts index fe386fa2ea4b..01bf94c6b93a 100644 --- a/arch/arm/boot/dts/uniphier-sld8-ref.dts +++ b/arch/arm/boot/dts/uniphier-sld8-ref.dts @@ -63,6 +63,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/uniphier-sld8.dtsi b/arch/arm/boot/dts/uniphier-sld8.dtsi index e9b9b4f3c558..f7fcf6b45995 100644 --- a/arch/arm/boot/dts/uniphier-sld8.dtsi +++ b/arch/arm/boot/dts/uniphier-sld8.dtsi @@ -63,6 +63,17 @@ cache-level = <2>; }; + spi: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -228,6 +239,40 @@ }; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a400000 0x200>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&mio_clk 0>; + reset-names = "host", "bridge"; + resets = <&mio_rst 0>, <&mio_rst 3>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; + + emmc: sdhc@5a500000 { + compatible = "socionext,uniphier-sd-v2.91"; + status = "disabled"; + reg = <0x5a500000 0x200>; + interrupts = <0 78 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emmc>; + clocks = <&mio_clk 1>; + reset-names = "host", "bridge", "hw"; + resets = <&mio_rst 1>, <&mio_rst 4>, <&mio_rst 6>; + bus-width = <8>; + cap-mmc-highspeed; + cap-mmc-hw-reset; + non-removable; + }; + usb0: usb@5a800100 { compatible = "socionext,uniphier-ehci", "generic-ehci"; status = "disabled"; @@ -351,7 +396,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand2cs>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts index 5f61d3609027..6f4f60ba5429 100644 --- a/arch/arm/boot/dts/versatile-ab.dts +++ b/arch/arm/boot/dts/versatile-ab.dts @@ -373,7 +373,7 @@ clock-names = "apb_pclk"; }; - ssp@101f4000 { + spi@101f4000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x101f4000 0x1000>; interrupts = <11>; diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index bbff0115e2fb..76a0949df4a8 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -1,43 +1,6 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2013 Freescale Semiconductor, Inc. #include "vfxxx.dtsi" #include <dt-bindings/interrupt-controller/arm-gic.h> diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts index 6be7a828ae64..59fceea8805d 100644 --- a/arch/arm/boot/dts/vf610-twr.dts +++ b/arch/arm/boot/dts/vf610-twr.dts @@ -1,43 +1,6 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2013 Freescale Semiconductor, Inc. /dts-v1/; #include "vf610.dtsi" diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/vf610-zii-cfu1.dts index 37777cf22e67..b76c3d0413df 100644 --- a/arch/arm/boot/dts/vf610-zii-cfu1.dts +++ b/arch/arm/boot/dts/vf610-zii-cfu1.dts @@ -66,6 +66,15 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; + + sff: sfp { + compatible = "sff,sff"; + pinctrl-0 = <&pinctrl_optical>; + pinctrl-names = "default"; + i2c-bus = <&i2c0>; + los-gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>; + tx-disable-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; + }; }; &adc0 { @@ -113,6 +122,8 @@ non-removable; no-1-8-v; keep-power-in-suspend; + no-sdio; + no-sd; status = "okay"; }; @@ -120,6 +131,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; bus-width = <4>; + no-sdio; status = "okay"; }; @@ -170,6 +182,14 @@ label = "eth_cu_1000_3"; }; + port@5 { + reg = <5>; + label = "eth_fc_1000_1"; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sff>; + }; + port@6 { reg = <6>; label = "cpu"; @@ -289,6 +309,16 @@ >; }; + pinctrl_optical: optical-grp { + fsl,pins = < + /* SFF SD input */ + VF610_PAD_PTE27__GPIO_132 0x3061 + + /* SFF Transmit disable output */ + VF610_PAD_PTE13__GPIO_118 0x3043 + >; + }; + pinctrl_switch: switch-grp { fsl,pins = < VF610_PAD_PTB28__GPIO_98 0x3061 diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts index 0b1e94c6f25b..6f4a5602cefd 100644 --- a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts +++ b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts @@ -200,6 +200,13 @@ phy-handle = <&switch1phy4>; }; + port@9 { + reg = <9>; + label = "sff2"; + phy-mode = "sgmii"; + managed = "in-band-status"; + sfp = <&sff2>; + }; switch1port10: port@10 { reg = <10>; @@ -245,6 +252,22 @@ #size-cells = <0>; }; }; + + sff2: sff2 { + /* lower */ + compatible = "sff,sff"; + i2c-bus = <&sff2_i2c>; + los-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>; + }; + + sff3: sff3 { + /* upper */ + compatible = "sff,sff"; + i2c-bus = <&sff3_i2c>; + los-gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>; + }; }; &dspi0 { @@ -329,13 +352,6 @@ interrupts = <23 IRQ_TYPE_EDGE_FALLING>; gpio-controller; interrupt-controller; - - enet_swr_en { - gpio-hog; - gpios = <0 GPIO_ACTIVE_HIGH>; - output-high; - line-name = "enet-swr-en"; - }; }; /* @@ -378,26 +394,16 @@ reg = <0>; }; - i2c@1 { + sff2_i2c: i2c@1 { #address-cells = <1>; #size-cells = <0>; reg = <1>; - - sfp2: at24c04@50 { - compatible = "atmel,24c02"; - reg = <0x50>; - }; }; - i2c@2 { + sff3_i2c: i2c@2 { #address-cells = <1>; #size-cells = <0>; reg = <2>; - - sfp3: at24c04@50 { - compatible = "atmel,24c02"; - reg = <0x50>; - }; }; i2c@3 { diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi index 80fef182c672..7fd39817f8ab 100644 --- a/arch/arm/boot/dts/vf610.dtsi +++ b/arch/arm/boot/dts/vf610.dtsi @@ -1,43 +1,7 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2013 Freescale Semiconductor, Inc. + #include "vf500.dtsi" diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index d392794d9c13..028e0ec30e0c 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -1,43 +1,6 @@ -/* - * Copyright 2013 Freescale Semiconductor, Inc. - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Copyright 2013 Freescale Semiconductor, Inc. #include "vf610-pinfunc.h" #include <dt-bindings/clock/vf610-clock.h> @@ -190,7 +153,7 @@ status = "disabled"; }; - dspi0: dspi0@4002c000 { + dspi0: spi@4002c000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-dspi"; @@ -205,7 +168,7 @@ status = "disabled"; }; - dspi1: dspi1@4002d000 { + dspi1: spi@4002d000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-dspi"; @@ -339,7 +302,7 @@ status = "disabled"; }; - qspi0: quadspi@40044000 { + qspi0: spi@40044000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-qspi"; @@ -569,7 +532,7 @@ status = "disabled"; }; - dspi2: dspi2@400ac000 { + dspi2: spi@400ac000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-dspi"; @@ -584,7 +547,7 @@ status = "disabled"; }; - dspi3: dspi3@400ad000 { + dspi3: spi@400ad000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-dspi"; @@ -665,7 +628,7 @@ status = "disabled"; }; - qspi1: quadspi@400c4000 { + qspi1: spi@400c4000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,vf610-qspi"; diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts index cc5a3dc2b4a0..27cd6cb52f1b 100644 --- a/arch/arm/boot/dts/zynq-zc702.dts +++ b/arch/arm/boot/dts/zynq-zc702.dts @@ -174,17 +174,17 @@ #address-cells = <1>; #size-cells = <0>; reg = <7>; - hwmon@52 { + hwmon@34 { compatible = "ti,ucd9248"; - reg = <52>; + reg = <0x34>; }; - hwmon@53 { + hwmon@35 { compatible = "ti,ucd9248"; - reg = <53>; + reg = <0x35>; }; - hwmon@54 { + hwmon@36 { compatible = "ti,ucd9248"; - reg = <54>; + reg = <0x36>; }; }; }; diff --git a/arch/arm/boot/dts/zynq-zc770-xm010.dts b/arch/arm/boot/dts/zynq-zc770-xm010.dts index 0e1bfdd3421f..0dd352289a45 100644 --- a/arch/arm/boot/dts/zynq-zc770-xm010.dts +++ b/arch/arm/boot/dts/zynq-zc770-xm010.dts @@ -68,7 +68,7 @@ status = "okay"; num-cs = <4>; is-decoded-cs = <0>; - flash@0 { + flash@1 { compatible = "sst25wf080", "jedec,spi-nor"; reg = <1>; spi-max-frequency = <1000000>; diff --git a/arch/arm/boot/dts/zynq-zc770-xm013.dts b/arch/arm/boot/dts/zynq-zc770-xm013.dts index 651913f1afa2..4ae2c85df3a0 100644 --- a/arch/arm/boot/dts/zynq-zc770-xm013.dts +++ b/arch/arm/boot/dts/zynq-zc770-xm013.dts @@ -62,7 +62,7 @@ status = "okay"; num-cs = <4>; is-decoded-cs = <0>; - eeprom: eeprom@0 { + eeprom: eeprom@2 { at25,byte-len = <8192>; at25,addr-mode = <2>; at25,page-size = <32>; diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index e9bc88937b1e..bb6a35fb1dd7 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -128,7 +128,7 @@ CONFIG_LEDS_TRIGGER_CAMERA=y CONFIG_DMADEVICES=y CONFIG_DMA_BCM2835=y CONFIG_STAGING=y -CONFIG_BCM2835_VCHIQ=m +CONFIG_SND_BCM2835=m CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y # CONFIG_IOMMU_SUPPORT is not set diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index 4cd2f4a2bff4..8661dd9b064a 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -3,6 +3,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_CGROUPS=y CONFIG_BLK_DEV_INITRD=y @@ -10,13 +11,6 @@ CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y CONFIG_PROFILING=y -CONFIG_OPROFILE=y -CONFIG_KPROBES=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set CONFIG_ARCH_MULTI_V4T=y CONFIG_ARCH_MULTI_V5=y # CONFIG_ARCH_MULTI_V7 is not set @@ -29,11 +23,17 @@ CONFIG_MACH_PCA100=y CONFIG_MACH_IMX27_DT=y CONFIG_SOC_IMX1=y CONFIG_SOC_IMX25=y -CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_PM_DEBUG=y +CONFIG_OPROFILE=y +CONFIG_KPROBES=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -141,11 +141,9 @@ CONFIG_USB_STORAGE=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y -CONFIG_USB_CHIPIDEA_ULPI=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_GADGET=y CONFIG_USB_ETH=m -CONFIG_USB_ULPI_BUS=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 7eca43ff69bb..1ad5736c8fa6 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -2,6 +2,7 @@ CONFIG_KERNEL_LZO=y CONFIG_SYSVIPC=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT_VOLUNTARY=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=18 @@ -12,11 +13,6 @@ CONFIG_EXPERT=y CONFIG_PERF_EVENTS=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -# CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_MULTI_V6=y CONFIG_ARCH_MXC=y CONFIG_MACH_MX31LILLY=y @@ -48,7 +44,6 @@ CONFIG_PCI_MSI=y CONFIG_PCI_IMX6=y CONFIG_SMP=y CONFIG_ARM_PSCI=y -CONFIG_PREEMPT_VOLUNTARY=y CONFIG_HIGHMEM=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" @@ -62,11 +57,17 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPUFREQ_DT=y CONFIG_ARM_IMX6Q_CPUFREQ=y CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y CONFIG_VFP=y CONFIG_NEON=y -CONFIG_BINFMT_MISC=m CONFIG_PM_DEBUG=y CONFIG_PM_TEST_SUSPEND=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BINFMT_MISC=m CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -90,6 +91,8 @@ CONFIG_RFKILL_INPUT=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_CMA_SIZE_MBYTES=64 CONFIG_IMX_WEIM=y CONFIG_CONNECTOR=y @@ -149,9 +152,12 @@ CONFIG_MICREL_PHY=y CONFIG_SMSC_PHY=y CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m -CONFIG_USB_RTL8152=m +CONFIG_USB_RTL8152=y +CONFIG_USB_LAN78XX=y CONFIG_USB_USBNET=y CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_MCS7830=y CONFIG_BRCMFMAC=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -211,6 +217,7 @@ CONFIG_POWER_RESET=y CONFIG_POWER_RESET_SYSCON=y CONFIG_POWER_RESET_SYSCON_POWEROFF=y CONFIG_POWER_SUPPLY=y +CONFIG_SENSORS_MC13783_ADC=y CONFIG_SENSORS_GPIO_FAN=y CONFIG_SENSORS_IIO_HWMON=y CONFIG_THERMAL_WRITABLE_TRIPS=y @@ -302,7 +309,6 @@ CONFIG_USB_STORAGE=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y -CONFIG_USB_CHIPIDEA_ULPI=y CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_FTDI_SIO=m @@ -339,7 +345,6 @@ CONFIG_USB_GADGETFS=m CONFIG_USB_FUNCTIONFS=m CONFIG_USB_MASS_STORAGE=m CONFIG_USB_G_SERIAL=m -CONFIG_USB_ULPI_BUS=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y @@ -409,6 +414,7 @@ CONFIG_ZISOFS=y CONFIG_UDF_FS=m CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=y +CONFIG_TMPFS_POSIX_ACL=y CONFIG_JFFS2_FS=y CONFIG_UBIFS_FS=y CONFIG_NFS_FS=y @@ -421,14 +427,6 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=m CONFIG_NLS_UTF8=y -CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_FS=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_SCHED_DEBUG is not set -CONFIG_PROVE_LOCKING=y -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_FTRACE is not set -# CONFIG_ARM_UNWIND is not set CONFIG_SECURITYFS=y CONFIG_CRYPTO_DEV_FSL_CAAM=y CONFIG_CRYPTO_DEV_SAHARA=y @@ -439,3 +437,10 @@ CONFIG_LIBCRC32C=m CONFIG_FONTS=y CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_PROVE_LOCKING=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index fc33444e94f0..63af6234c1b6 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -79,6 +79,7 @@ CONFIG_ARCH_R7S72100=y CONFIG_ARCH_R8A73A4=y CONFIG_ARCH_R8A7740=y CONFIG_ARCH_R8A7743=y +CONFIG_ARCH_R8A7744=y CONFIG_ARCH_R8A7745=y CONFIG_ARCH_R8A77470=y CONFIG_ARCH_R8A7778=y @@ -282,6 +283,7 @@ CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_MOUSE_CYAPA=m CONFIG_MOUSE_ELAN_I2C=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADC=m CONFIG_TOUCHSCREEN_ATMEL_MXT=m CONFIG_TOUCHSCREEN_MMS114=m CONFIG_TOUCHSCREEN_WM97XX=m @@ -391,6 +393,7 @@ CONFIG_SPI_S3C64XX=m CONFIG_SPI_SH_MSIOF=m CONFIG_SPI_SH_HSPI=y CONFIG_SPI_SIRF=y +CONFIG_SPI_STM32=m CONFIG_SPI_SUN4I=y CONFIG_SPI_SUN6I=y CONFIG_SPI_TEGRA114=y @@ -584,6 +587,7 @@ CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m CONFIG_VIDEO_STI_BDISP=m CONFIG_VIDEO_STI_HVA=m CONFIG_VIDEO_STI_DELTA=m +CONFIG_VIDEO_RENESAS_FDP1=m CONFIG_VIDEO_RENESAS_JPU=m CONFIG_VIDEO_RENESAS_VSP1=m CONFIG_V4L_TEST_DRIVERS=y @@ -614,6 +618,8 @@ CONFIG_DRM_RCAR_LVDS=y CONFIG_DRM_SUN4I=m CONFIG_DRM_FSL_DCU=m CONFIG_DRM_TEGRA=y +CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m +CONFIG_DRM_PANEL_RAYDIUM_RM68200=m CONFIG_DRM_PANEL_SIMPLE=y CONFIG_DRM_PANEL_SAMSUNG_LD9040=m CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m @@ -625,6 +631,8 @@ CONFIG_DRM_SII9234=m CONFIG_DRM_I2C_ADV7511=m CONFIG_DRM_I2C_ADV7511_AUDIO=y CONFIG_DRM_STI=m +CONFIG_DRM_STM=m +CONFIG_DRM_STM_DSI=m CONFIG_DRM_VC4=m CONFIG_DRM_ETNAVIV=m CONFIG_DRM_MXSFB=m @@ -636,6 +644,7 @@ CONFIG_FB_SIMPLE=y CONFIG_LCD_PLATFORM=m CONFIG_BACKLIGHT_PWM=y CONFIG_BACKLIGHT_AS3711=y +CONFIG_BACKLIGHT_GPIO=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y CONFIG_SOUND=m @@ -650,6 +659,7 @@ CONFIG_SND_SOC=m CONFIG_SND_ATMEL_SOC=m CONFIG_SND_ATMEL_SOC_WM8904=m CONFIG_SND_ATMEL_SOC_PDMIC=m +CONFIG_SND_ATMEL_SOC_I2S=m CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_SOC_FSL_SAI=m CONFIG_SND_SOC_ROCKCHIP=m @@ -771,6 +781,7 @@ CONFIG_MMC_ATMELMCI=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_MVSDIO=y CONFIG_MMC_SDHI=y +CONFIG_MMC_UNIPHIER=y CONFIG_MMC_DW=y CONFIG_MMC_DW_EXYNOS=y CONFIG_MMC_DW_ROCKCHIP=y @@ -943,6 +954,8 @@ CONFIG_PHY_STIH407_USB=y CONFIG_PHY_STM32_USBPHYC=y CONFIG_PHY_TEGRA_XUSB=y CONFIG_PHY_DM816X_USB=m +CONFIG_PHY_UNIPHIER_USB3=y +CONFIG_PHY_UNIPHIER_USB2=y CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y CONFIG_TWL4030_USB=m diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 7b8212857535..38480596c449 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -1,6 +1,7 @@ CONFIG_SYSVIPC=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT_VOLUNTARY=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y @@ -15,6 +16,9 @@ CONFIG_CGROUPS=y CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MXS=y +CONFIG_AEABI=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y @@ -23,11 +27,6 @@ CONFIG_MODVERSIONS=y CONFIG_BLK_DEV_INTEGRITY=y # CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_CFQ is not set -# CONFIG_ARCH_MULTI_V7 is not set -CONFIG_ARCH_MXS=y -# CONFIG_ARM_THUMB is not set -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_AEABI=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -80,7 +79,6 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_MXS_AUART=y # CONFIG_HW_RANDOM is not set -CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_MXS=y @@ -102,7 +100,6 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y -CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y @@ -163,6 +160,10 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_850=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC7=m +CONFIG_FONTS=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y CONFIG_FRAME_WARN=2048 @@ -174,7 +175,3 @@ CONFIG_PROVE_LOCKING=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_STRICT_DEVMEM=y CONFIG_DEBUG_USER=y -CONFIG_CRYPTO_DEV_MXS_DCP=y -CONFIG_CRC_ITU_T=m -CONFIG_CRC7=m -CONFIG_FONTS=y diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig index 6aa7046fb91f..bd6440f23493 100644 --- a/arch/arm/configs/qcom_defconfig +++ b/arch/arm/configs/qcom_defconfig @@ -207,6 +207,7 @@ CONFIG_MSM_MMCC_8974=y CONFIG_MSM_IOMMU=y CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y CONFIG_REMOTEPROC=y CONFIG_QCOM_ADSP_PIL=y CONFIG_QCOM_Q6V5_PIL=y diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index 2080025556b5..b0026f73083d 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -116,6 +116,7 @@ CONFIG_KEYBOARD_QT1070=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADC=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_SERIO is not set CONFIG_LEGACY_PTY_COUNT=4 @@ -167,6 +168,7 @@ CONFIG_SND_ATMEL_SOC_WM8904=y # CONFIG_HID_GENERIC is not set CONFIG_SND_ATMEL_SOC_PDMIC=y CONFIG_SND_ATMEL_SOC_TSE850_PCM5142=m +CONFIG_SND_ATMEL_SOC_I2S=y CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_EHCI_HCD=y diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index f8faf3729464..d090022ca975 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -13,6 +13,7 @@ CONFIG_ARCH_R7S72100=y CONFIG_ARCH_R8A73A4=y CONFIG_ARCH_R8A7740=y CONFIG_ARCH_R8A7743=y +CONFIG_ARCH_R8A7744=y CONFIG_ARCH_R8A7745=y CONFIG_ARCH_R8A77470=y CONFIG_ARCH_R8A7778=y @@ -32,10 +33,8 @@ CONFIG_PCI_RCAR_GEN2=y CONFIG_PCIE_RCAR=y CONFIG_SMP=y CONFIG_SCHED_MC=y -CONFIG_HAVE_ARM_ARCH_TIMER=y CONFIG_NR_CPUS=8 CONFIG_HIGHMEM=y -CONFIG_CMA=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y @@ -50,6 +49,7 @@ CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -129,10 +129,9 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_VIDEO_RCAR_VIN=y CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_RENESAS_FDP1=y CONFIG_VIDEO_RENESAS_JPU=y CONFIG_VIDEO_RENESAS_VSP1=y # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set @@ -209,7 +208,6 @@ CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_ARM_UNWIND is not set diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig index 925d1364727a..ef0c7feea6e2 100644 --- a/arch/arm/crypto/Kconfig +++ b/arch/arm/crypto/Kconfig @@ -99,6 +99,7 @@ config CRYPTO_GHASH_ARM_CE depends on KERNEL_MODE_NEON select CRYPTO_HASH select CRYPTO_CRYPTD + select CRYPTO_GF128MUL help Use an implementation of GHASH (used by the GCM AEAD chaining mode) that uses the 64x64 to 128 bit polynomial multiplication (vmull.p64) @@ -121,10 +122,4 @@ config CRYPTO_CHACHA20_NEON select CRYPTO_BLKCIPHER select CRYPTO_CHACHA20 -config CRYPTO_SPECK_NEON - tristate "NEON accelerated Speck cipher algorithms" - depends on KERNEL_MODE_NEON - select CRYPTO_BLKCIPHER - select CRYPTO_SPECK - endif diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile index 8de542c48ade..bd5bceef0605 100644 --- a/arch/arm/crypto/Makefile +++ b/arch/arm/crypto/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o -obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o @@ -54,7 +53,6 @@ ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o crct10dif-arm-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o -speck-neon-y := speck-neon-core.o speck-neon-glue.o ifdef REGENERATE_ARM_CRYPTO quiet_cmd_perl = PERL $@ diff --git a/arch/arm/crypto/chacha20-neon-core.S b/arch/arm/crypto/chacha20-neon-core.S index 451a849ad518..50e7b9896818 100644 --- a/arch/arm/crypto/chacha20-neon-core.S +++ b/arch/arm/crypto/chacha20-neon-core.S @@ -18,6 +18,34 @@ * (at your option) any later version. */ + /* + * NEON doesn't have a rotate instruction. The alternatives are, more or less: + * + * (a) vshl.u32 + vsri.u32 (needs temporary register) + * (b) vshl.u32 + vshr.u32 + vorr (needs temporary register) + * (c) vrev32.16 (16-bit rotations only) + * (d) vtbl.8 + vtbl.8 (multiple of 8 bits rotations only, + * needs index vector) + * + * ChaCha20 has 16, 12, 8, and 7-bit rotations. For the 12 and 7-bit + * rotations, the only choices are (a) and (b). We use (a) since it takes + * two-thirds the cycles of (b) on both Cortex-A7 and Cortex-A53. + * + * For the 16-bit rotation, we use vrev32.16 since it's consistently fastest + * and doesn't need a temporary register. + * + * For the 8-bit rotation, we use vtbl.8 + vtbl.8. On Cortex-A7, this sequence + * is twice as fast as (a), even when doing (a) on multiple registers + * simultaneously to eliminate the stall between vshl and vsri. Also, it + * parallelizes better when temporary registers are scarce. + * + * A disadvantage is that on Cortex-A53, the vtbl sequence is the same speed as + * (a), so the need to load the rotation table actually makes the vtbl method + * slightly slower overall on that CPU (~1.3% slower ChaCha20). Still, it + * seems to be a good compromise to get a more significant speed boost on some + * CPUs, e.g. ~4.8% faster ChaCha20 on Cortex-A7. + */ + #include <linux/linkage.h> .text @@ -46,7 +74,9 @@ ENTRY(chacha20_block_xor_neon) vmov q10, q2 vmov q11, q3 + adr ip, .Lrol8_table mov r3, #10 + vld1.8 {d10}, [ip, :64] .Ldoubleround: // x0 += x1, x3 = rotl32(x3 ^ x0, 16) @@ -62,9 +92,9 @@ ENTRY(chacha20_block_xor_neon) // x0 += x1, x3 = rotl32(x3 ^ x0, 8) vadd.i32 q0, q0, q1 - veor q4, q3, q0 - vshl.u32 q3, q4, #8 - vsri.u32 q3, q4, #24 + veor q3, q3, q0 + vtbl.8 d6, {d6}, d10 + vtbl.8 d7, {d7}, d10 // x2 += x3, x1 = rotl32(x1 ^ x2, 7) vadd.i32 q2, q2, q3 @@ -92,9 +122,9 @@ ENTRY(chacha20_block_xor_neon) // x0 += x1, x3 = rotl32(x3 ^ x0, 8) vadd.i32 q0, q0, q1 - veor q4, q3, q0 - vshl.u32 q3, q4, #8 - vsri.u32 q3, q4, #24 + veor q3, q3, q0 + vtbl.8 d6, {d6}, d10 + vtbl.8 d7, {d7}, d10 // x2 += x3, x1 = rotl32(x1 ^ x2, 7) vadd.i32 q2, q2, q3 @@ -139,13 +169,17 @@ ENTRY(chacha20_block_xor_neon) bx lr ENDPROC(chacha20_block_xor_neon) + .align 4 +.Lctrinc: .word 0, 1, 2, 3 +.Lrol8_table: .byte 3, 0, 1, 2, 7, 4, 5, 6 + .align 5 ENTRY(chacha20_4block_xor_neon) - push {r4-r6, lr} - mov ip, sp // preserve the stack pointer - sub r3, sp, #0x20 // allocate a 32 byte buffer - bic r3, r3, #0x1f // aligned to 32 bytes - mov sp, r3 + push {r4-r5} + mov r4, sp // preserve the stack pointer + sub ip, sp, #0x20 // allocate a 32 byte buffer + bic ip, ip, #0x1f // aligned to 32 bytes + mov sp, ip // r0: Input state matrix, s // r1: 4 data blocks output, o @@ -155,25 +189,24 @@ ENTRY(chacha20_4block_xor_neon) // This function encrypts four consecutive ChaCha20 blocks by loading // the state matrix in NEON registers four times. The algorithm performs // each operation on the corresponding word of each state matrix, hence - // requires no word shuffling. For final XORing step we transpose the - // matrix by interleaving 32- and then 64-bit words, which allows us to - // do XOR in NEON registers. + // requires no word shuffling. The words are re-interleaved before the + // final addition of the original state and the XORing step. // - // x0..15[0-3] = s0..3[0..3] - add r3, r0, #0x20 + // x0..15[0-3] = s0..15[0-3] + add ip, r0, #0x20 vld1.32 {q0-q1}, [r0] - vld1.32 {q2-q3}, [r3] + vld1.32 {q2-q3}, [ip] - adr r3, CTRINC + adr r5, .Lctrinc vdup.32 q15, d7[1] vdup.32 q14, d7[0] - vld1.32 {q11}, [r3, :128] + vld1.32 {q4}, [r5, :128] vdup.32 q13, d6[1] vdup.32 q12, d6[0] - vadd.i32 q12, q12, q11 // x12 += counter values 0-3 vdup.32 q11, d5[1] vdup.32 q10, d5[0] + vadd.u32 q12, q12, q4 // x12 += counter values 0-3 vdup.32 q9, d4[1] vdup.32 q8, d4[0] vdup.32 q7, d3[1] @@ -185,9 +218,13 @@ ENTRY(chacha20_4block_xor_neon) vdup.32 q1, d0[1] vdup.32 q0, d0[0] + adr ip, .Lrol8_table mov r3, #10 + b 1f .Ldoubleround4: + vld1.32 {q8-q9}, [sp, :256] +1: // x0 += x4, x12 = rotl32(x12 ^ x0, 16) // x1 += x5, x13 = rotl32(x13 ^ x1, 16) // x2 += x6, x14 = rotl32(x14 ^ x2, 16) @@ -236,24 +273,25 @@ ENTRY(chacha20_4block_xor_neon) // x1 += x5, x13 = rotl32(x13 ^ x1, 8) // x2 += x6, x14 = rotl32(x14 ^ x2, 8) // x3 += x7, x15 = rotl32(x15 ^ x3, 8) + vld1.8 {d16}, [ip, :64] vadd.i32 q0, q0, q4 vadd.i32 q1, q1, q5 vadd.i32 q2, q2, q6 vadd.i32 q3, q3, q7 - veor q8, q12, q0 - veor q9, q13, q1 - vshl.u32 q12, q8, #8 - vshl.u32 q13, q9, #8 - vsri.u32 q12, q8, #24 - vsri.u32 q13, q9, #24 + veor q12, q12, q0 + veor q13, q13, q1 + veor q14, q14, q2 + veor q15, q15, q3 - veor q8, q14, q2 - veor q9, q15, q3 - vshl.u32 q14, q8, #8 - vshl.u32 q15, q9, #8 - vsri.u32 q14, q8, #24 - vsri.u32 q15, q9, #24 + vtbl.8 d24, {d24}, d16 + vtbl.8 d25, {d25}, d16 + vtbl.8 d26, {d26}, d16 + vtbl.8 d27, {d27}, d16 + vtbl.8 d28, {d28}, d16 + vtbl.8 d29, {d29}, d16 + vtbl.8 d30, {d30}, d16 + vtbl.8 d31, {d31}, d16 vld1.32 {q8-q9}, [sp, :256] @@ -332,24 +370,25 @@ ENTRY(chacha20_4block_xor_neon) // x1 += x6, x12 = rotl32(x12 ^ x1, 8) // x2 += x7, x13 = rotl32(x13 ^ x2, 8) // x3 += x4, x14 = rotl32(x14 ^ x3, 8) + vld1.8 {d16}, [ip, :64] vadd.i32 q0, q0, q5 vadd.i32 q1, q1, q6 vadd.i32 q2, q2, q7 vadd.i32 q3, q3, q4 - veor q8, q15, q0 - veor q9, q12, q1 - vshl.u32 q15, q8, #8 - vshl.u32 q12, q9, #8 - vsri.u32 q15, q8, #24 - vsri.u32 q12, q9, #24 + veor q15, q15, q0 + veor q12, q12, q1 + veor q13, q13, q2 + veor q14, q14, q3 - veor q8, q13, q2 - veor q9, q14, q3 - vshl.u32 q13, q8, #8 - vshl.u32 q14, q9, #8 - vsri.u32 q13, q8, #24 - vsri.u32 q14, q9, #24 + vtbl.8 d30, {d30}, d16 + vtbl.8 d31, {d31}, d16 + vtbl.8 d24, {d24}, d16 + vtbl.8 d25, {d25}, d16 + vtbl.8 d26, {d26}, d16 + vtbl.8 d27, {d27}, d16 + vtbl.8 d28, {d28}, d16 + vtbl.8 d29, {d29}, d16 vld1.32 {q8-q9}, [sp, :256] @@ -379,104 +418,76 @@ ENTRY(chacha20_4block_xor_neon) vsri.u32 q6, q9, #25 subs r3, r3, #1 - beq 0f - - vld1.32 {q8-q9}, [sp, :256] - b .Ldoubleround4 - - // x0[0-3] += s0[0] - // x1[0-3] += s0[1] - // x2[0-3] += s0[2] - // x3[0-3] += s0[3] -0: ldmia r0!, {r3-r6} - vdup.32 q8, r3 - vdup.32 q9, r4 - vadd.i32 q0, q0, q8 - vadd.i32 q1, q1, q9 - vdup.32 q8, r5 - vdup.32 q9, r6 - vadd.i32 q2, q2, q8 - vadd.i32 q3, q3, q9 - - // x4[0-3] += s1[0] - // x5[0-3] += s1[1] - // x6[0-3] += s1[2] - // x7[0-3] += s1[3] - ldmia r0!, {r3-r6} - vdup.32 q8, r3 - vdup.32 q9, r4 - vadd.i32 q4, q4, q8 - vadd.i32 q5, q5, q9 - vdup.32 q8, r5 - vdup.32 q9, r6 - vadd.i32 q6, q6, q8 - vadd.i32 q7, q7, q9 - - // interleave 32-bit words in state n, n+1 - vzip.32 q0, q1 - vzip.32 q2, q3 - vzip.32 q4, q5 - vzip.32 q6, q7 - - // interleave 64-bit words in state n, n+2 + bne .Ldoubleround4 + + // x0..7[0-3] are in q0-q7, x10..15[0-3] are in q10-q15. + // x8..9[0-3] are on the stack. + + // Re-interleave the words in the first two rows of each block (x0..7). + // Also add the counter values 0-3 to x12[0-3]. + vld1.32 {q8}, [r5, :128] // load counter values 0-3 + vzip.32 q0, q1 // => (0 1 0 1) (0 1 0 1) + vzip.32 q2, q3 // => (2 3 2 3) (2 3 2 3) + vzip.32 q4, q5 // => (4 5 4 5) (4 5 4 5) + vzip.32 q6, q7 // => (6 7 6 7) (6 7 6 7) + vadd.u32 q12, q8 // x12 += counter values 0-3 vswp d1, d4 vswp d3, d6 + vld1.32 {q8-q9}, [r0]! // load s0..7 vswp d9, d12 vswp d11, d14 - // xor with corresponding input, write to output + // Swap q1 and q4 so that we'll free up consecutive registers (q0-q1) + // after XORing the first 32 bytes. + vswp q1, q4 + + // First two rows of each block are (q0 q1) (q2 q6) (q4 q5) (q3 q7) + + // x0..3[0-3] += s0..3[0-3] (add orig state to 1st row of each block) + vadd.u32 q0, q0, q8 + vadd.u32 q2, q2, q8 + vadd.u32 q4, q4, q8 + vadd.u32 q3, q3, q8 + + // x4..7[0-3] += s4..7[0-3] (add orig state to 2nd row of each block) + vadd.u32 q1, q1, q9 + vadd.u32 q6, q6, q9 + vadd.u32 q5, q5, q9 + vadd.u32 q7, q7, q9 + + // XOR first 32 bytes using keystream from first two rows of first block vld1.8 {q8-q9}, [r2]! veor q8, q8, q0 - veor q9, q9, q4 + veor q9, q9, q1 vst1.8 {q8-q9}, [r1]! + // Re-interleave the words in the last two rows of each block (x8..15). vld1.32 {q8-q9}, [sp, :256] - - // x8[0-3] += s2[0] - // x9[0-3] += s2[1] - // x10[0-3] += s2[2] - // x11[0-3] += s2[3] - ldmia r0!, {r3-r6} - vdup.32 q0, r3 - vdup.32 q4, r4 - vadd.i32 q8, q8, q0 - vadd.i32 q9, q9, q4 - vdup.32 q0, r5 - vdup.32 q4, r6 - vadd.i32 q10, q10, q0 - vadd.i32 q11, q11, q4 - - // x12[0-3] += s3[0] - // x13[0-3] += s3[1] - // x14[0-3] += s3[2] - // x15[0-3] += s3[3] - ldmia r0!, {r3-r6} - vdup.32 q0, r3 - vdup.32 q4, r4 - adr r3, CTRINC - vadd.i32 q12, q12, q0 - vld1.32 {q0}, [r3, :128] - vadd.i32 q13, q13, q4 - vadd.i32 q12, q12, q0 // x12 += counter values 0-3 - - vdup.32 q0, r5 - vdup.32 q4, r6 - vadd.i32 q14, q14, q0 - vadd.i32 q15, q15, q4 - - // interleave 32-bit words in state n, n+1 - vzip.32 q8, q9 - vzip.32 q10, q11 - vzip.32 q12, q13 - vzip.32 q14, q15 - - // interleave 64-bit words in state n, n+2 - vswp d17, d20 - vswp d19, d22 + vzip.32 q12, q13 // => (12 13 12 13) (12 13 12 13) + vzip.32 q14, q15 // => (14 15 14 15) (14 15 14 15) + vzip.32 q8, q9 // => (8 9 8 9) (8 9 8 9) + vzip.32 q10, q11 // => (10 11 10 11) (10 11 10 11) + vld1.32 {q0-q1}, [r0] // load s8..15 vswp d25, d28 vswp d27, d30 + vswp d17, d20 + vswp d19, d22 + + // Last two rows of each block are (q8 q12) (q10 q14) (q9 q13) (q11 q15) + + // x8..11[0-3] += s8..11[0-3] (add orig state to 3rd row of each block) + vadd.u32 q8, q8, q0 + vadd.u32 q10, q10, q0 + vadd.u32 q9, q9, q0 + vadd.u32 q11, q11, q0 + + // x12..15[0-3] += s12..15[0-3] (add orig state to 4th row of each block) + vadd.u32 q12, q12, q1 + vadd.u32 q14, q14, q1 + vadd.u32 q13, q13, q1 + vadd.u32 q15, q15, q1 - vmov q4, q1 + // XOR the rest of the data with the keystream vld1.8 {q0-q1}, [r2]! veor q0, q0, q8 @@ -509,13 +520,11 @@ ENTRY(chacha20_4block_xor_neon) vst1.8 {q0-q1}, [r1]! vld1.8 {q0-q1}, [r2] + mov sp, r4 // restore original stack pointer veor q0, q0, q11 veor q1, q1, q15 vst1.8 {q0-q1}, [r1] - mov sp, ip - pop {r4-r6, pc} + pop {r4-r5} + bx lr ENDPROC(chacha20_4block_xor_neon) - - .align 4 -CTRINC: .word 0, 1, 2, 3 diff --git a/arch/arm/crypto/crc32-ce-glue.c b/arch/arm/crypto/crc32-ce-glue.c index 96e62ec105d0..cd9e93b46c2d 100644 --- a/arch/arm/crypto/crc32-ce-glue.c +++ b/arch/arm/crypto/crc32-ce-glue.c @@ -236,7 +236,7 @@ static void __exit crc32_pmull_mod_exit(void) ARRAY_SIZE(crc32_pmull_algs)); } -static const struct cpu_feature crc32_cpu_feature[] = { +static const struct cpu_feature __maybe_unused crc32_cpu_feature[] = { { cpu_feature(CRC32) }, { cpu_feature(PMULL) }, { } }; MODULE_DEVICE_TABLE(cpu, crc32_cpu_feature); diff --git a/arch/arm/crypto/ghash-ce-core.S b/arch/arm/crypto/ghash-ce-core.S index 2f78c10b1881..406009afa9cf 100644 --- a/arch/arm/crypto/ghash-ce-core.S +++ b/arch/arm/crypto/ghash-ce-core.S @@ -63,6 +63,33 @@ k48 .req d31 SHASH2_p64 .req d31 + HH .req q10 + HH3 .req q11 + HH4 .req q12 + HH34 .req q13 + + HH_L .req d20 + HH_H .req d21 + HH3_L .req d22 + HH3_H .req d23 + HH4_L .req d24 + HH4_H .req d25 + HH34_L .req d26 + HH34_H .req d27 + SHASH2_H .req d29 + + XL2 .req q5 + XM2 .req q6 + XH2 .req q7 + T3 .req q8 + + XL2_L .req d10 + XL2_H .req d11 + XM2_L .req d12 + XM2_H .req d13 + T3_L .req d16 + T3_H .req d17 + .text .fpu crypto-neon-fp-armv8 @@ -175,12 +202,77 @@ beq 0f vld1.64 {T1}, [ip] teq r0, #0 - b 1f + b 3f + +0: .ifc \pn, p64 + tst r0, #3 // skip until #blocks is a + bne 2f // round multiple of 4 + + vld1.8 {XL2-XM2}, [r2]! +1: vld1.8 {T3-T2}, [r2]! + vrev64.8 XL2, XL2 + vrev64.8 XM2, XM2 + + subs r0, r0, #4 + + vext.8 T1, XL2, XL2, #8 + veor XL2_H, XL2_H, XL_L + veor XL, XL, T1 + + vrev64.8 T3, T3 + vrev64.8 T1, T2 + + vmull.p64 XH, HH4_H, XL_H // a1 * b1 + veor XL2_H, XL2_H, XL_H + vmull.p64 XL, HH4_L, XL_L // a0 * b0 + vmull.p64 XM, HH34_H, XL2_H // (a1 + a0)(b1 + b0) + + vmull.p64 XH2, HH3_H, XM2_L // a1 * b1 + veor XM2_L, XM2_L, XM2_H + vmull.p64 XL2, HH3_L, XM2_H // a0 * b0 + vmull.p64 XM2, HH34_L, XM2_L // (a1 + a0)(b1 + b0) + + veor XH, XH, XH2 + veor XL, XL, XL2 + veor XM, XM, XM2 + + vmull.p64 XH2, HH_H, T3_L // a1 * b1 + veor T3_L, T3_L, T3_H + vmull.p64 XL2, HH_L, T3_H // a0 * b0 + vmull.p64 XM2, SHASH2_H, T3_L // (a1 + a0)(b1 + b0) + + veor XH, XH, XH2 + veor XL, XL, XL2 + veor XM, XM, XM2 + + vmull.p64 XH2, SHASH_H, T1_L // a1 * b1 + veor T1_L, T1_L, T1_H + vmull.p64 XL2, SHASH_L, T1_H // a0 * b0 + vmull.p64 XM2, SHASH2_p64, T1_L // (a1 + a0)(b1 + b0) + + veor XH, XH, XH2 + veor XL, XL, XL2 + veor XM, XM, XM2 -0: vld1.64 {T1}, [r2]! + beq 4f + + vld1.8 {XL2-XM2}, [r2]! + + veor T1, XL, XH + veor XM, XM, T1 + + __pmull_reduce_p64 + + veor T1, T1, XH + veor XL, XL, T1 + + b 1b + .endif + +2: vld1.64 {T1}, [r2]! subs r0, r0, #1 -1: /* multiply XL by SHASH in GF(2^128) */ +3: /* multiply XL by SHASH in GF(2^128) */ #ifndef CONFIG_CPU_BIG_ENDIAN vrev64.8 T1, T1 #endif @@ -193,7 +285,7 @@ __pmull_\pn XL, XL_L, SHASH_L, s1l, s2l, s3l, s4l @ a0 * b0 __pmull_\pn XM, T1_L, SHASH2_\pn @ (a1+a0)(b1+b0) - veor T1, XL, XH +4: veor T1, XL, XH veor XM, XM, T1 __pmull_reduce_\pn @@ -212,8 +304,14 @@ * struct ghash_key const *k, const char *head) */ ENTRY(pmull_ghash_update_p64) - vld1.64 {SHASH}, [r3] + vld1.64 {SHASH}, [r3]! + vld1.64 {HH}, [r3]! + vld1.64 {HH3-HH4}, [r3] + veor SHASH2_p64, SHASH_L, SHASH_H + veor SHASH2_H, HH_L, HH_H + veor HH34_L, HH3_L, HH3_H + veor HH34_H, HH4_L, HH4_H vmov.i8 MASK, #0xe1 vshl.u64 MASK, MASK, #57 diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c index 8930fc4e7c22..b7d30b6cf49c 100644 --- a/arch/arm/crypto/ghash-ce-glue.c +++ b/arch/arm/crypto/ghash-ce-glue.c @@ -1,7 +1,7 @@ /* * Accelerated GHASH implementation with ARMv8 vmull.p64 instructions. * - * Copyright (C) 2015 Linaro Ltd. <ard.biesheuvel@linaro.org> + * Copyright (C) 2015 - 2018 Linaro Ltd. <ard.biesheuvel@linaro.org> * * 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 published @@ -28,8 +28,10 @@ MODULE_ALIAS_CRYPTO("ghash"); #define GHASH_DIGEST_SIZE 16 struct ghash_key { - u64 a; - u64 b; + u64 h[2]; + u64 h2[2]; + u64 h3[2]; + u64 h4[2]; }; struct ghash_desc_ctx { @@ -117,26 +119,40 @@ static int ghash_final(struct shash_desc *desc, u8 *dst) return 0; } +static void ghash_reflect(u64 h[], const be128 *k) +{ + u64 carry = be64_to_cpu(k->a) >> 63; + + h[0] = (be64_to_cpu(k->b) << 1) | carry; + h[1] = (be64_to_cpu(k->a) << 1) | (be64_to_cpu(k->b) >> 63); + + if (carry) + h[1] ^= 0xc200000000000000UL; +} + static int ghash_setkey(struct crypto_shash *tfm, const u8 *inkey, unsigned int keylen) { struct ghash_key *key = crypto_shash_ctx(tfm); - u64 a, b; + be128 h, k; if (keylen != GHASH_BLOCK_SIZE) { crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } - /* perform multiplication by 'x' in GF(2^128) */ - b = get_unaligned_be64(inkey); - a = get_unaligned_be64(inkey + 8); + memcpy(&k, inkey, GHASH_BLOCK_SIZE); + ghash_reflect(key->h, &k); + + h = k; + gf128mul_lle(&h, &k); + ghash_reflect(key->h2, &h); - key->a = (a << 1) | (b >> 63); - key->b = (b << 1) | (a >> 63); + gf128mul_lle(&h, &k); + ghash_reflect(key->h3, &h); - if (b >> 63) - key->b ^= 0xc200000000000000UL; + gf128mul_lle(&h, &k); + ghash_reflect(key->h4, &h); return 0; } diff --git a/arch/arm/crypto/speck-neon-core.S b/arch/arm/crypto/speck-neon-core.S deleted file mode 100644 index 57caa742016e..000000000000 --- a/arch/arm/crypto/speck-neon-core.S +++ /dev/null @@ -1,434 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS - * - * Copyright (c) 2018 Google, Inc - * - * Author: Eric Biggers <ebiggers@google.com> - */ - -#include <linux/linkage.h> - - .text - .fpu neon - - // arguments - ROUND_KEYS .req r0 // const {u64,u32} *round_keys - NROUNDS .req r1 // int nrounds - DST .req r2 // void *dst - SRC .req r3 // const void *src - NBYTES .req r4 // unsigned int nbytes - TWEAK .req r5 // void *tweak - - // registers which hold the data being encrypted/decrypted - X0 .req q0 - X0_L .req d0 - X0_H .req d1 - Y0 .req q1 - Y0_H .req d3 - X1 .req q2 - X1_L .req d4 - X1_H .req d5 - Y1 .req q3 - Y1_H .req d7 - X2 .req q4 - X2_L .req d8 - X2_H .req d9 - Y2 .req q5 - Y2_H .req d11 - X3 .req q6 - X3_L .req d12 - X3_H .req d13 - Y3 .req q7 - Y3_H .req d15 - - // the round key, duplicated in all lanes - ROUND_KEY .req q8 - ROUND_KEY_L .req d16 - ROUND_KEY_H .req d17 - - // index vector for vtbl-based 8-bit rotates - ROTATE_TABLE .req d18 - - // multiplication table for updating XTS tweaks - GF128MUL_TABLE .req d19 - GF64MUL_TABLE .req d19 - - // current XTS tweak value(s) - TWEAKV .req q10 - TWEAKV_L .req d20 - TWEAKV_H .req d21 - - TMP0 .req q12 - TMP0_L .req d24 - TMP0_H .req d25 - TMP1 .req q13 - TMP2 .req q14 - TMP3 .req q15 - - .align 4 -.Lror64_8_table: - .byte 1, 2, 3, 4, 5, 6, 7, 0 -.Lror32_8_table: - .byte 1, 2, 3, 0, 5, 6, 7, 4 -.Lrol64_8_table: - .byte 7, 0, 1, 2, 3, 4, 5, 6 -.Lrol32_8_table: - .byte 3, 0, 1, 2, 7, 4, 5, 6 -.Lgf128mul_table: - .byte 0, 0x87 - .fill 14 -.Lgf64mul_table: - .byte 0, 0x1b, (0x1b << 1), (0x1b << 1) ^ 0x1b - .fill 12 - -/* - * _speck_round_128bytes() - Speck encryption round on 128 bytes at a time - * - * Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for - * Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes - * of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64. - * - * The 8-bit rotates are implemented using vtbl instead of vshr + vsli because - * the vtbl approach is faster on some processors and the same speed on others. - */ -.macro _speck_round_128bytes n - - // x = ror(x, 8) - vtbl.8 X0_L, {X0_L}, ROTATE_TABLE - vtbl.8 X0_H, {X0_H}, ROTATE_TABLE - vtbl.8 X1_L, {X1_L}, ROTATE_TABLE - vtbl.8 X1_H, {X1_H}, ROTATE_TABLE - vtbl.8 X2_L, {X2_L}, ROTATE_TABLE - vtbl.8 X2_H, {X2_H}, ROTATE_TABLE - vtbl.8 X3_L, {X3_L}, ROTATE_TABLE - vtbl.8 X3_H, {X3_H}, ROTATE_TABLE - - // x += y - vadd.u\n X0, Y0 - vadd.u\n X1, Y1 - vadd.u\n X2, Y2 - vadd.u\n X3, Y3 - - // x ^= k - veor X0, ROUND_KEY - veor X1, ROUND_KEY - veor X2, ROUND_KEY - veor X3, ROUND_KEY - - // y = rol(y, 3) - vshl.u\n TMP0, Y0, #3 - vshl.u\n TMP1, Y1, #3 - vshl.u\n TMP2, Y2, #3 - vshl.u\n TMP3, Y3, #3 - vsri.u\n TMP0, Y0, #(\n - 3) - vsri.u\n TMP1, Y1, #(\n - 3) - vsri.u\n TMP2, Y2, #(\n - 3) - vsri.u\n TMP3, Y3, #(\n - 3) - - // y ^= x - veor Y0, TMP0, X0 - veor Y1, TMP1, X1 - veor Y2, TMP2, X2 - veor Y3, TMP3, X3 -.endm - -/* - * _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time - * - * This is the inverse of _speck_round_128bytes(). - */ -.macro _speck_unround_128bytes n - - // y ^= x - veor TMP0, Y0, X0 - veor TMP1, Y1, X1 - veor TMP2, Y2, X2 - veor TMP3, Y3, X3 - - // y = ror(y, 3) - vshr.u\n Y0, TMP0, #3 - vshr.u\n Y1, TMP1, #3 - vshr.u\n Y2, TMP2, #3 - vshr.u\n Y3, TMP3, #3 - vsli.u\n Y0, TMP0, #(\n - 3) - vsli.u\n Y1, TMP1, #(\n - 3) - vsli.u\n Y2, TMP2, #(\n - 3) - vsli.u\n Y3, TMP3, #(\n - 3) - - // x ^= k - veor X0, ROUND_KEY - veor X1, ROUND_KEY - veor X2, ROUND_KEY - veor X3, ROUND_KEY - - // x -= y - vsub.u\n X0, Y0 - vsub.u\n X1, Y1 - vsub.u\n X2, Y2 - vsub.u\n X3, Y3 - - // x = rol(x, 8); - vtbl.8 X0_L, {X0_L}, ROTATE_TABLE - vtbl.8 X0_H, {X0_H}, ROTATE_TABLE - vtbl.8 X1_L, {X1_L}, ROTATE_TABLE - vtbl.8 X1_H, {X1_H}, ROTATE_TABLE - vtbl.8 X2_L, {X2_L}, ROTATE_TABLE - vtbl.8 X2_H, {X2_H}, ROTATE_TABLE - vtbl.8 X3_L, {X3_L}, ROTATE_TABLE - vtbl.8 X3_H, {X3_H}, ROTATE_TABLE -.endm - -.macro _xts128_precrypt_one dst_reg, tweak_buf, tmp - - // Load the next source block - vld1.8 {\dst_reg}, [SRC]! - - // Save the current tweak in the tweak buffer - vst1.8 {TWEAKV}, [\tweak_buf:128]! - - // XOR the next source block with the current tweak - veor \dst_reg, TWEAKV - - /* - * Calculate the next tweak by multiplying the current one by x, - * modulo p(x) = x^128 + x^7 + x^2 + x + 1. - */ - vshr.u64 \tmp, TWEAKV, #63 - vshl.u64 TWEAKV, #1 - veor TWEAKV_H, \tmp\()_L - vtbl.8 \tmp\()_H, {GF128MUL_TABLE}, \tmp\()_H - veor TWEAKV_L, \tmp\()_H -.endm - -.macro _xts64_precrypt_two dst_reg, tweak_buf, tmp - - // Load the next two source blocks - vld1.8 {\dst_reg}, [SRC]! - - // Save the current two tweaks in the tweak buffer - vst1.8 {TWEAKV}, [\tweak_buf:128]! - - // XOR the next two source blocks with the current two tweaks - veor \dst_reg, TWEAKV - - /* - * Calculate the next two tweaks by multiplying the current ones by x^2, - * modulo p(x) = x^64 + x^4 + x^3 + x + 1. - */ - vshr.u64 \tmp, TWEAKV, #62 - vshl.u64 TWEAKV, #2 - vtbl.8 \tmp\()_L, {GF64MUL_TABLE}, \tmp\()_L - vtbl.8 \tmp\()_H, {GF64MUL_TABLE}, \tmp\()_H - veor TWEAKV, \tmp -.endm - -/* - * _speck_xts_crypt() - Speck-XTS encryption/decryption - * - * Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer - * using Speck-XTS, specifically the variant with a block size of '2n' and round - * count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and - * the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a - * nonzero multiple of 128. - */ -.macro _speck_xts_crypt n, decrypting - push {r4-r7} - mov r7, sp - - /* - * The first four parameters were passed in registers r0-r3. Load the - * additional parameters, which were passed on the stack. - */ - ldr NBYTES, [sp, #16] - ldr TWEAK, [sp, #20] - - /* - * If decrypting, modify the ROUND_KEYS parameter to point to the last - * round key rather than the first, since for decryption the round keys - * are used in reverse order. - */ -.if \decrypting -.if \n == 64 - add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #3 - sub ROUND_KEYS, #8 -.else - add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #2 - sub ROUND_KEYS, #4 -.endif -.endif - - // Load the index vector for vtbl-based 8-bit rotates -.if \decrypting - ldr r12, =.Lrol\n\()_8_table -.else - ldr r12, =.Lror\n\()_8_table -.endif - vld1.8 {ROTATE_TABLE}, [r12:64] - - // One-time XTS preparation - - /* - * Allocate stack space to store 128 bytes worth of tweaks. For - * performance, this space is aligned to a 16-byte boundary so that we - * can use the load/store instructions that declare 16-byte alignment. - * For Thumb2 compatibility, don't do the 'bic' directly on 'sp'. - */ - sub r12, sp, #128 - bic r12, #0xf - mov sp, r12 - -.if \n == 64 - // Load first tweak - vld1.8 {TWEAKV}, [TWEAK] - - // Load GF(2^128) multiplication table - ldr r12, =.Lgf128mul_table - vld1.8 {GF128MUL_TABLE}, [r12:64] -.else - // Load first tweak - vld1.8 {TWEAKV_L}, [TWEAK] - - // Load GF(2^64) multiplication table - ldr r12, =.Lgf64mul_table - vld1.8 {GF64MUL_TABLE}, [r12:64] - - // Calculate second tweak, packing it together with the first - vshr.u64 TMP0_L, TWEAKV_L, #63 - vtbl.u8 TMP0_L, {GF64MUL_TABLE}, TMP0_L - vshl.u64 TWEAKV_H, TWEAKV_L, #1 - veor TWEAKV_H, TMP0_L -.endif - -.Lnext_128bytes_\@: - - /* - * Load the source blocks into {X,Y}[0-3], XOR them with their XTS tweak - * values, and save the tweaks on the stack for later. Then - * de-interleave the 'x' and 'y' elements of each block, i.e. make it so - * that the X[0-3] registers contain only the second halves of blocks, - * and the Y[0-3] registers contain only the first halves of blocks. - * (Speck uses the order (y, x) rather than the more intuitive (x, y).) - */ - mov r12, sp -.if \n == 64 - _xts128_precrypt_one X0, r12, TMP0 - _xts128_precrypt_one Y0, r12, TMP0 - _xts128_precrypt_one X1, r12, TMP0 - _xts128_precrypt_one Y1, r12, TMP0 - _xts128_precrypt_one X2, r12, TMP0 - _xts128_precrypt_one Y2, r12, TMP0 - _xts128_precrypt_one X3, r12, TMP0 - _xts128_precrypt_one Y3, r12, TMP0 - vswp X0_L, Y0_H - vswp X1_L, Y1_H - vswp X2_L, Y2_H - vswp X3_L, Y3_H -.else - _xts64_precrypt_two X0, r12, TMP0 - _xts64_precrypt_two Y0, r12, TMP0 - _xts64_precrypt_two X1, r12, TMP0 - _xts64_precrypt_two Y1, r12, TMP0 - _xts64_precrypt_two X2, r12, TMP0 - _xts64_precrypt_two Y2, r12, TMP0 - _xts64_precrypt_two X3, r12, TMP0 - _xts64_precrypt_two Y3, r12, TMP0 - vuzp.32 Y0, X0 - vuzp.32 Y1, X1 - vuzp.32 Y2, X2 - vuzp.32 Y3, X3 -.endif - - // Do the cipher rounds - - mov r12, ROUND_KEYS - mov r6, NROUNDS - -.Lnext_round_\@: -.if \decrypting -.if \n == 64 - vld1.64 ROUND_KEY_L, [r12] - sub r12, #8 - vmov ROUND_KEY_H, ROUND_KEY_L -.else - vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12] - sub r12, #4 -.endif - _speck_unround_128bytes \n -.else -.if \n == 64 - vld1.64 ROUND_KEY_L, [r12]! - vmov ROUND_KEY_H, ROUND_KEY_L -.else - vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]! -.endif - _speck_round_128bytes \n -.endif - subs r6, r6, #1 - bne .Lnext_round_\@ - - // Re-interleave the 'x' and 'y' elements of each block -.if \n == 64 - vswp X0_L, Y0_H - vswp X1_L, Y1_H - vswp X2_L, Y2_H - vswp X3_L, Y3_H -.else - vzip.32 Y0, X0 - vzip.32 Y1, X1 - vzip.32 Y2, X2 - vzip.32 Y3, X3 -.endif - - // XOR the encrypted/decrypted blocks with the tweaks we saved earlier - mov r12, sp - vld1.8 {TMP0, TMP1}, [r12:128]! - vld1.8 {TMP2, TMP3}, [r12:128]! - veor X0, TMP0 - veor Y0, TMP1 - veor X1, TMP2 - veor Y1, TMP3 - vld1.8 {TMP0, TMP1}, [r12:128]! - vld1.8 {TMP2, TMP3}, [r12:128]! - veor X2, TMP0 - veor Y2, TMP1 - veor X3, TMP2 - veor Y3, TMP3 - - // Store the ciphertext in the destination buffer - vst1.8 {X0, Y0}, [DST]! - vst1.8 {X1, Y1}, [DST]! - vst1.8 {X2, Y2}, [DST]! - vst1.8 {X3, Y3}, [DST]! - - // Continue if there are more 128-byte chunks remaining, else return - subs NBYTES, #128 - bne .Lnext_128bytes_\@ - - // Store the next tweak -.if \n == 64 - vst1.8 {TWEAKV}, [TWEAK] -.else - vst1.8 {TWEAKV_L}, [TWEAK] -.endif - - mov sp, r7 - pop {r4-r7} - bx lr -.endm - -ENTRY(speck128_xts_encrypt_neon) - _speck_xts_crypt n=64, decrypting=0 -ENDPROC(speck128_xts_encrypt_neon) - -ENTRY(speck128_xts_decrypt_neon) - _speck_xts_crypt n=64, decrypting=1 -ENDPROC(speck128_xts_decrypt_neon) - -ENTRY(speck64_xts_encrypt_neon) - _speck_xts_crypt n=32, decrypting=0 -ENDPROC(speck64_xts_encrypt_neon) - -ENTRY(speck64_xts_decrypt_neon) - _speck_xts_crypt n=32, decrypting=1 -ENDPROC(speck64_xts_decrypt_neon) diff --git a/arch/arm/crypto/speck-neon-glue.c b/arch/arm/crypto/speck-neon-glue.c deleted file mode 100644 index f012c3ea998f..000000000000 --- a/arch/arm/crypto/speck-neon-glue.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS - * - * Copyright (c) 2018 Google, Inc - * - * Note: the NIST recommendation for XTS only specifies a 128-bit block size, - * but a 64-bit version (needed for Speck64) is fairly straightforward; the math - * is just done in GF(2^64) instead of GF(2^128), with the reducing polynomial - * x^64 + x^4 + x^3 + x + 1 from the original XEX paper (Rogaway, 2004: - * "Efficient Instantiations of Tweakable Blockciphers and Refinements to Modes - * OCB and PMAC"), represented as 0x1B. - */ - -#include <asm/hwcap.h> -#include <asm/neon.h> -#include <asm/simd.h> -#include <crypto/algapi.h> -#include <crypto/gf128mul.h> -#include <crypto/internal/skcipher.h> -#include <crypto/speck.h> -#include <crypto/xts.h> -#include <linux/kernel.h> -#include <linux/module.h> - -/* The assembly functions only handle multiples of 128 bytes */ -#define SPECK_NEON_CHUNK_SIZE 128 - -/* Speck128 */ - -struct speck128_xts_tfm_ctx { - struct speck128_tfm_ctx main_key; - struct speck128_tfm_ctx tweak_key; -}; - -asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *, - u8 *, const u8 *); -typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *, - const void *, unsigned int, void *); - -static __always_inline int -__speck128_xts_crypt(struct skcipher_request *req, - speck128_crypt_one_t crypt_one, - speck128_xts_crypt_many_t crypt_many) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - le128 tweak; - int err; - - err = skcipher_walk_virt(&walk, req, true); - - crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); - - while (walk.nbytes > 0) { - unsigned int nbytes = walk.nbytes; - u8 *dst = walk.dst.virt.addr; - const u8 *src = walk.src.virt.addr; - - if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { - unsigned int count; - - count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); - kernel_neon_begin(); - (*crypt_many)(ctx->main_key.round_keys, - ctx->main_key.nrounds, - dst, src, count, &tweak); - kernel_neon_end(); - dst += count; - src += count; - nbytes -= count; - } - - /* Handle any remainder with generic code */ - while (nbytes >= sizeof(tweak)) { - le128_xor((le128 *)dst, (const le128 *)src, &tweak); - (*crypt_one)(&ctx->main_key, dst, dst); - le128_xor((le128 *)dst, (const le128 *)dst, &tweak); - gf128mul_x_ble(&tweak, &tweak); - - dst += sizeof(tweak); - src += sizeof(tweak); - nbytes -= sizeof(tweak); - } - err = skcipher_walk_done(&walk, nbytes); - } - - return err; -} - -static int speck128_xts_encrypt(struct skcipher_request *req) -{ - return __speck128_xts_crypt(req, crypto_speck128_encrypt, - speck128_xts_encrypt_neon); -} - -static int speck128_xts_decrypt(struct skcipher_request *req) -{ - return __speck128_xts_crypt(req, crypto_speck128_decrypt, - speck128_xts_decrypt_neon); -} - -static int speck128_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - int err; - - err = xts_verify_key(tfm, key, keylen); - if (err) - return err; - - keylen /= 2; - - err = crypto_speck128_setkey(&ctx->main_key, key, keylen); - if (err) - return err; - - return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen); -} - -/* Speck64 */ - -struct speck64_xts_tfm_ctx { - struct speck64_tfm_ctx main_key; - struct speck64_tfm_ctx tweak_key; -}; - -asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *, - u8 *, const u8 *); -typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *, - const void *, unsigned int, void *); - -static __always_inline int -__speck64_xts_crypt(struct skcipher_request *req, speck64_crypt_one_t crypt_one, - speck64_xts_crypt_many_t crypt_many) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - __le64 tweak; - int err; - - err = skcipher_walk_virt(&walk, req, true); - - crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); - - while (walk.nbytes > 0) { - unsigned int nbytes = walk.nbytes; - u8 *dst = walk.dst.virt.addr; - const u8 *src = walk.src.virt.addr; - - if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { - unsigned int count; - - count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); - kernel_neon_begin(); - (*crypt_many)(ctx->main_key.round_keys, - ctx->main_key.nrounds, - dst, src, count, &tweak); - kernel_neon_end(); - dst += count; - src += count; - nbytes -= count; - } - - /* Handle any remainder with generic code */ - while (nbytes >= sizeof(tweak)) { - *(__le64 *)dst = *(__le64 *)src ^ tweak; - (*crypt_one)(&ctx->main_key, dst, dst); - *(__le64 *)dst ^= tweak; - tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^ - ((tweak & cpu_to_le64(1ULL << 63)) ? - 0x1B : 0)); - dst += sizeof(tweak); - src += sizeof(tweak); - nbytes -= sizeof(tweak); - } - err = skcipher_walk_done(&walk, nbytes); - } - - return err; -} - -static int speck64_xts_encrypt(struct skcipher_request *req) -{ - return __speck64_xts_crypt(req, crypto_speck64_encrypt, - speck64_xts_encrypt_neon); -} - -static int speck64_xts_decrypt(struct skcipher_request *req) -{ - return __speck64_xts_crypt(req, crypto_speck64_decrypt, - speck64_xts_decrypt_neon); -} - -static int speck64_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - int err; - - err = xts_verify_key(tfm, key, keylen); - if (err) - return err; - - keylen /= 2; - - err = crypto_speck64_setkey(&ctx->main_key, key, keylen); - if (err) - return err; - - return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen); -} - -static struct skcipher_alg speck_algs[] = { - { - .base.cra_name = "xts(speck128)", - .base.cra_driver_name = "xts-speck128-neon", - .base.cra_priority = 300, - .base.cra_blocksize = SPECK128_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx), - .base.cra_alignmask = 7, - .base.cra_module = THIS_MODULE, - .min_keysize = 2 * SPECK128_128_KEY_SIZE, - .max_keysize = 2 * SPECK128_256_KEY_SIZE, - .ivsize = SPECK128_BLOCK_SIZE, - .walksize = SPECK_NEON_CHUNK_SIZE, - .setkey = speck128_xts_setkey, - .encrypt = speck128_xts_encrypt, - .decrypt = speck128_xts_decrypt, - }, { - .base.cra_name = "xts(speck64)", - .base.cra_driver_name = "xts-speck64-neon", - .base.cra_priority = 300, - .base.cra_blocksize = SPECK64_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx), - .base.cra_alignmask = 7, - .base.cra_module = THIS_MODULE, - .min_keysize = 2 * SPECK64_96_KEY_SIZE, - .max_keysize = 2 * SPECK64_128_KEY_SIZE, - .ivsize = SPECK64_BLOCK_SIZE, - .walksize = SPECK_NEON_CHUNK_SIZE, - .setkey = speck64_xts_setkey, - .encrypt = speck64_xts_encrypt, - .decrypt = speck64_xts_decrypt, - } -}; - -static int __init speck_neon_module_init(void) -{ - if (!(elf_hwcap & HWCAP_NEON)) - return -ENODEV; - return crypto_register_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); -} - -static void __exit speck_neon_module_exit(void) -{ - crypto_unregister_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); -} - -module_init(speck_neon_module_init); -module_exit(speck_neon_module_exit); - -MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); -MODULE_ALIAS_CRYPTO("xts(speck128)"); -MODULE_ALIAS_CRYPTO("xts-speck128-neon"); -MODULE_ALIAS_CRYPTO("xts(speck64)"); -MODULE_ALIAS_CRYPTO("xts-speck64-neon"); diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h index 237aa52d8733..36c951dd23b8 100644 --- a/arch/arm/include/asm/bug.h +++ b/arch/arm/include/asm/bug.h @@ -62,8 +62,8 @@ do { \ struct pt_regs; void die(const char *msg, struct pt_regs *regs, int err); -struct siginfo; -void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, +void arm_notify_die(const char *str, struct pt_regs *regs, + int signo, int si_code, void __user *addr, unsigned long err, unsigned long trap); #ifdef CONFIG_ARM_LPAE diff --git a/arch/arm/include/asm/hugetlb-3level.h b/arch/arm/include/asm/hugetlb-3level.h index d4014fbe5ea3..0d9f3918fa7e 100644 --- a/arch/arm/include/asm/hugetlb-3level.h +++ b/arch/arm/include/asm/hugetlb-3level.h @@ -29,6 +29,7 @@ * ptes. * (The valid bit is automatically cleared by set_pte_at for PROT_NONE ptes). */ +#define __HAVE_ARCH_HUGE_PTEP_GET static inline pte_t huge_ptep_get(pte_t *ptep) { pte_t retval = *ptep; @@ -37,35 +38,4 @@ static inline pte_t huge_ptep_get(pte_t *ptep) return retval; } -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - -static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep) -{ - ptep_clear_flush(vma, addr, ptep); -} - -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - return ptep_get_and_clear(mm, addr, ptep); -} - -static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep, - pte_t pte, int dirty) -{ - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); -} - #endif /* _ASM_ARM_HUGETLB_3LEVEL_H */ diff --git a/arch/arm/include/asm/hugetlb.h b/arch/arm/include/asm/hugetlb.h index 7d26f6c4f0f5..b67256c22b08 100644 --- a/arch/arm/include/asm/hugetlb.h +++ b/arch/arm/include/asm/hugetlb.h @@ -23,18 +23,8 @@ #define _ASM_ARM_HUGETLB_H #include <asm/page.h> -#include <asm-generic/hugetlb.h> - #include <asm/hugetlb-3level.h> - -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - +#include <asm-generic/hugetlb.h> static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, unsigned long len) @@ -42,27 +32,6 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, return 0; } -static inline int prepare_hugepage_range(struct file *file, - unsigned long addr, unsigned long len) -{ - struct hstate *h = hstate_file(file); - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (addr & ~huge_page_mask(h)) - return -EINVAL; - return 0; -} - -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - static inline void arch_clear_hugepage_flags(struct page *page) { clear_bit(PG_dcache_clean, &page->flags); diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h index 2d43dca29c72..b95f8d0d9f17 100644 --- a/arch/arm/include/asm/kvm_arm.h +++ b/arch/arm/include/asm/kvm_arm.h @@ -133,8 +133,7 @@ * space. */ #define KVM_PHYS_SHIFT (40) -#define KVM_PHYS_SIZE (_AC(1, ULL) << KVM_PHYS_SHIFT) -#define KVM_PHYS_MASK (KVM_PHYS_SIZE - _AC(1, ULL)) + #define PTRS_PER_S2_PGD (_AC(1, ULL) << (KVM_PHYS_SHIFT - 30)) /* Virtualization Translation Control Register (VTCR) bits */ diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 3ad482d2f1eb..5ca5d9af0c26 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -273,7 +273,7 @@ static inline void __cpu_init_stage2(void) kvm_call_hyp(__init_stage2_translation); } -static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { return 0; } @@ -354,4 +354,15 @@ static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {} struct kvm *kvm_arch_alloc_vm(void); void kvm_arch_free_vm(struct kvm *kvm); +static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type) +{ + /* + * On 32bit ARM, VMs get a static 40bit IPA stage2 setup, + * so any non-zero value used as type is illegal. + */ + if (type) + return -EINVAL; + return 0; +} + #endif /* __ARM_KVM_HOST_H__ */ diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 847f01fa429d..1098ffc3d54b 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -35,16 +35,12 @@ addr; \ }) -/* - * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation levels. - */ -#define KVM_MMU_CACHE_MIN_PAGES 2 - #ifndef __ASSEMBLY__ #include <linux/highmem.h> #include <asm/cacheflush.h> #include <asm/cputype.h> +#include <asm/kvm_arm.h> #include <asm/kvm_hyp.h> #include <asm/pgalloc.h> #include <asm/stage2_pgtable.h> @@ -52,6 +48,13 @@ /* Ensure compatibility with arm64 */ #define VA_BITS 32 +#define kvm_phys_shift(kvm) KVM_PHYS_SHIFT +#define kvm_phys_size(kvm) (1ULL << kvm_phys_shift(kvm)) +#define kvm_phys_mask(kvm) (kvm_phys_size(kvm) - 1ULL) +#define kvm_vttbr_baddr_mask(kvm) VTTBR_BADDR_MASK + +#define stage2_pgd_size(kvm) (PTRS_PER_S2_PGD * sizeof(pgd_t)) + int create_hyp_mappings(void *from, void *to, pgprot_t prot); int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size, void __iomem **kaddr, @@ -355,6 +358,8 @@ static inline int hyp_map_aux_data(void) #define kvm_phys_to_vttbr(addr) (addr) +static inline void kvm_set_ipa_limit(void) {} + static inline bool kvm_cpu_has_cnp(void) { return false; diff --git a/arch/arm/include/asm/stage2_pgtable.h b/arch/arm/include/asm/stage2_pgtable.h index 460d616bb2d6..f6a7ea805232 100644 --- a/arch/arm/include/asm/stage2_pgtable.h +++ b/arch/arm/include/asm/stage2_pgtable.h @@ -19,43 +19,53 @@ #ifndef __ARM_S2_PGTABLE_H_ #define __ARM_S2_PGTABLE_H_ -#define stage2_pgd_none(pgd) pgd_none(pgd) -#define stage2_pgd_clear(pgd) pgd_clear(pgd) -#define stage2_pgd_present(pgd) pgd_present(pgd) -#define stage2_pgd_populate(pgd, pud) pgd_populate(NULL, pgd, pud) -#define stage2_pud_offset(pgd, address) pud_offset(pgd, address) -#define stage2_pud_free(pud) pud_free(NULL, pud) - -#define stage2_pud_none(pud) pud_none(pud) -#define stage2_pud_clear(pud) pud_clear(pud) -#define stage2_pud_present(pud) pud_present(pud) -#define stage2_pud_populate(pud, pmd) pud_populate(NULL, pud, pmd) -#define stage2_pmd_offset(pud, address) pmd_offset(pud, address) -#define stage2_pmd_free(pmd) pmd_free(NULL, pmd) - -#define stage2_pud_huge(pud) pud_huge(pud) +/* + * kvm_mmu_cache_min_pages() is the number of pages required + * to install a stage-2 translation. We pre-allocate the entry + * level table at VM creation. Since we have a 3 level page-table, + * we need only two pages to add a new mapping. + */ +#define kvm_mmu_cache_min_pages(kvm) 2 + +#define stage2_pgd_none(kvm, pgd) pgd_none(pgd) +#define stage2_pgd_clear(kvm, pgd) pgd_clear(pgd) +#define stage2_pgd_present(kvm, pgd) pgd_present(pgd) +#define stage2_pgd_populate(kvm, pgd, pud) pgd_populate(NULL, pgd, pud) +#define stage2_pud_offset(kvm, pgd, address) pud_offset(pgd, address) +#define stage2_pud_free(kvm, pud) pud_free(NULL, pud) + +#define stage2_pud_none(kvm, pud) pud_none(pud) +#define stage2_pud_clear(kvm, pud) pud_clear(pud) +#define stage2_pud_present(kvm, pud) pud_present(pud) +#define stage2_pud_populate(kvm, pud, pmd) pud_populate(NULL, pud, pmd) +#define stage2_pmd_offset(kvm, pud, address) pmd_offset(pud, address) +#define stage2_pmd_free(kvm, pmd) pmd_free(NULL, pmd) + +#define stage2_pud_huge(kvm, pud) pud_huge(pud) /* Open coded p*d_addr_end that can deal with 64bit addresses */ -static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end) +static inline phys_addr_t +stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) { phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK; return (boundary - 1 < end - 1) ? boundary : end; } -#define stage2_pud_addr_end(addr, end) (end) +#define stage2_pud_addr_end(kvm, addr, end) (end) -static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end) +static inline phys_addr_t +stage2_pmd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) { phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK; return (boundary - 1 < end - 1) ? boundary : end; } -#define stage2_pgd_index(addr) pgd_index(addr) +#define stage2_pgd_index(kvm, addr) pgd_index(addr) -#define stage2_pte_table_empty(ptep) kvm_page_empty(ptep) -#define stage2_pmd_table_empty(pmdp) kvm_page_empty(pmdp) -#define stage2_pud_table_empty(pudp) false +#define stage2_pte_table_empty(kvm, ptep) kvm_page_empty(ptep) +#define stage2_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp) +#define stage2_pud_table_empty(kvm, pudp) false #endif /* __ARM_S2_PGTABLE_H_ */ diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 076090d2dbf5..88ef2ce1f69a 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -16,23 +16,23 @@ #include <uapi/asm/unistd.h> #include <asm/unistd-nr.h> +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_OLD_MMAP #define __ARCH_WANT_SYS_OLD_SELECT +#define __ARCH_WANT_SYS_UTIME #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_SOCKETCALL diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index ecaa68dd1af5..13bcd3b867cb 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -87,14 +87,11 @@ void __init arm_dt_init_cpu_maps(void) if (!cpus) return; - for_each_child_of_node(cpus, cpu) { + for_each_of_cpu_node(cpu) { const __be32 *cell; int prop_bytes; u32 hwid; - if (of_node_cmp(cpu->type, "cpu")) - continue; - pr_debug(" * %pOF...\n", cpu); /* * A device tree containing CPU nodes with missing "reg" diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 36718a424358..6fa5b6387556 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -203,15 +203,8 @@ void ptrace_disable(struct task_struct *child) */ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) { - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void __user *)instruction_pointer(regs); - - force_sig_info(SIGTRAP, &info, tsk); + force_sig_fault(SIGTRAP, TRAP_BRKPT, + (void __user *)instruction_pointer(regs), tsk); } static int break_trap(struct pt_regs *regs, unsigned int instr) diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 80517f293eb9..a188d5e8ab7f 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -98,22 +98,20 @@ static int proc_status_show(struct seq_file *m, void *v) */ static void set_segfault(struct pt_regs *regs, unsigned long addr) { - siginfo_t info; + int si_code; - clear_siginfo(&info); down_read(¤t->mm->mmap_sem); if (find_vma(current->mm, addr) == NULL) - info.si_code = SEGV_MAPERR; + si_code = SEGV_MAPERR; else - info.si_code = SEGV_ACCERR; + si_code = SEGV_ACCERR; up_read(¤t->mm->mmap_sem); - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_addr = (void *) instruction_pointer(regs); - pr_debug("SWP{B} emulation: access caused memory abort!\n"); - arm_notify_die("Illegal memory access", regs, &info, 0, 0); + arm_notify_die("Illegal memory access", regs, + SIGSEGV, si_code, + (void __user *)instruction_pointer(regs), + 0, 0); abtcounter++; } diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 24ac3cab411d..60e375ce1ab2 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -94,12 +94,6 @@ static void __init parse_dt_topology(void) __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity), GFP_NOWAIT); - cn = of_find_node_by_path("/cpus"); - if (!cn) { - pr_err("No CPU information found in DT\n"); - return; - } - for_each_possible_cpu(cpu) { const u32 *rate; int len; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index badf02ca3693..2d668cff8ef4 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -365,13 +365,14 @@ void die(const char *str, struct pt_regs *regs, int err) } void arm_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, unsigned long err, unsigned long trap) + int signo, int si_code, void __user *addr, + unsigned long err, unsigned long trap) { if (user_mode(regs)) { current->thread.error_code = err; current->thread.trap_no = trap; - force_sig_info(info->si_signo, info, current); + force_sig_fault(signo, si_code, addr, current); } else { die(str, regs, err); } @@ -438,10 +439,8 @@ int call_undef_hook(struct pt_regs *regs, unsigned int instr) asmlinkage void do_undefinstr(struct pt_regs *regs) { unsigned int instr; - siginfo_t info; void __user *pc; - clear_siginfo(&info); pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { @@ -485,13 +484,8 @@ die_sig: dump_instr(KERN_INFO, regs); } #endif - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = pc; - - arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); + arm_notify_die("Oops - undefined instruction", regs, + SIGILL, ILL_ILLOPC, pc, 0, 6); } NOKPROBE_SYMBOL(do_undefinstr) @@ -539,9 +533,6 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) static int bad_syscall(int n, struct pt_regs *regs) { - siginfo_t info; - - clear_siginfo(&info); if ((current->personality & PER_MASK) != PER_LINUX) { send_sig(SIGSEGV, current, 1); return regs->ARM_r0; @@ -555,13 +546,10 @@ static int bad_syscall(int n, struct pt_regs *regs) } #endif - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); - - arm_notify_die("Oops - bad syscall", regs, &info, n, 0); + arm_notify_die("Oops - bad syscall", regs, SIGILL, ILL_ILLTRP, + (void __user *)instruction_pointer(regs) - + (thumb_mode(regs) ? 2 : 4), + n, 0); return regs->ARM_r0; } @@ -607,20 +595,13 @@ do_cache_op(unsigned long start, unsigned long end, int flags) #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) asmlinkage int arm_syscall(int no, struct pt_regs *regs) { - siginfo_t info; - - clear_siginfo(&info); if ((no >> 16) != (__ARM_NR_BASE>> 16)) return bad_syscall(no, regs); switch (no & 0xffff) { case 0: /* branch through 0 */ - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = NULL; - - arm_notify_die("branch through zero", regs, &info, 0, 0); + arm_notify_die("branch through zero", regs, + SIGSEGV, SEGV_MAPERR, NULL, 0, 0); return 0; case NR(breakpoint): /* SWI BREAK_POINT */ @@ -688,13 +669,10 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) } } #endif - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); - - arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0); + arm_notify_die("Oops - bad syscall(2)", regs, SIGILL, ILL_ILLTRP, + (void __user *)instruction_pointer(regs) - + (thumb_mode(regs) ? 2 : 4), + no, 0); return 0; } @@ -744,9 +722,6 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs) { unsigned long addr = instruction_pointer(regs); - siginfo_t info; - - clear_siginfo(&info); #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_BADABORT) { @@ -757,12 +732,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) } #endif - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = (void __user *)addr; - - arm_notify_die("unknown data abort code", regs, &info, instr, 0); + arm_notify_die("unknown data abort code", regs, + SIGILL, ILL_ILLOPC, (void __user *)addr, instr, 0); } void __readwrite_bug(const char *fn) diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 3593d5c1acd2..8c74037ade22 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -96,7 +96,6 @@ SECTIONS INIT_SETUP(16) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS } diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 32fae4dbd63b..51e808adb00c 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -143,15 +143,15 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set) /* Check if enabled on SHDWC. */ if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit)) - goto put_node; + goto put_device; mode |= wsi->pmc_fsmr_bit; if (wsi->set_polarity) polarity |= wsi->pmc_fsmr_bit; } -put_node: - of_node_put(np); +put_device: + put_device(&pdev->dev); } if (mode) { @@ -580,8 +580,6 @@ static int __init at91_pm_backup_init(void) if (!at91_is_pm_mode_active(AT91_PM_BACKUP)) return 0; - pm_bu = NULL; - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu"); if (!np) { pr_warn("%s: failed to find sfrbu!\n", __func__); @@ -590,7 +588,6 @@ static int __init at91_pm_backup_init(void) pm_data.sfrbu = of_iomap(np, 0); of_node_put(np); - pm_bu = NULL; np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam"); if (!np) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index a7c6ae13c945..bfe1c4d06901 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -149,6 +149,14 @@ exit_suspend: ENDPROC(at91_pm_suspend_in_sram) ENTRY(at91_backup_mode) + /* Switch the master clock source to slow clock. */ + ldr pmc, .pmc_base + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_CSS + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + /*BUMEN*/ ldr r0, .sfr mov tmp1, #0x1 diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index dcd21bb95e3b..f96730cce6e8 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -110,6 +110,7 @@ void exynos_firmware_init(void); #define EXYNOS_SLEEP_MAGIC 0x00000bad #define EXYNOS_AFTR_MAGIC 0xfcba0d10 +bool __init exynos_secure_firmware_available(void); void exynos_set_boot_flag(unsigned int cpu, unsigned int mode); void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode); diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index be1f20fe28f4..d602e3bf3f96 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -185,7 +185,7 @@ static void exynos_l2_configure(const struct l2x0_regs *regs) exynos_smc(SMC_CMD_L2X0SETUP2, regs->pwr_ctrl, regs->aux_ctrl, 0); } -void __init exynos_firmware_init(void) +bool __init exynos_secure_firmware_available(void) { struct device_node *nd; const __be32 *addr; @@ -193,14 +193,22 @@ void __init exynos_firmware_init(void) nd = of_find_compatible_node(NULL, NULL, "samsung,secure-firmware"); if (!nd) - return; + return false; addr = of_get_address(nd, 0, NULL, NULL); if (!addr) { pr_err("%s: No address specified.\n", __func__); - return; + return false; } + return true; +} + +void __init exynos_firmware_init(void) +{ + if (!exynos_secure_firmware_available()) + return; + pr_info("Running under secure firmware.\n"); register_firmware_ops(&exynos_firmware_ops); diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 7ead3acd6fa4..bb8e3985acdb 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -59,10 +59,15 @@ struct exynos_pm_data { int (*cpu_suspend)(unsigned long); }; -static const struct exynos_pm_data *pm_data __ro_after_init; +/* Used only on Exynos542x/5800 */ +struct exynos_pm_state { + int cpu_state; + unsigned int pmu_spare3; + void __iomem *sysram_base; +}; -static int exynos5420_cpu_state; -static unsigned int exynos_pmu_spare3; +static const struct exynos_pm_data *pm_data __ro_after_init; +static struct exynos_pm_state pm_state; /* * GIC wake-up support @@ -257,7 +262,7 @@ static int exynos5420_cpu_suspend(unsigned long arg) unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); - writel_relaxed(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE); + writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE); if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) { mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume); @@ -321,7 +326,7 @@ static void exynos5420_pm_prepare(void) /* Set wake-up mask registers */ exynos_pm_set_wakeup_mask(); - exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); + pm_state.pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); /* * The cpu state needs to be saved and restored so that the * secondary CPUs will enter low power start. Though the U-Boot @@ -329,8 +334,8 @@ static void exynos5420_pm_prepare(void) * needs to restore it back in case, the primary cpu fails to * suspend for any reason. */ - exynos5420_cpu_state = readl_relaxed(sysram_base_addr + - EXYNOS5420_CPU_STATE); + pm_state.cpu_state = readl_relaxed(pm_state.sysram_base + + EXYNOS5420_CPU_STATE); exynos_pm_enter_sleep_mode(); @@ -448,8 +453,8 @@ static void exynos5420_pm_resume(void) EXYNOS5_ARM_CORE0_SYS_PWR_REG); /* Restore the sysram cpu state register */ - writel_relaxed(exynos5420_cpu_state, - sysram_base_addr + EXYNOS5420_CPU_STATE); + writel_relaxed(pm_state.cpu_state, + pm_state.sysram_base + EXYNOS5420_CPU_STATE); pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); @@ -457,7 +462,7 @@ static void exynos5420_pm_resume(void) if (exynos_pm_central_resume()) goto early_wakeup; - pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); + pmu_raw_writel(pm_state.pmu_spare3, S5P_PMU_SPARE3); early_wakeup: @@ -654,4 +659,13 @@ void __init exynos_pm_init(void) register_syscore_ops(&exynos_pm_syscore_ops); suspend_set_ops(&exynos_suspend_ops); + + /* + * Applicable as of now only to Exynos542x. If booted under secure + * firmware, the non-secure region of sysram should be used. + */ + if (exynos_secure_firmware_available()) + pm_state.sysram_base = sysram_ns_base_addr; + else + pm_state.sysram_base = sysram_base_addr; } diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c index 61f3d94f1633..45d618abf26b 100644 --- a/arch/arm/mach-imx/anatop.c +++ b/arch/arm/mach-imx/anatop.c @@ -31,6 +31,8 @@ #define ANADIG_DIGPROG_IMX6SL 0x280 #define ANADIG_DIGPROG_IMX7D 0x800 +#define SRC_SBMR2 0x1c + #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000 #define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8 #define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000 @@ -148,6 +150,24 @@ void __init imx_init_revision_from_anatop(void) major_part = (digprog >> 8) & 0xf; minor_part = digprog & 0xf; revision = ((major_part + 1) << 4) | minor_part; + + if ((digprog >> 16) == MXC_CPU_IMX6ULL) { + void __iomem *src_base; + u32 sbmr2; + + np = of_find_compatible_node(NULL, NULL, + "fsl,imx6ul-src"); + src_base = of_iomap(np, 0); + WARN_ON(!src_base); + sbmr2 = readl_relaxed(src_base + SRC_SBMR2); + iounmap(src_base); + + /* src_sbmr2 bit 6 is to identify if it is i.MX6ULZ */ + if (sbmr2 & (1 << 6)) { + digprog &= ~(0xff << 16); + digprog |= (MXC_CPU_IMX6ULZ << 16); + } + } } mxc_set_cpu_type(digprog >> 16 & 0xff); diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index c6b1bf97a6c1..c73593e09121 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -136,6 +136,9 @@ struct device * __init imx_soc_device_init(void) case MXC_CPU_IMX6ULL: soc_id = "i.MX6ULL"; break; + case MXC_CPU_IMX6ULZ: + soc_id = "i.MX6ULZ"; + break; case MXC_CPU_IMX6SLL: soc_id = "i.MX6SLL"; break; diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c index 04b3bf71de94..e49e06834516 100644 --- a/arch/arm/mach-imx/mmdc.c +++ b/arch/arm/mach-imx/mmdc.c @@ -11,6 +11,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/clk.h> #include <linux/hrtimer.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -546,7 +547,20 @@ static int imx_mmdc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; void __iomem *mmdc_base, *reg; + struct clk *mmdc_ipg_clk; u32 val; + int err; + + /* the ipg clock is optional */ + mmdc_ipg_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mmdc_ipg_clk)) + mmdc_ipg_clk = NULL; + + err = clk_prepare_enable(mmdc_ipg_clk); + if (err) { + dev_err(&pdev->dev, "Unable to enable mmdc ipg clock.\n"); + return err; + } mmdc_base = of_iomap(np, 0); WARN_ON(!mmdc_base); diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index 026e2ca45f1e..b130a53ff62a 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -40,6 +40,8 @@ #define MXC_CPU_IMX6Q 0x63 #define MXC_CPU_IMX6UL 0x64 #define MXC_CPU_IMX6ULL 0x65 +/* virtual cpu id for i.mx6ulz */ +#define MXC_CPU_IMX6ULZ 0x6b #define MXC_CPU_IMX6SLL 0x67 #define MXC_CPU_IMX7D 0x72 @@ -80,6 +82,11 @@ static inline bool cpu_is_imx6ull(void) return __mxc_cpu_type == MXC_CPU_IMX6ULL; } +static inline bool cpu_is_imx6ulz(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6ULZ; +} + static inline bool cpu_is_imx6sll(void) { return __mxc_cpu_type == MXC_CPU_IMX6SLL; diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index b08e407d8d96..87f45b926c78 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -313,7 +313,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) if (cpu_is_imx6sl()) val |= BM_CLPCR_BYPASS_PMIC_READY; if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() || - cpu_is_imx6ull() || cpu_is_imx6sll()) + cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz()) val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; else val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; @@ -331,7 +331,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode) if (cpu_is_imx6sl() || cpu_is_imx6sx()) val |= BM_CLPCR_BYPASS_PMIC_READY; if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() || - cpu_is_imx6ull() || cpu_is_imx6sll()) + cpu_is_imx6ull() || cpu_is_imx6sll() || cpu_is_imx6ulz()) val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; else val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; @@ -618,6 +618,28 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata IMX6Q_GPR1_GINT); } +static void imx6_pm_stby_poweroff(void) +{ + imx6_set_lpm(STOP_POWER_OFF); + imx6q_suspend_finish(0); + + mdelay(1000); + + pr_emerg("Unable to poweroff system\n"); +} + +static int imx6_pm_stby_poweroff_probe(void) +{ + if (pm_power_off) { + pr_warn("%s: pm_power_off already claimed %p %pf!\n", + __func__, pm_power_off, pm_power_off); + return -EBUSY; + } + + pm_power_off = imx6_pm_stby_poweroff; + return 0; +} + void __init imx6_pm_ccm_init(const char *ccm_compat) { struct device_node *np; @@ -634,6 +656,9 @@ void __init imx6_pm_ccm_init(const char *ccm_compat) val = readl_relaxed(ccm_base + CLPCR); val &= ~BM_CLPCR_LPM; writel_relaxed(val, ccm_base + CLPCR); + + if (of_property_read_bool(np, "fsl,pmic-stby-poweroff")) + imx6_pm_stby_poweroff_probe(); } void __init imx6q_pm_init(void) diff --git a/arch/arm/mach-mmp/devices.c b/arch/arm/mach-mmp/devices.c index 671c7a09ab3d..0fca63c80e1a 100644 --- a/arch/arm/mach-mmp/devices.c +++ b/arch/arm/mach-mmp/devices.c @@ -277,21 +277,12 @@ struct platform_device pxa168_device_u2o = { #if IS_ENABLED(CONFIG_USB_EHCI_MV_U2O) struct resource pxa168_u2oehci_resources[] = { - /* regbase */ [0] = { - .start = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET, + .start = PXA168_U2O_REGBASE, .end = PXA168_U2O_REGBASE + USB_REG_RANGE, .flags = IORESOURCE_MEM, - .name = "capregs", }, - /* phybase */ [1] = { - .start = PXA168_U2O_PHYBASE, - .end = PXA168_U2O_PHYBASE + USB_PHY_RANGE, - .flags = IORESOURCE_MEM, - .name = "phyregs", - }, - [2] = { .start = IRQ_PXA168_USB1, .end = IRQ_PXA168_USB1, .flags = IORESOURCE_IRQ, diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index ccca95173e17..0b10acd7d1b9 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -145,6 +145,13 @@ static void __init mvebu_dt_init(void) i2c_quirk(); } +static void __init armada_370_xp_dt_fixup(void) +{ +#ifdef CONFIG_SMP + smp_set_ops(smp_ops(armada_xp_smp_ops)); +#endif +} + static const char * const armada_370_xp_dt_compat[] __initconst = { "marvell,armada-370-xp", NULL, @@ -153,17 +160,12 @@ static const char * const armada_370_xp_dt_compat[] __initconst = { DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, -/* - * The following field (.smp) is still needed to ensure backward - * compatibility with old Device Trees that were not specifying the - * cpus enable-method property. - */ - .smp = smp_ops(armada_xp_smp_ops), .init_machine = mvebu_dt_init, .init_irq = mvebu_init_irq, .restart = mvebu_restart, .reserve = mvebu_memblock_reserve, .dt_compat = armada_370_xp_dt_compat, + .dt_fixup = armada_370_xp_dt_fixup, MACHINE_END static const char * const armada_375_dt_compat[] __initconst = { diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S index ddc27638ba2a..e3faa0274b56 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S +++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S @@ -15,6 +15,7 @@ #include <linux/linkage.h> #include <linux/platform_data/ams-delta-fiq.h> +#include <linux/platform_data/gpio-omap.h> #include <asm/assembler.h> #include <mach/board-ams-delta.h> @@ -24,17 +25,10 @@ #include "soc.h" /* - * GPIO related definitions, copied from arch/arm/plat-omap/gpio.c. - * Unfortunately, those were not placed in a separate header file. + * OMAP1510 GPIO related symbol copied from arch/arm/mach-omap1/gpio15xx.c. + * Unfortunately, it was not placed in a separate header file. */ #define OMAP1510_GPIO_BASE 0xFFFCE000 -#define OMAP1510_GPIO_DATA_INPUT 0x00 -#define OMAP1510_GPIO_DATA_OUTPUT 0x04 -#define OMAP1510_GPIO_DIR_CONTROL 0x08 -#define OMAP1510_GPIO_INT_CONTROL 0x0c -#define OMAP1510_GPIO_INT_MASK 0x10 -#define OMAP1510_GPIO_INT_STATUS 0x14 -#define OMAP1510_GPIO_PIN_CONTROL 0x18 /* GPIO register bitmasks */ #define KEYBRD_DATA_MASK (0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_DATA) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index f226973f3d8c..af318d958fd2 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -250,39 +250,6 @@ static struct platform_device latch2_gpio_device = { #define LATCH2_PIN_HOOKFLASH1 14 #define LATCH2_PIN_HOOKFLASH2 15 -static const struct gpio latch_gpios[] __initconst = { - { - .gpio = LATCH1_GPIO_BASE + 6, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dockit1", - }, - { - .gpio = LATCH1_GPIO_BASE + 7, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dockit2", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_SCARD_RSTIN, - .flags = GPIOF_OUT_INIT_LOW, - .label = "scard_rstin", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_SCARD_CMDVCC, - .flags = GPIOF_OUT_INIT_LOW, - .label = "scard_cmdvcc", - }, - { - .gpio = AMS_DELTA_LATCH2_GPIO_BASE + 14, - .flags = GPIOF_OUT_INIT_LOW, - .label = "hookflash1", - }, - { - .gpio = AMS_DELTA_LATCH2_GPIO_BASE + 15, - .flags = GPIOF_OUT_INIT_LOW, - .label = "hookflash2", - }, -}; - static struct regulator_consumer_supply modem_nreset_consumers[] = { REGULATOR_SUPPLY("RESET#", "serial8250.1"), REGULATOR_SUPPLY("POR", "cx20442-codec"), @@ -329,20 +296,6 @@ struct modem_private_data { static struct modem_private_data modem_priv; -void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value) -{ - int bit = 0; - u16 bitpos = 1 << bit; - - for (; bit < ngpio; bit++, bitpos = bitpos << 1) { - if (!(mask & bitpos)) - continue; - else - gpio_set_value(base + bit, (value & bitpos) != 0); - } -} -EXPORT_SYMBOL(ams_delta_latch_write); - static struct resource ams_delta_nand_resources[] = { [0] = { .start = OMAP1_MPUIO_BASE, @@ -638,6 +591,28 @@ static struct gpiod_hog ams_delta_gpio_hogs[] = { {}, }; +static struct plat_serial8250_port ams_delta_modem_ports[]; + +/* + * Obtain MODEM IRQ GPIO descriptor using its hardware pin + * number and assign related IRQ number to the MODEM port. + * Keep the GPIO descriptor open so nobody steps in. + */ +static void __init modem_assign_irq(struct gpio_chip *chip) +{ + struct gpio_desc *gpiod; + + gpiod = gpiochip_request_own_desc(chip, AMS_DELTA_GPIO_PIN_MODEM_IRQ, + "modem_irq"); + if (IS_ERR(gpiod)) { + pr_err("%s: modem IRQ GPIO request failed (%ld)\n", __func__, + PTR_ERR(gpiod)); + } else { + gpiod_direction_input(gpiod); + ams_delta_modem_ports[0].irq = gpiod_to_irq(gpiod); + } +} + /* * The purpose of this function is to take care of proper initialization of * devices and data structures which depend on GPIO lines provided by OMAP GPIO @@ -657,7 +632,47 @@ static void __init omap_gpio_deps_init(void) return; } + /* + * Start with FIQ initialization as it may have to request + * and release successfully each OMAP GPIO pin in turn. + */ ams_delta_init_fiq(chip, &ams_delta_serio_device); + + modem_assign_irq(chip); +} + +/* + * Initialize latch2 pins with values which are safe for dependent on-board + * devices or useful for their successull initialization even before GPIO + * driver takes control over the latch pins: + * - LATCH2_PIN_LCD_VBLEN = 0 + * - LATCH2_PIN_LCD_NDISP = 0 Keep LCD device powered off before its + * driver takes control over it. + * - LATCH2_PIN_NAND_NCE = 0 + * - LATCH2_PIN_NAND_NWP = 0 Keep NAND device down and write- + * protected before its driver takes + * control over it. + * - LATCH2_PIN_KEYBRD_PWR = 0 Keep keyboard powered off before serio + * driver takes control over it. + * - LATCH2_PIN_KEYBRD_DATAOUT = 0 Keep low to avoid corruption of first + * byte of data received from attached + * keyboard when serio device is probed; + * the pin is also hogged low by the latch2 + * GPIO driver as soon as it is ready. + * - LATCH2_PIN_MODEM_NRESET = 1 Enable voice MODEM device, allowing for + * its successful probe even before a + * regulator it depends on, which in turn + * takes control over the pin, is set up. + * - LATCH2_PIN_MODEM_CODEC = 1 Attach voice MODEM CODEC data port + * to the MODEM so the CODEC is under + * control even if audio driver doesn't + * take it over. + */ +static void __init ams_delta_latch2_init(void) +{ + u16 latch2 = 1 << LATCH2_PIN_MODEM_NRESET | 1 << LATCH2_PIN_MODEM_CODEC; + + __raw_writew(latch2, LATCH2_VIRT); } static void __init ams_delta_init(void) @@ -681,6 +696,7 @@ static void __init ams_delta_init(void) omap_cfg_reg(J18_1610_CAM_D7); omap_gpio_deps_init(); + ams_delta_latch2_init(); gpiod_add_hogs(ams_delta_gpio_hogs); omap_serial_init(); @@ -821,7 +837,6 @@ static void __init ams_delta_led_init(struct gpio_chip *chip) static int __init ams_delta_gpio_init(void) { struct gpio_chip *chip; - int err; if (!machine_is_ams_delta()) return -ENODEV; @@ -832,11 +847,7 @@ static int __init ams_delta_gpio_init(void) else ams_delta_led_init(chip); - err = gpio_request_array(latch_gpios, ARRAY_SIZE(latch_gpios)); - if (err) - pr_err("Couldn't take over latch1/latch2 GPIO pins\n"); - - return err; + return 0; } device_initcall_sync(ams_delta_gpio_init); @@ -852,33 +863,44 @@ static int __init modem_nreset_init(void) } +/* + * This function expects MODEM IRQ number already assigned to the port + * and fails if it's not. + * The MODEM device requires its RESET# pin kept high during probe. + * That requirement can be fulfilled in several ways: + * - with a descriptor of already functional modem_nreset regulator + * assigned to the MODEM private data, + * - with the regulator not yet controlled by modem_pm function but + * already enabled by default on probe, + * - before the modem_nreset regulator is probed, with the pin already + * set high explicitly. + * The last one is already guaranteed by ams_delta_latch2_init() called + * from machine_init. + * In order to avoid taking over ttyS0 device slot, the MODEM device + * should be registered after OMAP serial ports. Since those ports + * are registered at arch_initcall, this function can be called safely + * at arch_initcall_sync earliest. + */ static int __init ams_delta_modem_init(void) { int err; - omap_cfg_reg(M14_1510_GPIO2); - ams_delta_modem_ports[0].irq = - gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ); + if (!machine_is_ams_delta()) + return -ENODEV; - err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem"); - if (err) { - pr_err("Couldn't request gpio pin for modem\n"); - return err; - } - gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ); + if (ams_delta_modem_ports[0].irq < 0) + return ams_delta_modem_ports[0].irq; + + omap_cfg_reg(M14_1510_GPIO2); /* Initialize the modem_nreset regulator consumer before use */ modem_priv.regulator = ERR_PTR(-ENODEV); - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - AMS_DELTA_LATCH2_MODEM_CODEC); - err = platform_device_register(&ams_delta_modem_device); - if (err) - gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ); return err; } +arch_initcall_sync(ams_delta_modem_init); static int __init late_init(void) { @@ -888,10 +910,6 @@ static int __init late_init(void) if (err) return err; - err = ams_delta_modem_init(); - if (err) - return err; - /* * Once the modem device is registered, the modem_nreset * regulator can be requested on behalf of that device. @@ -906,7 +924,6 @@ static int __init late_init(void) unregister: platform_device_unregister(&ams_delta_modem_device); - gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ); return err; } diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h b/arch/arm/mach-omap1/include/mach/board-ams-delta.h index ad6f865d1f16..3b2d8019238a 100644 --- a/arch/arm/mach-omap1/include/mach/board-ams-delta.h +++ b/arch/arm/mach-omap1/include/mach/board-ams-delta.h @@ -59,13 +59,6 @@ #define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN #define AMS_DELTA_LATCH2_NGPIO 16 -#ifndef __ASSEMBLY__ -void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value); -#define ams_delta_latch2_write(mask, value) \ - ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \ - AMS_DELTA_LATCH2_NGPIO, (mask), (value)) -#endif - #endif /* CONFIG_MACH_AMS_DELTA */ #endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */ diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index cd65ea4e9c54..56a1fe90d394 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -188,16 +188,16 @@ /** * struct clkctrl_provider - clkctrl provider mapping data - * @addr: base address for the provider - * @size: size of the provider address space - * @offset: offset of the provider from PRCM instance base + * @num_addrs: number of base address ranges for the provider + * @addr: base address(es) for the provider + * @size: size(s) of the provider address space(s) * @node: device node associated with the provider * @link: list link */ struct clkctrl_provider { - u32 addr; - u32 size; - u16 offset; + int num_addrs; + u32 *addr; + u32 *size; struct device_node *node; struct list_head link; }; @@ -724,23 +724,34 @@ static int __init _setup_clkctrl_provider(struct device_node *np) const __be32 *addrp; struct clkctrl_provider *provider; u64 size; + int i; provider = memblock_virt_alloc(sizeof(*provider), 0); if (!provider) return -ENOMEM; - addrp = of_get_address(np, 0, &size, NULL); - provider->addr = (u32)of_translate_address(np, addrp); - addrp = of_get_address(np->parent, 0, NULL, NULL); - provider->offset = provider->addr - - (u32)of_translate_address(np->parent, addrp); - provider->addr &= ~0xff; - provider->size = size | 0xff; provider->node = np; - pr_debug("%s: %s: %x...%x [+%x]\n", __func__, np->parent->name, - provider->addr, provider->addr + provider->size, - provider->offset); + provider->num_addrs = + of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2; + + provider->addr = + memblock_virt_alloc(sizeof(void *) * provider->num_addrs, 0); + if (!provider->addr) + return -ENOMEM; + + provider->size = + memblock_virt_alloc(sizeof(u32) * provider->num_addrs, 0); + if (!provider->size) + return -ENOMEM; + + for (i = 0; i < provider->num_addrs; i++) { + addrp = of_get_address(np, i, &size, NULL); + provider->addr[i] = (u32)of_translate_address(np, addrp); + provider->size[i] = size; + pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i], + provider->addr[i] + provider->size[i]); + } list_add(&provider->link, &clkctrl_providers); @@ -787,23 +798,26 @@ static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh) pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr); list_for_each_entry(provider, &clkctrl_providers, link) { - if (provider->addr <= addr && - provider->addr + provider->size >= addr) { - struct of_phandle_args clkspec; + int i; - clkspec.np = provider->node; - clkspec.args_count = 2; - clkspec.args[0] = addr - provider->addr - - provider->offset; - clkspec.args[1] = 0; + for (i = 0; i < provider->num_addrs; i++) { + if (provider->addr[i] <= addr && + provider->addr[i] + provider->size[i] > addr) { + struct of_phandle_args clkspec; - clk = of_clk_get_from_provider(&clkspec); + clkspec.np = provider->node; + clkspec.args_count = 2; + clkspec.args[0] = addr - provider->addr[0]; + clkspec.args[1] = 0; - pr_debug("%s: %s got %p (offset=%x, provider=%s)\n", - __func__, oh->name, clk, clkspec.args[0], - provider->node->parent->name); + clk = of_clk_get_from_provider(&clkspec); - return clk; + pr_debug("%s: %s got %p (offset=%x, provider=%pOF)\n", + __func__, oh->name, clk, + clkspec.args[0], provider->node); + + return clk; + } } } @@ -2107,8 +2121,8 @@ static int of_dev_find_hwmod(struct device_node *np, if (res) continue; if (!strcmp(p, oh->name)) { - pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n", - np->name, i, oh->name); + pr_debug("omap_hwmod: dt %pOFn[%i] uses hwmod %s\n", + np, i, oh->name); return i; } } @@ -2241,8 +2255,8 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, return -ENOENT; if (nr_addr != 1 || nr_size != 1) { - pr_err("%s: invalid range for %s->%s\n", __func__, - oh->name, np->name); + pr_err("%s: invalid range for %s->%pOFn\n", __func__, + oh->name, np); return -EINVAL; } @@ -2250,8 +2264,8 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, base = of_translate_address(np, ranges++); size = be32_to_cpup(ranges); - pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n", - oh ? oh->name : "", np->name, base, size); + pr_debug("omap_hwmod: %s %pOFn at 0x%llx size 0x%llx\n", + oh->name, np, base, size); if (oh && oh->mpu_rt_idx) { omap_hwmod_fix_mpu_rt_idx(oh, np, res); @@ -2359,8 +2373,8 @@ static int __init _init(struct omap_hwmod *oh, void *data) if (r) pr_debug("omap_hwmod: %s missing dt data\n", oh->name); else if (np && index) - pr_warn("omap_hwmod: %s using broken dt data from %s\n", - oh->name, np->name); + pr_warn("omap_hwmod: %s using broken dt data from %pOFn\n", + oh->name, np); r = _init_mpu_rt_base(oh, NULL, index, np); if (r < 0) { diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index 9d5595c4ad99..594901f3b8e5 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -219,17 +219,6 @@ static void gta02_udc_vbus_draw(unsigned int ma) #define gta02_udc_vbus_draw NULL #endif -/* - * This is called when pc50633 is probed, unfortunately quite late in the - * day since it is an I2C bus device. Here we can belatedly define some - * platform devices with the advantage that we can mark the pcf50633 as the - * parent. This makes them get suspended and resumed with their parent - * the pcf50633 still around. - */ - -static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf); - - static char *gta02_batteries[] = { "battery", }; @@ -355,7 +344,6 @@ static struct pcf50633_platform_data gta02_pcf_pdata = { }, }, - .probe_done = gta02_pmu_attach_child_devices, .mbc_event_callback = gta02_pmu_event_callback, }; @@ -512,36 +500,6 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c_device_ts, }; -/* These guys DO need to be children of PMU. */ - -static struct platform_device *gta02_devices_pmu_children[] = { -}; - - -/* - * This is called when pc50633 is probed, quite late in the day since it is an - * I2C bus device. Here we can define platform devices with the advantage that - * we can mark the pcf50633 as the parent. This makes them get suspended and - * resumed with their parent the pcf50633 still around. All devices whose - * operation depends on something from pcf50633 must have this relationship - * made explicit like this, or suspend and resume will become an unreliable - * hellworld. - */ - -static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf) -{ - int n; - - /* Grab a copy of the now probed PMU pointer. */ - gta02_pcf = pcf; - - for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++) - gta02_devices_pmu_children[n]->dev.parent = pcf->dev; - - platform_add_devices(gta02_devices_pmu_children, - ARRAY_SIZE(gta02_devices_pmu_children)); -} - static void gta02_poweroff(void) { pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1); diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index f9fc1f8d2b28..50d67d760efd 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -64,31 +64,31 @@ static struct map_desc mini2440_iodesc[] __initdata = { }; #define UCON S3C2410_UCON_DEFAULT -#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB -#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = { [0] = { - .hwport = 0, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [1] = { - .hwport = 1, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [2] = { - .hwport = 2, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, }; @@ -104,8 +104,8 @@ static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = { /* * This macro simplifies the table bellow */ -#define _LCD_DECLARE(_clock,_xres,margin_left,margin_right,hsync, \ - _yres,margin_top,margin_bottom,vsync, refresh) \ +#define _LCD_DECLARE(_clock, _xres, margin_left, margin_right, hsync, \ + _yres, margin_top, margin_bottom, vsync, refresh) \ .width = _xres, \ .xres = _xres, \ .height = _yres, \ @@ -128,7 +128,7 @@ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { [0] = { /* mini2440 + 3.5" TFT + touchscreen */ _LCD_DECLARE( 7, /* The 3.5 is quite fast */ - 240, 21, 38, 6, /* x timing */ + 240, 21, 38, 6, /* x timing */ 320, 4, 4, 2, /* y timing */ 60), /* refresh rate */ .lcdcon5 = (S3C2410_LCDCON5_FRM565 | @@ -140,7 +140,7 @@ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { [1] = { /* mini2440 + 7" TFT + touchscreen */ _LCD_DECLARE( 10, /* the 7" runs slower */ - 800, 40, 40, 48, /* x timing */ + 800, 40, 40, 48, /* x timing */ 480, 29, 3, 3, /* y timing */ 50), /* refresh rate */ .lcdcon5 = (S3C2410_LCDCON5_FRM565 | @@ -148,7 +148,7 @@ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN), }, - /* The VGA shield can outout at several resolutions. All share + /* The VGA shield can outout at several resolutions. All share * the same timings, however, anything smaller than 1024x768 * will only be displayed in the top left corner of a 1024x768 * XGA output unless you add optional dip switches to the shield. @@ -158,9 +158,10 @@ static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { _LCD_DECLARE( 10, 1024, 1, 2, 2, /* y timing */ - 768, 200, 16, 16, /* x timing */ + 768, 200, 16, 16, /* x timing */ 24), /* refresh rate, maximum stable, - tested with the FPGA shield */ + * tested with the FPGA shield + */ .lcdcon5 = (S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_HWSWP), }, @@ -196,7 +197,8 @@ static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN * and disable the pull down resistors on pins we are using for LCD - * data. */ + * data. + */ .gpcup = (0xf << 1) | (0x3f << 10), @@ -232,10 +234,11 @@ static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { /* MMC/SD */ static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = { - .gpio_detect = S3C2410_GPG(8), - .gpio_wprotect = S3C2410_GPH(8), - .set_power = NULL, - .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34, + .gpio_detect = S3C2410_GPG(8), + .gpio_wprotect = S3C2410_GPH(8), + .wprotect_invert = 1, + .set_power = NULL, + .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34, }; /* NAND Flash on MINI2440 board */ @@ -254,7 +257,8 @@ static struct mtd_partition mini2440_default_nand_part[] __initdata = { [2] = { .name = "kernel", /* 5 megabytes, for a kernel with no modules - * or a uImage with a ramdisk attached */ + * or a uImage with a ramdisk attached + */ .size = 0x00500000, .offset = SZ_256K + SZ_128K, }, @@ -271,7 +275,7 @@ static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = { .nr_chips = 1, .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part), .partitions = mini2440_default_nand_part, - .flash_bbt = 1, /* we use u-boot to create a BBT */ + .flash_bbt = 1, /* we use u-boot to create a BBT */ }, }; @@ -282,7 +286,7 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = { .nr_sets = ARRAY_SIZE(mini2440_nand_sets), .sets = mini2440_nand_sets, .ignore_unset_ecc = 1, - .ecc_mode = NAND_ECC_HW, + .ecc_mode = NAND_ECC_HW, }; /* DM9000AEP 10/100 ethernet controller */ @@ -290,7 +294,7 @@ static struct s3c2410_platform_nand mini2440_nand_info __initdata = { static struct resource mini2440_dm9k_resource[] = { [0] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE, 4), [1] = DEFINE_RES_MEM(MACH_MINI2440_DM9K_BASE + 4, 4), - [2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ \ + [2] = DEFINE_RES_NAMED(IRQ_EINT7, 1, NULL, IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), }; @@ -362,7 +366,8 @@ static struct gpio_keys_button mini2440_buttons[] = { }, #if 0 /* this pin is also known as TCLK1 and seems to already - * marked as "in use" somehow in the kernel -- possibly wrongly */ + * marked as "in use" somehow in the kernel -- possibly wrongly + */ { .gpio = S3C2410_GPG(11), /* K6 */ .code = KEY_F6, @@ -564,7 +569,8 @@ static char mini2440_features_str[12] __initdata = "0tb"; static int __init mini2440_features_setup(char *str) { if (str) - strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str)); + strlcpy(mini2440_features_str, str, + sizeof(mini2440_features_str)); return 1; } @@ -583,10 +589,10 @@ struct mini2440_features_t { }; static void __init mini2440_parse_features( - struct mini2440_features_t * features, - const char * features_str ) + struct mini2440_features_t *features, + const char *features_str) { - const char * fp = features_str; + const char *fp = features_str; features->count = 0; features->done = 0; @@ -598,13 +604,14 @@ static void __init mini2440_parse_features( switch (f) { case '0'...'9': /* tft screen */ if (features->done & FEATURE_SCREEN) { - printk(KERN_INFO "MINI2440: '%c' ignored, " - "screen type already set\n", f); + pr_info("MINI2440: '%c' ignored, screen type already set\n", + f); } else { int li = f - '0'; + if (li >= ARRAY_SIZE(mini2440_lcd_cfg)) - printk(KERN_INFO "MINI2440: " - "'%c' out of range LCD mode\n", f); + pr_info("MINI2440: '%c' out of range LCD mode\n", + f); else { features->optional[features->count++] = &s3c_device_lcd; @@ -615,8 +622,8 @@ static void __init mini2440_parse_features( break; case 'b': if (features->done & FEATURE_BACKLIGHT) - printk(KERN_INFO "MINI2440: '%c' ignored, " - "backlight already set\n", f); + pr_info("MINI2440: '%c' ignored, backlight already set\n", + f); else { features->optional[features->count++] = &mini2440_led_backlight; @@ -624,13 +631,13 @@ static void __init mini2440_parse_features( features->done |= FEATURE_BACKLIGHT; break; case 't': - printk(KERN_INFO "MINI2440: '%c' ignored, " - "touchscreen not compiled in\n", f); + pr_info("MINI2440: '%c' ignored, touchscreen not compiled in\n", + f); break; case 'c': if (features->done & FEATURE_CAMERA) - printk(KERN_INFO "MINI2440: '%c' ignored, " - "camera already registered\n", f); + pr_info("MINI2440: '%c' ignored, camera already registered\n", + f); else features->optional[features->count++] = &s3c_device_camif; @@ -645,7 +652,7 @@ static void __init mini2440_init(void) struct mini2440_features_t features = { 0 }; int i; - printk(KERN_INFO "MINI2440: Option string mini2440=%s\n", + pr_info("MINI2440: Option string mini2440=%s\n", mini2440_features_str); /* Parse the feature string */ @@ -674,17 +681,17 @@ static void __init mini2440_init(void) mini2440_fb_info.displays = &mini2440_lcd_cfg[features.lcd_index]; - printk(KERN_INFO "MINI2440: LCD"); + pr_info("MINI2440: LCD"); for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++) if (li == features.lcd_index) - printk(" [%d:%dx%d]", li, + pr_cont(" [%d:%dx%d]", li, mini2440_lcd_cfg[li].width, mini2440_lcd_cfg[li].height); else - printk(" %d:%dx%d", li, + pr_cont(" %d:%dx%d", li, mini2440_lcd_cfg[li].width, mini2440_lcd_cfg[li].height); - printk("\n"); + pr_cont("\n"); s3c24xx_fb_set_platdata(&mini2440_fb_info); } diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index aeb2eed08598..b100c26a858f 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -1,6 +1,4 @@ -config ARCH_SHMOBILE - bool - +# SPDX-License-Identifier: GPL-2.0 config PM_RMOBILE bool select PM @@ -30,7 +28,6 @@ config ARCH_RMOBILE menuconfig ARCH_RENESAS bool "Renesas ARM SoCs" depends on ARCH_MULTI_V7 && MMU - select ARCH_SHMOBILE select ARM_GIC select GPIOLIB select HAVE_ARM_SCU if SMP @@ -55,6 +52,12 @@ config ARCH_R7S72100 select SYS_SUPPORTS_SH_MTU2 select RENESAS_OSTM +config ARCH_R7S9210 + bool "RZ/A2 (R7S9210)" + select PM + select PM_GENERIC_DOMAINS + select RENESAS_OSTM + config ARCH_R8A73A4 bool "R-Mobile APE6 (R8A73A40)" select ARCH_RMOBILE @@ -72,6 +75,11 @@ config ARCH_R8A7743 select ARCH_RCAR_GEN2 select ARM_ERRATA_798181 if SMP +config ARCH_R8A7744 + bool "RZ/G1N (R8A77440)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + config ARCH_R8A7745 bool "RZ/G1E (R8A77450)" select ARCH_RCAR_GEN2 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index b33dc59d8698..5591646cb9bb 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o +obj-$(CONFIG_ARCH_R7S9210) += setup-r7s9210.o # CPU reset vector handling objects cpu-y := platsmp.o headsmp.o diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S index 936d7011c314..d0234296ae62 100644 --- a/arch/arm/mach-shmobile/headsmp-scu.S +++ b/arch/arm/mach-shmobile/headsmp-scu.S @@ -1,17 +1,8 @@ -/* +/* SPDX-License-Identifier: GPL-2.0+ + * * Shared SCU setup for mach-shmobile * * Copyright (C) 2012 Bastian Hecht - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/linkage.h> diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index cef8e8c555f8..9466ae61f56a 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -1,14 +1,11 @@ -/* +/* SPDX-License-Identifier: GPL-2.0 + * * SMP support for R-Mobile / SH-Mobile * * Copyright (C) 2010 Magnus Damm * Copyright (C) 2010 Takashi Yoshii * * Based on vexpress, Copyright (c) 2003 ARM Limited, All Rights Reserved - * - * 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 - * published by the Free Software Foundation. */ #include <linux/init.h> #include <linux/linkage.h> diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c index f1a1efde4beb..fcfcef1d1ae4 100644 --- a/arch/arm/mach-shmobile/platsmp-scu.c +++ b/arch/arm/mach-shmobile/platsmp-scu.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SMP support for SoCs with SCU covered by mach-shmobile * * Copyright (C) 2013 Magnus Damm - * - * 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 - * published by the Free Software Foundation. */ #include <linux/cpu.h> #include <linux/delay.h> diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index b23378f3d7e1..7437c01513f6 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SMP support for R-Mobile / SH-Mobile * @@ -5,10 +6,6 @@ * Copyright (C) 2011 Paul Mundt * * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved - * - * 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 - * published by the Free Software Foundation. */ #include <linux/init.h> #include <asm/cacheflush.h> diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c index 345af3ebcc3a..8c2a20591524 100644 --- a/arch/arm/mach-shmobile/pm-rcar-gen2.c +++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car Generation 2 Power management support * * Copyright (C) 2013 - 2015 Renesas Electronics Corporation * Copyright (C) 2011 Renesas Solutions Corp. * Copyright (C) 2011 Magnus Damm - * - * 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. */ #include <linux/kernel.h> @@ -50,7 +47,7 @@ void __init rcar_gen2_pm_init(void) void __iomem *p; u32 bar; static int once; - struct device_node *np, *cpus; + struct device_node *np; bool has_a7 = false; bool has_a15 = false; struct resource res; @@ -59,11 +56,7 @@ void __init rcar_gen2_pm_init(void) if (once++) return; - cpus = of_find_node_by_path("/cpus"); - if (!cpus) - return; - - for_each_child_of_node(cpus, np) { + for_each_of_cpu_node(np) { if (of_device_is_compatible(np, "arm,cortex-a15")) has_a15 = true; else if (of_device_is_compatible(np, "arm,cortex-a7")) diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index e348bcfe389d..c6a11b5ec6db 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * rmobile power management support * @@ -7,10 +8,6 @@ * * based on pm-sh7372.c * Copyright (C) 2011 Magnus Damm - * - * 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. */ #include <linux/clk/renesas.h> #include <linux/console.h> @@ -189,7 +186,7 @@ static void __init add_special_pd(struct device_node *np, enum pd_types type) return; } - pr_debug("Special PM domain %s type %d for %pOF\n", pd->name, type, np); + pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np); special_pds[num_special_pds].pd = pd; special_pds[num_special_pds].type = type; @@ -202,7 +199,7 @@ static void __init get_special_pds(void) const struct of_device_id *id; /* PM domains containing CPUs */ - for_each_node_by_type(np, "cpu") + for_each_of_cpu_node(np) add_special_pd(np, PD_CPU); /* PM domain containing console */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 8146bb6d7237..69f839259b09 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -1,11 +1,8 @@ -/* +/* SPDX-License-Identifier: GPL-2.0 + * * Copyright (C) 2012 Renesas Solutions Corp. * * Kuninori Morimoto <morimoto.kuninori@renesas.com> - * - * 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. */ #ifndef PM_RMOBILE_H #define PM_RMOBILE_H diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c index 21ebc7678ffd..8e50daa99151 100644 --- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c @@ -23,11 +23,12 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/list.h> #include <linux/notifier.h> #include <linux/of.h> +#include <linux/of_irq.h> #include <linux/mfd/da9063/registers.h> - #define IRQC_BASE 0xe61c0000 #define IRQC_MONITOR 0x104 /* IRQn Signal Level Monitor Register */ @@ -36,34 +37,45 @@ /* start of DA9210 System Control and Event Registers */ #define DA9210_REG_MASK_A 0x54 +struct regulator_quirk { + struct list_head list; + const struct of_device_id *id; + struct of_phandle_args irq_args; + struct i2c_msg i2c_msg; + bool shared; /* IRQ line is shared */ +}; + +static LIST_HEAD(quirk_list); static void __iomem *irqc; /* first byte sets the memory pointer, following are consecutive reg values */ static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff }; static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff }; -static struct i2c_msg da9xxx_msgs[3] = { - { - .addr = 0x58, - .len = ARRAY_SIZE(da9063_irq_clr), - .buf = da9063_irq_clr, - }, { - .addr = 0x68, - .len = ARRAY_SIZE(da9210_irq_clr), - .buf = da9210_irq_clr, - }, { - .addr = 0x70, - .len = ARRAY_SIZE(da9210_irq_clr), - .buf = da9210_irq_clr, - }, +static struct i2c_msg da9063_msg = { + .len = ARRAY_SIZE(da9063_irq_clr), + .buf = da9063_irq_clr, +}; + +static struct i2c_msg da9210_msg = { + .len = ARRAY_SIZE(da9210_irq_clr), + .buf = da9210_irq_clr, +}; + +static const struct of_device_id rcar_gen2_quirk_match[] = { + { .compatible = "dlg,da9063", .data = &da9063_msg }, + { .compatible = "dlg,da9210", .data = &da9210_msg }, + {}, }; static int regulator_quirk_notify(struct notifier_block *nb, unsigned long action, void *data) { + struct regulator_quirk *pos, *tmp; struct device *dev = data; struct i2c_client *client; static bool done; + int ret; u32 mon; if (done) @@ -80,17 +92,20 @@ static int regulator_quirk_notify(struct notifier_block *nb, client = to_i2c_client(dev); dev_dbg(dev, "Detected %s\n", client->name); - if ((client->addr == 0x58 && !strcmp(client->name, "da9063")) || - (client->addr == 0x68 && !strcmp(client->name, "da9210")) || - (client->addr == 0x70 && !strcmp(client->name, "da9210"))) { - int ret, len; + /* + * Send message to all PMICs that share an IRQ line to deassert it. + * + * WARNING: This works only if all the PMICs are on the same I2C bus. + */ + list_for_each_entry(pos, &quirk_list, list) { + if (!pos->shared) + continue; - /* There are two DA9210 on Stout, one on the other boards. */ - len = of_machine_is_compatible("renesas,stout") ? 3 : 2; + dev_info(&client->dev, "clearing %s@0x%02x interrupts\n", + pos->id->compatible, pos->i2c_msg.addr); - dev_info(&client->dev, "clearing da9063/da9210 interrupts\n"); - ret = i2c_transfer(client->adapter, da9xxx_msgs, len); - if (ret != len) + ret = i2c_transfer(client->adapter, &pos->i2c_msg, 1); + if (ret != 1) dev_err(&client->dev, "i2c error %d\n", ret); } @@ -103,6 +118,11 @@ static int regulator_quirk_notify(struct notifier_block *nb, remove: dev_info(dev, "IRQ2 is not asserted, removing quirk\n"); + list_for_each_entry_safe(pos, tmp, &quirk_list, list) { + list_del(&pos->list); + kfree(pos); + } + done = true; iounmap(irqc); return 0; @@ -114,7 +134,12 @@ static struct notifier_block regulator_quirk_nb = { static int __init rcar_gen2_regulator_quirk(void) { - u32 mon; + struct regulator_quirk *quirk, *pos, *tmp; + struct of_phandle_args *argsa, *argsb; + const struct of_device_id *id; + struct device_node *np; + u32 mon, addr; + int ret; if (!of_machine_is_compatible("renesas,koelsch") && !of_machine_is_compatible("renesas,lager") && @@ -122,22 +147,78 @@ static int __init rcar_gen2_regulator_quirk(void) !of_machine_is_compatible("renesas,gose")) return -ENODEV; + for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) { + if (!of_device_is_available(np)) + break; + + ret = of_property_read_u32(np, "reg", &addr); + if (ret) /* Skip invalid entry and continue */ + continue; + + quirk = kzalloc(sizeof(*quirk), GFP_KERNEL); + if (!quirk) { + ret = -ENOMEM; + goto err_mem; + } + + argsa = &quirk->irq_args; + memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg)); + + quirk->id = id; + quirk->i2c_msg.addr = addr; + + ret = of_irq_parse_one(np, 0, argsa); + if (ret) { /* Skip invalid entry and continue */ + kfree(quirk); + continue; + } + + list_for_each_entry(pos, &quirk_list, list) { + argsb = &pos->irq_args; + + if (argsa->args_count != argsb->args_count) + continue; + + ret = memcmp(argsa->args, argsb->args, + argsa->args_count * + sizeof(argsa->args[0])); + if (!ret) { + pos->shared = true; + quirk->shared = true; + } + } + + list_add_tail(&quirk->list, &quirk_list); + } + irqc = ioremap(IRQC_BASE, PAGE_SIZE); - if (!irqc) - return -ENOMEM; + if (!irqc) { + ret = -ENOMEM; + goto err_mem; + } mon = ioread32(irqc + IRQC_MONITOR); if (mon & REGULATOR_IRQ_MASK) { pr_debug("%s: IRQ2 is not asserted, not installing quirk\n", __func__); - iounmap(irqc); - return 0; + ret = 0; + goto err_free; } pr_info("IRQ2 is asserted, installing da9063/da9210 regulator quirk\n"); bus_register_notifier(&i2c_bus_type, ®ulator_quirk_nb); return 0; + +err_free: + iounmap(irqc); +err_mem: + list_for_each_entry_safe(pos, tmp, &quirk_list, list) { + list_del(&pos->list); + kfree(pos); + } + + return ret; } arch_initcall(rcar_gen2_regulator_quirk); diff --git a/arch/arm/mach-shmobile/setup-r7s9210.c b/arch/arm/mach-shmobile/setup-r7s9210.c new file mode 100644 index 000000000000..573fb9955e7e --- /dev/null +++ b/arch/arm/mach-shmobile/setup-r7s9210.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r7s9210 processor support + * + * Copyright (C) 2018 Renesas Electronics Corporation + * Copyright (C) 2018 Chris Brandt + * + */ + +#include <linux/kernel.h> + +#include <asm/mach/arch.h> + +#include "common.h" + +static const char *const r7s9210_boards_compat_dt[] __initconst = { + "renesas,r7s9210", + NULL, +}; + +DT_MACHINE_START(R7S72100_DT, "Generic R7S9210 (Flattened Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .init_early = shmobile_init_delay, + .init_late = shmobile_init_late, + .dt_compat = r7s9210_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index d589326099e0..b13ec9088ce5 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -7,9 +7,7 @@ * Copyright (C) 2013 Cogent Embedded, Inc. */ #include <linux/init.h> -#include <linux/irq.h> #include <linux/irqchip.h> -#include <linux/irqchip/arm-gic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 013acc97795c..eea60b20c6b4 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -25,6 +25,7 @@ static const struct of_device_id cpg_matches[] __initconst = { { .compatible = "renesas,rcar-gen2-cpg-clocks", }, { .compatible = "renesas,r8a7743-cpg-mssr", .data = "extal" }, + { .compatible = "renesas,r8a7744-cpg-mssr", .data = "extal" }, { .compatible = "renesas,r8a7790-cpg-mssr", .data = "extal" }, { .compatible = "renesas,r8a7791-cpg-mssr", .data = "extal" }, { .compatible = "renesas,r8a7793-cpg-mssr", .data = "extal" }, @@ -193,6 +194,7 @@ MACHINE_END static const char * const rz_g1_boards_compat_dt[] __initconst = { "renesas,r8a7743", + "renesas,r8a7744", "renesas,r8a7745", "renesas,r8a77470", NULL, diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 41137404382e..9bc543faba96 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SMP support for R-Mobile / SH-Mobile - sh73a0 portion * * Copyright (C) 2010 Magnus Damm * Copyright (C) 2010 Takashi Yoshii - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c index 74b30bade2c1..3969a499746e 100644 --- a/arch/arm/mach-shmobile/suspend.c +++ b/arch/arm/mach-shmobile/suspend.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Suspend-to-RAM support code for SH-Mobile ARM * * Copyright (C) 2011 Magnus Damm - * - * 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. */ #include <linux/pm.h> diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 828e8aea037e..2335311b5f36 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -1,17 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SH-Mobile Timer * * Copyright (C) 2010 Magnus Damm * Copyright (C) 2002 - 2009 Paul Mundt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/platform_device.h> #include <linux/clocksource.h> @@ -22,22 +14,16 @@ void __init shmobile_init_delay(void) { - struct device_node *np, *cpus; + struct device_node *np; u32 max_freq = 0; - cpus = of_find_node_by_path("/cpus"); - if (!cpus) - return; - - for_each_child_of_node(cpus, np) { + for_each_of_cpu_node(np) { u32 freq; if (!of_property_read_u32(np, "clock-frequency", &freq)) max_freq = max(max_freq, freq); } - of_node_put(cpus); - if (!max_freq) return; diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 4f43c1cd5db0..c3c8bf54f033 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -29,17 +29,4 @@ config U300_DEBUG help Debug support for U300 in sysfs, procfs etc. -config MACH_U300_SPIDUMMY - depends on ARCH_U300 - bool "SSP/SPI dummy chip" - select SPI - select SPI_MASTER - select SPI_PL022 - help - This creates a small kernel module that creates a dummy - SPI device to be used for loopback tests. Regularly used - to test reference designs. If you're not testing SPI, - you don't need it. Selecting this will activate the - SPI framework and ARM PL022 support. - endif diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index 87d37de054b6..5a8804fa8776 100644 --- a/arch/arm/mach-u300/Makefile +++ b/arch/arm/mach-u300/Makefile @@ -4,5 +4,4 @@ obj-y := core.o -obj-$(CONFIG_MACH_U300_SPIDUMMY) += dummyspichip.o obj-$(CONFIG_REGULATOR_AB3100) += regulator.o diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c deleted file mode 100644 index 68fe986ca42e..000000000000 --- a/arch/arm/mach-u300/dummyspichip.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * arch/arm/mach-u300/dummyspichip.c - * - * Copyright (C) 2007-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * This is a dummy loopback SPI "chip" used for testing SPI. - * Author: Linus Walleij <linus.walleij@stericsson.com> - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/sysfs.h> -#include <linux/mutex.h> -#include <linux/spi/spi.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -/* - * WARNING! Do not include this pl022-specific controller header - * for any generic driver. It is only done in this dummy chip - * because we alter the chip configuration in order to test some - * different settings on the loopback device. Normal chip configs - * shall be STATIC and not altered by the driver! - */ -#include <linux/amba/pl022.h> - -struct dummy { - struct device *dev; - struct mutex lock; -}; - -#define DMA_TEST_SIZE 2048 - -/* When we cat /sys/bus/spi/devices/spi0.0/looptest this will be triggered */ -static ssize_t dummy_looptest(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct dummy *p_dummy = dev_get_drvdata(&spi->dev); - - /* - * WARNING! Do not dereference the chip-specific data in any normal - * driver for a chip. It is usually STATIC and shall not be read - * or written to. Your chip driver should NOT depend on fields in this - * struct, this is just used here to alter the behaviour of the chip - * in order to perform tests. - */ - int status; - u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD, - 0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05, - 0xF0, 0x0D}; - u8 rxbuf[14]; - u8 *bigtxbuf_virtual; - u8 *bigrxbuf_virtual; - - if (mutex_lock_interruptible(&p_dummy->lock)) - return -ERESTARTSYS; - - bigtxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL); - if (bigtxbuf_virtual == NULL) { - status = -ENOMEM; - goto out; - } - bigrxbuf_virtual = kmalloc(DMA_TEST_SIZE, GFP_KERNEL); - - /* Fill TXBUF with some happy pattern */ - memset(bigtxbuf_virtual, 0xAA, DMA_TEST_SIZE); - - /* - * Force chip to 8 bit mode - * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC! - */ - spi->bits_per_word = 8; - /* You should NOT DO THIS EITHER */ - spi->master->setup(spi); - - /* Now run the tests for 8bit mode */ - pr_info("Simple test 1: write 0xAA byte, read back garbage byte " - "in 8bit mode\n"); - status = spi_w8r8(spi, 0xAA); - if (status < 0) - pr_warn("Simple test 1: FAILURE: spi_write_then_read failed with status %d\n", - status); - else - pr_info("Simple test 1: SUCCESS!\n"); - - pr_info("Simple test 2: write 8 bytes, read back 8 bytes garbage " - "in 8bit mode (full FIFO)\n"); - status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); - if (status < 0) - pr_warn("Simple test 2: FAILURE: spi_write_then_read() failed with status %d\n", - status); - else - pr_info("Simple test 2: SUCCESS!\n"); - - pr_info("Simple test 3: write 14 bytes, read back 14 bytes garbage " - "in 8bit mode (see if we overflow FIFO)\n"); - status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); - if (status < 0) - pr_warn("Simple test 3: FAILURE: failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 3: SUCCESS!\n"); - - pr_info("Simple test 4: write 8 bytes with spi_write(), read 8 " - "bytes garbage with spi_read() in 8bit mode\n"); - status = spi_write(spi, &txbuf[0], 8); - if (status < 0) - pr_warn("Simple test 4 step 1: FAILURE: spi_write() failed with status %d\n", - status); - else - pr_info("Simple test 4 step 1: SUCCESS!\n"); - status = spi_read(spi, &rxbuf[0], 8); - if (status < 0) - pr_warn("Simple test 4 step 2: FAILURE: spi_read() failed with status %d\n", - status); - else - pr_info("Simple test 4 step 2: SUCCESS!\n"); - - pr_info("Simple test 5: write 14 bytes with spi_write(), read " - "14 bytes garbage with spi_read() in 8bit mode\n"); - status = spi_write(spi, &txbuf[0], 14); - if (status < 0) - pr_warn("Simple test 5 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 5 step 1: SUCCESS!\n"); - status = spi_read(spi, &rxbuf[0], 14); - if (status < 0) - pr_warn("Simple test 5 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 5: SUCCESS!\n"); - - pr_info("Simple test 6: write %d bytes with spi_write(), " - "read %d bytes garbage with spi_read() in 8bit mode\n", - DMA_TEST_SIZE, DMA_TEST_SIZE); - status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); - if (status < 0) - pr_warn("Simple test 6 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 6 step 1: SUCCESS!\n"); - status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); - if (status < 0) - pr_warn("Simple test 6 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 6: SUCCESS!\n"); - - - /* - * Force chip to 16 bit mode - * WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC! - */ - spi->bits_per_word = 16; - /* You should NOT DO THIS EITHER */ - spi->master->setup(spi); - - pr_info("Simple test 7: write 0xAA byte, read back garbage byte " - "in 16bit bus mode\n"); - status = spi_w8r8(spi, 0xAA); - if (status == -EIO) - pr_info("Simple test 7: SUCCESS! (expected failure with " - "status EIO)\n"); - else if (status < 0) - pr_warn("Simple test 7: FAILURE: spi_write_then_read failed with status %d\n", - status); - else - pr_warn("Simple test 7: FAILURE: spi_write_then_read succeeded but it was expected to fail!\n"); - - pr_info("Simple test 8: write 8 bytes, read back 8 bytes garbage " - "in 16bit mode (full FIFO)\n"); - status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); - if (status < 0) - pr_warn("Simple test 8: FAILURE: spi_write_then_read() failed with status %d\n", - status); - else - pr_info("Simple test 8: SUCCESS!\n"); - - pr_info("Simple test 9: write 14 bytes, read back 14 bytes garbage " - "in 16bit mode (see if we overflow FIFO)\n"); - status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); - if (status < 0) - pr_warn("Simple test 9: FAILURE: failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 9: SUCCESS!\n"); - - pr_info("Simple test 10: write %d bytes with spi_write(), " - "read %d bytes garbage with spi_read() in 16bit mode\n", - DMA_TEST_SIZE, DMA_TEST_SIZE); - status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); - if (status < 0) - pr_warn("Simple test 10 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 10 step 1: SUCCESS!\n"); - - status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); - if (status < 0) - pr_warn("Simple test 10 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", - status); - else - pr_info("Simple test 10: SUCCESS!\n"); - - status = sprintf(buf, "loop test complete\n"); - kfree(bigrxbuf_virtual); - kfree(bigtxbuf_virtual); - out: - mutex_unlock(&p_dummy->lock); - return status; -} - -static DEVICE_ATTR(looptest, S_IRUGO, dummy_looptest, NULL); - -static int pl022_dummy_probe(struct spi_device *spi) -{ - struct dummy *p_dummy; - int status; - - dev_info(&spi->dev, "probing dummy SPI device\n"); - - p_dummy = kzalloc(sizeof *p_dummy, GFP_KERNEL); - if (!p_dummy) - return -ENOMEM; - - dev_set_drvdata(&spi->dev, p_dummy); - mutex_init(&p_dummy->lock); - - /* sysfs hook */ - status = device_create_file(&spi->dev, &dev_attr_looptest); - if (status) { - dev_dbg(&spi->dev, "device_create_file looptest failure.\n"); - goto out_dev_create_looptest_failed; - } - - return 0; - -out_dev_create_looptest_failed: - dev_set_drvdata(&spi->dev, NULL); - kfree(p_dummy); - return status; -} - -static int pl022_dummy_remove(struct spi_device *spi) -{ - struct dummy *p_dummy = dev_get_drvdata(&spi->dev); - - dev_info(&spi->dev, "removing dummy SPI device\n"); - device_remove_file(&spi->dev, &dev_attr_looptest); - dev_set_drvdata(&spi->dev, NULL); - kfree(p_dummy); - - return 0; -} - -static const struct of_device_id pl022_dummy_dt_match[] = { - { .compatible = "arm,pl022-dummy" }, - {}, -}; - -static struct spi_driver pl022_dummy_driver = { - .driver = { - .name = "spi-dummy", - .of_match_table = pl022_dummy_dt_match, - }, - .probe = pl022_dummy_probe, - .remove = pl022_dummy_remove, -}; - -module_spi_driver(pl022_dummy_driver); -MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); -MODULE_DESCRIPTION("PL022 SSP/SPI DUMMY Linux driver"); -MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index f0292a30e6f6..10ef99ce1d90 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -233,7 +233,7 @@ int __init zynq_early_slcr_init(void) register_restart_handler(&zynq_slcr_restart_nb); - pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); + pr_info("%pOFn mapped to %p\n", np, zynq_slcr_base); of_node_put(np); diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index bd2c739d8083..b54f8f8def36 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -948,15 +948,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) goto fixup; if (ai_usermode & UM_SIGNAL) { - siginfo_t si; - - clear_siginfo(&si); - si.si_signo = SIGBUS; - si.si_errno = 0; - si.si_code = BUS_ADRALN; - si.si_addr = (void __user *)addr; - - force_sig_info(si.si_signo, &si, current); + force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr, current); } else { /* * We're about to disable the alignment trap and return to diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 3232afb6fdc0..f4ea4c62c613 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -161,13 +161,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, unsigned int fsr, unsigned int sig, int code, struct pt_regs *regs) { - struct siginfo si; - if (addr > TASK_SIZE) harden_branch_predictor(); - clear_siginfo(&si); - #ifdef CONFIG_DEBUG_USER if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) || ((user_debug & UDBG_BUS) && (sig == SIGBUS))) { @@ -181,11 +177,7 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, tsk->thread.address = addr; tsk->thread.error_code = fsr; tsk->thread.trap_no = 14; - si.si_signo = sig; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void __user *)addr; - force_sig_info(sig, &si, tsk); + force_sig_fault(sig, code, (void __user *)addr, tsk); } void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -554,7 +546,6 @@ asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + fsr_fs(fsr); - struct siginfo info; if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; @@ -563,12 +554,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) inf->name, fsr, addr); show_pte(current->mm, addr); - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm_notify_die("", regs, &info, fsr, 0); + arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, + fsr, 0); } void __init @@ -588,7 +575,6 @@ asmlinkage void do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) { const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); - struct siginfo info; if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; @@ -596,12 +582,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", inf->name, ifsr, addr); - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm_notify_die("", regs, &info, ifsr, 0); + arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, + ifsr, 0); } /* diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index b600e38364eb..377ff9cda667 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -256,7 +256,7 @@ config S3C_PM_DEBUG_LED_SMDK config SAMSUNG_PM_CHECK bool "S3C2410 PM Suspend Memory CRC" - depends on PM + depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210) select CRC32 help Enable the PM code's memory area checksum over sleep. This option diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2b287d0d6bc2..aff6e6eadc70 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -216,13 +216,6 @@ static struct notifier_block vfp_notifier_block = { */ static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) { - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = SIGFPE; - info.si_code = sicode; - info.si_addr = (void __user *)(instruction_pointer(regs) - 4); - /* * This is the same as NWFPE, because it's not clear what * this is used for @@ -230,7 +223,9 @@ static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) current->thread.error_code = 0; current->thread.trap_no = 6; - send_sig_info(SIGFPE, &info, current); + send_sig_fault(SIGFPE, sicode, + (void __user *)(instruction_pointer(regs) - 4), + current); } static void vfp_panic(char *reason, u32 inst) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index c03cd0d765d3..964f682a2b7b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -11,6 +11,8 @@ config ARM64 select ARCH_CLOCKSOURCE_DATA select ARCH_HAS_DEBUG_VIRTUAL select ARCH_HAS_DEVMEM_IS_ALLOWED + select ARCH_HAS_DMA_COHERENT_TO_PFN + select ARCH_HAS_DMA_MMAP_PGPROT select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FAST_MULTIPLIER @@ -24,6 +26,8 @@ config ARM64 select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_MODULE_RWX + select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select ARCH_HAS_SYNC_DMA_FOR_CPU select ARCH_HAS_SYSCALL_WRAPPER select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAVE_NMI_SAFE_CMPXCHG diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 393d2b524284..51bc479334a4 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -3,6 +3,7 @@ menu "Platform selection" config ARCH_ACTIONS bool "Actions Semi Platforms" select OWL_TIMER + select PINCTRL help This enables support for the Actions Semiconductor S900 SoC family. @@ -67,6 +68,7 @@ config ARCH_EXYNOS select HAVE_S3C_RTC if RTC_CLASS select PINCTRL select PINCTRL_EXYNOS + select PM_GENERIC_DOMAINS if PM select SOC_SAMSUNG help This enables support for ARMv8 based Samsung Exynos SoC family. @@ -128,6 +130,7 @@ config ARCH_MVEBU select MVEBU_ICU select MVEBU_ODMI select MVEBU_PIC + select MVEBU_SEI select OF_GPIO select PINCTRL select PINCTRL_ARMADA_37XX @@ -152,40 +155,30 @@ config ARCH_REALTEK This enables support for the ARMv8 based Realtek chipsets, like the RTD1295. -config ARCH_ROCKCHIP - bool "Rockchip Platforms" - select ARCH_HAS_RESET_CONTROLLER - select GPIOLIB - select PINCTRL - select PINCTRL_ROCKCHIP - select PM - select ROCKCHIP_TIMER - help - This enables support for the ARMv8 based Rockchip chipsets, - like the RK3368. - -config ARCH_SEATTLE - bool "AMD Seattle SoC Family" - help - This enables support for AMD Seattle SOC Family - -config ARCH_SHMOBILE - bool - -config ARCH_SYNQUACER - bool "Socionext SynQuacer SoC Family" - config ARCH_RENESAS bool "Renesas SoC Platforms" - select ARCH_SHMOBILE select PINCTRL select PM select PM_GENERIC_DOMAINS select RENESAS_IRQC select SOC_BUS + select SYS_SUPPORTS_SH_CMT + select SYS_SUPPORTS_SH_TMU help This enables support for the ARMv8 based Renesas SoCs. +config ARCH_R8A774A1 + bool "Renesas RZ/G2M SoC Platform" + depends on ARCH_RENESAS + help + This enables support for the Renesas RZ/G2M SoC. + +config ARCH_R8A774C0 + bool "Renesas RZ/G2E SoC Platform" + depends on ARCH_RENESAS + help + This enables support for the Renesas RZ/G2E SoC. + config ARCH_R8A7795 bool "Renesas R-Car H3 SoC Platform" depends on ARCH_RENESAS @@ -228,11 +221,31 @@ config ARCH_R8A77995 help This enables support for the Renesas R-Car D3 SoC. +config ARCH_ROCKCHIP + bool "Rockchip Platforms" + select ARCH_HAS_RESET_CONTROLLER + select GPIOLIB + select PINCTRL + select PINCTRL_ROCKCHIP + select PM + select ROCKCHIP_TIMER + help + This enables support for the ARMv8 based Rockchip chipsets, + like the RK3368. + +config ARCH_SEATTLE + bool "AMD Seattle SoC Family" + help + This enables support for AMD Seattle SOC Family + config ARCH_STRATIX10 bool "Altera's Stratix 10 SoCFPGA Family" help This enables support for Altera's Stratix 10 SoCFPGA Family. +config ARCH_SYNQUACER + bool "Socionext SynQuacer SoC Family" + config ARCH_TEGRA bool "NVIDIA Tegra SoC Family" select ARCH_HAS_RESET_CONTROLLER @@ -301,6 +314,7 @@ config ARCH_ZX config ARCH_ZYNQMP bool "Xilinx ZynqMP Family" + select ZYNQMP_FIRMWARE help This enables support for Xilinx ZynqMP Family diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 106039d25e2f..b4e994cd3a42 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -113,9 +113,8 @@ core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a # Default target when executing plain make boot := arch/arm64/boot KBUILD_IMAGE := $(boot)/Image.gz -KBUILD_DTBS := dtbs -all: Image.gz $(KBUILD_DTBS) +all: Image.gz Image: vmlinux @@ -127,17 +126,6 @@ Image.%: Image zinstall install: $(Q)$(MAKE) $(build)=$(boot) $@ -%.dtb: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - -PHONY += dtbs dtbs_install - -dtbs: prepare scripts - $(Q)$(MAKE) $(build)=$(boot)/dts - -dtbs_install: - $(Q)$(MAKE) $(dtbinst)=$(boot)/dts - PHONY += vdso_install vdso_install: $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@ @@ -145,7 +133,6 @@ vdso_install: # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) - $(Q)$(MAKE) $(clean)=$(boot)/dts # We need to generate vdso-offsets.h before compiling certain files in kernel/. # In order to do that, we should use the archprepare target, but we can't since @@ -160,8 +147,6 @@ vdso_prepare: prepare0 define archhelp echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)' echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' - echo '* dtbs - Build device tree blobs for enabled boards' - echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' echo ' Install using (your) ~/bin/installkernel or' diff --git a/arch/arm64/boot/dts/actions/Makefile b/arch/arm64/boot/dts/actions/Makefile index d8b923480f5a..b57fd2372ecd 100644 --- a/arch/arm64/boot/dts/actions/Makefile +++ b/arch/arm64/boot/dts/actions/Makefile @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ + dtb-$(CONFIG_ARCH_ACTIONS) += s700-cubieboard7.dtb dtb-$(CONFIG_ARCH_ACTIONS) += s900-bubblegum-96.dtb diff --git a/arch/arm64/boot/dts/actions/s700-cubieboard7.dts b/arch/arm64/boot/dts/actions/s700-cubieboard7.dts index ef79d7905f44..28f3f4a0f7f0 100644 --- a/arch/arm64/boot/dts/actions/s700-cubieboard7.dts +++ b/arch/arm64/boot/dts/actions/s700-cubieboard7.dts @@ -28,12 +28,6 @@ device_type = "memory"; reg = <0x1 0xe0000000 0x0 0x0>; }; - - uart3_clk: uart3-clk { - compatible = "fixed-clock"; - clock-frequency = <921600>; - #clock-cells = <0>; - }; }; &timer { @@ -42,5 +36,4 @@ &uart3 { status = "okay"; - clocks = <&uart3_clk>; }; diff --git a/arch/arm64/boot/dts/actions/s700.dtsi b/arch/arm64/boot/dts/actions/s700.dtsi index 66dd5309f0a2..192c7b39c8c1 100644 --- a/arch/arm64/boot/dts/actions/s700.dtsi +++ b/arch/arm64/boot/dts/actions/s700.dtsi @@ -3,6 +3,7 @@ * Copyright (c) 2017 Andreas Färber */ +#include <dt-bindings/clock/actions,s700-cmu.h> #include <dt-bindings/interrupt-controller/arm-gic.h> / { @@ -87,6 +88,12 @@ #clock-cells = <0>; }; + losc: losc { + compatible = "fixed-clock"; + clock-frequency = <32768>; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; @@ -107,6 +114,7 @@ uart0: serial@e0120000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0120000 0x0 0x2000>; + clocks = <&cmu CLK_UART0>; interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -114,6 +122,7 @@ uart1: serial@e0122000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0122000 0x0 0x2000>; + clocks = <&cmu CLK_UART1>; interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -121,6 +130,7 @@ uart2: serial@e0124000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0124000 0x0 0x2000>; + clocks = <&cmu CLK_UART2>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -128,6 +138,7 @@ uart3: serial@e0126000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0126000 0x0 0x2000>; + clocks = <&cmu CLK_UART3>; interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -135,6 +146,7 @@ uart4: serial@e0128000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0128000 0x0 0x2000>; + clocks = <&cmu CLK_UART4>; interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -142,6 +154,7 @@ uart5: serial@e012a000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe012a000 0x0 0x2000>; + clocks = <&cmu CLK_UART5>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -149,10 +162,18 @@ uart6: serial@e012c000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe012c000 0x0 0x2000>; + clocks = <&cmu CLK_UART6>; interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; + cmu: clock-controller@e0168000 { + compatible = "actions,s700-cmu"; + reg = <0x0 0xe0168000 0x0 0x1000>; + clocks = <&hosc>, <&losc>; + #clock-cells = <1>; + }; + sps: power-controller@e01b0100 { compatible = "actions,s700-sps"; reg = <0x0 0xe01b0100 0x0 0x100>; diff --git a/arch/arm64/boot/dts/actions/s900-bubblegum-96.dts b/arch/arm64/boot/dts/actions/s900-bubblegum-96.dts index 21ca80f9941c..732daaa6e9d3 100644 --- a/arch/arm64/boot/dts/actions/s900-bubblegum-96.dts +++ b/arch/arm64/boot/dts/actions/s900-bubblegum-96.dts @@ -1,7 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /dts-v1/; @@ -24,11 +23,223 @@ device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; }; +}; + +&i2c0 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_default>; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_default>; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_default>; +}; + +/* + * GPIO name legend: proper name = the GPIO line is used as GPIO + * NC = not connected (pin out but not routed from the chip to + * anything the board) + * "[PER]" = pin is muxed for [peripheral] (not GPIO) + * LSEC = Low Speed External Connector + * HSEC = High Speed External Connector + * + * Line names are taken from the schematic "Schematics Bubblegum96" + * version v1.0 + * + * For the lines routed to the external connectors the + * lines are named after the 96Boards CE Specification 1.0, + * Appendix "Expansion Connector Signal Description". + * + * When the 96Boards naming of a line and the schematic name of + * the same line are in conflict, the 96Boards specification + * takes precedence, which means that the external UART on the + * LSEC is named UART0 while the schematic and SoC names this + * UART2. Only exception is the I2C lines for which the schematic + * naming has been preferred. This is only for the informational + * lines i.e. "[FOO]", the GPIO named lines "GPIO-A" thru "GPIO-L" + * are the only ones actually used for GPIO. + */ + +&pinctrl { + gpio-line-names = + "GPIO-A", /* GPIO_0, LSEC pin 23 */ + "GPIO-B", /* GPIO_1, LSEC pin 24 */ + "GPIO-C", /* GPIO_2, LSEC pin 25 */ + "GPIO-D", /* GPIO_3, LSEC pin 26 */ + "GPIO-E", /* GPIO_4, LSEC pin 27 */ + "GPIO-F", /* GPIO_5, LSEC pin 28 */ + "GPIO-G", /* GPIO_6, LSEC pin 29 */ + "GPIO-H", /* GPIO_7, LSEC pin 30 */ + "GPIO-I", /* GPIO_8, LSEC pin 31 */ + "GPIO-J", /* GPIO_9, LSEC pin 32 */ + "NC", /* GPIO_10 */ + "NC", /* GPIO_11 */ + "SIRQ2_1V8", /* GPIO_12 */ + "PCM0_OUT", /* GPIO_13 */ + "WIFI_LED", /* GPIO_14 */ + "PCM0_SYNC", /* GPIO_15 */ + "PCM0_CLK", /* GPIO_16 */ + "PCM0_IN", /* GPIO_17 */ + "BT_LED", /* GPIO_18 */ + "LED0", /* GPIO_19 */ + "LED1", /* GPIO_20 */ + "JTAG_TCK", /* GPIO_21 */ + "JTAG_TMS", /* GPIO_22 */ + "JTAG_TDI", /* GPIO_23 */ + "JTAG_TDO", /* GPIO_24 */ + "[UART1_RxD]", /* GPIO_25, LSEC pin 13 */ + "NC", /* GPIO_26 */ + "[UART1_TxD]", /* GPIO_27, LSEC pin 11 */ + "SD0_D0", /* GPIO_28 */ + "SD0_D1", /* GPIO_29 */ + "SD0_D2", /* GPIO_30 */ + "SD0_D3", /* GPIO_31 */ + "SD1_D0", /* GPIO_32 */ + "SD1_D1", /* GPIO_33 */ + "SD1_D2", /* GPIO_34 */ + "SD1_D3", /* GPIO_35 */ + "SD0_CMD", /* GPIO_36 */ + "SD0_CLK", /* GPIO_37 */ + "SD1_CMD", /* GPIO_38 */ + "SD1_CLK", /* GPIO_39 */ + "SPI0_SCLK", /* GPIO_40, LSEC pin 8 */ + "SPI0_CS", /* GPIO_41, LSEC pin 12 */ + "SPI0_DIN", /* GPIO_42, LSEC pin 10 */ + "SPI0_DOUT", /* GPIO_43, LSEC pin 14 */ + "I2C5_SDATA", /* GPIO_44, HSEC pin 36 */ + "I2C5_SCLK", /* GPIO_45, HSEC pin 38 */ + "UART0_RX", /* GPIO_46, LSEC pin 7 */ + "UART0_TX", /* GPIO_47, LSEC pin 5 */ + "UART0_RTSB", /* GPIO_48, LSEC pin 9 */ + "UART0_CTSB", /* GPIO_49, LSEC pin 3 */ + "I2C4_SCLK", /* GPIO_50, HSEC pin 32 */ + "I2C4_SDATA", /* GPIO_51, HSEC pin 34 */ + "I2C0_SCLK", /* GPIO_52 */ + "I2C0_SDATA", /* GPIO_53 */ + "I2C1_SCLK", /* GPIO_54, LSEC pin 15 */ + "I2C1_SDATA", /* GPIO_55, LSEC pin 17 */ + "I2C2_SCLK", /* GPIO_56, LSEC pin 19 */ + "I2C2_SDATA", /* GPIO_57, LSEC pin 21 */ + "CSI0_DN0", /* GPIO_58, HSEC pin 10 */ + "CSI0_DP0", /* GPIO_59, HSEC pin 8 */ + "CSI0_DN1", /* GPIO_60, HSEC pin 16 */ + "CSI0_DP1", /* GPIO_61, HSEC pin 14 */ + "CSI0_CN", /* GPIO_62, HSEC pin 4 */ + "CSI0_CP", /* GPIO_63, HSEC pin 2 */ + "CSI0_DN2", /* GPIO_64, HSEC pin 22 */ + "CSI0_DP2", /* GPIO_65, HSEC pin 20 */ + "CSI0_DN3", /* GPIO_66, HSEC pin 28 */ + "CSI0_DP3", /* GPIO_67, HSEC pin 26 */ + "[CLK0]", /* GPIO_68, HSEC pin 15 */ + "CSI1_DN0", /* GPIO_69, HSEC pin 44 */ + "CSI1_DP0", /* GPIO_70, HSEC pin 42 */ + "CSI1_DN1", /* GPIO_71, HSEC pin 50 */ + "CSI1_DP1", /* GPIO_72, HSEC pin 48 */ + "CSI1_CN", /* GPIO_73, HSEC pin 56 */ + "CSI1_CP", /* GPIO_74, HSEC pin 54 */ + "[CLK1]", /* GPIO_75, HSEC pin 17 */ + "[GPIOD0]", /* GPIO_76 */ + "[GPIOD1]", /* GPIO_77 */ + "BT_RST_N", /* GPIO_78 */ + "EXT_DC_EN", /* GPIO_79 */ + "[PCM_DI]", /* GPIO_80, LSEC pin 22 */ + "[PCM_DO]", /* GPIO_81, LSEC pin 20 */ + "[PCM_CLK]", /* GPIO_82, LSEC pin 18 */ + "[PCM_FS]", /* GPIO_83, LSEC pin 16 */ + "WAKE_BT", /* GPIO_84 */ + "WL_REG_ON", /* GPIO_85 */ + "NC", /* GPIO_86 */ + "NC", /* GPIO_87 */ + "NC", /* GPIO_88 */ + "NC", /* GPIO_89 */ + "NC", /* GPIO_90 */ + "WIFI_WAKE", /* GPIO_91 */ + "BT_WAKE", /* GPIO_92 */ + "NC", /* GPIO_93 */ + "OTG_EN2", /* GPIO_94 */ + "OTG_EN", /* GPIO_95 */ + "DSI_DP3", /* GPIO_96, HSEC pin 45 */ + "DSI_DN3", /* GPIO_97, HSEC pin 47 */ + "DSI_DP1", /* GPIO_98, HSEC pin 33 */ + "DSI_DN1", /* GPIO_99, HSEC pin 35 */ + "DSI_CP", /* GPIO_100, HSEC pin 21 */ + "DSI_CN", /* GPIO_101, HSEC pin 23 */ + "DSI_DP0", /* GPIO_102, HSEC pin 27 */ + "DSI_DN0", /* GPIO_103, HSEC pin 29 */ + "DSI_DP2", /* GPIO_104, HSEC pin 39 */ + "DSI_DN2", /* GPIO_105, HSEC pin 41 */ + "N0_D0", /* GPIO_106 */ + "N0_D1", /* GPIO_107 */ + "N0_D2", /* GPIO_108 */ + "N0_D3", /* GPIO_109 */ + "N0_D4", /* GPIO_110 */ + "N0_D5", /* GPIO_111 */ + "N0_D6", /* GPIO_112 */ + "N0_D7", /* GPIO_113 */ + "N0_DQS", /* GPIO_114 */ + "N0_DQSN", /* GPIO_115 */ + "NC", /* GPIO_116 */ + "NC", /* GPIO_117 */ + "NC", /* GPIO_118 */ + "N0_CEB1", /* GPIO_119 */ + "CARD_DT", /* GPIO_120 */ + "N0_CEB3", /* GPIO_121 */ + "SD_DAT0", /* GPIO_122, HSEC pin 1 */ + "SD_DAT1", /* GPIO_123, HSEC pin 3 */ + "SD_DAT2", /* GPIO_124, HSEC pin 5 */ + "SD_DAT3", /* GPIO_125, HSEC pin 7 */ + "NC", /* GPIO_126 */ + "NC", /* GPIO_127 */ + "[PWR_BTN_N]", /* GPIO_128, LSEC pin 4 */ + "[RST_BTN_N]", /* GPIO_129, LSEC pin 6 */ + "NC", /* GPIO_130 */ + "SD_CMD", /* GPIO_131 */ + "GPIO-L", /* GPIO_132, LSEC pin 34 */ + "GPIO-K", /* GPIO_133, LSEC pin 33 */ + "NC", /* GPIO_134 */ + "SD_SCLK", /* GPIO_135 */ + "NC", /* GPIO_136 */ + "JTAG_TRST", /* GPIO_137 */ + "I2C3_SCLK", /* GPIO_138 */ + "LED2", /* GPIO_139 */ + "LED3", /* GPIO_140 */ + "I2C3_SDATA", /* GPIO_141 */ + "UART3_RX", /* GPIO_142 */ + "UART3_TX", /* GPIO_143 */ + "UART3_RTSB", /* GPIO_144 */ + "UART3_CTSB"; /* GPIO_145 */ + + i2c0_default: i2c0-default { + pinmux { + groups = "i2c0_mfp"; + function = "i2c0"; + }; + pinconf { + pins = "i2c0_sclk", "i2c0_sdata"; + bias-pull-up; + }; + }; + + i2c1_default: i2c1-default { + pinconf { + pins = "i2c1_sclk", "i2c1_sdata"; + bias-pull-up; + }; + }; - uart5_clk: uart5-clk { - compatible = "fixed-clock"; - clock-frequency = <921600>; - #clock-cells = <0>; + i2c2_default: i2c2-default { + pinconf { + pins = "i2c2_sclk", "i2c2_sdata"; + bias-pull-up; + }; }; }; @@ -38,5 +249,4 @@ &uart5 { status = "okay"; - clocks = <&uart5_clk>; }; diff --git a/arch/arm64/boot/dts/actions/s900.dtsi b/arch/arm64/boot/dts/actions/s900.dtsi index 11406f6d3a6d..491ddccc9038 100644 --- a/arch/arm64/boot/dts/actions/s900.dtsi +++ b/arch/arm64/boot/dts/actions/s900.dtsi @@ -1,9 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2017 Andreas Färber - * - * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +#include <dt-bindings/clock/actions,s900-cmu.h> #include <dt-bindings/interrupt-controller/arm-gic.h> / { @@ -88,6 +88,18 @@ #clock-cells = <0>; }; + losc: losc { + compatible = "fixed-clock"; + clock-frequency = <32768>; + #clock-cells = <0>; + }; + + diff24M: diff24M { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; @@ -108,6 +120,7 @@ uart0: serial@e0120000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0120000 0x0 0x2000>; + clocks = <&cmu CLK_UART0>; interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -115,6 +128,7 @@ uart1: serial@e0122000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0122000 0x0 0x2000>; + clocks = <&cmu CLK_UART1>; interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -122,6 +136,7 @@ uart2: serial@e0124000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0124000 0x0 0x2000>; + clocks = <&cmu CLK_UART2>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -129,6 +144,7 @@ uart3: serial@e0126000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0126000 0x0 0x2000>; + clocks = <&cmu CLK_UART3>; interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -136,6 +152,7 @@ uart4: serial@e0128000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe0128000 0x0 0x2000>; + clocks = <&cmu CLK_UART4>; interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -143,6 +160,7 @@ uart5: serial@e012a000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe012a000 0x0 0x2000>; + clocks = <&cmu CLK_UART5>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -150,15 +168,111 @@ uart6: serial@e012c000 { compatible = "actions,s900-uart", "actions,owl-uart"; reg = <0x0 0xe012c000 0x0 0x2000>; + clocks = <&cmu CLK_UART6>; interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; + sps: power-controller@e012e000 { + compatible = "actions,s900-sps"; + reg = <0x0 0xe012e000 0x0 0x2000>; + #power-domain-cells = <1>; + }; + + cmu: clock-controller@e0160000 { + compatible = "actions,s900-cmu"; + reg = <0x0 0xe0160000 0x0 0x1000>; + clocks = <&hosc>, <&losc>; + #clock-cells = <1>; + }; + + i2c0: i2c@e0170000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe0170000 0 0x1000>; + clocks = <&cmu CLK_I2C0>; + interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@e0172000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe0172000 0 0x1000>; + clocks = <&cmu CLK_I2C1>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@e0174000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe0174000 0 0x1000>; + clocks = <&cmu CLK_I2C2>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@e0176000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe0176000 0 0x1000>; + clocks = <&cmu CLK_I2C3>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c4: i2c@e0178000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe0178000 0 0x1000>; + clocks = <&cmu CLK_I2C4>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c5: i2c@e017a000 { + compatible = "actions,s900-i2c"; + reg = <0 0xe017a000 0 0x1000>; + clocks = <&cmu CLK_I2C5>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pinctrl: pinctrl@e01b0000 { + compatible = "actions,s900-pinctrl"; + reg = <0x0 0xe01b0000 0x0 0x1000>; + clocks = <&cmu CLK_GPIO>; + gpio-controller; + gpio-ranges = <&pinctrl 0 0 146>; + #gpio-cells = <2>; + }; + timer: timer@e0228000 { compatible = "actions,s900-timer"; reg = <0x0 0xe0228000 0x0 0x8000>; interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "timer1"; }; + + dma: dma-controller@e0260000 { + compatible = "actions,s900-dma"; + reg = <0x0 0xe0260000 0x0 0x1000>; + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + #dma-cells = <1>; + dma-channels = <12>; + dma-requests = <46>; + clocks = <&cmu CLK_DMAC>; + }; }; }; diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 9ffa7a038791..8d4f97f279e0 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -4,10 +4,13 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-lts.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinebook.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb @@ -15,4 +18,5 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts index eac4793c8502..6cb2b7f0c817 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts @@ -203,7 +203,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts index 094cfed13df9..ef1c90401bb2 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts @@ -60,6 +60,17 @@ stdout-path = "serial0:115200n8"; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + leds { compatible = "gpio-leds"; @@ -86,6 +97,10 @@ }; }; +&de { + status = "okay"; +}; + &ehci0 { status = "okay"; }; @@ -103,6 +118,17 @@ status = "okay"; }; +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -151,7 +177,7 @@ &mmc2 { pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins>; + pinctrl-0 = <&mmc2_pins>, <&mmc2_ds_pin>; vmmc-supply = <®_dcdc1>; bus-width = <8>; non-removable; @@ -302,7 +328,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts index 98dbff19f5cc..31884dbc8838 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts @@ -51,12 +51,44 @@ compatible = "friendlyarm,nanopi-a64", "allwinner,sun50i-a64"; aliases { + ethernet0 = &emac; serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + blue { + label = "nanopi-a64:blue:status"; + gpios = <&pio 3 24 GPIO_ACTIVE_LOW>; /* PD24 */ + }; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rtc 1>; + clock-names = "ext_clock"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + }; +}; + +&de { + status = "okay"; }; &ehci0 { @@ -67,6 +99,26 @@ status = "okay"; }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_dcdc1>; + status = "okay"; +}; + +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + /* i2c1 connected with gpio headers like pine64, bananapi */ &i2c1 { pinctrl-names = "default"; @@ -78,6 +130,13 @@ bias-pull-up; }; +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; @@ -88,6 +147,24 @@ status = "okay"; }; +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <®_dcdc1>; + vqmmc-supply = <®_dldo4>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; + + rtl8189etv: wifi@1 { + reg = <1>; + interrupt-parent = <&r_pio>; + interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* PL3 */ + interrupt-names = "host-wake"; + }; +}; + &ohci0 { status = "okay"; }; @@ -125,9 +202,9 @@ ®_dcdc1 { regulator-always-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-name = "vcc-3v"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-3v3"; }; ®_dcdc2 { @@ -201,7 +278,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts index 3f531393eaee..f7a4bccaa5d4 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts @@ -51,6 +51,7 @@ compatible = "olimex,a64-olinuxino", "allwinner,sun50i-a64"; aliases { + ethernet0 = &emac; serial0 = &uart0; }; @@ -58,12 +59,74 @@ stdout-path = "serial0:115200n8"; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + reg_usb1_vbus: usb1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb1-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + enable-active-high; + gpio = <&pio 6 9 GPIO_ACTIVE_HIGH>; /* PG9 */ + status = "okay"; + }; + wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ }; }; +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_dcdc1>; + allwinner,tx-delay-ps = <600>; + status = "okay"; +}; + +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; @@ -92,6 +155,14 @@ }; }; +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + &r_rsb { status = "okay"; @@ -100,6 +171,7 @@ reg = <0x3a3>; interrupt-parent = <&r_intc>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */ }; }; @@ -142,10 +214,14 @@ /* DCDC3 is polyphased with DCDC2 */ +/* + * The board uses DDR3L DRAM chips. 1.36V is the closest to the nominal + * 1.35V that the PMIC can drive. + */ ®_dcdc5 { regulator-always-on; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; + regulator-min-microvolt = <1360000>; + regulator-max-microvolt = <1360000>; regulator-name = "vcc-ddr3"; }; @@ -180,6 +256,11 @@ regulator-name = "vcc-wifi-io"; }; +®_drivevbus { + regulator-name = "usb0-vbus"; + status = "okay"; +}; + ®_eldo1 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -220,6 +301,18 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { status = "okay"; + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts index 1221764f5719..b0c64f75792c 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts @@ -1,5 +1,6 @@ /* * Copyright (C) 2017 Jagan Teki <jteki@openedev.com> + * Copyright (C) 2017-2018 Samuel Holland <samuel@sholland.org> * * This file is dual-licensed: you can use it either under the terms * of the GPL or the X11 license, at your option. Note that this dual @@ -51,23 +52,127 @@ compatible = "xunlong,orangepi-win", "allwinner,sun50i-a64"; aliases { + ethernet0 = &emac; serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; }; chosen { stdout-path = "serial0:115200n8"; }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + status { + label = "orangepi:green:status"; + gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + enable-active-high; + gpio = <&pio 3 14 GPIO_ACTIVE_HIGH>; /* PD14 */ + status = "okay"; + }; + + reg_usb1_vbus: usb1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb1-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + enable-active-high; + gpio = <&pio 3 7 GPIO_ACTIVE_HIGH>; /* PD7 */ + status = "okay"; + }; + + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */ + }; +}; + +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; }; &ehci1 { status = "okay"; }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_gmac_3v3>; + status = "okay"; +}; + +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; vmmc-supply = <®_dcdc1>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + disable-wp; + bus-width = <4>; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <®_dldo2>; + vqmmc-supply = <®_dldo4>; + mmc-pwrseq = <&wifi_pwrseq>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&ohci0 { status = "okay"; }; @@ -89,9 +194,8 @@ #include "axp803.dtsi" ®_aldo1 { - regulator-always-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; regulator-name = "afvcc-csi"; }; @@ -163,12 +267,23 @@ regulator-name = "vcc-wifi-io"; }; +®_drivevbus { + regulator-name = "usb0-vbus"; + status = "okay"; +}; + ®_eldo1 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-name = "cpvdd"; }; +®_eldo3 { + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1800000>; + regulator-name = "dvdd-csi"; +}; + ®_fldo1 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; @@ -195,13 +310,61 @@ vcc-hdmi-supply = <®_dldo1>; }; +&spi0 { + status = "okay"; + + spi-flash@0 { + compatible = "mxicy,mx25l1606e", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + m25p,fast-read; + status = "okay"; + }; +}; + +/* On debug connector */ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; -&usbphy { +/* Bluetooth */ +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; status = "okay"; }; +/* On Pi-2 connector, RTS/CTS optional */ +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; +}; + +/* On Pi-2 connector, RTS/CTS optional */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + status = "disabled"; +}; + +/* On Pi-2 connector (labeled for SPI1), RTS/CTS optional */ +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins>; + status = "disabled"; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts new file mode 100644 index 000000000000..72d6961dc312 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + * + * Copyright (c) 2018 ARM Ltd. + */ + +#include "sun50i-a64-sopine-baseboard.dts" + +/ { + model = "Pine64 LTS"; + compatible = "pine64,pine64-lts", "allwinner,sun50i-r18", + "allwinner,sun50i-a64"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts index 1b9b92e541d2..c077b6c1f458 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts @@ -62,6 +62,21 @@ chosen { stdout-path = "serial0:115200n8"; }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; +}; + +&de { + status = "okay"; }; &ehci0 { @@ -82,6 +97,17 @@ }; +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -241,7 +267,7 @@ /* On Exp and Euler connectors */ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 897e60cbe38d..77fac84797e9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -80,8 +80,7 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; vmmc-supply = <®_dcdc1>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; disable-wp; bus-width = <4>; status = "okay"; @@ -104,7 +103,7 @@ &mmc2 { pinctrl-names = "default"; - pinctrl-0 = <&mmc2_pins>; + pinctrl-0 = <&mmc2_pins>, <&mmc2_ds_pin>; vmmc-supply = <®_dcdc1>; vqmmc-supply = <®_eldo1>; bus-width = <8>; @@ -143,7 +142,7 @@ &r_i2c { clock-frequency = <100000>; pinctrl-names = "default"; - pinctrl-0 = <&r_i2c_pins_a>; + pinctrl-0 = <&r_i2c_pl89_pins>; status = "okay"; }; @@ -270,7 +269,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts index c21f2331add6..53fcc9098df3 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts @@ -61,6 +61,17 @@ stdout-path = "serial0:115200n8"; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + reg_vcc1v8: vcc1v8 { compatible = "regulator-fixed"; regulator-name = "vcc1v8"; @@ -69,6 +80,10 @@ }; }; +&de { + status = "okay"; +}; + &ehci0 { status = "okay"; }; @@ -86,6 +101,17 @@ status = "okay"; }; +&hdmi { + hvcc-supply = <®_dldo1>; + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + &mdio { ext_rgmii_phy: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; @@ -140,7 +166,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts index 81f8e0098699..c455b24dd079 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts @@ -260,7 +260,7 @@ &uart0 { pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; + pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index d3daf90a8715..f3a66f888205 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -88,6 +88,7 @@ device_type = "cpu"; reg = <0>; enable-method = "psci"; + next-level-cache = <&L2>; }; cpu1: cpu@1 { @@ -95,6 +96,7 @@ device_type = "cpu"; reg = <1>; enable-method = "psci"; + next-level-cache = <&L2>; }; cpu2: cpu@2 { @@ -102,6 +104,7 @@ device_type = "cpu"; reg = <2>; enable-method = "psci"; + next-level-cache = <&L2>; }; cpu3: cpu@3 { @@ -109,7 +112,20 @@ device_type = "cpu"; reg = <3>; enable-method = "psci"; + next-level-cache = <&L2>; }; + + L2: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + + de: display-engine { + compatible = "allwinner,sun50i-a64-display-engine"; + allwinner,pipelines = <&mixer0>, + <&mixer1>; + status = "disabled"; }; osc24M: osc24M_clk { @@ -194,6 +210,52 @@ #clock-cells = <1>; #reset-cells = <1>; }; + + mixer0: mixer@100000 { + compatible = "allwinner,sun50i-a64-de2-mixer-0"; + reg = <0x100000 0x100000>; + clocks = <&display_clocks CLK_BUS_MIXER0>, + <&display_clocks CLK_MIXER0>; + clock-names = "bus", + "mod"; + resets = <&display_clocks RST_MIXER0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mixer0_out: port@1 { + reg = <1>; + + mixer0_out_tcon0: endpoint { + remote-endpoint = <&tcon0_in_mixer0>; + }; + }; + }; + }; + + mixer1: mixer@200000 { + compatible = "allwinner,sun50i-a64-de2-mixer-1"; + reg = <0x200000 0x100000>; + clocks = <&display_clocks CLK_BUS_MIXER1>, + <&display_clocks CLK_MIXER1>; + clock-names = "bus", + "mod"; + resets = <&display_clocks RST_MIXER1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mixer1_out: port@1 { + reg = <1>; + + mixer1_out_tcon1: endpoint { + remote-endpoint = <&tcon1_in_mixer1>; + }; + }; + }; + }; }; syscon: syscon@1c00000 { @@ -228,6 +290,75 @@ #dma-cells = <1>; }; + tcon0: lcd-controller@1c0c000 { + compatible = "allwinner,sun50i-a64-tcon-lcd", + "allwinner,sun8i-a83t-tcon-lcd"; + reg = <0x01c0c000 0x1000>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>; + clock-names = "ahb", "tcon-ch0"; + clock-output-names = "tcon-pixel-clock"; + resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>; + reset-names = "lcd", "lvds"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + tcon0_in: port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + tcon0_in_mixer0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mixer0_out_tcon0>; + }; + }; + + tcon0_out: port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + }; + }; + + tcon1: lcd-controller@1c0d000 { + compatible = "allwinner,sun50i-a64-tcon-tv", + "allwinner,sun8i-a83t-tcon-tv"; + reg = <0x01c0d000 0x1000>; + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_TCON1>, <&ccu CLK_TCON1>; + clock-names = "ahb", "tcon-ch1"; + resets = <&ccu RST_BUS_TCON1>; + reset-names = "lcd"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + tcon1_in: port@0 { + reg = <0>; + + tcon1_in_mixer1: endpoint { + remote-endpoint = <&mixer1_out_tcon1>; + }; + }; + + tcon1_out: port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + tcon1_out_hdmi: endpoint@1 { + reg = <1>; + remote-endpoint = <&hdmi_in_tcon1>; + }; + }; + }; + }; + mmc0: mmc@1c0f000 { compatible = "allwinner,sun50i-a64-mmc"; reg = <0x01c0f000 0x1000>; @@ -270,6 +401,11 @@ #size-cells = <0>; }; + sid: eeprom@1c14000 { + compatible = "allwinner,sun50i-a64-sid"; + reg = <0x1c14000 0x400>; + }; + usb_otg: usb@1c19000 { compatible = "allwinner,sun8i-a33-musb"; reg = <0x01c19000 0x0400>; @@ -399,7 +535,7 @@ }; mmc2_pins: mmc2-pins { - pins = "PC1", "PC5", "PC6", "PC8", "PC9", + pins = "PC5", "PC6", "PC8", "PC9", "PC10","PC11", "PC12", "PC13", "PC14", "PC15", "PC16"; function = "mmc2"; @@ -407,6 +543,13 @@ bias-pull-up; }; + mmc2_ds_pin: mmc2-ds-pin { + pins = "PC1"; + function = "mmc2"; + drive-strength = <30>; + bias-pull-up; + }; + pwm_pin: pwm_pin { pins = "PD22"; function = "pwm"; @@ -442,7 +585,7 @@ function = "spi1"; }; - uart0_pins_a: uart0 { + uart0_pb_pins: uart0-pb-pins { pins = "PB8", "PB9"; function = "uart0"; }; @@ -686,6 +829,50 @@ status = "disabled"; }; + hdmi: hdmi@1ee0000 { + compatible = "allwinner,sun50i-a64-dw-hdmi", + "allwinner,sun8i-a83t-dw-hdmi"; + reg = <0x01ee0000 0x10000>; + reg-io-width = <1>; + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>, + <&ccu CLK_HDMI>; + clock-names = "iahb", "isfr", "tmds"; + resets = <&ccu RST_BUS_HDMI1>; + reset-names = "ctrl"; + phys = <&hdmi_phy>; + phy-names = "hdmi-phy"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + hdmi_in: port@0 { + reg = <0>; + + hdmi_in_tcon1: endpoint { + remote-endpoint = <&tcon1_out_hdmi>; + }; + }; + + hdmi_out: port@1 { + reg = <1>; + }; + }; + }; + + hdmi_phy: hdmi-phy@1ef0000 { + compatible = "allwinner,sun50i-a64-hdmi-phy"; + reg = <0x01ef0000 0x10000>; + clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>, + <&ccu 7>; + clock-names = "bus", "mod", "pll-0"; + resets = <&ccu RST_BUS_HDMI0>; + reset-names = "phy"; + #phy-cells = <0>; + }; + rtc: rtc@1f00000 { compatible = "allwinner,sun6i-a31-rtc"; reg = <0x01f00000 0x54>; @@ -749,7 +936,7 @@ interrupt-controller; #interrupt-cells = <3>; - r_i2c_pins_a: i2c-a { + r_i2c_pl89_pins: r-i2c-pl89-pins { pins = "PL8", "PL9"; function = "s_i2c"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts new file mode 100644 index 000000000000..2e2b14c0ae75 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus-v1.2.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org> + +/dts-v1/; +#include "sun50i-h5.dtsi" +#include <arm/sunxi-bananapi-m2-plus-v1.2.dtsi> + +/ { + model = "Banana Pi BPI-M2-Plus v1.2 H5"; + compatible = "bananapi,bpi-m2-plus-v1.2", "allwinner,sun50i-h5"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts new file mode 100644 index 000000000000..77661006dfba --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-bananapi-m2-plus.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org> + +/dts-v1/; +#include "sun50i-h5.dtsi" +#include <arm/sunxi-bananapi-m2-plus.dtsi> + +/ { + model = "Banana Pi BPI-M2-Plus H5"; + compatible = "sinovoip,bpi-m2-plus", "allwinner,sun50i-h5"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi index 62d646baac3c..b41dc1aab67d 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi @@ -92,6 +92,49 @@ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; }; + + soc { + mali: gpu@1e80000 { + compatible = "allwinner,sun50i-h5-mali", "arm,mali-450"; + reg = <0x01e80000 0x30000>; + /* + * While the datasheet lists an interrupt for the + * PMU, the actual silicon does not have the PMU + * block. Reads all return zero, and writes are + * ignored. + */ + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 97 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 98 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "gp", + "gpmmu", + "pp", + "pp0", + "ppmmu0", + "pp1", + "ppmmu1", + "pp2", + "ppmmu2", + "pp3", + "ppmmu3", + "pmu"; + clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>; + clock-names = "bus", "core"; + resets = <&ccu RST_BUS_GPU>; + + assigned-clocks = <&ccu CLK_GPU>; + assigned-clock-rates = <384000000>; + }; + }; }; &ccu { diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts new file mode 100644 index 000000000000..0612c19cd994 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (C) 2018 Amarula Solutions + * Author: Jagan Teki <jagan@amarulasolutions.com> + */ + +/dts-v1/; + +#include "sun50i-h6.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "OrangePi One Plus"; + compatible = "xunlong,orangepi-one-plus", "allwinner,sun50i-h6"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + vmmc-supply = <®_cldo1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; + bus-width = <4>; + status = "okay"; +}; + +&r_i2c { + status = "okay"; + + axp805: pmic@36 { + compatible = "x-powers,axp805", "x-powers,axp806"; + reg = <0x36>; + interrupt-parent = <&r_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + x-powers,self-working-mode; + + regulators { + reg_aldo1: aldo1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pl"; + }; + + reg_aldo2: aldo2 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-ac200"; + }; + + reg_aldo3: aldo3 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc25-dram"; + }; + + reg_bldo1: bldo1 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-bias-pll"; + }; + + reg_bldo2: bldo2 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-efuse-pcie-hdmi-io"; + }; + + reg_bldo3: bldo3 { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc-dcxoio"; + }; + + bldo4 { + /* unused */ + }; + + reg_cldo1: cldo1 { + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-3v3"; + }; + + reg_cldo2: cldo2 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi-1"; + }; + + reg_cldo3: cldo3 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-wifi-2"; + }; + + reg_dcdca: dcdca { + regulator-always-on; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; + regulator-name = "vdd-cpu"; + }; + + reg_dcdcc: dcdcc { + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; + regulator-name = "vdd-gpu"; + }; + + reg_dcdcd: dcdcd { + regulator-always-on; + regulator-min-microvolt = <960000>; + regulator-max-microvolt = <960000>; + regulator-name = "vdd-sys"; + }; + + reg_dcdce: dcdce { + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vcc-dram"; + }; + + sw { + /* unused */ + }; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index cfa5fffcf62b..040828d2e2c0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -92,6 +92,29 @@ #size-cells = <1>; ranges; + syscon: syscon@3000000 { + compatible = "allwinner,sun50i-h6-system-control", + "allwinner,sun50i-a64-system-control"; + reg = <0x03000000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram_c: sram@28000 { + compatible = "mmio-sram"; + reg = <0x00028000 0x1e000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00028000 0x1e000>; + + de2_sram: sram-section@0 { + compatible = "allwinner,sun50i-h6-sram-c", + "allwinner,sun50i-a64-sram-c"; + reg = <0x0000 0x1e000>; + }; + }; + }; + ccu: clock@3001000 { compatible = "allwinner,sun50i-h6-ccu"; reg = <0x03001000 0x1000>; diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index 8a2641c742ae..8253a1a9e985 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi @@ -341,7 +341,7 @@ sysmgr: sysmgr@ffd12000 { compatible = "altr,sys-mgr", "syscon"; - reg = <0xffd12000 0x1000>; + reg = <0xffd12000 0x228>; }; /* Local timer */ @@ -473,16 +473,51 @@ status = "disabled"; }; + sdr: sdr@f8011100 { + compatible = "altr,sdr-ctl", "syscon"; + reg = <0xf8011100 0xc0>; + }; + eccmgr { - compatible = "altr,socfpga-s10-ecc-manager"; + compatible = "altr,socfpga-a10-ecc-manager"; + altr,sysmgr-syscon = <&sysmgr>; + #address-cells = <1>; + #size-cells = <1>; interrupts = <0 15 4>, <0 95 4>; interrupt-controller; #interrupt-cells = <2>; + ranges; sdramedac { compatible = "altr,sdram-edac-s10"; + altr,sdr-syscon = <&sdr>; interrupts = <16 4>, <48 4>; }; + + usb0-ecc@ff8c4000 { + compatible = "altr,socfpga-usb-ecc"; + reg = <0xff8c4000 0x100>; + altr,ecc-parent = <&usb0>; + interrupts = <2 4>, + <34 4>; + }; + + emac0-rx-ecc@ff8c0000 { + compatible = "altr,socfpga-eth-mac-ecc"; + reg = <0xff8c0000 0x100>; + altr,ecc-parent = <&gmac0>; + interrupts = <4 4>, + <36 4>; + }; + + emac0-tx-ecc@ff8c0400 { + compatible = "altr,socfpga-eth-mac-ecc"; + reg = <0xff8c0400 0x100>; + altr,ecc-parent = <&gmac0>; + interrupts = <5 4>, + <37 4>; + }; + }; qspi: spi@ff8d2000 { diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts index 7c661753bfaf..2e3863ee12b3 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts @@ -21,6 +21,9 @@ aliases { serial0 = &uart0; + ethernet0 = &gmac0; + ethernet1 = &gmac1; + ethernet2 = &gmac2; }; chosen { @@ -124,6 +127,8 @@ &i2c1 { status = "okay"; clock-frequency = <100000>; + i2c-sda-falling-time-ns = <890>; /* hcnt */ + i2c-sdl-falling-time-ns = <890>; /* lcnt */ adc@14 { compatible = "lltc,ltc2497"; diff --git a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi index 125f4deb52fe..b664e7af74eb 100644 --- a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi +++ b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi @@ -107,7 +107,7 @@ clock-names = "uartclk", "apb_pclk"; }; - spi0: ssp@e1020000 { + spi0: spi@e1020000 { status = "disabled"; compatible = "arm,pl022", "arm,primecell"; reg = <0 0xe1020000 0 0x1000>; @@ -117,7 +117,7 @@ clock-names = "apb_pclk"; }; - spi1: ssp@e1030000 { + spi1: spi@e1030000 { status = "disabled"; compatible = "arm,pl022", "arm,primecell"; reg = <0 0xe1030000 0 0x1000>; diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index a97c0e2d7bc6..c31f29d660de 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts index d5c01427a5ca..18778ada7bd3 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts +++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts @@ -60,6 +60,55 @@ serial1 = &uart_A; }; + linein: audio-codec@0 { + #sound-dai-cells = <0>; + compatible = "everest,es7241"; + VDDA-supply = <&vcc_3v3>; + VDDP-supply = <&vcc_3v3>; + VDDD-supply = <&vcc_3v3>; + status = "okay"; + sound-name-prefix = "Linein"; + }; + + lineout: audio-codec@1 { + #sound-dai-cells = <0>; + compatible = "everest,es7154"; + VDD-supply = <&vcc_3v3>; + PVDD-supply = <&vcc_5v>; + status = "okay"; + sound-name-prefix = "Lineout"; + }; + + spdif_dit: audio-codec@2 { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + status = "okay"; + sound-name-prefix = "DIT"; + }; + + dmics: audio-codec@3 { + #sound-dai-cells = <0>; + compatible = "dmic-codec"; + num-channels = <7>; + wakeup-delay-ms = <50>; + status = "okay"; + sound-name-prefix = "MIC"; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; + }; + main_12v: regulator-main_12v { compatible = "regulator-fixed"; regulator-name = "12V"; @@ -68,15 +117,26 @@ regulator-always-on; }; - vddio_boot: regulator-vddio_boot { + vcc_3v3: regulator-vcc_3v3 { compatible = "regulator-fixed"; - regulator-name = "VDDIO_BOOT"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; vin-supply = <&vddao_3v3>; 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>; + + gpio = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + vddao_3v3: regulator-vddao_3v3 { compatible = "regulator-fixed"; regulator-name = "VDDAO_3V3"; @@ -95,26 +155,15 @@ regulator-always-on; }; - vcc_3v3: regulator-vcc_3v3 { + vddio_boot: regulator-vddio_boot { compatible = "regulator-fixed"; - regulator-name = "VCC_3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; vin-supply = <&vddao_3v3>; 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>; - - gpio = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - usb_pwr: regulator-usb_pwr { compatible = "regulator-fixed"; regulator-name = "USB_PWR"; @@ -126,11 +175,6 @@ enable-active-high; }; - emmc_pwrseq: emmc-pwrseq { - compatible = "mmc-pwrseq-emmc"; - reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; - }; - sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&gpio GPIOX_7 GPIO_ACTIVE_LOW>; @@ -138,13 +182,6 @@ clock-names = "ext_clock"; }; - wifi32k: wifi32k { - compatible = "pwm-clock"; - #clock-cells = <0>; - clock-frequency = <32768>; - pwms = <&pwm_ab 0 30518 0>; /* PWM_A at 32.768KHz */ - }; - speaker-leds { compatible = "gpio-leds"; @@ -179,30 +216,129 @@ }; }; - linein: audio-codec@0 { - #sound-dai-cells = <0>; - compatible = "everest,es7241"; - VDDA-supply = <&vcc_3v3>; - VDDP-supply = <&vcc_3v3>; - VDDD-supply = <&vcc_3v3>; + sound { + compatible = "amlogic,axg-sound-card"; + model = "AXG-S400"; + audio-aux-devs = <&tdmin_a>, <&tdmin_b>, <&tdmin_c>, + <&tdmin_lb>, <&tdmout_c>; + audio-widgets = "Line", "Lineout", + "Line", "Linein", + "Speaker", "Speaker1 Left", + "Speaker", "Speaker1 Right"; + audio-routing = "TDMOUT_C IN 0", "FRDDR_A OUT 2", + "SPDIFOUT IN 0", "FRDDR_A OUT 3", + "TDMOUT_C IN 1", "FRDDR_B OUT 2", + "SPDIFOUT IN 1", "FRDDR_B OUT 3", + "TDMOUT_C IN 2", "FRDDR_C OUT 2", + "SPDIFOUT IN 2", "FRDDR_C OUT 3", + "TDM_C Playback", "TDMOUT_C OUT", + "TDMIN_A IN 2", "TDM_C Capture", + "TDMIN_A IN 5", "TDM_C Loopback", + "TDMIN_B IN 2", "TDM_C Capture", + "TDMIN_B IN 5", "TDM_C Loopback", + "TDMIN_C IN 2", "TDM_C Capture", + "TDMIN_C IN 5", "TDM_C Loopback", + "TDMIN_LB IN 2", "TDM_C Loopback", + "TDMIN_LB IN 5", "TDM_C Capture", + "TODDR_A IN 0", "TDMIN_A OUT", + "TODDR_B IN 0", "TDMIN_A OUT", + "TODDR_C IN 0", "TDMIN_A OUT", + "TODDR_A IN 1", "TDMIN_B OUT", + "TODDR_B IN 1", "TDMIN_B OUT", + "TODDR_C IN 1", "TDMIN_B OUT", + "TODDR_A IN 2", "TDMIN_C OUT", + "TODDR_B IN 2", "TDMIN_C OUT", + "TODDR_C IN 2", "TDMIN_C OUT", + "TODDR_A IN 4", "PDM Capture", + "TODDR_B IN 4", "PDM Capture", + "TODDR_C IN 4", "PDM Capture", + "TODDR_A IN 6", "TDMIN_LB OUT", + "TODDR_B IN 6", "TDMIN_LB OUT", + "TODDR_C IN 6", "TDMIN_LB OUT", + "Lineout", "Lineout AOUTL", + "Lineout", "Lineout AOUTR", + "Speaker1 Left", "SPK1 OUT_A", + "Speaker1 Left", "SPK1 OUT_B", + "Speaker1 Right", "SPK1 OUT_C", + "Speaker1 Right", "SPK1 OUT_D", + "Linein AINL", "Linein", + "Linein AINR", "Linein"; + assigned-clocks = <&clkc CLKID_HIFI_PLL>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>; + assigned-clock-parents = <0>, <0>, <0>; + assigned-clock-rates = <589824000>, + <270950400>, + <393216000>; status = "okay"; - sound-name-prefix = "Linein"; - }; - lineout: audio-codec@1 { - #sound-dai-cells = <0>; - compatible = "everest,es7154"; - VDD-supply = <&vcc_3v3>; - PVDD-supply = <&vcc_5v>; - status = "okay"; - sound-name-prefix = "Lineout"; + dai-link@0 { + sound-dai = <&frddr_a>; + }; + + dai-link@1 { + sound-dai = <&frddr_b>; + }; + + dai-link@2 { + sound-dai = <&frddr_c>; + }; + + dai-link@3 { + sound-dai = <&toddr_a>; + }; + + dai-link@4 { + sound-dai = <&toddr_b>; + }; + + dai-link@5 { + sound-dai = <&toddr_c>; + }; + + dai-link@6 { + sound-dai = <&tdmif_c>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-2 = <1 1>; + dai-tdm-slot-rx-mask-1 = <1 1>; + mclk-fs = <256>; + + codec@0 { + sound-dai = <&lineout>; + }; + + codec@1 { + sound-dai = <&speaker_amp1>; + }; + + codec@2 { + sound-dai = <&linein>; + }; + + }; + + dai-link@7 { + sound-dai = <&spdifout>; + + codec { + sound-dai = <&spdif_dit>; + }; + }; + + dai-link@8 { + sound-dai = <&pdm>; + + codec { + sound-dai = <&dmics>; + }; + }; }; - spdif_dit: audio-codec@2 { - #sound-dai-cells = <0>; - compatible = "linux,spdif-dit"; - status = "okay"; - sound-name-prefix = "DIT"; + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ab 0 30518 0>; /* PWM_A at 32.768KHz */ }; }; @@ -226,16 +362,16 @@ }; }; -&uart_A { +&frddr_a { status = "okay"; - pinctrl-0 = <&uart_a_pins>; - pinctrl-names = "default"; }; -&uart_AO { +&frddr_b { + status = "okay"; +}; + +&frddr_c { status = "okay"; - pinctrl-0 = <&uart_ao_a_pins>; - pinctrl-names = "default"; }; &ir { @@ -260,6 +396,7 @@ PVDD_B-supply = <&main_12v>; PVDD_C-supply = <&main_12v>; PVDD_D-supply = <&main_12v>; + sound-name-prefix = "SPK1"; }; }; @@ -277,30 +414,22 @@ }; }; +&pdm { + pinctrl-0 = <&pdm_dclk_a14_pins>, <&pdm_din0_pins>, + <&pdm_din1_pins>, <&pdm_din2_pins>, <&pdm_din3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + &pwm_ab { status = "okay"; pinctrl-0 = <&pwm_a_x20_pins>; pinctrl-names = "default"; }; -/* emmc storage */ -&sd_emmc_c { +&saradc { status = "okay"; - pinctrl-0 = <&emmc_pins>; - pinctrl-1 = <&emmc_clk_gate_pins>; - pinctrl-names = "default", "clk-gate"; - - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <180000000>; - non-removable; - disable-wp; - mmc-ddr-1_8v; - mmc-hs200-1_8v; - - vmmc-supply = <&vcc_3v3>; - vqmmc-supply = <&vddio_boot>; + vref-supply = <&vddio_ao18>; }; /* wifi module */ @@ -330,7 +459,96 @@ }; }; -&saradc { +/* emmc storage */ +&sd_emmc_c { + status = "disabled"; + pinctrl-0 = <&emmc_pins>; + pinctrl-1 = <&emmc_clk_gate_pins>; + pinctrl-names = "default", "clk-gate"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <180000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +&spdifout { + pinctrl-0 = <&spdif_out_a20_pins>; + pinctrl-names = "default"; status = "okay"; - vref-supply = <&vddio_ao18>; +}; + +&tdmif_a { + pinctrl-0 = <&tdma_sclk_pins>, <&tdma_fs_pins>, + <&tdma_din0_pins>, <&tdma_dout0_x15_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tdmif_b { + pinctrl-0 = <&tdmb_sclk_pins>, <&tdmb_fs_pins>, + <&tdmb_din3_pins>, <&mclk_b_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tdmif_c { + pinctrl-0 = <&tdmc_sclk_pins>, <&tdmc_fs_pins>, + <&tdmc_din1_pins>, <&tdmc_dout2_pins>, + <&mclk_c_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tdmin_a { + status = "okay"; +}; + +&tdmin_b { + status = "okay"; +}; + +&tdmin_c { + status = "okay"; +}; + +&tdmin_lb { + status = "okay"; +}; + +&tdmout_c { + status = "okay"; +}; + +&toddr_a { + status = "okay"; +}; + +&toddr_b { + status = "okay"; +}; + +&toddr_c { + status = "okay"; +}; + +&uart_A { + status = "okay"; + pinctrl-0 = <&uart_a_pins>; + pinctrl-names = "default"; +}; + +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi index c518130e5ce7..df017dbd2e57 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi @@ -3,13 +3,14 @@ * Copyright (c) 2017 Amlogic, Inc. All rights reserved. */ -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/interrupt-controller/irq.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/axg-aoclkc.h> #include <dt-bindings/clock/axg-audio-clkc.h> #include <dt-bindings/clock/axg-clkc.h> -#include <dt-bindings/clock/axg-aoclkc.h> +#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/meson-axg-gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h> #include <dt-bindings/reset/amlogic,meson-axg-reset.h> / { @@ -19,22 +20,53 @@ #address-cells = <2>; #size-cells = <2>; - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; + tdmif_a: audio-controller@0 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_A"; + clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>, + <&clkc_audio AUD_CLKID_MST_A_SCLK>, + <&clkc_audio AUD_CLKID_MST_A_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; - /* 16 MiB reserved for Hardware ROM Firmware */ - hwrom_reserved: hwrom@0 { - reg = <0x0 0x0 0x0 0x1000000>; - no-map; - }; + tdmif_b: audio-controller@1 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_B"; + clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>, + <&clkc_audio AUD_CLKID_MST_B_SCLK>, + <&clkc_audio AUD_CLKID_MST_B_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; - /* Alternate 3 MiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@5000000 { - reg = <0x0 0x05000000 0x0 0x300000>; - no-map; - }; + tdmif_c: audio-controller@2 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0>; + sound-name-prefix = "TDM_C"; + clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>, + <&clkc_audio AUD_CLKID_MST_C_SCLK>, + <&clkc_audio AUD_CLKID_MST_C_LRCLK>; + clock-names = "mclk", "sclk", "lrclk"; + status = "disabled"; + }; + + ao_alt_xtal: ao_alt_xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <32000000>; + clock-output-names = "ao_alt_xtal"; + #clock-cells = <0>; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; }; cpus { @@ -78,77 +110,27 @@ }; }; - arm-pmu { - compatible = "arm,cortex-a53-pmu"; - interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; - }; - psci { compatible = "arm,psci-1.0"; method = "smc"; }; - tdmif_a: audio-controller@0 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_A"; - clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>, - <&clkc_audio AUD_CLKID_MST_A_SCLK>, - <&clkc_audio AUD_CLKID_MST_A_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - - tdmif_b: audio-controller@1 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_B"; - clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>, - <&clkc_audio AUD_CLKID_MST_B_SCLK>, - <&clkc_audio AUD_CLKID_MST_B_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - - tdmif_c: audio-controller@2 { - compatible = "amlogic,axg-tdm-iface"; - #sound-dai-cells = <0>; - sound-name-prefix = "TDM_C"; - clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>, - <&clkc_audio AUD_CLKID_MST_C_SCLK>, - <&clkc_audio AUD_CLKID_MST_C_LRCLK>; - clock-names = "mclk", "sclk", "lrclk"; - status = "disabled"; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <GIC_PPI 13 - (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 14 - (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 11 - (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 10 - (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>; - }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; + /* 16 MiB reserved for Hardware ROM Firmware */ + hwrom_reserved: hwrom@0 { + reg = <0x0 0x0 0x0 0x1000000>; + no-map; + }; - ao_alt_xtal: ao_alt_xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <32000000>; - clock-output-names = "ao_alt_xtal"; - #clock-cells = <0>; + /* Alternate 3 MiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@5000000 { + reg = <0x0 0x05000000 0x0 0x300000>; + no-map; + }; }; soc { @@ -157,310 +139,10 @@ #size-cells = <2>; ranges; - apb: apb@ffe00000 { - compatible = "simple-bus"; - reg = <0x0 0xffe00000 0x0 0x200000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x200000>; - - sd_emmc_b: sd@5000 { - compatible = "amlogic,meson-axg-mmc"; - reg = <0x0 0x5000 0x0 0x800>; - interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>; - status = "disabled"; - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_CLK0>, - <&clkc CLKID_FCLK_DIV2>; - clock-names = "core", "clkin0", "clkin1"; - resets = <&reset RESET_SD_EMMC_B>; - }; - - sd_emmc_c: mmc@7000 { - compatible = "amlogic,meson-axg-mmc"; - reg = <0x0 0x7000 0x0 0x800>; - interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>; - status = "disabled"; - clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_CLK0>, - <&clkc CLKID_FCLK_DIV2>; - clock-names = "core", "clkin0", "clkin1"; - resets = <&reset RESET_SD_EMMC_C>; - }; - }; - - audio: bus@ff642000 { - compatible = "simple-bus"; - reg = <0x0 0xff642000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; - - clkc_audio: clock-controller@0 { - compatible = "amlogic,axg-audio-clkc"; - reg = <0x0 0x0 0x0 0xb4>; - #clock-cells = <1>; - - clocks = <&clkc CLKID_AUDIO>, - <&clkc CLKID_MPLL0>, - <&clkc CLKID_MPLL1>, - <&clkc CLKID_MPLL2>, - <&clkc CLKID_MPLL3>, - <&clkc CLKID_HIFI_PLL>, - <&clkc CLKID_FCLK_DIV3>, - <&clkc CLKID_FCLK_DIV4>, - <&clkc CLKID_GP0_PLL>; - clock-names = "pclk", - "mst_in0", - "mst_in1", - "mst_in2", - "mst_in3", - "mst_in4", - "mst_in5", - "mst_in6", - "mst_in7"; - - resets = <&reset RESET_AUDIO>; - }; - - arb: reset-controller@280 { - compatible = "amlogic,meson-axg-audio-arb"; - reg = <0x0 0x280 0x0 0x4>; - #reset-cells = <1>; - clocks = <&clkc_audio AUD_CLKID_DDR_ARB>; - }; - - tdmin_a: audio-controller@300 { - compatible = "amlogic,axg-tdmin"; - reg = <0x0 0x300 0x0 0x40>; - sound-name-prefix = "TDMIN_A"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_A>, - <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_b: audio-controller@340 { - compatible = "amlogic,axg-tdmin"; - reg = <0x0 0x340 0x0 0x40>; - sound-name-prefix = "TDMIN_B"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_B>, - <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_c: audio-controller@380 { - compatible = "amlogic,axg-tdmin"; - reg = <0x0 0x380 0x0 0x40>; - sound-name-prefix = "TDMIN_C"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_C>, - <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmin_lb: audio-controller@3c0 { - compatible = "amlogic,axg-tdmin"; - reg = <0x0 0x3c0 0x0 0x40>; - sound-name-prefix = "TDMIN_LB"; - clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>, - <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>, - <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>, - <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - spdifout: audio-controller@480 { - compatible = "amlogic,axg-spdifout"; - reg = <0x0 0x480 0x0 0x50>; - #sound-dai-cells = <0>; - sound-name-prefix = "SPDIFOUT"; - clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>, - <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>; - clock-names = "pclk", "mclk"; - status = "disabled"; - }; - - tdmout_a: audio-controller@500 { - compatible = "amlogic,axg-tdmout"; - reg = <0x0 0x500 0x0 0x40>; - sound-name-prefix = "TDMOUT_A"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, - <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmout_b: audio-controller@540 { - compatible = "amlogic,axg-tdmout"; - reg = <0x0 0x540 0x0 0x40>; - sound-name-prefix = "TDMOUT_B"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>, - <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - - tdmout_c: audio-controller@580 { - compatible = "amlogic,axg-tdmout"; - reg = <0x0 0x580 0x0 0x40>; - sound-name-prefix = "TDMOUT_C"; - clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>, - <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>, - <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>, - <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>; - clock-names = "pclk", "sclk", "sclk_sel", - "lrclk", "lrclk_sel"; - status = "disabled"; - }; - }; - - cbus: bus@ffd00000 { - compatible = "simple-bus"; - reg = <0x0 0xffd00000 0x0 0x25000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>; - - gpio_intc: interrupt-controller@f080 { - compatible = "amlogic,meson-gpio-intc"; - reg = <0x0 0xf080 0x0 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>; - status = "disabled"; - }; - - pwm_ab: pwm@1b000 { - compatible = "amlogic,meson-axg-ee-pwm"; - reg = <0x0 0x1b000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - pwm_cd: pwm@1a000 { - compatible = "amlogic,meson-axg-ee-pwm"; - reg = <0x0 0x1a000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - - reset: reset-controller@1004 { - compatible = "amlogic,meson-axg-reset"; - reg = <0x0 0x01004 0x0 0x9c>; - #reset-cells = <1>; - }; - - spicc0: spi@13000 { - compatible = "amlogic,meson-axg-spicc"; - reg = <0x0 0x13000 0x0 0x3c>; - interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clkc CLKID_SPICC0>; - clock-names = "core"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spicc1: spi@15000 { - compatible = "amlogic,meson-axg-spicc"; - reg = <0x0 0x15000 0x0 0x3c>; - interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clkc CLKID_SPICC1>; - clock-names = "core"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c0: i2c@1f000 { - compatible = "amlogic,meson-axg-i2c"; - reg = <0x0 0x1f000 0x0 0x20>; - interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkc CLKID_I2C>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c1: i2c@1e000 { - compatible = "amlogic,meson-axg-i2c"; - reg = <0x0 0x1e000 0x0 0x20>; - interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkc CLKID_I2C>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c2: i2c@1d000 { - compatible = "amlogic,meson-axg-i2c"; - reg = <0x0 0x1d000 0x0 0x20>; - interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkc CLKID_I2C>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c3: i2c@1c000 { - compatible = "amlogic,meson-axg-i2c"; - reg = <0x0 0x1c000 0x0 0x20>; - interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkc CLKID_I2C>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart_A: serial@24000 { - compatible = "amlogic,meson-gx-uart"; - reg = <0x0 0x24000 0x0 0x18>; - interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; - status = "disabled"; - clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - }; - - uart_B: serial@23000 { - compatible = "amlogic,meson-gx-uart"; - reg = <0x0 0x23000 0x0 0x18>; - interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; - status = "disabled"; - clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>; - clock-names = "xtal", "pclk", "baud"; - }; - }; - ethmac: ethernet@ff3f0000 { - compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac"; + compatible = "amlogic,meson-axg-dwmac", "snps,dwmac"; reg = <0x0 0xff3f0000 0x0 0x10000 - 0x0 0xff634540 0x0 0x8>; + 0x0 0xff634540 0x0 0x8>; interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>; interrupt-names = "macirq"; clocks = <&clkc CLKID_ETH>, @@ -470,54 +152,26 @@ status = "disabled"; }; - gic: interrupt-controller@ffc01000 { - compatible = "arm,gic-400"; - reg = <0x0 0xffc01000 0 0x1000>, - <0x0 0xffc02000 0 0x2000>, - <0x0 0xffc04000 0 0x2000>, - <0x0 0xffc06000 0 0x2000>; - interrupt-controller; - interrupts = <GIC_PPI 9 - (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; - #interrupt-cells = <3>; - #address-cells = <0>; - }; - - hiubus: bus@ff63c000 { - compatible = "simple-bus"; - reg = <0x0 0xff63c000 0x0 0x1c00>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>; - - sysctrl: system-controller@0 { - compatible = "amlogic,meson-axg-hhi-sysctrl", "syscon", "simple-mfd"; - reg = <0 0 0 0x400>; - - clkc: clock-controller { - compatible = "amlogic,axg-clkc"; - #clock-cells = <1>; - }; - }; - }; - - mailbox: mailbox@ff63dc00 { - compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu"; - reg = <0 0xff63dc00 0 0x400>; - interrupts = <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 209 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>; - #mbox-cells = <1>; + pdm: audio-controller@ff632000 { + compatible = "amlogic,axg-pdm"; + reg = <0x0 0xff632000 0x0 0x34>; + #sound-dai-cells = <0>; + sound-name-prefix = "PDM"; + clocks = <&clkc_audio AUD_CLKID_PDM>, + <&clkc_audio AUD_CLKID_PDM_DCLK>, + <&clkc_audio AUD_CLKID_PDM_SYSCLK>; + clock-names = "pclk", "dclk", "sysclk"; + status = "disabled"; }; - periphs: periphs@ff634000 { + periphs: bus@ff634000 { compatible = "simple-bus"; reg = <0x0 0xff634000 0x0 0x2000>; #address-cells = <2>; #size-cells = <2>; ranges = <0x0 0x0 0x0 0xff634000 0x0 0x2000>; - hwrng: rng { + hwrng: rng@18 { compatible = "amlogic,meson-rng"; reg = <0x0 0x18 0x0 0x4>; clocks = <&clkc CLKID_RNG0>; @@ -532,28 +186,92 @@ gpio: bank@480 { reg = <0x0 0x00480 0x0 0x40>, - <0x0 0x004e8 0x0 0x14>, - <0x0 0x00520 0x0 0x14>, - <0x0 0x00430 0x0 0x3c>; + <0x0 0x004e8 0x0 0x14>, + <0x0 0x00520 0x0 0x14>, + <0x0 0x00430 0x0 0x3c>; reg-names = "mux", "pull", "pull-enable", "gpio"; gpio-controller; #gpio-cells = <2>; gpio-ranges = <&pinctrl_periphs 0 0 86>; }; + i2c0_pins: i2c0 { + mux { + groups = "i2c0_sck", + "i2c0_sda"; + function = "i2c0"; + }; + }; + + i2c1_x_pins: i2c1_x { + mux { + groups = "i2c1_sck_x", + "i2c1_sda_x"; + function = "i2c1"; + }; + }; + + i2c1_z_pins: i2c1_z { + mux { + groups = "i2c1_sck_z", + "i2c1_sda_z"; + function = "i2c1"; + }; + }; + + i2c2_a_pins: i2c2_a { + mux { + groups = "i2c2_sck_a", + "i2c2_sda_a"; + function = "i2c2"; + }; + }; + + i2c2_x_pins: i2c2_x { + mux { + groups = "i2c2_sck_x", + "i2c2_sda_x"; + function = "i2c2"; + }; + }; + + i2c3_a6_pins: i2c3_a6 { + mux { + groups = "i2c3_sda_a6", + "i2c3_sck_a7"; + function = "i2c3"; + }; + }; + + i2c3_a12_pins: i2c3_a12 { + mux { + groups = "i2c3_sda_a12", + "i2c3_sck_a13"; + function = "i2c3"; + }; + }; + + i2c3_a19_pins: i2c3_a19 { + mux { + groups = "i2c3_sda_a19", + "i2c3_sck_a20"; + function = "i2c3"; + }; + }; + emmc_pins: emmc { 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", - "emmc_clk", - "emmc_cmd", - "emmc_ds"; + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "emmc_clk", + "emmc_cmd", + "emmc_ds"; function = "emmc"; }; }; @@ -569,40 +287,57 @@ }; }; - sdio_pins: sdio { + eth_rgmii_x_pins: eth-x-rgmii { mux { - groups = "sdio_d0", - "sdio_d1", - "sdio_d2", - "sdio_d3", - "sdio_cmd", - "sdio_clk"; - function = "sdio"; + groups = "eth_mdio_x", + "eth_mdc_x", + "eth_rgmii_rx_clk_x", + "eth_rx_dv_x", + "eth_rxd0_x", + "eth_rxd1_x", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen_x", + "eth_txd0_x", + "eth_txd1_x", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; }; }; - sdio_clk_gate_pins: sdio_clk_gate { + eth_rgmii_y_pins: eth-y-rgmii { mux { - groups = "GPIOX_4"; - function = "gpio_periphs"; - }; - cfg-pull-down { - pins = "GPIOX_4"; - bias-pull-down; + groups = "eth_mdio_y", + "eth_mdc_y", + "eth_rgmii_rx_clk_y", + "eth_rx_dv_y", + "eth_rxd0_y", + "eth_rxd1_y", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen_y", + "eth_txd0_y", + "eth_txd1_y", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; }; }; eth_rmii_x_pins: eth-x-rmii { mux { groups = "eth_mdio_x", - "eth_mdc_x", - "eth_rgmii_rx_clk_x", - "eth_rx_dv_x", - "eth_rxd0_x", - "eth_rxd1_x", - "eth_txen_x", - "eth_txd0_x", - "eth_txd1_x"; + "eth_mdc_x", + "eth_rgmii_rx_clk_x", + "eth_rx_dv_x", + "eth_rxd0_x", + "eth_rxd1_x", + "eth_txen_x", + "eth_txd0_x", + "eth_txd1_x"; function = "eth"; }; }; @@ -610,55 +345,29 @@ eth_rmii_y_pins: eth-y-rmii { mux { groups = "eth_mdio_y", - "eth_mdc_y", - "eth_rgmii_rx_clk_y", - "eth_rx_dv_y", - "eth_rxd0_y", - "eth_rxd1_y", - "eth_txen_y", - "eth_txd0_y", - "eth_txd1_y"; + "eth_mdc_y", + "eth_rgmii_rx_clk_y", + "eth_rx_dv_y", + "eth_rxd0_y", + "eth_rxd1_y", + "eth_txen_y", + "eth_txd0_y", + "eth_txd1_y"; function = "eth"; }; }; - eth_rgmii_x_pins: eth-x-rgmii { + mclk_b_pins: mclk_b { mux { - groups = "eth_mdio_x", - "eth_mdc_x", - "eth_rgmii_rx_clk_x", - "eth_rx_dv_x", - "eth_rxd0_x", - "eth_rxd1_x", - "eth_rxd2_rgmii", - "eth_rxd3_rgmii", - "eth_rgmii_tx_clk", - "eth_txen_x", - "eth_txd0_x", - "eth_txd1_x", - "eth_txd2_rgmii", - "eth_txd3_rgmii"; - function = "eth"; + groups = "mclk_b"; + function = "mclk_b"; }; }; - eth_rgmii_y_pins: eth-y-rgmii { + mclk_c_pins: mclk_c { mux { - groups = "eth_mdio_y", - "eth_mdc_y", - "eth_rgmii_rx_clk_y", - "eth_rx_dv_y", - "eth_rxd0_y", - "eth_rxd1_y", - "eth_rxd2_rgmii", - "eth_rxd3_rgmii", - "eth_rgmii_tx_clk", - "eth_txen_y", - "eth_txd0_y", - "eth_txd1_y", - "eth_txd2_rgmii", - "eth_txd3_rgmii"; - function = "eth"; + groups = "mclk_c"; + function = "mclk_c"; }; }; @@ -788,6 +497,29 @@ }; }; + sdio_pins: sdio { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_cmd", + "sdio_clk"; + function = "sdio"; + }; + }; + + sdio_clk_gate_pins: sdio_clk_gate { + mux { + groups = "GPIOX_4"; + function = "gpio_periphs"; + }; + cfg-pull-down { + pins = "GPIOX_4"; + bias-pull-down; + }; + }; + spdif_in_z_pins: spdif_in_z { mux { groups = "spdif_in_z"; @@ -823,13 +555,6 @@ }; }; - spdif_out_z_pins: spdif_out_z { - mux { - groups = "spdif_out_z"; - function = "spdif_out"; - }; - }; - spdif_out_a1_pins: spdif_out_a1 { mux { groups = "spdif_out_a1"; @@ -858,11 +583,18 @@ }; }; + spdif_out_z_pins: spdif_out_z { + mux { + groups = "spdif_out_z"; + function = "spdif_out"; + }; + }; + spi0_pins: spi0 { mux { groups = "spi0_miso", - "spi0_mosi", - "spi0_clk"; + "spi0_mosi", + "spi0_clk"; function = "spi0"; }; }; @@ -888,12 +620,11 @@ }; }; - spi1_a_pins: spi1_a { mux { groups = "spi1_miso_a", - "spi1_mosi_a", - "spi1_clk_a"; + "spi1_mosi_a", + "spi1_clk_a"; function = "spi1"; }; }; @@ -915,8 +646,8 @@ spi1_x_pins: spi1_x { mux { groups = "spi1_miso_x", - "spi1_mosi_x", - "spi1_clk_x"; + "spi1_mosi_x", + "spi1_clk_x"; function = "spi1"; }; }; @@ -928,145 +659,52 @@ }; }; - i2c0_pins: i2c0 { - mux { - groups = "i2c0_sck", - "i2c0_sda"; - function = "i2c0"; - }; - }; - - i2c1_z_pins: i2c1_z { - mux { - groups = "i2c1_sck_z", - "i2c1_sda_z"; - function = "i2c1"; - }; - }; - - i2c1_x_pins: i2c1_x { - mux { - groups = "i2c1_sck_x", - "i2c1_sda_x"; - function = "i2c1"; - }; - }; - - i2c2_x_pins: i2c2_x { - mux { - groups = "i2c2_sck_x", - "i2c2_sda_x"; - function = "i2c2"; - }; - }; - - i2c2_a_pins: i2c2_a { - mux { - groups = "i2c2_sck_a", - "i2c2_sda_a"; - function = "i2c2"; - }; - }; - - i2c3_a6_pins: i2c3_a6 { - mux { - groups = "i2c3_sda_a6", - "i2c3_sck_a7"; - function = "i2c3"; - }; - }; - - i2c3_a12_pins: i2c3_a12 { - mux { - groups = "i2c3_sda_a12", - "i2c3_sck_a13"; - function = "i2c3"; - }; - }; - - i2c3_a19_pins: i2c3_a19 { - mux { - groups = "i2c3_sda_a19", - "i2c3_sck_a20"; - function = "i2c3"; - }; - }; - - uart_a_pins: uart_a { - mux { - groups = "uart_tx_a", - "uart_rx_a"; - function = "uart_a"; - }; - }; - - uart_a_cts_rts_pins: uart_a_cts_rts { - mux { - groups = "uart_cts_a", - "uart_rts_a"; - function = "uart_a"; - }; - }; - - uart_b_x_pins: uart_b_x { - mux { - groups = "uart_tx_b_x", - "uart_rx_b_x"; - function = "uart_b"; - }; - }; - - uart_b_x_cts_rts_pins: uart_b_x_cts_rts { + tdma_din0_pins: tdma_din0 { mux { - groups = "uart_cts_b_x", - "uart_rts_b_x"; - function = "uart_b"; + groups = "tdma_din0"; + function = "tdma"; }; }; - uart_b_z_pins: uart_b_z { + tdma_dout0_x14_pins: tdma_dout0_x14 { mux { - groups = "uart_tx_b_z", - "uart_rx_b_z"; - function = "uart_b"; + groups = "tdma_dout0_x14"; + function = "tdma"; }; }; - uart_b_z_cts_rts_pins: uart_b_z_cts_rts { + tdma_dout0_x15_pins: tdma_dout0_x15 { mux { - groups = "uart_cts_b_z", - "uart_rts_b_z"; - function = "uart_b"; + groups = "tdma_dout0_x15"; + function = "tdma"; }; }; - uart_ao_b_z_pins: uart_ao_b_z { + tdma_dout1_pins: tdma_dout1 { mux { - groups = "uart_ao_tx_b_z", - "uart_ao_rx_b_z"; - function = "uart_ao_b_z"; + groups = "tdma_dout1"; + function = "tdma"; }; }; - uart_ao_b_z_cts_rts_pins: uart_ao_b_z_cts_rts { + tdma_din1_pins: tdma_din1 { mux { - groups = "uart_ao_cts_b_z", - "uart_ao_rts_b_z"; - function = "uart_ao_b_z"; + groups = "tdma_din1"; + function = "tdma"; }; }; - mclk_b_pins: mclk_b { + tdma_fs_pins: tdma_fs { mux { - groups = "mclk_b"; - function = "mclk_b"; + groups = "tdma_fs"; + function = "tdma"; }; }; - mclk_c_pins: mclk_c { + tdma_fs_slv_pins: tdma_fs_slv { mux { - groups = "mclk_c"; - function = "mclk_c"; + groups = "tdma_fs_slv"; + function = "tdma"; }; }; @@ -1084,65 +722,58 @@ }; }; - tdma_fs_pins: tdma_fs { - mux { - groups = "tdma_fs"; - function = "tdma"; - }; - }; - - tdma_fs_slv_pins: tdma_fs_slv { + tdmb_din0_pins: tdmb_din0 { mux { - groups = "tdma_fs_slv"; - function = "tdma"; + groups = "tdmb_din0"; + function = "tdmb"; }; }; - tdma_din0_pins: tdma_din0 { + tdmb_din1_pins: tdmb_din1 { mux { - groups = "tdma_din0"; - function = "tdma"; + groups = "tdmb_din1"; + function = "tdmb"; }; }; - tdma_dout0_x14_pins: tdma_dout0_x14 { + tdmb_din2_pins: tdmb_din2 { mux { - groups = "tdma_dout0_x14"; - function = "tdma"; + groups = "tdmb_din2"; + function = "tdmb"; }; }; - tdma_dout0_x15_pins: tdma_dout0_x15 { + tdmb_din3_pins: tdmb_din3 { mux { - groups = "tdma_dout0_x15"; - function = "tdma"; + groups = "tdmb_din3"; + function = "tdmb"; }; }; - tdma_dout1_pins: tdma_dout1 { + tdmb_dout0_pins: tdmb_dout0 { mux { - groups = "tdma_dout1"; - function = "tdma"; + groups = "tdmb_dout0"; + function = "tdmb"; }; }; - tdma_din1_pins: tdma_din1 { + tdmb_dout1_pins: tdmb_dout1 { mux { - groups = "tdma_din1"; - function = "tdma"; + groups = "tdmb_dout1"; + function = "tdmb"; }; }; - tdmb_sclk_pins: tdmb_sclk { + tdmb_dout2_pins: tdmb_dout2 { mux { - groups = "tdmb_sclk"; + groups = "tdmb_dout2"; function = "tdmb"; }; }; - tdmb_sclk_slv_pins: tdmb_sclk_slv { + tdmb_dout3_pins: tdmb_dout3 { mux { - groups = "tdmb_sclk_slv"; + groups = "tdmb_dout3"; function = "tdmb"; }; }; @@ -1161,163 +792,412 @@ }; }; - tdmb_din0_pins: tdmb_din0 { + tdmb_sclk_pins: tdmb_sclk { mux { - groups = "tdmb_din0"; + groups = "tdmb_sclk"; function = "tdmb"; }; }; - tdmb_dout0_pins: tdmb_dout0 { + tdmb_sclk_slv_pins: tdmb_sclk_slv { mux { - groups = "tdmb_dout0"; + groups = "tdmb_sclk_slv"; function = "tdmb"; }; }; - tdmb_din1_pins: tdmb_din1 { + tdmc_fs_pins: tdmc_fs { mux { - groups = "tdmb_din1"; - function = "tdmb"; + groups = "tdmc_fs"; + function = "tdmc"; }; }; - tdmb_dout1_pins: tdmb_dout1 { + tdmc_fs_slv_pins: tdmc_fs_slv { mux { - groups = "tdmb_dout1"; - function = "tdmb"; + groups = "tdmc_fs_slv"; + function = "tdmc"; }; }; - tdmb_din2_pins: tdmb_din2 { + tdmc_sclk_pins: tdmc_sclk { mux { - groups = "tdmb_din2"; - function = "tdmb"; + groups = "tdmc_sclk"; + function = "tdmc"; }; }; - tdmb_dout2_pins: tdmb_dout2 { + tdmc_sclk_slv_pins: tdmc_sclk_slv { mux { - groups = "tdmb_dout2"; - function = "tdmb"; + groups = "tdmc_sclk_slv"; + function = "tdmc"; }; }; - tdmb_din3_pins: tdmb_din3 { + tdmc_din0_pins: tdmc_din0 { mux { - groups = "tdmb_din3"; - function = "tdmb"; + groups = "tdmc_din0"; + function = "tdmc"; }; }; - tdmb_dout3_pins: tdmb_dout3 { + tdmc_din1_pins: tdmc_din1 { mux { - groups = "tdmb_dout3"; - function = "tdmb"; + groups = "tdmc_din1"; + function = "tdmc"; }; }; - tdmc_sclk_pins: tdmc_sclk { + tdmc_din2_pins: tdmc_din2 { mux { - groups = "tdmc_sclk"; + groups = "tdmc_din2"; function = "tdmc"; }; }; - tdmc_sclk_slv_pins: tdmc_sclk_slv { + tdmc_din3_pins: tdmc_din3 { mux { - groups = "tdmc_sclk_slv"; + groups = "tdmc_din3"; function = "tdmc"; }; }; - tdmc_fs_pins: tdmc_fs { + tdmc_dout0_pins: tdmc_dout0 { mux { - groups = "tdmc_fs"; + groups = "tdmc_dout0"; function = "tdmc"; }; }; - tdmc_fs_slv_pins: tdmc_fs_slv { + tdmc_dout1_pins: tdmc_dout1 { mux { - groups = "tdmc_fs_slv"; + groups = "tdmc_dout1"; function = "tdmc"; }; }; - tdmc_din0_pins: tdmc_din0 { + tdmc_dout2_pins: tdmc_dout2 { mux { - groups = "tdmc_din0"; + groups = "tdmc_dout2"; function = "tdmc"; }; }; - tdmc_dout0_pins: tdmc_dout0 { + tdmc_dout3_pins: tdmc_dout3 { mux { - groups = "tdmc_dout0"; + groups = "tdmc_dout3"; function = "tdmc"; }; }; - tdmc_din1_pins: tdmc_din1 { + uart_a_pins: uart_a { mux { - groups = "tdmc_din1"; - function = "tdmc"; + groups = "uart_tx_a", + "uart_rx_a"; + function = "uart_a"; }; }; - tdmc_dout1_pins: tdmc_dout1 { + uart_a_cts_rts_pins: uart_a_cts_rts { mux { - groups = "tdmc_dout1"; - function = "tdmc"; + groups = "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; }; }; - tdmc_din2_pins: tdmc_din2 { + uart_b_x_pins: uart_b_x { mux { - groups = "tdmc_din2"; - function = "tdmc"; + groups = "uart_tx_b_x", + "uart_rx_b_x"; + function = "uart_b"; }; }; - tdmc_dout2_pins: tdmc_dout2 { + uart_b_x_cts_rts_pins: uart_b_x_cts_rts { mux { - groups = "tdmc_dout2"; - function = "tdmc"; + groups = "uart_cts_b_x", + "uart_rts_b_x"; + function = "uart_b"; }; }; - tdmc_din3_pins: tdmc_din3 { + uart_b_z_pins: uart_b_z { mux { - groups = "tdmc_din3"; - function = "tdmc"; + groups = "uart_tx_b_z", + "uart_rx_b_z"; + function = "uart_b"; }; }; - tdmc_dout3_pins: tdmc_dout3 { + uart_b_z_cts_rts_pins: uart_b_z_cts_rts { mux { - groups = "tdmc_dout3"; - function = "tdmc"; + groups = "uart_cts_b_z", + "uart_rts_b_z"; + function = "uart_b"; + }; + }; + + uart_ao_b_z_pins: uart_ao_b_z { + mux { + groups = "uart_ao_tx_b_z", + "uart_ao_rx_b_z"; + function = "uart_ao_b_z"; + }; + }; + + uart_ao_b_z_cts_rts_pins: uart_ao_b_z_cts_rts { + mux { + groups = "uart_ao_cts_b_z", + "uart_ao_rts_b_z"; + function = "uart_ao_b_z"; }; }; }; }; - sram: sram@fffc0000 { - compatible = "amlogic,meson-axg-sram", "mmio-sram"; - reg = <0x0 0xfffc0000 0x0 0x20000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x0 0xfffc0000 0x20000>; + hiubus: bus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x1c00>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>; - cpu_scp_lpri: scp-shmem@0 { - compatible = "amlogic,meson-axg-scp-shmem"; - reg = <0x13000 0x400>; + sysctrl: system-controller@0 { + compatible = "amlogic,meson-axg-hhi-sysctrl", + "simple-mfd", "syscon"; + reg = <0 0 0 0x400>; + + clkc: clock-controller { + compatible = "amlogic,axg-clkc"; + #clock-cells = <1>; + }; }; + }; - cpu_scp_hpri: scp-shmem@200 { - compatible = "amlogic,meson-axg-scp-shmem"; - reg = <0x13400 0x400>; + mailbox: mailbox@ff63dc00 { + compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu"; + reg = <0 0xff63dc00 0 0x400>; + interrupts = <GIC_SPI 208 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 209 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 210 IRQ_TYPE_EDGE_RISING>; + #mbox-cells = <1>; + }; + + audio: bus@ff642000 { + compatible = "simple-bus"; + reg = <0x0 0xff642000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; + + clkc_audio: clock-controller@0 { + compatible = "amlogic,axg-audio-clkc"; + reg = <0x0 0x0 0x0 0xb4>; + #clock-cells = <1>; + + clocks = <&clkc CLKID_AUDIO>, + <&clkc CLKID_MPLL0>, + <&clkc CLKID_MPLL1>, + <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL3>, + <&clkc CLKID_HIFI_PLL>, + <&clkc CLKID_FCLK_DIV3>, + <&clkc CLKID_FCLK_DIV4>, + <&clkc CLKID_GP0_PLL>; + clock-names = "pclk", + "mst_in0", + "mst_in1", + "mst_in2", + "mst_in3", + "mst_in4", + "mst_in5", + "mst_in6", + "mst_in7"; + + resets = <&reset RESET_AUDIO>; + }; + + toddr_a: audio-controller@100 { + compatible = "amlogic,axg-toddr"; + reg = <0x0 0x100 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_A"; + interrupts = <GIC_SPI 84 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_TODDR_A>; + resets = <&arb AXG_ARB_TODDR_A>; + status = "disabled"; + }; + + toddr_b: audio-controller@140 { + compatible = "amlogic,axg-toddr"; + reg = <0x0 0x140 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_B"; + interrupts = <GIC_SPI 85 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_TODDR_B>; + resets = <&arb AXG_ARB_TODDR_B>; + status = "disabled"; + }; + + toddr_c: audio-controller@180 { + compatible = "amlogic,axg-toddr"; + reg = <0x0 0x180 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "TODDR_C"; + interrupts = <GIC_SPI 86 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_TODDR_C>; + resets = <&arb AXG_ARB_TODDR_C>; + status = "disabled"; + }; + + frddr_a: audio-controller@1c0 { + compatible = "amlogic,axg-frddr"; + reg = <0x0 0x1c0 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_A"; + interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; + resets = <&arb AXG_ARB_FRDDR_A>; + status = "disabled"; + }; + + frddr_b: audio-controller@200 { + compatible = "amlogic,axg-frddr"; + reg = <0x0 0x200 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_B"; + interrupts = <GIC_SPI 89 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_FRDDR_B>; + resets = <&arb AXG_ARB_FRDDR_B>; + status = "disabled"; + }; + + frddr_c: audio-controller@240 { + compatible = "amlogic,axg-frddr"; + reg = <0x0 0x240 0x0 0x1c>; + #sound-dai-cells = <0>; + sound-name-prefix = "FRDDR_C"; + interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc_audio AUD_CLKID_FRDDR_C>; + resets = <&arb AXG_ARB_FRDDR_C>; + status = "disabled"; + }; + + arb: reset-controller@280 { + compatible = "amlogic,meson-axg-audio-arb"; + reg = <0x0 0x280 0x0 0x4>; + #reset-cells = <1>; + clocks = <&clkc_audio AUD_CLKID_DDR_ARB>; + }; + + tdmin_a: audio-controller@300 { + compatible = "amlogic,axg-tdmin"; + reg = <0x0 0x300 0x0 0x40>; + sound-name-prefix = "TDMIN_A"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_A>, + <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_b: audio-controller@340 { + compatible = "amlogic,axg-tdmin"; + reg = <0x0 0x340 0x0 0x40>; + sound-name-prefix = "TDMIN_B"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_B>, + <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_c: audio-controller@380 { + compatible = "amlogic,axg-tdmin"; + reg = <0x0 0x380 0x0 0x40>; + sound-name-prefix = "TDMIN_C"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_C>, + <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmin_lb: audio-controller@3c0 { + compatible = "amlogic,axg-tdmin"; + reg = <0x0 0x3c0 0x0 0x40>; + sound-name-prefix = "TDMIN_LB"; + clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>, + <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>, + <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>, + <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + spdifout: audio-controller@480 { + compatible = "amlogic,axg-spdifout"; + reg = <0x0 0x480 0x0 0x50>; + #sound-dai-cells = <0>; + sound-name-prefix = "SPDIFOUT"; + clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>, + <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>; + clock-names = "pclk", "mclk"; + status = "disabled"; + }; + + tdmout_a: audio-controller@500 { + compatible = "amlogic,axg-tdmout"; + reg = <0x0 0x500 0x0 0x40>; + sound-name-prefix = "TDMOUT_A"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmout_b: audio-controller@540 { + compatible = "amlogic,axg-tdmout"; + reg = <0x0 0x540 0x0 0x40>; + sound-name-prefix = "TDMOUT_B"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>, + <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; + }; + + tdmout_c: audio-controller@580 { + compatible = "amlogic,axg-tdmout"; + reg = <0x0 0x580 0x0 0x40>; + sound-name-prefix = "TDMOUT_C"; + clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>, + <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>, + <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>, + <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>; + clock-names = "pclk", "sclk", "sclk_sel", + "lrclk", "lrclk_sel"; + status = "disabled"; }; }; @@ -1329,7 +1209,7 @@ ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>; sysctrl_AO: sys-ctrl@0 { - compatible = "amlogic,meson-axg-ao-sysctrl", "syscon", "simple-mfd"; + compatible = "amlogic,meson-axg-ao-sysctrl", "simple-mfd", "syscon"; reg = <0x0 0x0 0x0 0x100>; clkc_AO: clock-controller { @@ -1347,8 +1227,8 @@ gpio_ao: bank@14 { reg = <0x0 0x00014 0x0 0x8>, - <0x0 0x0002c 0x0 0x4>, - <0x0 0x00024 0x0 0x8>; + <0x0 0x0002c 0x0 0x4>, + <0x0 0x00024 0x0 0x8>; reg-names = "mux", "pull", "gpio"; gpio-controller; #gpio-cells = <2>; @@ -1407,7 +1287,7 @@ uart_ao_a_pins: uart_ao_a { mux { groups = "uart_ao_tx_a", - "uart_ao_rx_a"; + "uart_ao_rx_a"; function = "uart_ao_a"; }; }; @@ -1415,7 +1295,7 @@ uart_ao_a_cts_rts_pins: uart_ao_a_cts_rts { mux { groups = "uart_ao_cts_a", - "uart_ao_rts_a"; + "uart_ao_rts_a"; function = "uart_ao_a"; }; }; @@ -1423,7 +1303,7 @@ uart_ao_b_pins: uart_ao_b { mux { groups = "uart_ao_tx_b", - "uart_ao_rx_b"; + "uart_ao_rx_b"; function = "uart_ao_b"; }; }; @@ -1431,7 +1311,7 @@ uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts { mux { groups = "uart_ao_cts_b", - "uart_ao_rts_b"; + "uart_ao_rts_b"; function = "uart_ao_b"; }; }; @@ -1443,13 +1323,6 @@ amlogic,has-chip-id; }; - pwm_AO_ab: pwm@7000 { - compatible = "amlogic,meson-axg-ao-pwm"; - reg = <0x0 0x07000 0x0 0x20>; - #pwm-cells = <3>; - status = "disabled"; - }; - pwm_AO_cd: pwm@2000 { compatible = "amlogic,meson-axg-ao-pwm"; reg = <0x0 0x02000 0x0 0x20>; @@ -1457,16 +1330,6 @@ status = "disabled"; }; - i2c_AO: i2c@5000 { - compatible = "amlogic,meson-axg-i2c"; - reg = <0x0 0x05000 0x0 0x20>; - interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkc CLKID_AO_I2C>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - uart_AO: serial@3000 { compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart"; reg = <0x0 0x3000 0x0 0x18>; @@ -1485,6 +1348,23 @@ status = "disabled"; }; + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_AO_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,meson-axg-ao-pwm"; + reg = <0x0 0x07000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + ir: ir@8000 { compatible = "amlogic,meson-gxbb-ir"; reg = <0x0 0x8000 0x0 0x20>; @@ -1499,12 +1379,211 @@ #io-channel-cells = <1>; interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>; clocks = <&xtal>, - <&clkc_AO CLKID_AO_SAR_ADC>, - <&clkc_AO CLKID_AO_SAR_ADC_CLK>, - <&clkc_AO CLKID_AO_SAR_ADC_SEL>; + <&clkc_AO CLKID_AO_SAR_ADC>, + <&clkc_AO CLKID_AO_SAR_ADC_CLK>, + <&clkc_AO CLKID_AO_SAR_ADC_SEL>; clock-names = "clkin", "core", "adc_clk", "adc_sel"; status = "disabled"; }; }; + + gic: interrupt-controller@ffc01000 { + compatible = "arm,gic-400"; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x2000>, + <0x0 0xffc04000 0 0x2000>, + <0x0 0xffc06000 0 0x2000>; + interrupt-controller; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; + #interrupt-cells = <3>; + #address-cells = <0>; + }; + + cbus: bus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x25000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>; + + reset: reset-controller@1004 { + compatible = "amlogic,meson-axg-reset"; + reg = <0x0 0x01004 0x0 0x9c>; + #reset-cells = <1>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>; + status = "disabled"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,meson-axg-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,meson-axg-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + status = "disabled"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-axg-spicc"; + reg = <0x0 0x13000 0x0 0x3c>; + interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_SPICC0>; + clock-names = "core"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-axg-spicc"; + reg = <0x0 0x15000 0x0 0x3c>; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_SPICC1>; + clock-names = "core"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-axg-i2c"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart_B: serial@23000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x0 0x23000 0x0 0x18>; + interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + clocks = <&xtal>, <&clkc CLKID_UART1>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + }; + + uart_A: serial@24000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x0 0x24000 0x0 0x18>; + interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + clocks = <&xtal>, <&clkc CLKID_UART0>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + }; + }; + + apb: bus@ffe00000 { + compatible = "simple-bus"; + reg = <0x0 0xffe00000 0x0 0x200000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x200000>; + + sd_emmc_b: sd@5000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x5000 0x0 0x800>; + interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_CLK0>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_B>; + }; + + sd_emmc_c: mmc@7000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x7000 0x0 0x800>; + interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_CLK0>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; + resets = <&reset RESET_SD_EMMC_C>; + }; + }; + + sram: sram@fffc0000 { + compatible = "amlogic,meson-axg-sram", "mmio-sram"; + reg = <0x0 0xfffc0000 0x0 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0xfffc0000 0x20000>; + + cpu_scp_lpri: scp-shmem@0 { + compatible = "amlogic,meson-axg-scp-shmem"; + reg = <0x13000 0x400>; + }; + + cpu_scp_hpri: scp-shmem@200 { + compatible = "amlogic,meson-axg-scp-shmem"; + reg = <0x13400 0x400>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts new file mode 100644 index 000000000000..c44dbdddf2cf --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Amlogic, Inc. All rights reserved. + */ + +/dts-v1/; + +#include "meson-g12a.dtsi" + +/ { + compatible = "amlogic,u200", "amlogic,g12a"; + model = "Amlogic Meson G12A U200 Development Board"; + + aliases { + serial0 = &uart_AO; + }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; + }; +}; + +&uart_AO { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi new file mode 100644 index 000000000000..3b82a975c663 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Amlogic, Inc. All rights reserved. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "amlogic,g12a"; + + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + l2: l2-cache0 { + compatible = "cache"; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 3 MiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@5000000 { + reg = <0x0 0x05000000 0x0 0x300000>; + no-map; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + periphs: periphs@ff634000 { + compatible = "simple-bus"; + reg = <0x0 0xff634000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff634000 0x0 0x2000>; + }; + + hiubus: bus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x1c00>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>; + }; + + aobus: bus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0x100000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>; + + uart_AO: serial@3000 { + compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>, <&xtal>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>, <&xtal>, <&xtal>; + clock-names = "xtal", "pclk", "baud"; + status = "disabled"; + }; + }; + + gic: interrupt-controller@ffc01000 { + compatible = "arm,gic-400"; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x2000>, + <0x0 0xffc04000 0 0x2000>, + <0x0 0xffc06000 0 0x2000>; + interrupt-controller; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; + #interrupt-cells = <3>; + #address-cells = <0>; + }; + + cbus: bus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x25000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>; + }; + + apb: apb@ffe00000 { + compatible = "simple-bus"; + reg = <0x0 0xffe00000 0x0 0x200000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x200000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 + (GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi index b8dc4dbb391b..f1e5cdbade5e 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -44,7 +44,7 @@ linux,cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0xbc00000>; + size = <0x0 0x10000000>; alignment = <0x0 0x400000>; linux,cma-default; }; @@ -344,7 +344,7 @@ ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>; sysctrl_AO: sys-ctrl@0 { - compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd"; + compatible = "amlogic,meson-gx-ao-sysctrl", "simple-mfd", "syscon"; reg = <0x0 0x0 0x0 0x100>; pwrc_vpu: power-controller-vpu { @@ -423,6 +423,19 @@ }; }; + dmcbus: bus@c8838000 { + compatible = "simple-bus"; + reg = <0x0 0xc8838000 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xc8838000 0x0 0x400>; + + canvas: video-lut@48 { + compatible = "amlogic,canvas"; + reg = <0x0 0x48 0x0 0x14>; + }; + }; + hiubus: bus@c883c000 { compatible = "simple-bus"; reg = <0x0 0xc883c000 0x0 0x2000>; @@ -431,7 +444,7 @@ ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>; sysctrl: system-controller@0 { - compatible = "amlogic,meson-gx-hhi-sysctrl", "syscon", "simple-mfd"; + compatible = "amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon"; reg = <0 0 0 0x400>; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi index 98cbba6809ca..1ade7e486828 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -390,7 +390,7 @@ }; }; - spi_pins: spi { + spi_pins: spi-pins { mux { groups = "spi_miso", "spi_mosi", 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 f63bceb88caa..90a56af967a7 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 @@ -13,7 +13,7 @@ / { compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl"; - model = "Libre Technology CC"; + model = "Libre Computer Board AML-S905X-CC"; aliases { serial0 = &uart_AO; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi index c87a80e9bcc6..8f0bb3c44bd6 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi @@ -337,7 +337,7 @@ }; }; - spi_pins: spi { + spi_pins: spi-pins { mux { groups = "spi_miso", "spi_mosi", diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index ce56a4acda4f..ed774ee8f659 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -115,22 +115,17 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - /* input port */ - port@0 { - reg = <0>; + in-ports { + port { etf0_in_port: endpoint { - slave-mode; remote-endpoint = <&main_funnel_out_port>; }; }; + }; - /* output port */ - port@1 { - reg = <0>; + out-ports { + port { etf0_out_port: endpoint { }; }; @@ -144,10 +139,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - tpiu_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port0>; + in-ports { + port { + tpiu_in_port: endpoint { + remote-endpoint = <&replicator_out_port0>; + }; }; }; }; @@ -160,31 +156,29 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - /* output port */ - port@0 { - reg = <0>; + out-ports { + port { main_funnel_out_port: endpoint { remote-endpoint = <&etf0_in_port>; }; }; + }; - /* input ports */ - port@1 { + main_funnel_in_ports: in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; main_funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&cluster0_funnel_out_port>; }; }; - port@2 { + port@1 { reg = <1>; main_funnel_in_port1: endpoint { - slave-mode; remote-endpoint = <&cluster1_funnel_out_port>; }; }; @@ -199,10 +193,12 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - etr_in_port: endpoint { - slave-mode; - remote-endpoint = <&replicator_out_port1>; + arm,scatter-gather; + in-ports { + port { + etr_in_port: endpoint { + remote-endpoint = <&replicator_out_port1>; + }; }; }; }; @@ -216,8 +212,10 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - stm_out_port: endpoint { + out-ports { + port { + stm_out_port: endpoint { + }; }; }; }; @@ -238,9 +236,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster0_etm0_out_port: endpoint { - remote-endpoint = <&cluster0_funnel_in_port0>; + out-ports { + port { + cluster0_etm0_out_port: endpoint { + remote-endpoint = <&cluster0_funnel_in_port0>; + }; }; }; }; @@ -252,29 +252,28 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + out-ports { + port { cluster0_funnel_out_port: endpoint { remote-endpoint = <&main_funnel_in_port0>; }; }; + }; - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; cluster0_funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&cluster0_etm0_out_port>; }; }; - port@2 { + port@1 { reg = <1>; cluster0_funnel_in_port1: endpoint { - slave-mode; remote-endpoint = <&cluster0_etm1_out_port>; }; }; @@ -297,9 +296,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster0_etm1_out_port: endpoint { - remote-endpoint = <&cluster0_funnel_in_port1>; + out-ports { + port { + cluster0_etm1_out_port: endpoint { + remote-endpoint = <&cluster0_funnel_in_port1>; + }; }; }; }; @@ -320,9 +321,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster1_etm0_out_port: endpoint { - remote-endpoint = <&cluster1_funnel_in_port0>; + out-ports { + port { + cluster1_etm0_out_port: endpoint { + remote-endpoint = <&cluster1_funnel_in_port0>; + }; }; }; }; @@ -334,43 +337,40 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + out-ports { + port { cluster1_funnel_out_port: endpoint { remote-endpoint = <&main_funnel_in_port1>; }; }; + }; - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; cluster1_funnel_in_port0: endpoint { - slave-mode; remote-endpoint = <&cluster1_etm0_out_port>; }; }; - port@2 { + port@1 { reg = <1>; cluster1_funnel_in_port1: endpoint { - slave-mode; remote-endpoint = <&cluster1_etm1_out_port>; }; }; - port@3 { + port@2 { reg = <2>; cluster1_funnel_in_port2: endpoint { - slave-mode; remote-endpoint = <&cluster1_etm2_out_port>; }; }; - port@4 { + port@3 { reg = <3>; cluster1_funnel_in_port3: endpoint { - slave-mode; remote-endpoint = <&cluster1_etm3_out_port>; }; }; @@ -393,9 +393,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster1_etm1_out_port: endpoint { - remote-endpoint = <&cluster1_funnel_in_port1>; + out-ports { + port { + cluster1_etm1_out_port: endpoint { + remote-endpoint = <&cluster1_funnel_in_port1>; + }; }; }; }; @@ -416,9 +418,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster1_etm2_out_port: endpoint { - remote-endpoint = <&cluster1_funnel_in_port2>; + out-ports { + port { + cluster1_etm2_out_port: endpoint { + remote-endpoint = <&cluster1_funnel_in_port2>; + }; }; }; }; @@ -439,9 +443,11 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - port { - cluster1_etm3_out_port: endpoint { - remote-endpoint = <&cluster1_funnel_in_port3>; + out-ports { + port { + cluster1_etm3_out_port: endpoint { + remote-endpoint = <&cluster1_funnel_in_port3>; + }; }; }; }; @@ -454,7 +460,7 @@ clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -472,12 +478,10 @@ remote-endpoint = <&etr_in_port>; }; }; - - /* replicator input port */ - port@2 { - reg = <0>; + }; + in-ports { + port { replicator_in_port0: endpoint { - slave-mode; }; }; }; diff --git a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi index 0c43fb3525eb..cf285152deab 100644 --- a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi +++ b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi @@ -7,23 +7,16 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* output port */ - port@0 { - reg = <0>; + out-ports { + port { csys1_funnel_out_port: endpoint { remote-endpoint = <&etf1_in_port>; }; }; - - /* input port */ - port@1 { - reg = <0>; + }; + in-ports { + port { csys1_funnel_in_port0: endpoint { - slave-mode; }; }; @@ -37,22 +30,15 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* input port */ - port@0 { - reg = <0>; + in-ports { + port { etf1_in_port: endpoint { - slave-mode; remote-endpoint = <&csys1_funnel_out_port>; }; }; - - /* output port */ - port@1 { - reg = <0>; + }; + out-ports { + port { etf1_out_port: endpoint { remote-endpoint = <&csys2_funnel_in_port1>; }; @@ -67,20 +53,18 @@ clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; power-domains = <&scpi_devpd 0>; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* output port */ - port@0 { - reg = <0>; + out-ports { + port { csys2_funnel_out_port: endpoint { remote-endpoint = <&replicator_in_port0>; }; }; + }; - /* input ports */ - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; csys2_funnel_in_port0: endpoint { slave-mode; @@ -88,7 +72,7 @@ }; }; - port@2 { + port@1 { reg = <1>; csys2_funnel_in_port1: endpoint { slave-mode; diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts index 1fb5c5a0f32e..08d4ba1716c3 100644 --- a/arch/arm64/boot/dts/arm/juno.dts +++ b/arch/arm64/boot/dts/arm/juno.dts @@ -257,14 +257,11 @@ remote-endpoint = <&main_funnel_in_port2>; }; -&main_funnel { - ports { - port@3 { - reg = <2>; - main_funnel_in_port2: endpoint { - slave-mode; - remote-endpoint = <&stm_out_port>; - }; +&main_funnel_in_ports { + port@2 { + reg = <2>; + main_funnel_in_port2: endpoint { + remote-endpoint = <&stm_out_port>; }; }; }; diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile index 1193a9e34bbb..667ca989c11b 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb \ - bcm2837-rpi-3-b-plus.dtb + bcm2837-rpi-3-b-plus.dtb \ + bcm2837-rpi-cm3-io3.dtb subdir-y += northstar2 subdir-y += stingray diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts new file mode 100644 index 000000000000..b1c4ab212c64 --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-cm3-io3.dts @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "arm/bcm2837-rpi-cm3-io3.dts" diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi index 1a406a76c86a..ea854f689fda 100644 --- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi @@ -639,7 +639,7 @@ status = "disabled"; }; - ssp0: ssp@66180000 { + ssp0: spi@66180000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x66180000 0x1000>; interrupts = <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>; @@ -650,7 +650,7 @@ status = "disabled"; }; - ssp1: ssp@66190000 { + ssp1: spi@66190000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x66190000 0x1000>; interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm64/boot/dts/broadcom/stingray/bcm958742-base.dtsi b/arch/arm64/boot/dts/broadcom/stingray/bcm958742-base.dtsi index bc299c3d9068..a9b92e52d50e 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/bcm958742-base.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/bcm958742-base.dtsi @@ -138,7 +138,7 @@ &i2c1 { status = "okay"; - pcf8574: pcf8574@20 { + pcf8574: pcf8574@27 { compatible = "nxp,pcf8574a"; gpio-controller; #gpio-cells = <2>; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi index e283480bfc7e..cfeaa855bd05 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi @@ -521,7 +521,7 @@ status = "disabled"; }; - ssp0: ssp@180000 { + ssp0: spi@180000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x00180000 0x1000>; interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; @@ -533,7 +533,7 @@ status = "disabled"; }; - ssp1: ssp@190000 { + ssp1: spi@190000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x00190000 0x1000>; interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi index a1e3194b7483..f3ed4c078ba5 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi @@ -868,6 +868,14 @@ }; }; }; + + ports { + port { + muic_to_usb: endpoint { + remote-endpoint = <&usb_to_muic>; + }; + }; + }; }; regulators { @@ -939,8 +947,7 @@ status = "okay"; cap-sd-highspeed; disable-wp; - cd-gpios = <&gpa2 4 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&gpa2 4 GPIO_ACTIVE_LOW>; card-detect-delay = <200>; samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <0 4>; @@ -1283,12 +1290,17 @@ &usbdrd_dwc3 { dr_mode = "otg"; - extcon = <&muic>; }; &usbdrd30_phy { vbus-supply = <&safeout1_reg>; status = "okay"; + + port { + usb_to_muic: endpoint { + remote-endpoint = <&muic_to_usb>; + }; + }; }; &xxti { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi index 68ac78c4564d..5da732f82fa0 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi @@ -337,7 +337,7 @@ status = "disabled"; }; - dspi: dspi@2100000 { + dspi: spi@2100000 { compatible = "fsl,ls1012a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts index c7b8d2c009cd..dff3d648172e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts @@ -3,6 +3,7 @@ * Device Tree Include file for Freescale Layerscape-1043A family SoC. * * Copyright 2014-2015 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * Mingkai Hu <Mingkai.hu@freescale.com> */ @@ -50,6 +51,7 @@ nor@0,0 { compatible = "cfi-flash"; reg = <0x0 0x0 0x8000000>; + big-endian; bank-width = <2>; device-width = <1>; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts index 7b01ba8d3b7e..17ca357e854f 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts @@ -3,6 +3,7 @@ * Device Tree Include file for Freescale Layerscape-1043A family SoC. * * Copyright 2014-2015 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * Mingkai Hu <Mingkai.hu@freescale.com> */ @@ -65,6 +66,7 @@ #address-cells = <1>; #size-cells = <1>; reg = <0x0 0x0 0x8000000>; + big-endian; bank-width = <2>; device-width = <1>; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index 7881e3d81a9a..3fed504b5381 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -3,6 +3,7 @@ * Device Tree Include file for Freescale Layerscape-1043A family SoC. * * Copyright 2014-2015 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * Mingkai Hu <Mingkai.hu@freescale.com> */ @@ -280,11 +281,10 @@ ifc: ifc@1530000 { compatible = "fsl,ifc", "simple-bus"; reg = <0x0 0x1530000 0x0 0x10000>; - big-endian; interrupts = <0 43 0x4>; }; - qspi: quadspi@1550000 { + qspi: spi@1550000 { compatible = "fsl,ls1043a-qspi", "fsl,ls1021a-qspi"; #address-cells = <1>; #size-cells = <0>; @@ -382,7 +382,7 @@ ranges = <0x0 0x5 0x00000000 0x8000000>; }; - dspi0: dspi@2100000 { + dspi0: spi@2100000 { compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; @@ -395,7 +395,7 @@ status = "disabled"; }; - dspi1: dspi@2110000 { + dspi1: spi@2110000 { compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts index e69306e6b0b1..e58a8ca1386c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts @@ -3,6 +3,7 @@ * Device Tree Include file for Freescale Layerscape-1046A family SoC. * * Copyright 2016 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * Shaohui Xie <Shaohui.Xie@nxp.com> */ @@ -141,6 +142,7 @@ nor@0,0 { compatible = "cfi-flash"; reg = <0x0 0x0 0x8000000>; + big-endian; bank-width = <2>; device-width = <1>; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts index 440e111651d5..a59b48203688 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts @@ -57,12 +57,12 @@ reg = <0x4c>; }; - eeprom@56 { + eeprom@52 { compatible = "atmel,24c512"; reg = <0x52>; }; - eeprom@57 { + eeprom@53 { compatible = "atmel,24c512"; reg = <0x53>; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi index ef83786b8b90..51cbd50012d6 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi @@ -3,6 +3,7 @@ * Device Tree Include file for Freescale Layerscape-1046A family SoC. * * Copyright 2016 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * * Mingkai Hu <mingkai.hu@nxp.com> */ @@ -198,11 +199,10 @@ ifc: ifc@1530000 { compatible = "fsl,ifc", "simple-bus"; reg = <0x0 0x1530000 0x0 0x10000>; - big-endian; interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; }; - qspi: quadspi@1550000 { + qspi: spi@1550000 { compatible = "fsl,ls1021a-qspi"; #address-cells = <1>; #size-cells = <0>; @@ -361,7 +361,7 @@ #thermal-sensor-cells = <1>; }; - dspi: dspi@2100000 { + dspi: spi@2100000 { compatible = "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi index 8cb78dd99672..d188774a36e8 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi @@ -22,6 +22,8 @@ crypto = &crypto; serial0 = &serial0; serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; }; cpu: cpus { @@ -148,6 +150,7 @@ #address-cells = <2>; #size-cells = <2>; ranges; + dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>; clockgen: clocking@1300000 { compatible = "fsl,ls2080a-clockgen"; @@ -221,6 +224,20 @@ interrupts = <0 32 0x4>; /* Level high type */ }; + serial2: serial@21d0500 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x0 0x21d0500 0x0 0x100>; + clocks = <&clockgen 4 3>; + interrupts = <0 33 0x4>; /* Level high type */ + }; + + serial3: serial@21d0600 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x0 0x21d0600 0x0 0x100>; + clocks = <&clockgen 4 3>; + interrupts = <0 33 0x4>; /* Level high type */ + }; + cluster1_core0_watchdog: wdt@c000000 { compatible = "arm,sp805-wdt", "arm,primecell"; reg = <0x0 0xc000000 0x0 0x1000>; @@ -321,6 +338,8 @@ reg = <0x00000008 0x0c000000 0 0x40>, /* MC portal base */ <0x00000000 0x08340000 0 0x40000>; /* MC control reg */ msi-parent = <&its>; + iommu-map = <0 &smmu 0 0>; /* This is fixed-up by u-boot */ + dma-coherent; #address-cells = <3>; #size-cells = <1>; @@ -424,6 +443,9 @@ compatible = "arm,mmu-500"; reg = <0 0x5000000 0 0x800000>; #global-interrupts = <12>; + #iommu-cells = <1>; + stream-match-mask = <0x7C00>; + dma-coherent; interrupts = <0 13 4>, /* global secure fault */ <0 14 4>, /* combined secure interrupt */ <0 15 4>, /* global non-secure fault */ @@ -466,10 +488,9 @@ <0 204 4>, <0 205 4>, <0 206 4>, <0 207 4>, <0 208 4>, <0 209 4>; - mmu-masters = <&fsl_mc 0x300 0>; }; - dspi: dspi@2100000 { + dspi: spi@2100000 { status = "disabled"; compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi"; #address-cells = <1>; @@ -595,7 +616,7 @@ 3 0 0x5 0x20000000 0x00010000>; }; - qspi: quadspi@20c0000 { + qspi: spi@20c0000 { status = "disabled"; compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile index 03d93f8ef8a9..f4d68caeba83 100644 --- a/arch/arm64/boot/dts/hisilicon/Makefile +++ b/arch/arm64/boot/dts/hisilicon/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 dtb-$(CONFIG_ARCH_HISI) += hi3660-hikey960.dtb +dtb-$(CONFIG_ARCH_HISI) += hi3670-hikey970.dtb dtb-$(CONFIG_ARCH_HISI) += hi3798cv200-poplar.dtb dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb diff --git a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts new file mode 100644 index 000000000000..4f5118642024 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dts file for Hisilicon HiKey970 Development Board + * + * Copyright (C) 2016, Hisilicon Ltd. + * Copyright (C) 2018, Linaro Ltd. + * + */ + +/dts-v1/; + +#include "hi3670.dtsi" + +/ { + model = "HiKey970"; + compatible = "hisilicon,hi3670-hikey970", "hisilicon,hi3670"; + + aliases { + serial6 = &uart6; /* console UART */ + }; + + chosen { + stdout-path = "serial6:115200n8"; + }; + + memory@0 { + device_type = "memory"; + /* expect bootloader to fill in this region */ + reg = <0x0 0x0 0x0 0x0>; + }; +}; + +&uart6 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi3670.dtsi b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi new file mode 100644 index 000000000000..c90e6f6a34ec --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dts file for Hisilicon Hi3670 SoC + * + * Copyright (C) 2016, Hisilicon Ltd. + * Copyright (C) 2018, Linaro Ltd. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "hisilicon,hi3670"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + }; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x1>; + enable-method = "psci"; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x2>; + enable-method = "psci"; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x3>; + enable-method = "psci"; + }; + + cpu4: cpu@100 { + compatible = "arm,cortex-a73", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; + + cpu5: cpu@101 { + compatible = "arm,cortex-a73", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x101>; + enable-method = "psci"; + }; + + cpu6: cpu@102 { + compatible = "arm,cortex-a73", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x102>; + enable-method = "psci"; + }; + + cpu7: cpu@103 { + compatible = "arm,cortex-a73", "arm,armv8"; + device_type = "cpu"; + reg = <0x0 0x103>; + enable-method = "psci"; + }; + }; + + gic: interrupt-controller@e82b0000 { + compatible = "arm,gic-400"; + reg = <0x0 0xe82b1000 0 0x1000>, /* GICD */ + <0x0 0xe82b2000 0 0x2000>, /* GICC */ + <0x0 0xe82b4000 0 0x2000>, /* GICH */ + <0x0 0xe82b6000 0 0x2000>; /* GICV */ + #interrupt-cells = <3>; + #address-cells = <0>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | + IRQ_TYPE_LEVEL_HIGH)>; + interrupt-controller; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | + IRQ_TYPE_LEVEL_LOW)>; + clock-frequency = <1920000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + uart6_clk: clk_19_2M { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + }; + + uart6: serial@fff32000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0xfff32000 0x0 0x1000>; + interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&uart6_clk &uart6_clk>; + clock-names = "uartclk", "apb_pclk"; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi index 7afee5d5087b..68c52f1149be 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi @@ -20,22 +20,18 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + out-ports { + port { soc_funnel_out: endpoint { remote-endpoint = <&etf_in>; }; }; + }; - port@1 { - reg = <0>; + in-ports { + port { soc_funnel_in: endpoint { - slave-mode; remote-endpoint = <&acpu_funnel_out>; }; @@ -49,21 +45,17 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { etf_in: endpoint { - slave-mode; remote-endpoint = <&soc_funnel_out>; }; }; + }; - port@1 { - reg = <0>; + out-ports { + port { etf_out: endpoint { remote-endpoint = <&replicator_in>; @@ -77,20 +69,20 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { replicator_in: endpoint { - slave-mode; remote-endpoint = <&etf_out>; }; }; + }; - port@1 { + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; replicator_out0: endpoint { remote-endpoint = @@ -98,7 +90,7 @@ }; }; - port@2 { + port@1 { reg = <1>; replicator_out1: endpoint { remote-endpoint = @@ -114,14 +106,9 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { etr_in: endpoint { - slave-mode; remote-endpoint = <&replicator_out0>; }; @@ -135,14 +122,9 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { tpiu_in: endpoint { - slave-mode; remote-endpoint = <&replicator_out1>; }; @@ -156,85 +138,78 @@ clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; clock-names = "apb_pclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + out-ports { + port { acpu_funnel_out: endpoint { remote-endpoint = <&soc_funnel_in>; }; }; + }; - port@1 { + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; acpu_funnel_in0: endpoint { - slave-mode; remote-endpoint = <&etm0_out>; }; }; - port@2 { + port@1 { reg = <1>; acpu_funnel_in1: endpoint { - slave-mode; remote-endpoint = <&etm1_out>; }; }; - port@3 { + port@2 { reg = <2>; acpu_funnel_in2: endpoint { - slave-mode; remote-endpoint = <&etm2_out>; }; }; - port@4 { + port@3 { reg = <3>; acpu_funnel_in3: endpoint { - slave-mode; remote-endpoint = <&etm3_out>; }; }; - port@5 { + port@4 { reg = <4>; acpu_funnel_in4: endpoint { - slave-mode; remote-endpoint = <&etm4_out>; }; }; - port@6 { + port@5 { reg = <5>; acpu_funnel_in5: endpoint { - slave-mode; remote-endpoint = <&etm5_out>; }; }; - port@7 { + port@6 { reg = <6>; acpu_funnel_in6: endpoint { - slave-mode; remote-endpoint = <&etm6_out>; }; }; - port@8 { + port@7 { reg = <7>; acpu_funnel_in7: endpoint { - slave-mode; remote-endpoint = <&etm7_out>; }; @@ -251,10 +226,12 @@ cpu = <&cpu0>; - port { - etm0_out: endpoint { - remote-endpoint = - <&acpu_funnel_in0>; + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = + <&acpu_funnel_in0>; + }; }; }; }; @@ -268,10 +245,12 @@ cpu = <&cpu1>; - port { - etm1_out: endpoint { - remote-endpoint = - <&acpu_funnel_in1>; + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = + <&acpu_funnel_in1>; + }; }; }; }; @@ -285,10 +264,12 @@ cpu = <&cpu2>; - port { - etm2_out: endpoint { - remote-endpoint = - <&acpu_funnel_in2>; + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = + <&acpu_funnel_in2>; + }; }; }; }; @@ -302,10 +283,12 @@ cpu = <&cpu3>; - port { - etm3_out: endpoint { - remote-endpoint = - <&acpu_funnel_in3>; + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = + <&acpu_funnel_in3>; + }; }; }; }; @@ -319,10 +302,12 @@ cpu = <&cpu4>; - port { - etm4_out: endpoint { - remote-endpoint = - <&acpu_funnel_in4>; + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = + <&acpu_funnel_in4>; + }; }; }; }; @@ -336,10 +321,12 @@ cpu = <&cpu5>; - port { - etm5_out: endpoint { - remote-endpoint = - <&acpu_funnel_in5>; + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = + <&acpu_funnel_in5>; + }; }; }; }; @@ -353,10 +340,12 @@ cpu = <&cpu6>; - port { - etm6_out: endpoint { - remote-endpoint = - <&acpu_funnel_in6>; + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = + <&acpu_funnel_in6>; + }; }; }; }; @@ -370,10 +359,12 @@ cpu = <&cpu7>; - port { - etm7_out: endpoint { - remote-endpoint = - <&acpu_funnel_in7>; + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = + <&acpu_funnel_in7>; + }; }; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 247024df714f..97d5bf2c6ec5 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -99,6 +99,7 @@ reg = <0x0 0x1>; enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -111,6 +112,7 @@ reg = <0x0 0x2>; enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -123,6 +125,7 @@ reg = <0x0 0x3>; enable-method = "psci"; next-level-cache = <&CLUSTER0_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -135,6 +138,7 @@ reg = <0x0 0x100>; enable-method = "psci"; next-level-cache = <&CLUSTER1_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -147,6 +151,7 @@ reg = <0x0 0x101>; enable-method = "psci"; next-level-cache = <&CLUSTER1_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -159,6 +164,7 @@ reg = <0x0 0x102>; enable-method = "psci"; next-level-cache = <&CLUSTER1_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ @@ -171,6 +177,7 @@ reg = <0x0 0x103>; enable-method = "psci"; next-level-cache = <&CLUSTER1_L2>; + clocks = <&stub_clock 0>; operating-points-v2 = <&cpu_opp_table>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; #cooling-cells = <2>; /* min followed by max */ diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi b/arch/arm64/boot/dts/lg/lg1312.dtsi index 860c8fb10795..4bde7b6f2b11 100644 --- a/arch/arm64/boot/dts/lg/lg1312.dtsi +++ b/arch/arm64/boot/dts/lg/lg1312.dtsi @@ -168,14 +168,14 @@ clock-names = "apb_pclk"; status="disabled"; }; - spi0: ssp@fe800000 { + spi0: spi@fe800000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x0 0xfe800000 0x1000>; interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_bus>; clock-names = "apb_pclk"; }; - spi1: ssp@fe900000 { + spi1: spi@fe900000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x0 0xfe900000 0x1000>; interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm64/boot/dts/lg/lg1313.dtsi b/arch/arm64/boot/dts/lg/lg1313.dtsi index 1887af654a7d..16ced1ff1ad3 100644 --- a/arch/arm64/boot/dts/lg/lg1313.dtsi +++ b/arch/arm64/boot/dts/lg/lg1313.dtsi @@ -168,14 +168,14 @@ clock-names = "apb_pclk"; status="disabled"; }; - spi0: ssp@fe800000 { + spi0: spi@fe800000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x0 0xfe800000 0x1000>; interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_bus>; clock-names = "apb_pclk"; }; - spi1: ssp@fe900000 { + spi1: spi@fe900000 { compatible = "arm,pl022", "arm,primecell"; reg = <0x0 0xfe900000 0x1000>; interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile index ea9d49f2a911..eca8bac6303a 100644 --- a/arch/arm64/boot/dts/marvell/Makefile +++ b/arch/arm64/boot/dts/marvell/Makefile @@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-espressobin.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-7040-db.dtb +dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-clearfog-gt-8k.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8080-db.dtb diff --git a/arch/arm64/boot/dts/marvell/armada-372x.dtsi b/arch/arm64/boot/dts/marvell/armada-372x.dtsi index 97558a64e276..6800945a88ad 100644 --- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi @@ -16,7 +16,7 @@ compatible = "marvell,armada3720", "marvell,armada3710"; cpus { - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; reg = <0x1>; diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index d9531e242eb4..4472bcd8f9fb 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -40,7 +40,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0>; @@ -80,6 +80,19 @@ /* 32M internal register @ 0xd000_0000 */ ranges = <0x0 0x0 0xd0000000 0x2000000>; + wdt: watchdog@8300 { + compatible = "marvell,armada-3700-wdt"; + reg = <0x8300 0x40>; + marvell,system-controller = <&cpu_misc>; + clocks = <&xtalclk>; + }; + + cpu_misc: system-controller@d000 { + compatible = "marvell,armada-3700-cpu-misc", + "syscon"; + reg = <0xd000 0x1000>; + }; + spi0: spi@10600 { compatible = "marvell,armada-3700-spi"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts new file mode 100644 index 000000000000..9473d40a292a --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 SolidRun ltd. + * Based on Marvell MACCHIATOBin board + * + * Device Tree file for SolidRun's ClearFog GT 8K + */ + +#include "armada-8040.dtsi" + +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "SolidRun ClearFog GT 8K"; + compatible = "solidrun,clearfog-gt-8k", "marvell,armada8040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + aliases { + ethernet0 = &cp1_eth1; + ethernet1 = &cp0_eth0; + ethernet2 = &cp1_eth2; + }; + + v_3_3: regulator-3-3v { + compatible = "regulator-fixed"; + regulator-name = "v_3_3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + status = "okay"; + }; + + v_5v0_usb3_hst_vbus: regulator-usb3-vbus0 { + compatible = "regulator-fixed"; + gpio = <&cp0_gpio2 15 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_xhci_vbus_pins>; + regulator-name = "v_5v0_usb3_hst_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + status = "okay"; + }; + + usb3h0_phy: usb3_phy0 { + compatible = "usb-nop-xceiv"; + vcc-supply = <&v_5v0_usb3_hst_vbus>; + }; + + sfp_cp0_eth0: sfp-cp0-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&cp0_i2c1>; + mod-def0-gpio = <&cp0_gpio2 17 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_sfp_present_pins &cp1_sfp_tx_disable_pins>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&cp0_led0_pins + &cp0_led1_pins>; + pinctrl-names = "default"; + /* No designated function for these LEDs at the moment */ + led0 { + label = "clearfog-gt-8k:green:led0"; + gpios = <&cp0_gpio2 8 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + led1 { + label = "clearfog-gt-8k:green:led1"; + gpios = <&cp0_gpio2 9 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&cp0_gpio_reset_pins &cp1_wps_button_pins>; + pinctrl-names = "default"; + + button_0 { + /* The rear button */ + label = "Rear Button"; + gpios = <&cp0_gpio2 7 GPIO_ACTIVE_LOW>; + linux,can-disable; + linux,code = <BTN_0>; + }; + + button_1 { + /* The wps button */ + label = "WPS Button"; + gpios = <&cp1_gpio1 30 GPIO_ACTIVE_LOW>; + linux,can-disable; + linux,code = <KEY_WPS_BUTTON>; + }; + }; +}; + +&uart0 { + status = "okay"; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&ap_sdhci0 { + bus-width = <8>; + no-1-8-v; + no-sd; + no-sdio; + non-removable; + status = "okay"; + vqmmc-supply = <&v_3_3>; +}; + +&cp0_i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + status = "okay"; +}; + +&cp0_i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c1_pins>; + status = "okay"; +}; + +&cp0_pinctrl { + /* + * MPP Bus: + * [0-31] = 0xff: Keep default CP0_shared_pins: + * [11] CLKOUT_MPP_11 (out) + * [23] LINK_RD_IN_CP2CP (in) + * [25] CLKOUT_MPP_25 (out) + * [29] AVS_FB_IN_CP2CP (in) + * [32, 33, 34] pci0/1/2 reset + * [35-38] CP0 I2C1 and I2C0 + * [39] GPIO reset button + * [40,41] LED0 and LED1 + * [43] 1512 phy reset + * [47] USB VBUS EN (active low) + * [48] FAN PWM + * [49] SFP+ present signal + * [50] TPM interrupt + * [51] WLAN0 disable + * [52] WLAN1 disable + * [53] LTE disable + * [54] NFC reset + * [55] Micro SD card detect + * [56-61] Micro SD + */ + + cp0_pci0_reset_pins: pci0-reset-pins { + marvell,pins = "mpp32"; + marvell,function = "gpio"; + }; + + cp0_pci1_reset_pins: pci1-reset-pins { + marvell,pins = "mpp33"; + marvell,function = "gpio"; + }; + + cp0_pci2_reset_pins: pci2-reset-pins { + marvell,pins = "mpp34"; + marvell,function = "gpio"; + }; + + cp0_i2c1_pins: i2c1-pins { + marvell,pins = "mpp35", "mpp36"; + marvell,function = "i2c1"; + }; + + cp0_i2c0_pins: i2c0-pins { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + + cp0_gpio_reset_pins: gpio-reset-pins { + marvell,pins = "mpp39"; + marvell,function = "gpio"; + }; + + cp0_led0_pins: led0-pins { + marvell,pins = "mpp40"; + marvell,function = "gpio"; + }; + + cp0_led1_pins: led1-pins { + marvell,pins = "mpp41"; + marvell,function = "gpio"; + }; + + cp0_copper_eth_phy_reset: copper-eth-phy-reset { + marvell,pins = "mpp43"; + marvell,function = "gpio"; + }; + + cp0_xhci_vbus_pins: xhci0-vbus-pins { + marvell,pins = "mpp47"; + marvell,function = "gpio"; + }; + + cp0_fan_pwm_pins: fan-pwm-pins { + marvell,pins = "mpp48"; + marvell,function = "gpio"; + }; + + cp0_sfp_present_pins: sfp-present-pins { + marvell,pins = "mpp49"; + marvell,function = "gpio"; + }; + + cp0_tpm_irq_pins: tpm-irq-pins { + marvell,pins = "mpp50"; + marvell,function = "gpio"; + }; + + cp0_sdhci_pins: sdhci-pins { + marvell,pins = "mpp55", "mpp56", "mpp57", "mpp58", "mpp59", + "mpp60", "mpp61"; + marvell,function = "sdio"; + }; +}; + +&cp0_pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_pci0_reset_pins>; + reset-gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&cp0_gpio2 { + sata_reset { + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&cp0_ethernet { + status = "okay"; +}; + +/* SFP */ +&cp0_eth0 { + status = "okay"; + phy-mode = "10gbase-kr"; + managed = "in-band-status"; + phys = <&cp0_comphy2 0>; + sfp = <&sfp_cp0_eth0>; +}; + +&cp0_sdhci0 { + broken-cd; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_sdhci_pins>; + status = "okay"; + vqmmc-supply = <&v_3_3>; +}; + +&cp1_pinctrl { + /* + * MPP Bus: + * [0-5] TDM + * [6] VHV Enable + * [7] CP1 SPI0 CSn1 (FXS) + * [8] CP1 SPI0 CSn0 (TPM) + * [9.11]CP1 SPI0 MOSI/MISO/CLK + * [13] CP1 SPI1 MISO (TDM and SPI ROM shared) + * [14] CP1 SPI1 CS0n (64Mb SPI ROM) + * [15] CP1 SPI1 MOSI (TDM and SPI ROM shared) + * [16] CP1 SPI1 CLK (TDM and SPI ROM shared) + * [24] Topaz switch reset + * [26] Buzzer + * [27] CP1 SMI MDIO + * [28] CP1 SMI MDC + * [29] CP0 10G SFP TX Disable + * [30] WPS button + * [31] Front panel button + */ + + cp1_spi1_pins: spi1-pins { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + + cp1_switch_reset_pins: switch-reset-pins { + marvell,pins = "mpp24"; + marvell,function = "gpio"; + }; + + cp1_ge_mdio_pins: ge-mdio-pins { + marvell,pins = "mpp27", "mpp28"; + marvell,function = "ge"; + }; + + cp1_sfp_tx_disable_pins: sfp-tx-disable-pins { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + cp1_wps_button_pins: wps-button-pins { + marvell,pins = "mpp30"; + marvell,function = "gpio"; + }; +}; + +&cp1_sata0 { + pinctrl-0 = <&cp0_pci1_reset_pins>; + status = "okay"; +}; + +&cp1_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&cp1_ge_mdio_pins>; + status = "okay"; + + ge_phy: ethernet-phy@0 { + /* LED0 - GB link + * LED1 - on: link, blink: activity + */ + marvell,reg-init = <3 16 0 0x1017>; + reg = <0>; + }; + + switch0: switch0@4 { + compatible = "marvell,mv88e6085"; + reg = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&cp1_switch_reset_pins>; + reset-gpios = <&cp1_gpio1 24 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan2"; + phy-handle = <&switch0phy0>; + }; + + port@2 { + reg = <2>; + label = "lan1"; + phy-handle = <&switch0phy1>; + }; + + port@3 { + reg = <3>; + label = "lan4"; + phy-handle = <&switch0phy2>; + }; + + port@4 { + reg = <4>; + label = "lan3"; + phy-handle = <&switch0phy3>; + }; + + port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&cp1_eth2>; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + switch0phy0: switch0phy0@11 { + reg = <0x11>; + }; + + switch0phy1: switch0phy1@12 { + reg = <0x12>; + }; + + switch0phy2: switch0phy2@13 { + reg = <0x13>; + }; + + switch0phy3: switch0phy3@14 { + reg = <0x14>; + }; + }; + }; +}; + +&cp1_ethernet { + status = "okay"; +}; + +/* 1G copper */ +&cp1_eth1 { + status = "okay"; + phy-mode = "sgmii"; + phy = <&ge_phy>; + phys = <&cp1_comphy3 1>; +}; + +/* Switch uplink */ +&cp1_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy5 2>; + fixed-link { + speed = <2500>; + full-duplex; + }; +}; + +&cp1_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&cp1_spi1_pins>; + status = "okay"; + + spi-flash@0 { + compatible = "st,w25q32"; + spi-max-frequency = <50000000>; + reg = <0>; + }; +}; + +&cp1_usb3_0 { + usb-phy = <&usb3h0_phy>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi index 64b5e61a698e..d3c0636558ff 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi @@ -15,13 +15,13 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x000>; enable-method = "psci"; }; - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x001>; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi index 746e792767f5..64632c873888 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi @@ -15,29 +15,33 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x000>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; }; - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x001>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; }; - cpu@100 { + cpu2: cpu@100 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x100>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; }; - cpu@101 { + cpu3: cpu@101 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x101>; enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; }; }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index 176e38d54872..073610ac0a53 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -6,6 +6,7 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/thermal/thermal.h> /dts-v1/; @@ -27,6 +28,33 @@ method = "smc"; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + idle_states { + entry_method = "arm,pcsi"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <80>; + exit-latency-us = <160>; + min-residency-us = <320>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + }; + ap806 { #address-cells = <2>; #size-cells = <2>; @@ -124,6 +152,15 @@ interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>; }; + sei: interrupt-controller@3f0200 { + compatible = "marvell,ap806-sei"; + reg = <0x3f0200 0x40>; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <1>; + interrupt-controller; + msi-controller; + }; + xor@400000 { compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; reg = <0x400000 0x1000>, @@ -247,11 +284,76 @@ }; }; - ap_thermal: thermal@6f808c { - compatible = "marvell,armada-ap806-thermal"; - reg = <0x6f808c 0x4>, - <0x6f8084 0x8>; + ap_syscon1: system-controller@6f8000 { + compatible = "syscon", "simple-mfd"; + reg = <0x6f8000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + ap_thermal: thermal-sensor@80 { + compatible = "marvell,armada-ap806-thermal"; + reg = <0x80 0x10>; + #thermal-sensor-cells = <1>; + }; }; }; }; + + /* + * The thermal IP features one internal sensor plus, if applicable, one + * remote channel wired to one sensor per CPU. + * + * The cooling maps are always empty as there are no cooling devices. + */ + thermal-zones { + ap_thermal_ic: ap-thermal-ic { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&ap_thermal 0>; + + trips { }; + cooling-maps { }; + }; + + ap_thermal_cpu1: ap-thermal-cpu1 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&ap_thermal 1>; + + trips { }; + cooling-maps { }; + }; + + ap_thermal_cpu2: ap-thermal-cpu2 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&ap_thermal 2>; + + trips { }; + cooling-maps { }; + }; + + ap_thermal_cpu3: ap-thermal-cpu3 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&ap_thermal 3>; + + trips { }; + cooling-maps { }; + }; + + ap_thermal_cpu4: ap-thermal-cpu4 { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&ap_thermal 4>; + + trips { }; + cooling-maps { }; + }; + }; }; diff --git a/arch/arm64/boot/dts/marvell/armada-ap810-ap0-octa-core.dtsi b/arch/arm64/boot/dts/marvell/armada-ap810-ap0-octa-core.dtsi index 7d00ae78fc79..b788cb63caf2 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap810-ap0-octa-core.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap810-ap0-octa-core.dtsi @@ -13,49 +13,49 @@ #size-cells = <0>; compatible = "marvell,armada-ap810-octa"; - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x000>; enable-method = "psci"; }; - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x001>; enable-method = "psci"; }; - cpu@100 { + cpu2: cpu@100 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x100>; enable-method = "psci"; }; - cpu@101 { + cpu3: cpu@101 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x101>; enable-method = "psci"; }; - cpu@200 { + cpu4: cpu@200 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x200>; enable-method = "psci"; }; - cpu@201 { + cpu5: cpu@201 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x201>; enable-method = "psci"; }; - cpu@300 { + cpu6: cpu@300 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x300>; enable-method = "psci"; }; - cpu@301 { + cpu7: cpu@301 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0x301>; diff --git a/arch/arm64/boot/dts/marvell/armada-common.dtsi b/arch/arm64/boot/dts/marvell/armada-common.dtsi index d5e8aedec188..b29c6405d214 100644 --- a/arch/arm64/boot/dts/marvell/armada-common.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-common.dtsi @@ -7,4 +7,5 @@ #define PASTER(x, y) x ## y #define EVALUATOR(x, y) PASTER(x, y) #define CP110_LABEL(name) EVALUATOR(CP110_NAME, EVALUATOR(_, name)) +#define CP110_NODE_NAME(name) EVALUATOR(CP110_NAME, EVALUATOR(-, name)) #define ADDRESSIFY(addr) EVALUATOR(0x, addr) diff --git a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi index 840c8454d03e..b9d9f31e3ba1 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi @@ -6,6 +6,7 @@ */ #include <dt-bindings/interrupt-controller/mvebu-icu.h> +#include <dt-bindings/thermal/thermal.h> #include "armada-common.dtsi" @@ -19,13 +20,30 @@ * save one indentation level */ CP110_NAME: CP110_NAME { }; + + /* + * CPs only have one sensor in the thermal IC. + * + * The cooling maps are empty as there are no cooling devices. + */ + thermal-zones { + CP110_LABEL(thermal_ic): CP110_NODE_NAME(thermal-ic) { + polling-delay-passive = <1000>; + polling-delay = <1000>; + + thermal-sensors = <&CP110_LABEL(thermal) 0>; + + trips { }; + cooling-maps { }; + }; + }; }; &CP110_NAME { #address-cells = <2>; #size-cells = <2>; compatible = "simple-bus"; - interrupt-parent = <&CP110_LABEL(icu)>; + interrupt-parent = <&CP110_LABEL(icu_nsr)>; ranges; config-space@CP110_BASE { @@ -47,42 +65,57 @@ dma-coherent; CP110_LABEL(eth0): eth0 { - interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 43 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 47 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 51 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 55 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 129 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2", - "tx-cpu3", "rx-shared", "link"; + interrupts = <39 IRQ_TYPE_LEVEL_HIGH>, + <43 IRQ_TYPE_LEVEL_HIGH>, + <47 IRQ_TYPE_LEVEL_HIGH>, + <51 IRQ_TYPE_LEVEL_HIGH>, + <55 IRQ_TYPE_LEVEL_HIGH>, + <59 IRQ_TYPE_LEVEL_HIGH>, + <63 IRQ_TYPE_LEVEL_HIGH>, + <67 IRQ_TYPE_LEVEL_HIGH>, + <71 IRQ_TYPE_LEVEL_HIGH>, + <129 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hif0", "hif1", "hif2", + "hif3", "hif4", "hif5", "hif6", "hif7", + "hif8", "link"; port-id = <0>; gop-port-id = <0>; status = "disabled"; }; CP110_LABEL(eth1): eth1 { - interrupts = <ICU_GRP_NSR 40 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 44 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 48 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 52 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 56 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 128 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2", - "tx-cpu3", "rx-shared", "link"; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH>, + <44 IRQ_TYPE_LEVEL_HIGH>, + <48 IRQ_TYPE_LEVEL_HIGH>, + <52 IRQ_TYPE_LEVEL_HIGH>, + <56 IRQ_TYPE_LEVEL_HIGH>, + <60 IRQ_TYPE_LEVEL_HIGH>, + <64 IRQ_TYPE_LEVEL_HIGH>, + <68 IRQ_TYPE_LEVEL_HIGH>, + <72 IRQ_TYPE_LEVEL_HIGH>, + <128 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hif0", "hif1", "hif2", + "hif3", "hif4", "hif5", "hif6", "hif7", + "hif8", "link"; port-id = <1>; gop-port-id = <2>; status = "disabled"; }; CP110_LABEL(eth2): eth2 { - interrupts = <ICU_GRP_NSR 41 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 45 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 49 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 53 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 57 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 127 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "tx-cpu0", "tx-cpu1", "tx-cpu2", - "tx-cpu3", "rx-shared", "link"; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH>, + <45 IRQ_TYPE_LEVEL_HIGH>, + <49 IRQ_TYPE_LEVEL_HIGH>, + <53 IRQ_TYPE_LEVEL_HIGH>, + <57 IRQ_TYPE_LEVEL_HIGH>, + <61 IRQ_TYPE_LEVEL_HIGH>, + <65 IRQ_TYPE_LEVEL_HIGH>, + <69 IRQ_TYPE_LEVEL_HIGH>, + <73 IRQ_TYPE_LEVEL_HIGH>, + <127 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hif0", "hif1", "hif2", + "hif3", "hif4", "hif5", "hif6", "hif7", + "hif8", "link"; port-id = <2>; gop-port-id = <3>; status = "disabled"; @@ -150,22 +183,31 @@ CP110_LABEL(icu): interrupt-controller@1e0000 { compatible = "marvell,cp110-icu"; reg = <0x1e0000 0x440>; - #interrupt-cells = <3>; - interrupt-controller; - msi-parent = <&gicp>; + #address-cells = <1>; + #size-cells = <1>; + + CP110_LABEL(icu_nsr): interrupt-controller@10 { + compatible = "marvell,cp110-icu-nsr"; + reg = <0x10 0x20>; + #interrupt-cells = <2>; + interrupt-controller; + msi-parent = <&gicp>; + }; + + CP110_LABEL(icu_sei): interrupt-controller@50 { + compatible = "marvell,cp110-icu-sei"; + reg = <0x50 0x10>; + #interrupt-cells = <2>; + interrupt-controller; + msi-parent = <&sei>; + }; }; CP110_LABEL(rtc): rtc@284000 { compatible = "marvell,armada-8k-rtc"; reg = <0x284000 0x20>, <0x284080 0x24>; reg-names = "rtc", "rtc-soc"; - interrupts = <ICU_GRP_NSR 77 IRQ_TYPE_LEVEL_HIGH>; - }; - - CP110_LABEL(thermal): thermal@400078 { - compatible = "marvell,armada-cp110-thermal"; - reg = <0x400078 0x4>, - <0x400070 0x8>; + interrupts = <77 IRQ_TYPE_LEVEL_HIGH>; }; CP110_LABEL(syscon0): system-controller@440000 { @@ -185,10 +227,10 @@ #gpio-cells = <2>; gpio-ranges = <&CP110_LABEL(pinctrl) 0 0 32>; interrupt-controller; - interrupts = <ICU_GRP_NSR 86 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 85 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 84 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 83 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <86 IRQ_TYPE_LEVEL_HIGH>, + <85 IRQ_TYPE_LEVEL_HIGH>, + <84 IRQ_TYPE_LEVEL_HIGH>, + <83 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; @@ -200,20 +242,33 @@ #gpio-cells = <2>; gpio-ranges = <&CP110_LABEL(pinctrl) 0 32 31>; interrupt-controller; - interrupts = <ICU_GRP_NSR 82 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 81 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 80 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 79 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <82 IRQ_TYPE_LEVEL_HIGH>, + <81 IRQ_TYPE_LEVEL_HIGH>, + <80 IRQ_TYPE_LEVEL_HIGH>, + <79 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; }; + CP110_LABEL(syscon1): system-controller@400000 { + compatible = "syscon", "simple-mfd"; + reg = <0x400000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + CP110_LABEL(thermal): thermal-sensor@70 { + compatible = "marvell,armada-cp110-thermal"; + reg = <0x70 0x10>; + #thermal-sensor-cells = <1>; + }; + }; + CP110_LABEL(usb3_0): usb3@500000 { compatible = "marvell,armada-8k-xhci", "generic-xhci"; reg = <0x500000 0x4000>; dma-coherent; - interrupts = <ICU_GRP_NSR 106 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <106 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 22>, <&CP110_LABEL(clk) 1 16>; @@ -225,7 +280,7 @@ "generic-xhci"; reg = <0x510000 0x4000>; dma-coherent; - interrupts = <ICU_GRP_NSR 105 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <105 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 23>, <&CP110_LABEL(clk) 1 16>; @@ -237,7 +292,7 @@ "generic-ahci"; reg = <0x540000 0x30000>; dma-coherent; - interrupts = <ICU_GRP_NSR 107 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&CP110_LABEL(clk) 1 15>, <&CP110_LABEL(clk) 1 16>; status = "disabled"; @@ -290,7 +345,7 @@ reg = <0x701000 0x20>; #address-cells = <1>; #size-cells = <0>; - interrupts = <ICU_GRP_NSR 120 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <120 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 21>, <&CP110_LABEL(clk) 1 17>; @@ -302,7 +357,7 @@ reg = <0x701100 0x20>; #address-cells = <1>; #size-cells = <0>; - interrupts = <ICU_GRP_NSR 121 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <121 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 21>, <&CP110_LABEL(clk) 1 17>; @@ -313,7 +368,7 @@ compatible = "snps,dw-apb-uart"; reg = <0x702000 0x100>; reg-shift = <2>; - interrupts = <ICU_GRP_NSR 122 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <122 IRQ_TYPE_LEVEL_HIGH>; reg-io-width = <1>; clock-names = "baudclk", "apb_pclk"; clocks = <&CP110_LABEL(clk) 1 21>, @@ -325,7 +380,7 @@ compatible = "snps,dw-apb-uart"; reg = <0x702100 0x100>; reg-shift = <2>; - interrupts = <ICU_GRP_NSR 123 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <123 IRQ_TYPE_LEVEL_HIGH>; reg-io-width = <1>; clock-names = "baudclk", "apb_pclk"; clocks = <&CP110_LABEL(clk) 1 21>, @@ -337,7 +392,7 @@ compatible = "snps,dw-apb-uart"; reg = <0x702200 0x100>; reg-shift = <2>; - interrupts = <ICU_GRP_NSR 124 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <124 IRQ_TYPE_LEVEL_HIGH>; reg-io-width = <1>; clock-names = "baudclk", "apb_pclk"; clocks = <&CP110_LABEL(clk) 1 21>, @@ -349,7 +404,7 @@ compatible = "snps,dw-apb-uart"; reg = <0x702300 0x100>; reg-shift = <2>; - interrupts = <ICU_GRP_NSR 125 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <125 IRQ_TYPE_LEVEL_HIGH>; reg-io-width = <1>; clock-names = "baudclk", "apb_pclk"; clocks = <&CP110_LABEL(clk) 1 21>, @@ -368,7 +423,7 @@ reg = <0x720000 0x54>; #address-cells = <1>; #size-cells = <0>; - interrupts = <ICU_GRP_NSR 115 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <115 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 2>, <&CP110_LABEL(clk) 1 17>; @@ -380,7 +435,7 @@ compatible = "marvell,armada-8k-rng", "inside-secure,safexcel-eip76"; reg = <0x760000 0x7d>; - interrupts = <ICU_GRP_NSR 95 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 25>, <&CP110_LABEL(clk) 1 17>; @@ -390,7 +445,7 @@ CP110_LABEL(sdhci0): sdhci@780000 { compatible = "marvell,armada-cp110-sdhci"; reg = <0x780000 0x300>; - interrupts = <ICU_GRP_NSR 27 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <27 IRQ_TYPE_LEVEL_HIGH>; clock-names = "core", "axi"; clocks = <&CP110_LABEL(clk) 1 4>, <&CP110_LABEL(clk) 1 18>; dma-coherent; @@ -400,12 +455,12 @@ CP110_LABEL(crypto): crypto@800000 { compatible = "inside-secure,safexcel-eip197b"; reg = <0x800000 0x200000>; - interrupts = <ICU_GRP_NSR 87 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 88 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 89 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 90 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 91 IRQ_TYPE_LEVEL_HIGH>, - <ICU_GRP_NSR 92 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <87 IRQ_TYPE_LEVEL_HIGH>, + <88 IRQ_TYPE_LEVEL_HIGH>, + <89 IRQ_TYPE_LEVEL_HIGH>, + <90 IRQ_TYPE_LEVEL_HIGH>, + <91 IRQ_TYPE_LEVEL_HIGH>, + <92 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "mem", "ring0", "ring1", "ring2", "ring3", "eip"; clock-names = "core", "reg"; @@ -434,8 +489,8 @@ /* non-prefetchable memory */ 0x82000000 0 CP110_PCIEx_MEM_BASE(0) 0 CP110_PCIEx_MEM_BASE(0) 0 0xf00000>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &CP110_LABEL(icu) ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>; - interrupts = <ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map = <0 0 0 0 &CP110_LABEL(icu_nsr) 22 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; num-lanes = <1>; clock-names = "core", "reg"; clocks = <&CP110_LABEL(clk) 1 13>, <&CP110_LABEL(clk) 1 14>; @@ -461,8 +516,8 @@ /* non-prefetchable memory */ 0x82000000 0 CP110_PCIEx_MEM_BASE(1) 0 CP110_PCIEx_MEM_BASE(1) 0 0xf00000>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &CP110_LABEL(icu) ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>; - interrupts = <ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map = <0 0 0 0 &CP110_LABEL(icu_nsr) 24 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; num-lanes = <1>; clock-names = "core", "reg"; @@ -489,8 +544,8 @@ /* non-prefetchable memory */ 0x82000000 0 CP110_PCIEx_MEM_BASE(2) 0 CP110_PCIEx_MEM_BASE(2) 0 0xf00000>; interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &CP110_LABEL(icu) ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>; - interrupts = <ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map = <0 0 0 0 &CP110_LABEL(icu_nsr) 23 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; num-lanes = <1>; clock-names = "core", "reg"; diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile index 5b7fd6ad96e4..e8f952fb279b 100644 --- a/arch/arm64/boot/dts/mediatek/Makefile +++ b/arch/arm64/boot/dts/mediatek/Makefile @@ -5,4 +5,5 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb +dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi index 75cc0f7cc088..ee627a7c7b45 100644 --- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi @@ -301,6 +301,17 @@ status = "disabled"; }; + spis1: spi@10013000 { + compatible = "mediatek,mt2712-spi-slave"; + reg = <0 0x10013000 0 0x100>; + interrupts = <GIC_SPI 283 IRQ_TYPE_LEVEL_LOW>; + clocks = <&infracfg CLK_INFRA_AO_SPI1>; + clock-names = "spi"; + assigned-clocks = <&topckgen CLK_TOP_SPISLV_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>; + status = "disabled"; + }; + apmixedsys: syscon@10209000 { compatible = "mediatek,mt2712-apmixedsys", "syscon"; reg = <0 0x10209000 0 0x1000>; diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts new file mode 100644 index 000000000000..5d6005c9b097 --- /dev/null +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@mediatek.com> + * + * SPDX-License-Identifier: (GPL-2.0 OR MIT) + */ + +/dts-v1/; +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> + +#include "mt7622.dtsi" +#include "mt6380.dtsi" + +/ { + model = "Bananapi BPI-R64"; + compatible = "bananapi,bpi-r64", "mediatek,mt7622"; + + chosen { + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { + cpu@0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + + cpu@1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + factory { + label = "factory"; + linux,code = <BTN_0>; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + + wps { + label = "wps"; + linux,code = <KEY_WPS_BUTTON>; + gpios = <&pio 102 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + green { + label = "bpi-r64:pio:green"; + gpios = <&pio 89 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red { + label = "bpi-r64:pio:red"; + gpios = <&pio 88 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&bch { + status = "disabled"; +}; + +&btif { + status = "okay"; +}; + +&cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy5>; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "sgmii"; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&emmc_pins_default>; + pinctrl-1 = <&emmc_pins_uhs>; + status = "okay"; + bus-width = <8>; + max-frequency = <50000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; + non-removable; +}; + +&mmc1 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&sd0_pins_default>; + pinctrl-1 = <&sd0_pins_uhs>; + status = "okay"; + bus-width = <4>; + max-frequency = <50000000>; + cap-sd-highspeed; + r_smpl = <1>; + cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; + assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; +}; + +&nandc { + pinctrl-names = "default"; + pinctrl-0 = <¶llel_nand_pins>; + status = "disabled"; +}; + +&nor_flash { + pinctrl-names = "default"; + pinctrl-0 = <&spi_nor_pins>; + status = "disabled"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; + status = "okay"; + + pcie@0,0 { + status = "okay"; + }; + + pcie@1,0 { + status = "okay"; + }; +}; + +&pio { + /* Attention: GPIO 90 is used to switch between PCIe@1,0 and + * SATA functions. i.e. output-high: PCIe, output-low: SATA + */ + asm_sel { + gpio-hog; + gpios = <90 GPIO_ACTIVE_HIGH>; + output-high; + }; + + /* eMMC is shared pin with parallel NAND */ + emmc_pins_default: emmc-pins-default { + mux { + function = "emmc", "emmc_rst"; + groups = "emmc"; + }; + + /* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7", + * "NRB","NCLE" pins are used as DAT0,DAT1,DAT2,DAT3,DAT4, + * DAT5,DAT6,DAT7,CMD,CLK for eMMC respectively + */ + conf-cmd-dat { + pins = "NDL0", "NDL1", "NDL2", + "NDL3", "NDL4", "NDL5", + "NDL6", "NDL7", "NRB"; + input-enable; + bias-pull-up; + }; + + conf-clk { + pins = "NCLE"; + bias-pull-down; + }; + }; + + emmc_pins_uhs: emmc-pins-uhs { + mux { + function = "emmc"; + groups = "emmc"; + }; + + conf-cmd-dat { + pins = "NDL0", "NDL1", "NDL2", + "NDL3", "NDL4", "NDL5", + "NDL6", "NDL7", "NRB"; + input-enable; + drive-strength = <4>; + bias-pull-up; + }; + + conf-clk { + pins = "NCLE"; + drive-strength = <4>; + bias-pull-down; + }; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + i2c1_pins: i2c1-pins { + mux { + function = "i2c"; + groups = "i2c1_0"; + }; + }; + + i2c2_pins: i2c2-pins { + mux { + function = "i2c"; + groups = "i2c2_0"; + }; + }; + + i2s1_pins: i2s1-pins { + mux { + function = "i2s"; + groups = "i2s_out_mclk_bclk_ws", + "i2s1_in_data", + "i2s1_out_data"; + }; + + conf { + pins = "I2S1_IN", "I2S1_OUT", "I2S_BCLK", + "I2S_WS", "I2S_MCLK"; + drive-strength = <12>; + bias-pull-down; + }; + }; + + irrx_pins: irrx-pins { + mux { + function = "ir"; + groups = "ir_1_rx"; + }; + }; + + irtx_pins: irtx-pins { + mux { + function = "ir"; + groups = "ir_1_tx"; + }; + }; + + /* Parallel nand is shared pin with eMMC */ + parallel_nand_pins: parallel-nand-pins { + mux { + function = "flash"; + groups = "par_nand"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_1_waken", + "pcie0_1_clkreq"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie1_pad_perst", + "pcie1_0_waken", + "pcie1_0_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + pwm7_pins: pwm1-2-pins { + mux { + function = "pwm"; + groups = "pwm_ch7_2"; + }; + }; + + wled_pins: wled-pins { + mux { + function = "led"; + groups = "wled"; + }; + }; + + sd0_pins_default: sd0-pins-default { + mux { + function = "sd"; + groups = "sd_0"; + }; + + /* "I2S2_OUT, "I2S4_IN"", "I2S3_IN", "I2S2_IN", + * "I2S4_OUT", "I2S3_OUT" are used as DAT0, DAT1, + * DAT2, DAT3, CMD, CLK for SD respectively. + */ + conf-cmd-data { + pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN", + "I2S2_IN","I2S4_OUT"; + input-enable; + drive-strength = <8>; + bias-pull-up; + }; + conf-clk { + pins = "I2S3_OUT"; + drive-strength = <12>; + bias-pull-down; + }; + conf-cd { + pins = "TXD3"; + bias-pull-up; + }; + }; + + sd0_pins_uhs: sd0-pins-uhs { + mux { + function = "sd"; + groups = "sd_0"; + }; + + conf-cmd-data { + pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN", + "I2S2_IN","I2S4_OUT"; + input-enable; + bias-pull-up; + }; + + conf-clk { + pins = "I2S3_OUT"; + bias-pull-down; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + spic0_pins: spic0-pins { + mux { + function = "spi"; + groups = "spic0_0"; + }; + }; + + spic1_pins: spic1-pins { + mux { + function = "spi"; + groups = "spic1_0"; + }; + }; + + /* SPI-NOR is shared pin with serial NAND */ + spi_nor_pins: spi-nor-pins { + mux { + function = "flash"; + groups = "spi_nor"; + }; + }; + + /* serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx" ; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2_1_tx_rx" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm7_pins>; + status = "okay"; +}; + +&pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; + + status = "okay"; +}; + +&sata { + status = "disable"; +}; + +&sata_phy { + status = "disable"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spic0_pins>; + status = "okay"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic1_pins>; + status = "okay"; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&u3phy { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts index a747b7bf132d..dcad0869b84c 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts @@ -51,7 +51,7 @@ }; memory { - reg = <0 0x40000000 0 0x3F000000>; + reg = <0 0x40000000 0 0x20000000>; }; reg_1p8v: regulator-1p8v { @@ -81,6 +81,103 @@ }; }; +&bch { + status = "disabled"; +}; + +&btif { + status = "okay"; +}; + +&cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy5>; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "sgmii"; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&emmc_pins_default>; + pinctrl-1 = <&emmc_pins_uhs>; + status = "okay"; + bus-width = <8>; + max-frequency = <50000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; + non-removable; +}; + +&mmc1 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&sd0_pins_default>; + pinctrl-1 = <&sd0_pins_uhs>; + status = "okay"; + bus-width = <4>; + max-frequency = <50000000>; + cap-sd-highspeed; + r_smpl = <1>; + cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_3p3v>; + assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; +}; + +&nandc { + pinctrl-names = "default"; + pinctrl-0 = <¶llel_nand_pins>; + status = "disabled"; +}; + +&nor_flash { + pinctrl-names = "default"; + pinctrl-0 = <&spi_nor_pins>; + status = "disabled"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + }; +}; + &pcie { pinctrl-names = "default"; pinctrl-0 = <&pcie0_pins>; @@ -344,103 +441,6 @@ }; }; -&bch { - status = "disabled"; -}; - -&btif { - status = "okay"; -}; - -&cir { - pinctrl-names = "default"; - pinctrl-0 = <&irrx_pins>; - status = "okay"; -}; - -ð { - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - status = "okay"; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-handle = <&phy5>; - }; - - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - phy5: ethernet-phy@5 { - reg = <5>; - phy-mode = "sgmii"; - }; - }; -}; - -&i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; - status = "okay"; -}; - -&i2c2 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_pins>; - status = "okay"; -}; - -&mmc0 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&emmc_pins_default>; - pinctrl-1 = <&emmc_pins_uhs>; - status = "okay"; - bus-width = <8>; - max-frequency = <50000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; - assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; - non-removable; -}; - -&mmc1 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&sd0_pins_default>; - pinctrl-1 = <&sd0_pins_uhs>; - status = "okay"; - bus-width = <4>; - max-frequency = <50000000>; - cap-sd-highspeed; - r_smpl = <1>; - cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_3p3v>; - assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; -}; - -&nandc { - pinctrl-names = "default"; - pinctrl-0 = <¶llel_nand_pins>; - status = "disabled"; -}; - -&nor_flash { - pinctrl-names = "default"; - pinctrl-0 = <&spi_nor_pins>; - status = "disabled"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - }; -}; - &pwm { pinctrl-names = "default"; pinctrl-0 = <&pwm7_pins>; diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi index de2c47bdbe64..fe0c875f1d95 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -79,6 +79,7 @@ #cooling-cells = <2>; enable-method = "psci"; clock-frequency = <1300000000>; + cci-control-port = <&cci_control2>; }; cpu1: cpu@1 { @@ -92,6 +93,7 @@ #cooling-cells = <2>; enable-method = "psci"; clock-frequency = <1300000000>; + cci-control-port = <&cci_control2>; }; }; @@ -113,6 +115,13 @@ method = "smc"; }; + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_LOW>, + <GIC_SPI 9 IRQ_TYPE_LEVEL_LOW>; + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -218,6 +227,16 @@ #reset-cells = <1>; }; + timer: timer@10004000 { + compatible = "mediatek,mt7622-timer", + "mediatek,mt6577-timer"; + reg = <0 0x10004000 0 0x80>; + interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>; + clocks = <&infracfg CLK_INFRA_APXGPT_PD>, + <&topckgen CLK_TOP_RTC>; + clock-names = "system-clk", "rtc-clk"; + }; + scpsys: scpsys@10006000 { compatible = "mediatek,mt7622-scpsys", "syscon"; @@ -325,6 +344,42 @@ <0 0x10360000 0 0x2000>; }; + cci: cci@10390000 { + compatible = "arm,cci-400"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0x10390000 0 0x1000>; + ranges = <0 0 0x10390000 0x10000>; + + cci_control0: slave-if@1000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace-lite"; + reg = <0x1000 0x1000>; + }; + + cci_control1: slave-if@4000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x4000 0x1000>; + }; + + cci_control2: slave-if@5000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x5000 0x1000>; + }; + + pmu@9000 { + compatible = "arm,cci-400-pmu,r1"; + reg = <0x9000 0x5000>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + auxadc: adc@11001000 { compatible = "mediatek,mt7622-auxadc"; reg = <0 0x11001000 0 0x1000>; @@ -475,6 +530,13 @@ reg-shift = <2>; reg-io-width = <4>; status = "disabled"; + + bluetooth { + compatible = "mediatek,mt7622-bluetooth"; + power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; + clocks = <&clk25m>; + clock-names = "ref"; + }; }; nandc: nfi@1100d000 { diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi index b762227f6aa1..2f3c8e29520d 100644 --- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi @@ -4,6 +4,7 @@ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/mailbox/tegra186-hsp.h> #include <dt-bindings/memory/tegra186-mc.h> +#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> #include <dt-bindings/power/tegra186-powergate.h> #include <dt-bindings/reset/tegra186-reset.h> #include <dt-bindings/thermal/tegra186-bpmp-thermal.h> @@ -236,6 +237,20 @@ clock-names = "sdhci"; resets = <&bpmp TEGRA186_RESET_SDMMC1>; reset-names = "sdhci"; + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; + pinctrl-0 = <&sdmmc1_3v3>; + pinctrl-1 = <&sdmmc1_1v8>; + nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>; + nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>; + nvidia,pad-autocal-pull-up-offset-sdr104 = <0x03>; + nvidia,pad-autocal-pull-down-offset-sdr104 = <0x05>; + nvidia,default-tap = <0x5>; + nvidia,default-trim = <0xb>; + assigned-clocks = <&bpmp TEGRA186_CLK_SDMMC1>, + <&bpmp TEGRA186_CLK_PLLP_OUT0>; + assigned-clock-parents = <&bpmp TEGRA186_CLK_PLLP_OUT0>; status = "disabled"; }; @@ -247,6 +262,15 @@ clock-names = "sdhci"; resets = <&bpmp TEGRA186_RESET_SDMMC2>; reset-names = "sdhci"; + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; + pinctrl-0 = <&sdmmc2_3v3>; + pinctrl-1 = <&sdmmc2_1v8>; + nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>; + nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>; + nvidia,default-tap = <0x5>; + nvidia,default-trim = <0xb>; status = "disabled"; }; @@ -258,6 +282,17 @@ clock-names = "sdhci"; resets = <&bpmp TEGRA186_RESET_SDMMC3>; reset-names = "sdhci"; + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; + pinctrl-0 = <&sdmmc3_3v3>; + pinctrl-1 = <&sdmmc3_1v8>; + nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>; + nvidia,pad-autocal-pull-down-offset-1v8 = <0x7a>; + nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x06>; + nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x07>; + nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>; + nvidia,default-tap = <0x5>; + nvidia,default-trim = <0xb>; status = "disabled"; }; @@ -267,8 +302,19 @@ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; clocks = <&bpmp TEGRA186_CLK_SDMMC4>; clock-names = "sdhci"; + assigned-clocks = <&bpmp TEGRA186_CLK_SDMMC4>, + <&bpmp TEGRA186_CLK_PLLC4_VCO>; + assigned-clock-parents = <&bpmp TEGRA186_CLK_PLLC4_VCO>; resets = <&bpmp TEGRA186_RESET_SDMMC4>; reset-names = "sdhci"; + nvidia,pad-autocal-pull-up-offset-hs400 = <0x05>; + nvidia,pad-autocal-pull-down-offset-hs400 = <0x05>; + nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>; + nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x0a>; + nvidia,default-tap = <0x5>; + nvidia,default-trim = <0x9>; + nvidia,dqs-trim = <63>; + mmc-hs400-1_8v; status = "disabled"; }; @@ -368,6 +414,36 @@ <0 0x0c380000 0 0x10000>, <0 0x0c390000 0 0x10000>; reg-names = "pmc", "wake", "aotag", "scratch"; + + sdmmc1_3v3: sdmmc1-3v3 { + pins = "sdmmc1-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>; + }; + + sdmmc1_1v8: sdmmc1-1v8 { + pins = "sdmmc1-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>; + }; + + sdmmc2_3v3: sdmmc2-3v3 { + pins = "sdmmc2-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>; + }; + + sdmmc2_1v8: sdmmc2-1v8 { + pins = "sdmmc2-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>; + }; + + sdmmc3_3v3: sdmmc3-3v3 { + pins = "sdmmc3-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>; + }; + + sdmmc3_1v8: sdmmc3-1v8 { + pins = "sdmmc3-hv"; + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>; + }; }; ccplex@e000000 { diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi index a4dfcd19b9e8..9fc14bb9a0af 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi @@ -118,7 +118,7 @@ }; gen1_i2c: i2c@3160000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x03160000 0x10000>; interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -143,7 +143,7 @@ }; cam_i2c: i2c@3180000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x03180000 0x10000>; interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -157,7 +157,7 @@ /* shares pads with dpaux1 */ dp_aux_ch1_i2c: i2c@3190000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x03190000 0x10000>; interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -171,7 +171,7 @@ /* shares pads with dpaux0 */ dp_aux_ch0_i2c: i2c@31b0000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x031b0000 0x10000>; interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -184,7 +184,7 @@ }; gen7_i2c: i2c@31c0000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x031c0000 0x10000>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -197,7 +197,7 @@ }; gen9_i2c: i2c@31e0000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x031e0000 0x10000>; interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -264,7 +264,7 @@ }; gen2_i2c: i2c@c240000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x0c240000 0x10000>; interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; @@ -277,7 +277,7 @@ }; gen8_i2c: i2c@c250000 { - compatible = "nvidia,tegra194-i2c", "nvidia,tegra114-i2c"; + compatible = "nvidia,tegra194-i2c"; reg = <0x0c250000 0x10000>; interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi index 212e6634c9ba..053458a5db55 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi @@ -178,16 +178,7 @@ vddio_sdmmc: ldo2 { regulator-name = "VDDIO_SDMMC"; - /* - * Technically this supply should have - * a supported range from 1.8 - 3.3 V. - * However, that would cause the SDHCI - * driver to request 2.7 V upon access - * and that in turn will cause traffic - * to be broken. Leave it at 3.3 V for - * now. - */ - regulator-min-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; @@ -282,6 +273,7 @@ status = "okay"; bus-width = <8>; non-removable; + vqmmc-supply = <&vdd_1v8>; }; clocks { diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi index 9d5a0e6b2ca4..365726ddd418 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -1452,7 +1452,6 @@ sdhci@700b0000 { status = "okay"; bus-width = <4>; - no-1-8-v; cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>; diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 3be920efee82..8fe47d6445a5 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -3,6 +3,7 @@ #include <dt-bindings/gpio/tegra-gpio.h> #include <dt-bindings/memory/tegra210-mc.h> #include <dt-bindings/pinctrl/pinctrl-tegra.h> +#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/thermal/tegra124-soctherm.h> @@ -776,6 +777,26 @@ #power-domain-cells = <0>; }; }; + + sdmmc1_3v3: sdmmc1-3v3 { + pins = "sdmmc1"; + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>; + }; + + sdmmc1_1v8: sdmmc1-1v8 { + pins = "sdmmc1"; + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>; + }; + + sdmmc3_3v3: sdmmc3-3v3 { + pins = "sdmmc3"; + power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>; + }; + + sdmmc3_1v8: sdmmc3-1v8 { + pins = "sdmmc3"; + power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>; + }; }; fuse@7000f800 { @@ -1027,6 +1048,20 @@ clock-names = "sdhci"; resets = <&tegra_car 14>; reset-names = "sdhci"; + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; + pinctrl-0 = <&sdmmc1_3v3>; + pinctrl-1 = <&sdmmc1_1v8>; + nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>; + nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>; + nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>; + nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>; + nvidia,default-tap = <0x2>; + nvidia,default-trim = <0x4>; + assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>, + <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>, + <&tegra_car TEGRA210_CLK_PLL_C4>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>; + assigned-clock-rates = <200000000>, <1000000000>, <1000000000>; status = "disabled"; }; @@ -1038,6 +1073,10 @@ clock-names = "sdhci"; resets = <&tegra_car 9>; reset-names = "sdhci"; + nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>; + nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>; + nvidia,default-tap = <0x8>; + nvidia,default-trim = <0x0>; status = "disabled"; }; @@ -1049,6 +1088,15 @@ clock-names = "sdhci"; resets = <&tegra_car 69>; reset-names = "sdhci"; + pinctrl-names = "sdmmc-3v3", "sdmmc-1v8"; + pinctrl-0 = <&sdmmc3_3v3>; + pinctrl-1 = <&sdmmc3_1v8>; + nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>; + nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>; + nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>; + nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>; + nvidia,default-tap = <0x3>; + nvidia,default-trim = <0x3>; status = "disabled"; }; @@ -1060,6 +1108,15 @@ clock-names = "sdhci"; resets = <&tegra_car 15>; reset-names = "sdhci"; + nvidia,pad-autocal-pull-up-offset-1v8 = <0x05>; + nvidia,pad-autocal-pull-down-offset-1v8 = <0x05>; + nvidia,default-tap = <0x8>; + nvidia,default-trim = <0x0>; + assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>, + <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>; + assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>; + nvidia,dqs-trim = <40>; + mmc-hs400-1_8v; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9319e74b8906..a658c07652a7 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -6,4 +6,5 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += msm8998-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 78ce3979ef09..46feedf7c989 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -545,6 +545,20 @@ }; }; +&spmi_bus { + pm8916_0: pm8916@0 { + pon@800 { + resin { + compatible = "qcom,pm8941-resin"; + interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_VOLUMEDOWN>; + }; + }; + }; +}; + &wcd_codec { status = "okay"; clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts index 230e9c8484ac..da23bdafbd33 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts @@ -17,5 +17,5 @@ / { model = "Qualcomm Technologies, Inc. DB820c"; - compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc"; + compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc", "qcom,apq8096"; }; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi index 0ef90c6554a9..bf20c55a6bc4 100644 --- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi @@ -623,3 +623,17 @@ }; }; }; + +&spmi_bus { + pmic@0 { + pon@800 { + resin { + compatible = "qcom,pm8941-resin"; + interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_VOLUMEDOWN>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 7b32b8990d62..d302d8d639a1 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -18,9 +18,6 @@ #include <dt-bindings/thermal/thermal.h> / { - model = "Qualcomm Technologies, Inc. MSM8916"; - compatible = "qcom,msm8916"; - interrupt-parent = <&intc>; #address-cells = <2>; @@ -1099,10 +1096,11 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - port { - tpiu_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out1>; + in-ports { + port { + tpiu_in: endpoint { + remote-endpoint = <&replicator_out1>; + }; }; }; }; @@ -1114,7 +1112,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; @@ -1132,12 +1130,13 @@ port@4 { reg = <4>; funnel0_in4: endpoint { - slave-mode; remote-endpoint = <&funnel1_out>; }; }; - port@8 { - reg = <0>; + }; + + out-ports { + port { funnel0_out: endpoint { remote-endpoint = <&etf_in>; }; @@ -1152,7 +1151,7 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + out-ports { #address-cells = <1>; #size-cells = <0>; @@ -1168,10 +1167,11 @@ remote-endpoint = <&tpiu_in>; }; }; - port@2 { - reg = <0>; + }; + + in-ports { + port { replicator_in: endpoint { - slave-mode; remote-endpoint = <&etf_out>; }; }; @@ -1185,19 +1185,16 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; + in-ports { + port { etf_in: endpoint { - slave-mode; remote-endpoint = <&funnel0_out>; }; }; - port@1 { - reg = <0>; + }; + + out-ports { + port { etf_out: endpoint { remote-endpoint = <&replicator_in>; }; @@ -1212,10 +1209,11 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - port { - etr_in: endpoint { - slave-mode; - remote-endpoint = <&replicator_out0>; + in-ports { + port { + etr_in: endpoint { + remote-endpoint = <&replicator_out0>; + }; }; }; }; @@ -1227,40 +1225,38 @@ clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>; clock-names = "apb_pclk", "atclk"; - ports { + in-ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; funnel1_in0: endpoint { - slave-mode; remote-endpoint = <&etm0_out>; }; }; port@1 { reg = <1>; funnel1_in1: endpoint { - slave-mode; remote-endpoint = <&etm1_out>; }; }; port@2 { reg = <2>; funnel1_in2: endpoint { - slave-mode; remote-endpoint = <&etm2_out>; }; }; port@3 { reg = <3>; funnel1_in3: endpoint { - slave-mode; remote-endpoint = <&etm3_out>; }; }; - port@4 { - reg = <0>; + }; + + out-ports { + port { funnel1_out: endpoint { remote-endpoint = <&funnel0_in4>; }; @@ -1309,9 +1305,11 @@ cpu = <&CPU0>; - port { - etm0_out: endpoint { - remote-endpoint = <&funnel1_in0>; + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&funnel1_in0>; + }; }; }; }; @@ -1325,9 +1323,11 @@ cpu = <&CPU1>; - port { - etm1_out: endpoint { - remote-endpoint = <&funnel1_in1>; + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&funnel1_in1>; + }; }; }; }; @@ -1341,9 +1341,11 @@ cpu = <&CPU2>; - port { - etm2_out: endpoint { - remote-endpoint = <&funnel1_in2>; + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&funnel1_in2>; + }; }; }; }; @@ -1357,9 +1359,11 @@ cpu = <&CPU3>; - port { - etm3_out: endpoint { - remote-endpoint = <&funnel1_in3>; + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&funnel1_in3>; + }; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index cd3865e7a270..b29fe80d7288 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -16,8 +16,6 @@ #include <dt-bindings/clock/qcom,rpmcc.h> / { - model = "Qualcomm Technologies, Inc. MSM8996"; - interrupt-parent = <&intc>; #address-cells = <2>; @@ -409,11 +407,6 @@ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; }; - apcs: syscon@9820000 { - compatible = "syscon"; - reg = <0x9820000 0x1000>; - }; - apcs_glb: mailbox@9820000 { compatible = "qcom,msm8996-apcs-hmss-global"; reg = <0x9820000 0x1000>; @@ -1140,7 +1133,7 @@ interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>; label = "lpass"; - qcom,ipc = <&apcs 16 8>; + mboxes = <&apcs_glb 8>; qcom,smd-edge = <1>; qcom,remote-pid = <2>; }; @@ -1152,7 +1145,7 @@ interrupts = <0 158 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 16 10>; + mboxes = <&apcs_glb 10>; qcom,local-pid = <0>; qcom,remote-pid = <2>; @@ -1176,7 +1169,7 @@ interrupts = <GIC_SPI 451 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 16 14>; + mboxes = <&apcs_glb 14>; qcom,local-pid = <0>; qcom,remote-pid = <1>; @@ -1200,7 +1193,7 @@ interrupts = <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>; - qcom,ipc = <&apcs 16 26>; + mboxes = <&apcs_glb 26>; qcom,local-pid = <0>; qcom,remote-pid = <3>; diff --git a/arch/arm64/boot/dts/qcom/msm8998-mtp.dts b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts new file mode 100644 index 000000000000..66540d2ca13b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. */ + +/dts-v1/; + +#include "msm8998-mtp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8998 v1 MTP"; + compatible = "qcom,msm8998-mtp"; + + qcom,board-id = <8 0>; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi new file mode 100644 index 000000000000..b4276da1fb0d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. */ + +#include "msm8998.dtsi" +#include "pm8998.dtsi" +#include "pmi8998.dtsi" +#include "pm8005.dtsi" + +/ { + aliases { + serial0 = &blsp2_uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + thermal-zones { + battery-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 0>; + + trips { + battery_crit: trip0 { + temperature = <60000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + skin-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 5>; + + trips { + skin_alert: trip0 { + temperature = <44000>; + hysteresis = <2000>; + type = "passive"; + }; + + skip_crit: trip1 { + temperature = <70000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&blsp2_uart1 { + status = "okay"; +}; + +&rpm_requests { + pm8998-regulators { + compatible = "qcom,rpm-pm8998-regulators"; + + vdd_s1-supply = <&vph_pwr>; + vdd_s2-supply = <&vph_pwr>; + vdd_s3-supply = <&vph_pwr>; + vdd_s4-supply = <&vph_pwr>; + vdd_s5-supply = <&vph_pwr>; + vdd_s6-supply = <&vph_pwr>; + vdd_s7-supply = <&vph_pwr>; + vdd_s8-supply = <&vph_pwr>; + vdd_s9-supply = <&vph_pwr>; + vdd_s10-supply = <&vph_pwr>; + vdd_s11-supply = <&vph_pwr>; + vdd_s12-supply = <&vph_pwr>; + vdd_s13-supply = <&vph_pwr>; + vdd_l1_l27-supply = <&vreg_s7a_1p025>; + vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>; + vdd_l3_l11-supply = <&vreg_s7a_1p025>; + vdd_l4_l5-supply = <&vreg_s7a_1p025>; + vdd_l6-supply = <&vreg_s5a_2p04>; + vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>; + vdd_l9-supply = <&vreg_bob>; + vdd_l10_l23_l25-supply = <&vreg_bob>; + vdd_l13_l19_l21-supply = <&vreg_bob>; + vdd_l16_l28-supply = <&vreg_bob>; + vdd_l18_l22-supply = <&vreg_bob>; + vdd_l20_l24-supply = <&vreg_bob>; + vdd_l26-supply = <&vreg_s3a_1p35>; + vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>; + + vreg_s3a_1p35: s3 { + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + }; + vreg_s4a_1p8: s4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_s5a_2p04: s5 { + regulator-min-microvolt = <1904000>; + regulator-max-microvolt = <2040000>; + }; + vreg_s7a_1p025: s7 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1028000>; + }; + vreg_l1a_0p875: l1 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + }; + vreg_l2a_1p2: l2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l3a_1p0: l3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l5a_0p8: l5 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + }; + vreg_l6a_1p8: l6 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + }; + vreg_l7a_1p8: l7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l8a_1p2: l8 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l9a_1p8: l9 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l10a_1p8: l10 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l11a_1p0: l11 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + vreg_l12a_1p8: l12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l13a_2p95: l13 { + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l14a_1p88: l14 { + regulator-min-microvolt = <1880000>; + regulator-max-microvolt = <1880000>; + }; + vreg_15a_1p8: l15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + vreg_l16a_2p7: l16 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + }; + vreg_l17a_1p3: l17 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + }; + vreg_l18a_2p7: l18 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + }; + vreg_l19a_3p0: l19 { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3008000>; + }; + vreg_l20a_2p95: l20 { + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l21a_2p95: l21 { + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + }; + vreg_l22a_2p85: l22 { + regulator-min-microvolt = <2864000>; + regulator-max-microvolt = <2864000>; + }; + vreg_l23a_3p3: l23 { + regulator-min-microvolt = <3312000>; + regulator-max-microvolt = <3312000>; + }; + vreg_l24a_3p075: l24 { + regulator-min-microvolt = <3088000>; + regulator-max-microvolt = <3088000>; + }; + vreg_l25a_3p3: l25 { + regulator-min-microvolt = <3104000>; + regulator-max-microvolt = <3312000>; + }; + vreg_l26a_1p2: l26 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + vreg_l28_3p0: l28 { + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3008000>; + }; + + vreg_lvs1a_1p8: lvs1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_lvs2a_1p8: lvs2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + }; + + pmi8998-regulators { + compatible = "qcom,rpm-pmi8998-regulators"; + + vdd_bob-supply = <&vph_pwr>; + + vreg_bob: bob { + regulator-min-microvolt = <3312000>; + regulator-max-microvolt = <3600000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi new file mode 100644 index 000000000000..78227cce16db --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/qcom,gcc-msm8998.h> + +/ { + interrupt-parent = <&intc>; + + qcom,msm-id = <292 0x0>; + + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + memory { + device_type = "memory"; + /* We expect the bootloader to fill in the reg */ + reg = <0 0 0 0>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + memory@85800000 { + reg = <0x0 0x85800000 0x0 0x800000>; + no-map; + }; + + smem_mem: smem-mem@86000000 { + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + }; + + memory@86200000 { + reg = <0x0 0x86200000 0x0 0x2600000>; + no-map; + }; + + rmtfs { + compatible = "qcom,rmtfs-mem"; + + size = <0x0 0x200000>; + alloc-ranges = <0x0 0xa0000000 0x0 0x2000000>; + no-map; + + qcom,client-id = <1>; + qcom,vmid = <15>; + }; + }; + + clocks { + xo_board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + }; + + sleep_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32764>; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + efficiency = <1024>; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "arm,arch-cache"; + cache-level = <2>; + }; + L1_I_0: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_0: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + efficiency = <1024>; + next-level-cache = <&L2_0>; + L1_I_1: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_1: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU2: cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + efficiency = <1024>; + next-level-cache = <&L2_0>; + L1_I_2: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_2: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU3: cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + efficiency = <1024>; + next-level-cache = <&L2_0>; + L1_I_3: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_3: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU4: cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + efficiency = <1536>; + next-level-cache = <&L2_1>; + L2_1: l2-cache { + compatible = "arm,arch-cache"; + cache-level = <2>; + }; + L1_I_100: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_100: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU5: cpu@101 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + efficiency = <1536>; + next-level-cache = <&L2_1>; + L1_I_101: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_101: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU6: cpu@102 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + efficiency = <1536>; + next-level-cache = <&L2_1>; + L1_I_102: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_102: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + CPU7: cpu@103 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + efficiency = <1536>; + next-level-cache = <&L2_1>; + L1_I_103: l1-icache { + compatible = "arm,arch-cache"; + }; + L1_D_103: l1-dcache { + compatible = "arm,arch-cache"; + }; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + + core1 { + cpu = <&CPU1>; + }; + + core2 { + cpu = <&CPU2>; + }; + + core3 { + cpu = <&CPU3>; + }; + }; + + cluster1 { + core0 { + cpu = <&CPU4>; + }; + + core1 { + cpu = <&CPU5>; + }; + + core2 { + cpu = <&CPU6>; + }; + + core3 { + cpu = <&CPU7>; + }; + }; + }; + }; + + firmware { + scm { + compatible = "qcom,scm-msm8998"; + }; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x1000>; + #hwlock-cells = <1>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + rpm-glink { + compatible = "qcom,glink-rpm"; + + interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; + qcom,rpm-msg-ram = <&rpm_msg_ram>; + mboxes = <&apcs_glb 0>; + + rpm_requests: rpm-requests { + compatible = "qcom,rpm-msm8998"; + qcom,glink-channels = "rpm_requests"; + }; + }; + + smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; + + smp2p-lpass { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + + interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>; + + mboxes = <&apcs_glb 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-mpss { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + interrupts = <GIC_SPI 451 IRQ_TYPE_EDGE_RISING>; + mboxes = <&apcs_glb 14>; + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-slpi { + compatible = "qcom,smp2p"; + qcom,smem = <481>, <430>; + interrupts = <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>; + mboxes = <&apcs_glb 26>; + qcom,local-pid = <0>; + qcom,remote-pid = <3>; + + slpi_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + slpi_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + thermal-zones { + cpu-thermal0 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 6>; + + trips { + cpu_alert0: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit0: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal1 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 7>; + + trips { + cpu_alert1: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit1: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal2 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 8>; + + trips { + cpu_alert2: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit2: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal3 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 9>; + + trips { + cpu_alert3: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit3: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal4 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 10>; + + trips { + cpu_alert4: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit4: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal5 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 11>; + + trips { + cpu_alert5: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit5: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal6 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 0>; + + trips { + cpu_alert6: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit6: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + cpu-thermal7 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 1>; + + trips { + cpu_alert7: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit7: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + gpu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens1 3>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 3 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>; + }; + + soc: soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + rpm_msg_ram: memory@68000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x778000 0x7000>; + }; + + qfprom: qfprom@780000 { + compatible = "qcom,qfprom"; + reg = <0x780000 0x621c>; + #address-cells = <1>; + #size-cells = <1>; + }; + + gcc: clock-controller@100000 { + compatible = "qcom,gcc-msm8998"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + reg = <0x100000 0xb0000>; + }; + + tlmm: pinctrl@3400000 { + compatible = "qcom,msm8998-pinctrl"; + reg = <0x3400000 0xc00000>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <0x2>; + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + spmi_bus: spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x800f000 0x1000>, + <0x8400000 0x1000000>, + <0x9400000 0x1000000>, + <0xa400000 0x220000>, + <0x800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + }; + + tsens0: thermal@10aa000 { + compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; + reg = <0x10aa000 0x2000>; + + #qcom,sensors = <12>; + #thermal-sensor-cells = <1>; + }; + + tsens1: thermal@10ad000 { + compatible = "qcom,msm8998-tsens", "qcom,tsens-v2"; + reg = <0x10ad000 0x2000>; + + #qcom,sensors = <8>; + #thermal-sensor-cells = <1>; + }; + + tcsr_mutex_regs: syscon@1f40000 { + compatible = "syscon"; + reg = <0x1f40000 0x20000>; + }; + + apcs_glb: mailbox@9820000 { + compatible = "qcom,msm8998-apcs-hmss-global"; + reg = <0x17911000 0x1000>; + + #mbox-cells = <1>; + }; + + blsp2_uart1: serial@c1b0000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xc1b0000 0x1000>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>, + <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; + }; + + timer@17920000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0x17920000 0x1000>; + + frame@17921000 { + frame-number = <0>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17921000 0x1000>, + <0x17922000 0x1000>; + }; + + frame@17923000 { + frame-number = <1>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17923000 0x1000>; + status = "disabled"; + }; + + frame@17924000 { + frame-number = <2>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17924000 0x1000>; + status = "disabled"; + }; + + frame@17925000 { + frame-number = <3>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17925000 0x1000>; + status = "disabled"; + }; + + frame@17926000 { + frame-number = <4>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17926000 0x1000>; + status = "disabled"; + }; + + frame@17927000 { + frame-number = <5>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17927000 0x1000>; + status = "disabled"; + }; + + frame@17928000 { + frame-number = <6>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x17928000 0x1000>; + status = "disabled"; + }; + }; + + intc: interrupt-controller@17a00000 { + compatible = "arm,gic-v3"; + reg = <0x17a00000 0x10000>, /* GICD */ + <0x17b00000 0x100000>; /* GICR * 8 */ + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-controller; + #redistributor-regions = <1>; + redistributor-stride = <0x0 0x20000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi index 196b1c0ceb9b..15a37cbcd216 100644 --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <dt-bindings/iio/qcom,spmi-vadc.h> #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/spmi/spmi.h> &spmi_bus { @@ -18,12 +19,19 @@ interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; }; - pwrkey@800 { - compatible = "qcom,pm8941-pwrkey"; + pon@800 { + compatible = "qcom,pm8916-pon"; reg = <0x800>; - interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; - debounce = <15625>; - bias-pull-up; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_POWER>; + }; }; pm8916_gpios: gpios@c000 { diff --git a/arch/arm64/boot/dts/qcom/pm8994.dtsi b/arch/arm64/boot/dts/qcom/pm8994.dtsi index 80024c0b1c7c..76b5a3e6a2b5 100644 --- a/arch/arm64/boot/dts/qcom/pm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8994.dtsi @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/spmi/spmi.h> +#include <dt-bindings/input/linux-event-codes.h> &spmi_bus { @@ -17,6 +18,23 @@ interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; }; + pon@800 { + compatible = "qcom,pm8916-pon"; + + reg = <0x800>; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_POWER>; + }; + + }; + pm8994_gpios: gpios@c000 { compatible = "qcom,pm8994-gpio"; reg = <0xc000>; diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi index 92bed1e7d4bb..048f19fa0150 100644 --- a/arch/arm64/boot/dts/qcom/pm8998.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi @@ -1,8 +1,35 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* Copyright 2018 Google LLC. */ -#include <dt-bindings/spmi/spmi.h> +#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> +#include <dt-bindings/thermal/thermal.h> + +/ { + thermal-zones { + pm8998 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&pm8998_temp>; + + trips { + pm8998_alert0: pm8998-alert0 { + temperature = <105000>; + hysteresis = <2000>; + type = "passive"; + }; + pm8998_crit: pm8998-crit { + temperature = <125000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; +}; &spmi_bus { pm8998_lsid0: pmic@0 { @@ -11,6 +38,52 @@ #address-cells = <1>; #size-cells = <0>; + pm8998_pon: pon@800 { + compatible = "qcom,pm8916-pon"; + + reg = <0x800>; + mode-bootloader = <0x2>; + mode-recovery = <0x1>; + + pwrkey { + compatible = "qcom,pm8941-pwrkey"; + interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + bias-pull-up; + linux,code = <KEY_POWER>; + }; + }; + + pm8998_temp: temp-alarm@2400 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0x2400>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <0>; + }; + + pm8998_coincell: coincell@2800 { + compatible = "qcom,pm8941-coincell"; + reg = <0x2800>; + + status = "disabled"; + }; + + pm8998_adc: adc@3100 { + compatible = "qcom,spmi-adc-rev2"; + reg = <0x3100>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + }; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000>, <0x6100>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + pm8998_gpio: gpios@c000 { compatible = "qcom,pm8998-gpio", "qcom,spmi-gpio"; reg = <0xc000>; diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi new file mode 100644 index 000000000000..da3285e216e2 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/spmi/spmi.h> + +&spmi_bus { + pmi8998_lsid0: pmic@2 { + compatible = "qcom,pmi8998", "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmi8998_gpio: gpios@c000 { + compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio"; + reg = <0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <0 0xc0 0 IRQ_TYPE_NONE>, + <0 0xc1 0 IRQ_TYPE_NONE>, + <0 0xc2 0 IRQ_TYPE_NONE>, + <0 0xc3 0 IRQ_TYPE_NONE>, + <0 0xc4 0 IRQ_TYPE_NONE>, + <0 0xc5 0 IRQ_TYPE_NONE>, + <0 0xc6 0 IRQ_TYPE_NONE>, + <0 0xc7 0 IRQ_TYPE_NONE>, + <0 0xc8 0 IRQ_TYPE_NONE>, + <0 0xc9 0 IRQ_TYPE_NONE>, + <0 0xca 0 IRQ_TYPE_NONE>, + <0 0xcb 0 IRQ_TYPE_NONE>, + <0 0xcc 0 IRQ_TYPE_NONE>, + <0 0xcd 0 IRQ_TYPE_NONE>; + }; + }; + + pmi8998_lsid1: pmic@3 { + compatible = "qcom,pmi8998", "qcom,spmi-pmic"; + reg = <0x3 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts index 6d651f314193..eedfaf8922e2 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts @@ -7,6 +7,7 @@ /dts-v1/; +#include <dt-bindings/regulator/qcom,rpmh-regulator.h> #include "sdm845.dtsi" / { @@ -20,6 +21,326 @@ chosen { stdout-path = "serial0:115200n8"; }; + + vph_pwr: vph-pwr-regulator { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + }; + + /* + * Apparently RPMh does not provide support for PM8998 S4 because it + * is always-on; model it as a fixed regulator. + */ + vreg_s4a_1p8: pm8998-smps4 { + compatible = "regulator-fixed"; + regulator-name = "vreg_s4a_1p8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-always-on; + regulator-boot-on; + + vin-supply = <&vph_pwr>; + }; +}; + +&apps_rsc { + pm8998-rpmh-regulators { + compatible = "qcom,pm8998-rpmh-regulators"; + qcom,pmic-id = "a"; + + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + vdd-s3-supply = <&vph_pwr>; + vdd-s4-supply = <&vph_pwr>; + vdd-s5-supply = <&vph_pwr>; + vdd-s6-supply = <&vph_pwr>; + vdd-s7-supply = <&vph_pwr>; + vdd-s8-supply = <&vph_pwr>; + vdd-s9-supply = <&vph_pwr>; + vdd-s10-supply = <&vph_pwr>; + vdd-s11-supply = <&vph_pwr>; + vdd-s12-supply = <&vph_pwr>; + vdd-s13-supply = <&vph_pwr>; + vdd-l1-l27-supply = <&vreg_s7a_1p025>; + vdd-l2-l8-l17-supply = <&vreg_s3a_1p35>; + vdd-l3-l11-supply = <&vreg_s7a_1p025>; + vdd-l4-l5-supply = <&vreg_s7a_1p025>; + vdd-l6-supply = <&vph_pwr>; + vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p04>; + vdd-l9-supply = <&vreg_bob>; + vdd-l10-l23-l25-supply = <&vreg_bob>; + vdd-l13-l19-l21-supply = <&vreg_bob>; + vdd-l16-l28-supply = <&vreg_bob>; + vdd-l18-l22-supply = <&vreg_bob>; + vdd-l20-l24-supply = <&vreg_bob>; + vdd-l26-supply = <&vreg_s3a_1p35>; + vin-lvs-1-2-supply = <&vreg_s4a_1p8>; + + vreg_s2a_1p125: smps2 { + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + vreg_s3a_1p35: smps3 { + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + }; + + vreg_s5a_2p04: smps5 { + regulator-min-microvolt = <1904000>; + regulator-max-microvolt = <2040000>; + }; + + vreg_s7a_1p025: smps7 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1028000>; + }; + + vdd_qusb_hs0: + vdda_hp_pcie_core: + vdda_mipi_csi0_0p9: + vdda_mipi_csi1_0p9: + vdda_mipi_csi2_0p9: + vdda_mipi_dsi0_pll: + vdda_mipi_dsi1_pll: + vdda_qlink_lv: + vdda_qlink_lv_ck: + vdda_qrefs_0p875: + vdda_pcie_core: + vdda_pll_cc_ebi01: + vdda_pll_cc_ebi23: + vdda_sp_sensor: + vdda_ufs1_core: + vdda_ufs2_core: + vdda_usb1_ss_core: + vdda_usb2_ss_core: + vreg_l1a_0p875: ldo1 { + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vddpx_10: + vreg_l2a_1p2: ldo2 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + regulator-always-on; + }; + + vreg_l3a_1p0: ldo3 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vdd_wcss_cx: + vdd_wcss_mx: + vdda_wcss_pll: + vreg_l5a_0p8: ldo5 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vddpx_13: + vreg_l6a_1p8: ldo6 { + regulator-min-microvolt = <1856000>; + regulator-max-microvolt = <1856000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l7a_1p8: ldo7 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l8a_1p2: ldo8 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1248000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l9a_1p8: ldo9 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <2928000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l10a_1p8: ldo10 { + regulator-min-microvolt = <1704000>; + regulator-max-microvolt = <2928000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l11a_1p0: ldo11 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1048000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vdd_qfprom: + vdd_qfprom_sp: + vdda_apc1_cs_1p8: + vdda_gfx_cs_1p8: + vdda_qrefs_1p8: + vdda_qusb_hs0_1p8: + vddpx_11: + vreg_l12a_1p8: ldo12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vddpx_2: + vreg_l13a_2p95: ldo13 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l14a_1p88: ldo14 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l15a_1p8: ldo15 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l16a_2p7: ldo16 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l17a_1p3: ldo17 { + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l18a_2p7: ldo18 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l19a_3p0: ldo19 { + regulator-min-microvolt = <2856000>; + regulator-max-microvolt = <3104000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l20a_2p95: ldo20 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l21a_2p95: ldo21 { + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l22a_2p85: ldo22 { + regulator-min-microvolt = <2864000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l23a_3p3: ldo23 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vdda_qusb_hs0_3p1: + vreg_l24a_3p075: ldo24 { + regulator-min-microvolt = <3088000>; + regulator-max-microvolt = <3088000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l25a_3p3: ldo25 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vdda_hp_pcie_1p2: + vdda_hv_ebi0: + vdda_hv_ebi1: + vdda_hv_ebi2: + vdda_hv_ebi3: + vdda_mipi_csi_1p25: + vdda_mipi_dsi0_1p2: + vdda_mipi_dsi1_1p2: + vdda_pcie_1p2: + vdda_ufs1_1p2: + vdda_ufs2_1p2: + vdda_usb1_ss_1p2: + vdda_usb2_ss_1p2: + vreg_l26a_1p2: ldo26 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l28a_3p0: ldo28 { + regulator-min-microvolt = <2856000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_lvs1a_1p8: lvs1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_lvs2a_1p8: lvs2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + }; + + pmi8998-rpmh-regulators { + compatible = "qcom,pmi8998-rpmh-regulators"; + qcom,pmic-id = "b"; + + vdd-bob-supply = <&vph_pwr>; + + vreg_bob: bob { + regulator-min-microvolt = <3312000>; + regulator-max-microvolt = <3600000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>; + regulator-allow-bypass; + }; + }; + + pm8005-rpmh-regulators { + compatible = "qcom,pm8005-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + vdd-s3-supply = <&vph_pwr>; + vdd-s4-supply = <&vph_pwr>; + + vreg_s3c_0p6: smps3 { + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <600000>; + }; + }; }; &i2c10 { @@ -35,6 +356,67 @@ status = "okay"; }; +&usb_1 { + status = "okay"; +}; + +&usb_1_dwc3 { + /* Until we have Type C hooked up we'll force this as host. */ + dr_mode = "host"; +}; + +&usb_1_hsphy { + status = "okay"; + + vdd-supply = <&vdda_usb1_ss_core>; + vdda-pll-supply = <&vdda_qusb_hs0_1p8>; + vdda-phy-dpdm-supply = <&vdda_qusb_hs0_3p1>; + + qcom,imp-res-offset-value = <8>; + qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_21_6_MA>; + qcom,preemphasis-level = <QUSB2_V2_PREEMPHASIS_5_PERCENT>; + qcom,preemphasis-width = <QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT>; +}; + +&usb_1_qmpphy { + status = "okay"; + + vdda-phy-supply = <&vdda_usb1_ss_1p2>; + vdda-pll-supply = <&vdda_usb1_ss_core>; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_dwc3 { + /* + * Though the USB block on SDM845 can support host, there's no vbus + * signal for this port on MTP. Thus (unless you have a non-compliant + * hub that works without vbus) the only sensible thing is to force + * peripheral mode. + */ + dr_mode = "peripheral"; +}; + +&usb_2_hsphy { + status = "okay"; + + vdd-supply = <&vdda_usb2_ss_core>; + vdda-pll-supply = <&vdda_qusb_hs0_1p8>; + vdda-phy-dpdm-supply = <&vdda_qusb_hs0_3p1>; + + qcom,imp-res-offset-value = <8>; + qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_22_8_MA>; +}; + +&usb_2_qmpphy { + status = "okay"; + + vdda-phy-supply = <&vdda_usb2_ss_1p2>; + vdda-pll-supply = <&vdda_usb2_ss_core>; +}; + /* PINCTRL - additions to nodes defined in sdm845.dtsi */ &qup_i2c10_default { diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 0c9a2aa6a1b5..b72bdb0a31a5 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -5,9 +5,12 @@ * Copyright (c) 2018, The Linux Foundation. All rights reserved. */ +#include <dt-bindings/clock/qcom,dispcc-sdm845.h> #include <dt-bindings/clock/qcom,gcc-sdm845.h> #include <dt-bindings/clock/qcom,rpmh.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/phy/phy-qcom-qusb2.h> +#include <dt-bindings/reset/qcom,sdm845-aoss.h> #include <dt-bindings/soc/qcom,rpmh-rsc.h> / { @@ -230,6 +233,94 @@ hwlocks = <&tcsr_mutex 3>; }; + smp2p-cdsp { + compatible = "qcom,smp2p"; + qcom,smem = <94>, <432>; + + interrupts = <GIC_SPI 576 IRQ_TYPE_EDGE_RISING>; + + mboxes = <&apss_shared 6>; + + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + cdsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + cdsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-lpass { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + + interrupts = <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>; + + mboxes = <&apss_shared 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-mpss { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + interrupts = <GIC_SPI 451 IRQ_TYPE_EDGE_RISING>; + mboxes = <&apss_shared 14>; + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + modem_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + modem_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-slpi { + compatible = "qcom,smp2p"; + qcom,smem = <481>, <430>; + interrupts = <GIC_SPI 172 IRQ_TYPE_EDGE_RISING>; + mboxes = <&apss_shared 26>; + qcom,local-pid = <0>; + qcom,remote-pid = <3>; + + slpi_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + slpi_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -249,6 +340,23 @@ #power-domain-cells = <1>; }; + qfprom@784000 { + compatible = "qcom,qfprom"; + reg = <0x784000 0x8ff>; + #address-cells = <1>; + #size-cells = <1>; + + qusb2p_hstx_trim: hstx-trim-primary@1eb { + reg = <0x1eb 0x1>; + bits = <1 4>; + }; + + qusb2s_hstx_trim: hstx-trim-secondary@1eb { + reg = <0x1eb 0x2>; + bits = <6 4>; + }; + }; + qupv3_id_0: geniqup@8c0000 { compatible = "qcom,geni-se-qup"; reg = <0x8c0000 0x6000>; @@ -962,6 +1070,192 @@ }; }; + usb_1_hsphy: phy@88e2000 { + compatible = "qcom,sdm845-qusb2-phy"; + reg = <0x88e2000 0x400>; + status = "disabled"; + #phy-cells = <0>; + + clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "cfg_ahb", "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + + nvmem-cells = <&qusb2p_hstx_trim>; + }; + + usb_2_hsphy: phy@88e3000 { + compatible = "qcom,sdm845-qusb2-phy"; + reg = <0x88e3000 0x400>; + status = "disabled"; + #phy-cells = <0>; + + clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "cfg_ahb", "ref"; + + resets = <&gcc GCC_QUSB2PHY_SEC_BCR>; + + nvmem-cells = <&qusb2s_hstx_trim>; + }; + + usb_1_qmpphy: phy@88e9000 { + compatible = "qcom,sdm845-qmp-usb3-phy"; + reg = <0x88e9000 0x18c>, + <0x88e8000 0x10>; + reg-names = "reg-base", "dp_com"; + status = "disabled"; + #clock-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_PRIM_CLKREF_CLK>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "com_aux"; + + resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>, + <&gcc GCC_USB3_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + + usb_1_ssphy: lane@88e9200 { + reg = <0x88e9200 0x128>, + <0x88e9400 0x200>, + <0x88e9c00 0x218>, + <0x88e9a00 0x100>; + #phy-cells = <0>; + clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "pipe0"; + clock-output-names = "usb3_phy_pipe_clk_src"; + }; + }; + + usb_2_qmpphy: phy@88eb000 { + compatible = "qcom,sdm845-qmp-usb3-uni-phy"; + reg = <0x88eb000 0x18c>; + status = "disabled"; + #clock-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, + <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&gcc GCC_USB3_SEC_CLKREF_CLK>, + <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>; + clock-names = "aux", "cfg_ahb", "ref", "com_aux"; + + resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>, + <&gcc GCC_USB3_PHY_SEC_BCR>; + reset-names = "phy", "common"; + + usb_2_ssphy: lane@88eb200 { + reg = <0x88eb200 0x128>, + <0x88eb400 0x1fc>, + <0x88eb800 0x218>, + <0x88e9600 0x70>; + #phy-cells = <0>; + clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; + clock-names = "pipe0"; + clock-output-names = "usb3_uni_phy_pipe_clk_src"; + }; + }; + + usb_1: usb@a6f8800 { + compatible = "qcom,sdm845-dwc3", "qcom,dwc3"; + reg = <0xa6f8800 0x400>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>; + clock-names = "cfg_noc", "core", "iface", "mock_utmi", + "sleep"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <150000000>; + + interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hs_phy_irq", "ss_phy_irq", + "dm_hs_phy_irq", "dp_hs_phy_irq"; + + power-domains = <&gcc USB30_PRIM_GDSC>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + usb_1_dwc3: dwc3@a600000 { + compatible = "snps,dwc3"; + reg = <0xa600000 0xcd00>; + interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + phys = <&usb_1_hsphy>, <&usb_1_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + usb_2: usb@a8f8800 { + compatible = "qcom,sdm845-dwc3", "qcom,dwc3"; + reg = <0xa8f8800 0x400>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + clocks = <&gcc GCC_CFG_NOC_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>, + <&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>, + <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_SEC_SLEEP_CLK>; + clock-names = "cfg_noc", "core", "iface", "mock_utmi", + "sleep"; + + assigned-clocks = <&gcc GCC_USB30_SEC_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_SEC_MASTER_CLK>; + assigned-clock-rates = <19200000>, <150000000>; + + interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 487 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 490 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 491 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hs_phy_irq", "ss_phy_irq", + "dm_hs_phy_irq", "dp_hs_phy_irq"; + + power-domains = <&gcc USB30_SEC_GDSC>; + + resets = <&gcc GCC_USB30_SEC_BCR>; + + usb_2_dwc3: dwc3@a800000 { + compatible = "snps,dwc3"; + reg = <0xa800000 0xcd00>; + interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + phys = <&usb_2_hsphy>, <&usb_2_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + dispcc: clock-controller@af00000 { + compatible = "qcom,sdm845-dispcc"; + reg = <0xaf00000 0x10000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + tsens0: thermal-sensor@c263000 { compatible = "qcom,sdm845-tsens", "qcom,tsens-v2"; reg = <0xc263000 0x1ff>, /* TM */ @@ -978,6 +1272,12 @@ #thermal-sensor-cells = <1>; }; + aoss_reset: reset-controller@c2a0000 { + compatible = "qcom,sdm845-aoss-cc"; + reg = <0xc2a0000 0x31000>; + #reset-cells = <1>; + }; + spmi_bus: spmi@c440000 { compatible = "qcom,spmi-pmic-arb"; reg = <0xc440000 0x1100>, diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile index 9e2394bc3c62..a8ce6594342d 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile @@ -8,6 +8,8 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb r8a77965-salvator-xs.dtb +dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb.dtb +dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle.dtb r8a77970-v3msk.dtb dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-condor.dtb r8a77980-v3hsk.dtb dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-ebisu.dtb diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi new file mode 100644 index 000000000000..012cbb64246e --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -0,0 +1,1663 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for the r8a774a1 SoC + * + * Copyright (C) 2018 Renesas Electronics Corp. + */ + +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/ { + compatible = "renesas,r8a774a1"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c_dvfs; + }; + + /* + * The external audio clocks are configured as 0 Hz fixed frequency + * clocks by default. + * Boards that provide audio clocks should override them. + */ + audio_clk_a: audio_clk_a { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + audio_clk_b: audio_clk_b { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + audio_clk_c: audio_clk_c { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + a57_0: cpu@0 { + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x0>; + device_type = "cpu"; + power-domains = <&sysc 0>; + next-level-cache = <&L2_CA57>; + enable-method = "psci"; + clocks = <&cpg CPG_CORE 0>; + }; + + a57_1: cpu@1 { + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x1>; + device_type = "cpu"; + power-domains = <&sysc 1>; + next-level-cache = <&L2_CA57>; + enable-method = "psci"; + clocks = <&cpg CPG_CORE 0>; + }; + + a53_0: cpu@100 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x100>; + device_type = "cpu"; + power-domains = <&sysc 5>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; + clocks =<&cpg CPG_CORE 1>; + }; + + a53_1: cpu@101 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x101>; + device_type = "cpu"; + power-domains = <&sysc 6>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; + clocks =<&cpg CPG_CORE 1>; + }; + + a53_2: cpu@102 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x102>; + device_type = "cpu"; + power-domains = <&sysc 7>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; + clocks =<&cpg CPG_CORE 1>; + }; + + a53_3: cpu@103 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x103>; + device_type = "cpu"; + power-domains = <&sysc 8>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; + clocks =<&cpg CPG_CORE 1>; + }; + + L2_CA57: cache-controller-0 { + compatible = "cache"; + power-domains = <&sysc 12>; + cache-unified; + cache-level = <2>; + }; + + L2_CA53: cache-controller-1 { + compatible = "cache"; + power-domains = <&sysc 21>; + cache-unified; + cache-level = <2>; + }; + }; + + extal_clk: extal { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + extalr_clk: extalr { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + /* External PCIe clock - can be overridden by the board */ + pcie_bus_clk: pcie_bus { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + pmu_a53 { + compatible = "arm,cortex-a53-pmu"; + interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>; + }; + + pmu_a57 { + compatible = "arm,cortex-a57-pmu"; + interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&a57_0>, <&a57_1>; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + /* External SCIF clock - to be overridden by boards that provide it */ + scif_clk: scif { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + rwdt: watchdog@e6020000 { + compatible = "renesas,r8a774a1-wdt", + "renesas,rcar-gen3-wdt"; + reg = <0 0xe6020000 0 0x0c>; + clocks = <&cpg CPG_MOD 402>; + power-domains = <&sysc 32>; + resets = <&cpg 402>; + status = "disabled"; + }; + + gpio0: gpio@e6050000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6050000 0 0x50>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 0 16>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 912>; + power-domains = <&sysc 32>; + resets = <&cpg 912>; + }; + + gpio1: gpio@e6051000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6051000 0 0x50>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 32 29>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 911>; + power-domains = <&sysc 32>; + resets = <&cpg 911>; + }; + + gpio2: gpio@e6052000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6052000 0 0x50>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 64 15>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 910>; + power-domains = <&sysc 32>; + resets = <&cpg 910>; + }; + + gpio3: gpio@e6053000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6053000 0 0x50>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 96 16>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 909>; + power-domains = <&sysc 32>; + resets = <&cpg 909>; + }; + + gpio4: gpio@e6054000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6054000 0 0x50>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 128 18>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 908>; + power-domains = <&sysc 32>; + resets = <&cpg 908>; + }; + + gpio5: gpio@e6055000 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6055000 0 0x50>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 160 26>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 907>; + power-domains = <&sysc 32>; + resets = <&cpg 907>; + }; + + gpio6: gpio@e6055400 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6055400 0 0x50>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 192 32>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 906>; + power-domains = <&sysc 32>; + resets = <&cpg 906>; + }; + + gpio7: gpio@e6055800 { + compatible = "renesas,gpio-r8a774a1", + "renesas,rcar-gen3-gpio"; + reg = <0 0xe6055800 0 0x50>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 224 4>; + #interrupt-cells = <2>; + interrupt-controller; + clocks = <&cpg CPG_MOD 905>; + power-domains = <&sysc 32>; + resets = <&cpg 905>; + }; + + pfc: pin-controller@e6060000 { + compatible = "renesas,pfc-r8a774a1"; + reg = <0 0xe6060000 0 0x50c>; + }; + + cpg: clock-controller@e6150000 { + compatible = "renesas,r8a774a1-cpg-mssr"; + reg = <0 0xe6150000 0 0x0bb0>; + clocks = <&extal_clk>, <&extalr_clk>; + clock-names = "extal", "extalr"; + #clock-cells = <2>; + #power-domain-cells = <0>; + #reset-cells = <1>; + }; + + rst: reset-controller@e6160000 { + compatible = "renesas,r8a774a1-rst"; + reg = <0 0xe6160000 0 0x018c>; + }; + + sysc: system-controller@e6180000 { + compatible = "renesas,r8a774a1-sysc"; + reg = <0 0xe6180000 0 0x0400>; + #power-domain-cells = <1>; + }; + + tsc: thermal@e6198000 { + compatible = "renesas,r8a774a1-thermal"; + reg = <0 0xe6198000 0 0x100>, + <0 0xe61a0000 0 0x100>, + <0 0xe61a8000 0 0x100>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 522>; + power-domains = <&sysc 32>; + resets = <&cpg 522>; + #thermal-sensor-cells = <1>; + }; + + intc_ex: interrupt-controller@e61c0000 { + compatible = "renesas,intc-ex-r8a774a1", "renesas,irqc"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0 0xe61c0000 0 0x200>; + 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 18 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 407>; + power-domains = <&sysc 32>; + resets = <&cpg 407>; + }; + + i2c0: i2c@e6500000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6500000 0 0x40>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 931>; + power-domains = <&sysc 32>; + resets = <&cpg 931>; + dmas = <&dmac1 0x91>, <&dmac1 0x90>, + <&dmac2 0x91>, <&dmac2 0x90>; + dma-names = "tx", "rx", "tx", "rx"; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c1: i2c@e6508000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6508000 0 0x40>; + interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 930>; + power-domains = <&sysc 32>; + resets = <&cpg 930>; + dmas = <&dmac1 0x93>, <&dmac1 0x92>, + <&dmac2 0x93>, <&dmac2 0x92>; + dma-names = "tx", "rx", "tx", "rx"; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c2: i2c@e6510000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6510000 0 0x40>; + interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 929>; + power-domains = <&sysc 32>; + resets = <&cpg 929>; + dmas = <&dmac1 0x95>, <&dmac1 0x94>, + <&dmac2 0x95>, <&dmac2 0x94>; + dma-names = "tx", "rx", "tx", "rx"; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c3: i2c@e66d0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66d0000 0 0x40>; + interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 928>; + power-domains = <&sysc 32>; + resets = <&cpg 928>; + dmas = <&dmac0 0x97>, <&dmac0 0x96>; + dma-names = "tx", "rx"; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c4: i2c@e66d8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66d8000 0 0x40>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 927>; + power-domains = <&sysc 32>; + resets = <&cpg 927>; + dmas = <&dmac0 0x99>, <&dmac0 0x98>; + dma-names = "tx", "rx"; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c5: i2c@e66e0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66e0000 0 0x40>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 919>; + power-domains = <&sysc 32>; + resets = <&cpg 919>; + dmas = <&dmac0 0x9b>, <&dmac0 0x9a>; + dma-names = "tx", "rx"; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c6: i2c@e66e8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a774a1", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66e8000 0 0x40>; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 918>; + power-domains = <&sysc 32>; + resets = <&cpg 918>; + dmas = <&dmac0 0x9d>, <&dmac0 0x9c>; + dma-names = "tx", "rx"; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c_dvfs: i2c@e60b0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,iic-r8a774a1", + "renesas,rcar-gen3-iic", + "renesas,rmobile-iic"; + reg = <0 0xe60b0000 0 0x425>; + interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 926>; + power-domains = <&sysc 32>; + resets = <&cpg 926>; + dmas = <&dmac0 0x11>, <&dmac0 0x10>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + hscif0: serial@e6540000 { + compatible = "renesas,hscif-r8a774a1", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe6540000 0 0x60>; + interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 520>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x31>, <&dmac1 0x30>, + <&dmac2 0x31>, <&dmac2 0x30>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 520>; + status = "disabled"; + }; + + hscif1: serial@e6550000 { + compatible = "renesas,hscif-r8a774a1", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe6550000 0 0x60>; + interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 519>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x33>, <&dmac1 0x32>, + <&dmac2 0x33>, <&dmac2 0x32>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 519>; + status = "disabled"; + }; + + hscif2: serial@e6560000 { + compatible = "renesas,hscif-r8a774a1", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe6560000 0 0x60>; + interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 518>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x35>, <&dmac1 0x34>, + <&dmac2 0x35>, <&dmac2 0x34>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 518>; + status = "disabled"; + }; + + hscif3: serial@e66a0000 { + compatible = "renesas,hscif-r8a774a1", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe66a0000 0 0x60>; + interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 517>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x37>, <&dmac0 0x36>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 517>; + status = "disabled"; + }; + + hscif4: serial@e66b0000 { + compatible = "renesas,hscif-r8a774a1", + "renesas,rcar-gen3-hscif", + "renesas,hscif"; + reg = <0 0xe66b0000 0 0x60>; + interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 516>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x39>, <&dmac0 0x38>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 516>; + status = "disabled"; + }; + + hsusb: usb@e6590000 { + compatible = "renesas,usbhs-r8a774a1", + "renesas,rcar-gen3-usbhs"; + reg = <0 0xe6590000 0 0x100>; + interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 704>; + dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, + <&usb_dmac1 0>, <&usb_dmac1 1>; + dma-names = "ch0", "ch1", "ch2", "ch3"; + renesas,buswait = <11>; + phys = <&usb2_phy0>; + phy-names = "usb"; + power-domains = <&sysc 32>; + resets = <&cpg 704>; + status = "disabled"; + }; + + usb_dmac0: dma-controller@e65a0000 { + compatible = "renesas,r8a774a1-usb-dmac", + "renesas,usb-dmac"; + reg = <0 0xe65a0000 0 0x100>; + interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ch0", "ch1"; + clocks = <&cpg CPG_MOD 330>; + power-domains = <&sysc 32>; + resets = <&cpg 330>; + #dma-cells = <1>; + dma-channels = <2>; + }; + + usb_dmac1: dma-controller@e65b0000 { + compatible = "renesas,r8a774a1-usb-dmac", + "renesas,usb-dmac"; + reg = <0 0xe65b0000 0 0x100>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ch0", "ch1"; + clocks = <&cpg CPG_MOD 331>; + power-domains = <&sysc 32>; + resets = <&cpg 331>; + #dma-cells = <1>; + dma-channels = <2>; + }; + + usb3_phy0: usb-phy@e65ee000 { + compatible = "renesas,r8a774a1-usb3-phy", + "renesas,rcar-gen3-usb3-phy"; + reg = <0 0xe65ee000 0 0x90>; + clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>, + <&usb_extal_clk>; + clock-names = "usb3-if", "usb3s_clk", "usb_extal"; + power-domains = <&sysc 32>; + resets = <&cpg 328>; + #phy-cells = <0>; + status = "disabled"; + }; + + dmac0: dma-controller@e6700000 { + compatible = "renesas,dmac-r8a774a1", + "renesas,rcar-dmac"; + reg = <0 0xe6700000 0 0x10000>; + interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 219>; + clock-names = "fck"; + power-domains = <&sysc 32>; + resets = <&cpg 219>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a774a1", + "renesas,rcar-dmac"; + reg = <0 0xe7300000 0 0x10000>; + interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 218>; + clock-names = "fck"; + power-domains = <&sysc 32>; + resets = <&cpg 218>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + dmac2: dma-controller@e7310000 { + compatible = "renesas,dmac-r8a774a1", + "renesas,rcar-dmac"; + reg = <0 0xe7310000 0 0x10000>; + interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 418 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 397 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 217>; + clock-names = "fck"; + power-domains = <&sysc 32>; + resets = <&cpg 217>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + ipmmu_ds0: mmu@e6740000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xe6740000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 0>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_ds1: mmu@e7740000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xe7740000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 1>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_hc: mmu@e6570000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xe6570000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 2>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_mm: mmu@e67b0000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xe67b0000 0 0x1000>; + interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_mp: mmu@ec670000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xec670000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 4>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_pv0: mmu@fd800000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xfd800000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 5>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_pv1: mmu@fd950000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xfd950000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 6>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + ipmmu_vc0: mmu@fe6b0000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xfe6b0000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 8>; + power-domains = <&sysc 14>; + #iommu-cells = <1>; + }; + + ipmmu_vi0: mmu@febd0000 { + compatible = "renesas,ipmmu-r8a774a1"; + reg = <0 0xfebd0000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 9>; + power-domains = <&sysc 32>; + #iommu-cells = <1>; + }; + + avb: ethernet@e6800000 { + compatible = "renesas,etheravb-r8a774a1", + "renesas,etheravb-rcar-gen3"; + reg = <0 0xe6800000 0 0x800>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15", + "ch16", "ch17", "ch18", "ch19", + "ch20", "ch21", "ch22", "ch23", + "ch24"; + clocks = <&cpg CPG_MOD 812>; + power-domains = <&sysc 32>; + resets = <&cpg 812>; + phy-mode = "rgmii"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm0: pwm@e6e30000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e30000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm5: pwm@e6e35000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e35000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + pwm6: pwm@e6e36000 { + compatible = "renesas,pwm-r8a774a1", "renesas,pwm-rcar"; + reg = <0 0xe6e36000 0 0x8>; + #pwm-cells = <2>; + clocks = <&cpg CPG_MOD 523>; + resets = <&cpg 523>; + power-domains = <&sysc 32>; + status = "disabled"; + }; + + scif0: serial@e6e60000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6e60000 0 0x40>; + interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 207>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x51>, <&dmac1 0x50>, + <&dmac2 0x51>, <&dmac2 0x50>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 207>; + status = "disabled"; + }; + + scif1: serial@e6e68000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6e68000 0 0x40>; + interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 206>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x53>, <&dmac1 0x52>, + <&dmac2 0x53>, <&dmac2 0x52>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 206>; + status = "disabled"; + }; + + scif2: serial@e6e88000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6e88000 0 0x40>; + interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 310>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + power-domains = <&sysc 32>; + resets = <&cpg 310>; + status = "disabled"; + }; + + scif3: serial@e6c50000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6c50000 0 0x40>; + interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 204>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x57>, <&dmac0 0x56>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 204>; + status = "disabled"; + }; + + scif4: serial@e6c40000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6c40000 0 0x40>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 203>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac0 0x59>, <&dmac0 0x58>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 203>; + status = "disabled"; + }; + + scif5: serial@e6f30000 { + compatible = "renesas,scif-r8a774a1", + "renesas,rcar-gen3-scif", "renesas,scif"; + reg = <0 0xe6f30000 0 0x40>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 202>, + <&cpg CPG_CORE 19>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + dmas = <&dmac1 0x5b>, <&dmac1 0x5a>, + <&dmac2 0x5b>, <&dmac2 0x5a>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 202>; + status = "disabled"; + }; + + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a774a1", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6e90000 0 0x0064>; + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 211>; + dmas = <&dmac1 0x41>, <&dmac1 0x40>, + <&dmac2 0x41>, <&dmac2 0x40>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 211>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof1: spi@e6ea0000 { + compatible = "renesas,msiof-r8a774a1", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6ea0000 0 0x0064>; + interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 210>; + dmas = <&dmac1 0x43>, <&dmac1 0x42>, + <&dmac2 0x43>, <&dmac2 0x42>; + dma-names = "tx", "rx", "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 210>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof2: spi@e6c00000 { + compatible = "renesas,msiof-r8a774a1", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6c00000 0 0x0064>; + interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 209>; + dmas = <&dmac0 0x45>, <&dmac0 0x44>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 209>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof3: spi@e6c10000 { + compatible = "renesas,msiof-r8a774a1", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6c10000 0 0x0064>; + interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 208>; + dmas = <&dmac0 0x47>, <&dmac0 0x46>; + dma-names = "tx", "rx"; + power-domains = <&sysc 32>; + resets = <&cpg 208>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + rcar_sound: sound@ec500000 { + /* + * #sound-dai-cells is required + * + * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>; + * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>; + */ + /* + * #clock-cells is required for audio_clkout0/1/2/3 + * + * clkout : #clock-cells = <0>; <&rcar_sound>; + * clkout0/1/2/3: #clock-cells = <1>; <&rcar_sound N>; + */ + compatible = "renesas,rcar_sound-r8a774a1", "renesas,rcar_sound-gen3"; + reg = <0 0xec500000 0 0x1000>, /* SCU */ + <0 0xec5a0000 0 0x100>, /* ADG */ + <0 0xec540000 0 0x1000>, /* SSIU */ + <0 0xec541000 0 0x280>, /* SSI */ + <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ + reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; + + clocks = <&cpg CPG_MOD 1005>, + <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, + <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, + <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, + <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, + <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, + <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, + <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, + <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, + <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, + <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, + <&audio_clk_a>, <&audio_clk_b>, + <&audio_clk_c>, + <&cpg CPG_CORE 10>; + clock-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", + "ssi.5", "ssi.4", "ssi.3", "ssi.2", + "ssi.1", "ssi.0", + "src.9", "src.8", "src.7", "src.6", + "src.5", "src.4", "src.3", "src.2", + "src.1", "src.0", + "mix.1", "mix.0", + "ctu.1", "ctu.0", + "dvc.0", "dvc.1", + "clk_a", "clk_b", "clk_c", "clk_i"; + power-domains = <&sysc 32>; + resets = <&cpg 1005>, + <&cpg 1006>, <&cpg 1007>, + <&cpg 1008>, <&cpg 1009>, + <&cpg 1010>, <&cpg 1011>, + <&cpg 1012>, <&cpg 1013>, + <&cpg 1014>, <&cpg 1015>; + reset-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", + "ssi.5", "ssi.4", "ssi.3", "ssi.2", + "ssi.1", "ssi.0"; + status = "disabled"; + + rcar_sound,dvc { + dvc0: dvc-0 { + dmas = <&audma1 0xbc>; + dma-names = "tx"; + }; + dvc1: dvc-1 { + dmas = <&audma1 0xbe>; + dma-names = "tx"; + }; + }; + + rcar_sound,mix { + mix0: mix-0 { }; + mix1: mix-1 { }; + }; + + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + + rcar_sound,src { + src0: src-0 { + interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x85>, <&audma1 0x9a>; + dma-names = "rx", "tx"; + }; + src1: src-1 { + interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x87>, <&audma1 0x9c>; + dma-names = "rx", "tx"; + }; + src2: src-2 { + interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x89>, <&audma1 0x9e>; + dma-names = "rx", "tx"; + }; + src3: src-3 { + interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8b>, <&audma1 0xa0>; + dma-names = "rx", "tx"; + }; + src4: src-4 { + interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8d>, <&audma1 0xb0>; + dma-names = "rx", "tx"; + }; + src5: src-5 { + interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8f>, <&audma1 0xb2>; + dma-names = "rx", "tx"; + }; + src6: src-6 { + interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x91>, <&audma1 0xb4>; + dma-names = "rx", "tx"; + }; + src7: src-7 { + interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x93>, <&audma1 0xb6>; + dma-names = "rx", "tx"; + }; + src8: src-8 { + interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x95>, <&audma1 0xb8>; + dma-names = "rx", "tx"; + }; + src9: src-9 { + interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x97>, <&audma1 0xba>; + dma-names = "rx", "tx"; + }; + }; + + rcar_sound,ssi { + ssi0: ssi-0 { + interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi1: ssi-1 { + interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi2: ssi-2 { + interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi3: ssi-3 { + interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi4: ssi-4 { + interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi5: ssi-5 { + interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi6: ssi-6 { + interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi7: ssi-7 { + interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi8: ssi-8 { + interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi9: ssi-9 { + interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + }; + port@1 { + reg = <1>; + }; + }; + }; + + audma0: dma-controller@ec700000 { + compatible = "renesas,dmac-r8a774a1", + "renesas,rcar-dmac"; + reg = <0 0xec700000 0 0x10000>; + interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 502>; + clock-names = "fck"; + power-domains = <&sysc 32>; + resets = <&cpg 502>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + audma1: dma-controller@ec720000 { + compatible = "renesas,dmac-r8a774a1", + "renesas,rcar-dmac"; + reg = <0 0xec720000 0 0x10000>; + interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 501>; + clock-names = "fck"; + power-domains = <&sysc 32>; + resets = <&cpg 501>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + xhci0: usb@ee000000 { + compatible = "renesas,xhci-r8a774a1", + "renesas,rcar-gen3-xhci"; + reg = <0 0xee000000 0 0xc00>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 328>; + power-domains = <&sysc 32>; + resets = <&cpg 328>; + status = "disabled"; + }; + + usb3_peri0: usb@ee020000 { + compatible = "renesas,r8a774a1-usb3-peri", + "renesas,rcar-gen3-usb3-peri"; + reg = <0 0xee020000 0 0x400>; + interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 328>; + power-domains = <&sysc 32>; + resets = <&cpg 328>; + status = "disabled"; + }; + + ohci0: usb@ee080000 { + compatible = "generic-ohci"; + reg = <0 0xee080000 0 0x100>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 703>; + phys = <&usb2_phy0>; + phy-names = "usb"; + power-domains = <&sysc 32>; + resets = <&cpg 703>; + status = "disabled"; + }; + + ohci1: usb@ee0a0000 { + compatible = "generic-ohci"; + reg = <0 0xee0a0000 0 0x100>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 702>; + phys = <&usb2_phy1>; + phy-names = "usb"; + power-domains = <&sysc 32>; + resets = <&cpg 702>; + status = "disabled"; + }; + + ehci0: usb@ee080100 { + compatible = "generic-ehci"; + reg = <0 0xee080100 0 0x100>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 703>; + phys = <&usb2_phy0>; + phy-names = "usb"; + companion = <&ohci0>; + power-domains = <&sysc 32>; + resets = <&cpg 703>; + status = "disabled"; + }; + + ehci1: usb@ee0a0100 { + compatible = "generic-ehci"; + reg = <0 0xee0a0100 0 0x100>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 702>; + phys = <&usb2_phy1>; + phy-names = "usb"; + companion = <&ohci1>; + power-domains = <&sysc 32>; + resets = <&cpg 702>; + status = "disabled"; + }; + + usb2_phy0: usb-phy@ee080200 { + compatible = "renesas,usb2-phy-r8a774a1", + "renesas,rcar-gen3-usb2-phy"; + reg = <0 0xee080200 0 0x700>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 703>; + power-domains = <&sysc 32>; + resets = <&cpg 703>; + #phy-cells = <0>; + status = "disabled"; + }; + + usb2_phy1: usb-phy@ee0a0200 { + compatible = "renesas,usb2-phy-r8a774a1", + "renesas,rcar-gen3-usb2-phy"; + reg = <0 0xee0a0200 0 0x700>; + clocks = <&cpg CPG_MOD 702>; + power-domains = <&sysc 32>; + resets = <&cpg 702>; + #phy-cells = <0>; + status = "disabled"; + }; + + sdhi0: sd@ee100000 { + compatible = "renesas,sdhi-r8a774a1", + "renesas,rcar-gen3-sdhi"; + reg = <0 0xee100000 0 0x2000>; + interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 314>; + max-frequency = <200000000>; + power-domains = <&sysc 32>; + resets = <&cpg 314>; + status = "disabled"; + }; + + sdhi1: sd@ee120000 { + compatible = "renesas,sdhi-r8a774a1", + "renesas,rcar-gen3-sdhi"; + reg = <0 0xee120000 0 0x2000>; + interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 313>; + max-frequency = <200000000>; + power-domains = <&sysc 32>; + resets = <&cpg 313>; + status = "disabled"; + }; + + sdhi2: sd@ee140000 { + compatible = "renesas,sdhi-r8a774a1", + "renesas,rcar-gen3-sdhi"; + reg = <0 0xee140000 0 0x2000>; + interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 312>; + max-frequency = <200000000>; + power-domains = <&sysc 32>; + resets = <&cpg 312>; + status = "disabled"; + }; + + sdhi3: sd@ee160000 { + compatible = "renesas,sdhi-r8a774a1", + "renesas,rcar-gen3-sdhi"; + reg = <0 0xee160000 0 0x2000>; + interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 311>; + max-frequency = <200000000>; + power-domains = <&sysc 32>; + resets = <&cpg 311>; + status = "disabled"; + }; + + gic: interrupt-controller@f1010000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xf1010000 0 0x1000>, + <0x0 0xf1020000 0 0x20000>, + <0x0 0xf1040000 0 0x20000>, + <0x0 0xf1060000 0 0x20000>; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>; + clocks = <&cpg CPG_MOD 408>; + clock-names = "clk"; + power-domains = <&sysc 32>; + resets = <&cpg 408>; + }; + + fcpf0: fcp@fe950000 { + compatible = "renesas,fcpf"; + reg = <0 0xfe950000 0 0x200>; + clocks = <&cpg CPG_MOD 615>; + power-domains = <&sysc 14>; + resets = <&cpg 615>; + }; + + fcpvb0: fcp@fe96f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe96f000 0 0x200>; + clocks = <&cpg CPG_MOD 607>; + power-domains = <&sysc 14>; + resets = <&cpg 607>; + }; + + fcpvd0: fcp@fea27000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea27000 0 0x200>; + clocks = <&cpg CPG_MOD 603>; + power-domains = <&sysc 32>; + resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; + }; + + fcpvd1: fcp@fea2f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea2f000 0 0x200>; + clocks = <&cpg CPG_MOD 602>; + power-domains = <&sysc 32>; + resets = <&cpg 602>; + iommus = <&ipmmu_vi0 9>; + }; + + fcpvd2: fcp@fea37000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea37000 0 0x200>; + clocks = <&cpg CPG_MOD 601>; + power-domains = <&sysc 32>; + resets = <&cpg 601>; + iommus = <&ipmmu_vi0 10>; + }; + + fcpvi0: fcp@fe9af000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9af000 0 0x200>; + clocks = <&cpg CPG_MOD 611>; + power-domains = <&sysc 14>; + resets = <&cpg 611>; + iommus = <&ipmmu_vc0 19>; + }; + + prr: chipid@fff00044 { + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; + }; + }; + + thermal-zones { + sensor_thermal1: sensor-thermal1 { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; + + trips { + sensor1_crit: sensor1-crit { + temperature = <120000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + + sensor_thermal2: sensor-thermal2 { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; + + trips { + sensor2_crit: sensor2-crit { + temperature = <120000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + + sensor_thermal3: sensor-thermal3 { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; + + trips { + sensor3_crit: sensor3-crit { + temperature = <120000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>; + }; + + /* External USB clocks - can be overridden by the board */ + usb3s0_clk: usb3s0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + usb_extal_clk: usb_extal { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts index 6b5fa91f1d5d..0895503b69d0 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts @@ -40,12 +40,11 @@ <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>, - <&cpg CPG_MOD 727>, <&versaclock5 1>, <&x21_clk>, <&x22_clk>, <&versaclock5 2>; - clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "du.3", "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi index 7b2fbaec9aef..0fb84c219b2f 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7795 ES1.x SoC + * Device Tree Source for the R-Car H3 (R8A77950) ES1.x SoC * * Copyright (C) 2015 Renesas Electronics Corp. */ @@ -232,7 +232,7 @@ port@1 { vin0csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin0>; + remote-endpoint = <&csi21vin0>; }; }; }; @@ -243,7 +243,7 @@ port@1 { vin1csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin1>; + remote-endpoint = <&csi21vin1>; }; }; }; @@ -254,7 +254,7 @@ port@1 { vin2csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin2>; + remote-endpoint = <&csi21vin2>; }; }; }; @@ -265,7 +265,7 @@ port@1 { vin3csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin3>; + remote-endpoint = <&csi21vin3>; }; }; }; @@ -276,7 +276,7 @@ port@1 { vin4csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin4>; + remote-endpoint = <&csi21vin4>; }; }; }; @@ -287,7 +287,7 @@ port@1 { vin5csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin5>; + remote-endpoint = <&csi21vin5>; }; }; }; @@ -298,7 +298,7 @@ port@1 { vin6csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin6>; + remote-endpoint = <&csi21vin6>; }; }; }; @@ -309,7 +309,7 @@ port@1 { vin7csi21: endpoint@1 { reg = <1>; - remote-endpoint= <&csi21vin7>; + remote-endpoint = <&csi21vin7>; }; }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts index df50bf46406e..54515eaf0310 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts @@ -41,11 +41,10 @@ <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>, - <&cpg CPG_MOD 727>, <&versaclock5 1>, <&versaclock5 3>, <&versaclock5 4>, <&versaclock5 2>; - clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "du.3", "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 446822f5751c..1620e8d8dacc 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -40,12 +40,11 @@ <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>, - <&cpg CPG_MOD 727>, <&versaclock5 1>, <&x21_clk>, <&x22_clk>, <&versaclock5 2>; - clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "du.3", "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts index 8ded64d0a4d5..cf08a119eec0 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts @@ -40,12 +40,11 @@ <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>, - <&cpg CPG_MOD 727>, <&versaclock6 1>, <&x21_clk>, <&x22_clk>, <&versaclock6 2>; - clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "du.3", "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; }; @@ -152,6 +151,15 @@ }; }; +&pca9654 { + pcie_sata_switch { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-low; /* enable SATA by default */ + line-name = "PCIE/SATA switch"; + }; +}; + &pfc { usb2_pins: usb2 { groups = "usb2"; @@ -176,6 +184,11 @@ }; }; +/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */ +&sata { + status = "okay"; +}; + &usb2_phy2 { pinctrl-0 = <&usb2_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index fb9d08ad7659..b5f2273caca4 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7795 SoC + * Device Tree Source for the R-Car H3 (R8A77950) SoC * * Copyright (C) 2015 Renesas Electronics Corp. */ @@ -123,7 +123,7 @@ power-domains = <&sysc R8A7795_PD_CA57_CPU0>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -135,7 +135,7 @@ power-domains = <&sysc R8A7795_PD_CA57_CPU1>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -147,7 +147,7 @@ power-domains = <&sysc R8A7795_PD_CA57_CPU2>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -159,7 +159,7 @@ power-domains = <&sysc R8A7795_PD_CA57_CPU3>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -171,7 +171,7 @@ power-domains = <&sysc R8A7795_PD_CA53_CPU0>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -182,7 +182,7 @@ power-domains = <&sysc R8A7795_PD_CA53_CPU1>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -193,7 +193,7 @@ power-domains = <&sysc R8A7795_PD_CA53_CPU2>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -204,7 +204,7 @@ power-domains = <&sysc R8A7795_PD_CA53_CPU3>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7795_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7795_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -455,7 +455,6 @@ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; resets = <&cpg 522>; #thermal-sensor-cells = <1>; - status = "okay"; }; intc_ex: interrupt-controller@e61c0000 { @@ -525,15 +524,6 @@ status = "disabled"; }; - arm_cc630p: crypto@e6601000 { - compatible = "arm,cryptocell-630p-ree"; - interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x0 0xe6601000 0 0x1000>; - clocks = <&cpg CPG_MOD 229>; - resets = <&cpg 229>; - power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - }; - i2c3: i2c@e66d0000 { #address-cells = <1>; #size-cells = <0>; @@ -707,7 +697,7 @@ "renesas,rcar-gen3-usbhs"; reg = <0 0xe6590000 0 0x100>; interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 704>; + clocks = <&cpg CPG_MOD 704>, <&cpg CPG_MOD 703>; dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, <&usb_dmac1 0>, <&usb_dmac1 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; @@ -715,7 +705,7 @@ phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 704>; + resets = <&cpg 704>, <&cpg 703>; status = "disabled"; }; @@ -724,7 +714,7 @@ "renesas,rcar-gen3-usbhs"; reg = <0 0xe659c000 0 0x100>; interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 705>; + clocks = <&cpg CPG_MOD 705>, <&cpg CPG_MOD 700>; dmas = <&usb_dmac2 0>, <&usb_dmac2 1>, <&usb_dmac3 0>, <&usb_dmac3 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; @@ -732,7 +722,7 @@ phys = <&usb2_phy3>; phy-names = "usb"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 705>; + resets = <&cpg 705>, <&cpg 700>; status = "disabled"; }; @@ -805,6 +795,15 @@ status = "disabled"; }; + arm_cc630p: crypto@e6601000 { + compatible = "arm,cryptocell-630p-ree"; + interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x0 0xe6601000 0 0x1000>; + clocks = <&cpg CPG_MOD 229>; + resets = <&cpg 229>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + }; + dmac0: dma-controller@e6700000 { compatible = "renesas,dmac-r8a7795", "renesas,rcar-dmac"; @@ -1425,11 +1424,11 @@ vin0csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin0>; + remote-endpoint = <&csi20vin0>; }; vin0csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin0>; + remote-endpoint = <&csi40vin0>; }; }; }; @@ -1457,11 +1456,11 @@ vin1csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin1>; + remote-endpoint = <&csi20vin1>; }; vin1csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin1>; + remote-endpoint = <&csi40vin1>; }; }; }; @@ -1489,11 +1488,11 @@ vin2csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin2>; + remote-endpoint = <&csi20vin2>; }; vin2csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin2>; + remote-endpoint = <&csi40vin2>; }; }; }; @@ -1521,11 +1520,11 @@ vin3csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin3>; + remote-endpoint = <&csi20vin3>; }; vin3csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin3>; + remote-endpoint = <&csi40vin3>; }; }; }; @@ -1553,11 +1552,11 @@ vin4csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin4>; + remote-endpoint = <&csi20vin4>; }; vin4csi41: endpoint@3 { reg = <3>; - remote-endpoint= <&csi41vin4>; + remote-endpoint = <&csi41vin4>; }; }; }; @@ -1585,11 +1584,11 @@ vin5csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin5>; + remote-endpoint = <&csi20vin5>; }; vin5csi41: endpoint@3 { reg = <3>; - remote-endpoint= <&csi41vin5>; + remote-endpoint = <&csi41vin5>; }; }; }; @@ -1617,11 +1616,11 @@ vin6csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin6>; + remote-endpoint = <&csi20vin6>; }; vin6csi41: endpoint@3 { reg = <3>; - remote-endpoint= <&csi41vin6>; + remote-endpoint = <&csi41vin6>; }; }; }; @@ -1649,11 +1648,11 @@ vin7csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin7>; + remote-endpoint = <&csi20vin7>; }; vin7csi41: endpoint@3 { reg = <3>; - remote-endpoint= <&csi41vin7>; + remote-endpoint = <&csi41vin7>; }; }; }; @@ -2098,11 +2097,11 @@ compatible = "generic-ohci"; reg = <0 0xee080000 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -2134,11 +2133,11 @@ compatible = "generic-ohci"; reg = <0 0xee0e0000 0 0x100>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 700>; + clocks = <&cpg CPG_MOD 700>, <&cpg CPG_MOD 705>; phys = <&usb2_phy3>; phy-names = "usb"; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 700>; + resets = <&cpg 700>, <&cpg 705>; status = "disabled"; }; @@ -2146,12 +2145,12 @@ compatible = "generic-ehci"; reg = <0 0xee080100 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; companion = <&ohci0>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -2185,12 +2184,12 @@ compatible = "generic-ehci"; reg = <0 0xee0e0100 0 0x100>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 700>; + clocks = <&cpg CPG_MOD 700>, <&cpg CPG_MOD 705>; phys = <&usb2_phy3>; phy-names = "usb"; companion = <&ohci3>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 700>; + resets = <&cpg 700>, <&cpg 705>; status = "disabled"; }; @@ -2199,9 +2198,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee080200 0 0x700>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; #phy-cells = <0>; status = "disabled"; }; @@ -2233,9 +2232,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee0e0200 0 0x700>; interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 700>; + clocks = <&cpg CPG_MOD 700>, <&cpg CPG_MOD 705>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - resets = <&cpg 700>; + resets = <&cpg 700>, <&cpg 705>; #phy-cells = <0>; status = "disabled"; }; @@ -2782,9 +2781,7 @@ du: display@feb00000 { compatible = "renesas,du-r8a7795"; - reg = <0 0xfeb00000 0 0x80000>, - <0 0xfeb90000 0 0x14>; - reg-names = "du", "lvds.0"; + reg = <0 0xfeb00000 0 0x80000>; interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>, @@ -2792,9 +2789,8 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, - <&cpg CPG_MOD 721>, - <&cpg CPG_MOD 727>; - clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0"; + <&cpg CPG_MOD 721>; + clock-names = "du.0", "du.1", "du.2", "du.3"; vsps = <&vspd0 0 &vspd1 0 &vspd2 0 &vspd0 1>; status = "disabled"; @@ -2822,6 +2818,33 @@ port@3 { reg = <3>; du_out_lvds0: endpoint { + remote-endpoint = <&lvds0_in>; + }; + }; + }; + }; + + lvds0: lvds@feb90000 { + compatible = "renesas,r8a7795-lvds"; + reg = <0 0xfeb90000 0 0x14>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 727>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds0_in: endpoint { + remote-endpoint = <&du_out_lvds0>; + }; + }; + port@1 { + reg = <1>; + lvds0_out: endpoint { }; }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts index cbd8acbf537e..9e4594c27fa6 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts @@ -30,10 +30,9 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, - <&cpg CPG_MOD 727>, <&versaclock5 1>, <&versaclock5 3>, <&versaclock5 2>; - clock-names = "du.0", "du.1", "du.2", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "dclkin.0", "dclkin.1", "dclkin.2"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts index 052d72acc862..b4f9567cb9f8 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts @@ -29,11 +29,10 @@ clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, <&cpg CPG_MOD 722>, - <&cpg CPG_MOD 727>, <&versaclock5 1>, <&x21_clk>, <&versaclock5 2>; - clock-names = "du.0", "du.1", "du.2", "lvds.0", + clock-names = "du.0", "du.1", "du.2", "dclkin.0", "dclkin.1", "dclkin.2"; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi index cbd35c00b4af..1ec6aaa520c1 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a7796 SoC + * Device Tree Source for the R-Car M3-W (R8A77960) SoC * * Copyright (C) 2016-2017 Renesas Electronics Corp. */ @@ -134,7 +134,7 @@ power-domains = <&sysc R8A7796_PD_CA57_CPU0>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -146,7 +146,7 @@ power-domains = <&sysc R8A7796_PD_CA57_CPU1>; next-level-cache = <&L2_CA57>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z>; operating-points-v2 = <&cluster0_opp>; #cooling-cells = <2>; }; @@ -158,7 +158,7 @@ power-domains = <&sysc R8A7796_PD_CA53_CPU0>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -169,7 +169,7 @@ power-domains = <&sysc R8A7796_PD_CA53_CPU1>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -180,7 +180,7 @@ power-domains = <&sysc R8A7796_PD_CA53_CPU2>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -191,7 +191,7 @@ power-domains = <&sysc R8A7796_PD_CA53_CPU3>; next-level-cache = <&L2_CA53>; enable-method = "psci"; - clocks =<&cpg CPG_CORE R8A7796_CLK_Z2>; + clocks = <&cpg CPG_CORE R8A7796_CLK_Z2>; operating-points-v2 = <&cluster1_opp>; }; @@ -434,7 +434,6 @@ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; resets = <&cpg 522>; #thermal-sensor-cells = <1>; - status = "okay"; }; intc_ex: interrupt-controller@e61c0000 { @@ -677,7 +676,7 @@ "renesas,rcar-gen3-usbhs"; reg = <0 0xe6590000 0 0x100>; interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 704>; + clocks = <&cpg CPG_MOD 704>, <&cpg CPG_MOD 703>; dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, <&usb_dmac1 0>, <&usb_dmac1 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; @@ -685,7 +684,7 @@ phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; - resets = <&cpg 704>; + resets = <&cpg 704>, <&cpg 703>; status = "disabled"; }; @@ -1299,11 +1298,11 @@ vin0csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin0>; + remote-endpoint = <&csi20vin0>; }; vin0csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin0>; + remote-endpoint = <&csi40vin0>; }; }; }; @@ -1331,11 +1330,11 @@ vin1csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin1>; + remote-endpoint = <&csi20vin1>; }; vin1csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin1>; + remote-endpoint = <&csi40vin1>; }; }; }; @@ -1363,11 +1362,11 @@ vin2csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin2>; + remote-endpoint = <&csi20vin2>; }; vin2csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin2>; + remote-endpoint = <&csi40vin2>; }; }; }; @@ -1395,11 +1394,11 @@ vin3csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin3>; + remote-endpoint = <&csi20vin3>; }; vin3csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin3>; + remote-endpoint = <&csi40vin3>; }; }; }; @@ -1427,11 +1426,11 @@ vin4csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin4>; + remote-endpoint = <&csi20vin4>; }; vin4csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin4>; + remote-endpoint = <&csi40vin4>; }; }; }; @@ -1459,11 +1458,11 @@ vin5csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin5>; + remote-endpoint = <&csi20vin5>; }; vin5csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin5>; + remote-endpoint = <&csi40vin5>; }; }; }; @@ -1491,11 +1490,11 @@ vin6csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin6>; + remote-endpoint = <&csi20vin6>; }; vin6csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin6>; + remote-endpoint = <&csi40vin6>; }; }; }; @@ -1523,11 +1522,11 @@ vin7csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin7>; + remote-endpoint = <&csi20vin7>; }; vin7csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin7>; + remote-endpoint = <&csi40vin7>; }; }; }; @@ -1970,11 +1969,11 @@ compatible = "generic-ohci"; reg = <0 0xee080000 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -1994,12 +1993,12 @@ compatible = "generic-ehci"; reg = <0 0xee080100 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; - companion= <&ohci0>; + companion = <&ohci0>; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -2010,7 +2009,7 @@ clocks = <&cpg CPG_MOD 702>; phys = <&usb2_phy1>; phy-names = "usb"; - companion= <&ohci1>; + companion = <&ohci1>; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; resets = <&cpg 702>; status = "disabled"; @@ -2021,9 +2020,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee080200 0 0x700>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; #phy-cells = <0>; status = "disabled"; }; @@ -2437,17 +2436,14 @@ du: display@feb00000 { compatible = "renesas,du-r8a7796"; - reg = <0 0xfeb00000 0 0x70000>, - <0 0xfeb90000 0 0x14>; - reg-names = "du", "lvds.0"; + reg = <0 0xfeb00000 0 0x70000>; interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 724>, <&cpg CPG_MOD 723>, - <&cpg CPG_MOD 722>, - <&cpg CPG_MOD 727>; - clock-names = "du.0", "du.1", "du.2", "lvds.0"; + <&cpg CPG_MOD 722>; + clock-names = "du.0", "du.1", "du.2"; status = "disabled"; vsps = <&vspd0 &vspd1 &vspd2>; @@ -2470,6 +2466,33 @@ port@2 { reg = <2>; du_out_lvds0: endpoint { + remote-endpoint = <&lvds0_in>; + }; + }; + }; + }; + + lvds0: lvds@feb90000 { + compatible = "renesas,r8a7796-lvds"; + reg = <0 0xfeb90000 0 0x14>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + resets = <&cpg 727>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds0_in: endpoint { + remote-endpoint = <&du_out_lvds0>; + }; + }; + port@1 { + reg = <1>; + lvds0_out: endpoint { }; }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts new file mode 100644 index 000000000000..dadad97051b9 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for the M3NULCB Kingfisher board + * + * Copyright (C) 2018 Renesas Electronics Corp. + * Copyright (C) 2018 Cogent Embedded, Inc. + */ + +#include "r8a77965-m3nulcb.dts" +#include "ulcb-kf.dtsi" + +/ { + model = "Renesas M3NULCB Kingfisher board based on r8a77965"; + compatible = "shimafuji,kingfisher", "renesas,m3nulcb", + "renesas,r8a77965"; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb.dts b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb.dts new file mode 100644 index 000000000000..964078b6cc49 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for the M3NULCB (R-Car Starter Kit Pro) board + * + * Copyright (C) 2018 Renesas Electronics Corp. + * Copyright (C) 2018 Cogent Embedded, Inc. + */ + +/dts-v1/; +#include "r8a77965.dtsi" +#include "ulcb.dtsi" + +/ { + model = "Renesas M3NULCB board based on r8a77965"; + compatible = "renesas,m3nulcb", "renesas,r8a77965"; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x78000000>; + }; +}; + +&du { + clocks = <&cpg CPG_MOD 724>, + <&cpg CPG_MOD 723>, + <&cpg CPG_MOD 721>, + <&versaclock5 1>, + <&versaclock5 3>, + <&versaclock5 2>; + clock-names = "du.0", "du.1", "du.3", + "dclkin.0", "dclkin.1", "dclkin.3"; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts index 9de4e3db1621..f03a5e9e0c42 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts +++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts @@ -47,3 +47,17 @@ &hdmi0_con { remote-endpoint = <&rcar_dw_hdmi0_out>; }; + +&pca9654 { + pcie_sata_switch { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-low; /* enable SATA by default */ + line-name = "PCIE/SATA switch"; + }; +}; + +/* SW12-7 must be set 'Off' (MD12 set to 1) which is not the default! */ +&sata { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index 0cd44461a0bd..83946ca2eba5 100644 --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a77965 SoC + * Device Tree Source for the R-Car M3-N (R8A77965) SoC * * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org> * @@ -12,7 +12,7 @@ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/power/r8a77965-sysc.h> -#define CPG_AUDIO_CLK_I 10 +#define CPG_AUDIO_CLK_I R8A77965_CLK_S0D4 / { compatible = "renesas,r8a77965"; @@ -60,6 +60,46 @@ clock-frequency = <0>; }; + cluster0_opp: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <830000>; + clock-latency-ns = <300000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <830000>; + clock-latency-ns = <300000>; + }; + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <830000>; + clock-latency-ns = <300000>; + opp-suspend; + }; + opp-1600000000 { + opp-hz = /bits/ 64 <1600000000>; + opp-microvolt = <900000>; + clock-latency-ns = <300000>; + turbo-mode; + }; + opp-1700000000 { + opp-hz = /bits/ 64 <1700000000>; + opp-microvolt = <900000>; + clock-latency-ns = <300000>; + turbo-mode; + }; + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <960000>; + clock-latency-ns = <300000>; + turbo-mode; + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -71,6 +111,8 @@ power-domains = <&sysc R8A77965_PD_CA57_CPU0>; next-level-cache = <&L2_CA57>; enable-method = "psci"; + clocks = <&cpg CPG_CORE R8A77965_CLK_Z>; + operating-points-v2 = <&cluster0_opp>; }; a57_1: cpu@1 { @@ -80,6 +122,8 @@ power-domains = <&sysc R8A77965_PD_CA57_CPU1>; next-level-cache = <&L2_CA57>; enable-method = "psci"; + clocks = <&cpg CPG_CORE R8A77965_CLK_Z>; + operating-points-v2 = <&cluster0_opp>; }; L2_CA57: cache-controller-0 { @@ -306,7 +350,6 @@ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; resets = <&cpg 522>; #thermal-sensor-cells = <1>; - status = "okay"; }; intc_ex: interrupt-controller@e61c0000 { @@ -545,11 +588,11 @@ }; hsusb: usb@e6590000 { - compatible = "renesas,usbhs-r8a7796", + compatible = "renesas,usbhs-r8a77965", "renesas,rcar-gen3-usbhs"; reg = <0 0xe6590000 0 0x100>; interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 704>; + clocks = <&cpg CPG_MOD 704>, <&cpg CPG_MOD 703>; dmas = <&usb_dmac0 0>, <&usb_dmac0 1>, <&usb_dmac1 0>, <&usb_dmac1 1>; dma-names = "ch0", "ch1", "ch2", "ch3"; @@ -557,7 +600,7 @@ phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 704>; + resets = <&cpg 704>, <&cpg 703>; status = "disabled"; }; @@ -634,6 +677,14 @@ resets = <&cpg 219>; #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>; }; dmac1: dma-controller@e7300000 { @@ -668,6 +719,14 @@ resets = <&cpg 218>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>, + <&ipmmu_ds1 2>, <&ipmmu_ds1 3>, + <&ipmmu_ds1 4>, <&ipmmu_ds1 5>, + <&ipmmu_ds1 6>, <&ipmmu_ds1 7>, + <&ipmmu_ds1 8>, <&ipmmu_ds1 9>, + <&ipmmu_ds1 10>, <&ipmmu_ds1 11>, + <&ipmmu_ds1 12>, <&ipmmu_ds1 13>, + <&ipmmu_ds1 14>, <&ipmmu_ds1 15>; }; dmac2: dma-controller@e7310000 { @@ -702,6 +761,14 @@ resets = <&cpg 217>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>, + <&ipmmu_ds1 18>, <&ipmmu_ds1 19>, + <&ipmmu_ds1 20>, <&ipmmu_ds1 21>, + <&ipmmu_ds1 22>, <&ipmmu_ds1 23>, + <&ipmmu_ds1 24>, <&ipmmu_ds1 25>, + <&ipmmu_ds1 26>, <&ipmmu_ds1 27>, + <&ipmmu_ds1 28>, <&ipmmu_ds1 29>, + <&ipmmu_ds1 30>, <&ipmmu_ds1 31>; }; ipmmu_ds0: mmu@e6740000 { @@ -838,6 +905,16 @@ status = "disabled"; }; + can0: can@e6c30000 { + reg = <0 0xe6c30000 0 0x1000>; + /* placeholder */ + }; + + can1: can@e6c38000 { + reg = <0 0xe6c38000 0 0x1000>; + /* placeholder */ + }; + pwm0: pwm@e6e30000 { compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar"; reg = <0 0xe6e30000 0 8>; @@ -1089,11 +1166,11 @@ vin0csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin0>; + remote-endpoint = <&csi20vin0>; }; vin0csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin0>; + remote-endpoint = <&csi40vin0>; }; }; }; @@ -1121,11 +1198,11 @@ vin1csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin1>; + remote-endpoint = <&csi20vin1>; }; vin1csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin1>; + remote-endpoint = <&csi40vin1>; }; }; }; @@ -1153,11 +1230,11 @@ vin2csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin2>; + remote-endpoint = <&csi20vin2>; }; vin2csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin2>; + remote-endpoint = <&csi40vin2>; }; }; }; @@ -1185,11 +1262,11 @@ vin3csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin3>; + remote-endpoint = <&csi20vin3>; }; vin3csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin3>; + remote-endpoint = <&csi40vin3>; }; }; }; @@ -1217,11 +1294,11 @@ vin4csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin4>; + remote-endpoint = <&csi20vin4>; }; vin4csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin4>; + remote-endpoint = <&csi40vin4>; }; }; }; @@ -1249,11 +1326,11 @@ vin5csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin5>; + remote-endpoint = <&csi20vin5>; }; vin5csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin5>; + remote-endpoint = <&csi40vin5>; }; }; }; @@ -1281,11 +1358,11 @@ vin6csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin6>; + remote-endpoint = <&csi20vin6>; }; vin6csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin6>; + remote-endpoint = <&csi40vin6>; }; }; }; @@ -1313,57 +1390,280 @@ vin7csi20: endpoint@0 { reg = <0>; - remote-endpoint= <&csi20vin7>; + remote-endpoint = <&csi20vin7>; }; vin7csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin7>; + remote-endpoint = <&csi40vin7>; }; }; }; }; rcar_sound: sound@ec500000 { + /* + * #sound-dai-cells is required + * + * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>; + * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>; + */ + /* + * #clock-cells is required for audio_clkout0/1/2/3 + * + * clkout : #clock-cells = <0>; <&rcar_sound>; + * clkout0/1/2/3: #clock-cells = <1>; <&rcar_sound N>; + */ + compatible = "renesas,rcar_sound-r8a77965", "renesas,rcar_sound-gen3"; reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ <0 0xec541000 0 0x280>, /* SSI */ <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ - /* placeholder */ + reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; + + clocks = <&cpg CPG_MOD 1005>, + <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>, + <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>, + <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>, + <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>, + <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>, + <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>, + <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>, + <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>, + <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>, + <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>, + <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>, + <&audio_clk_a>, <&audio_clk_b>, + <&audio_clk_c>, + <&cpg CPG_CORE R8A77965_CLK_S0D4>; + clock-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", + "ssi.5", "ssi.4", "ssi.3", "ssi.2", + "ssi.1", "ssi.0", + "src.9", "src.8", "src.7", "src.6", + "src.5", "src.4", "src.3", "src.2", + "src.1", "src.0", + "mix.1", "mix.0", + "ctu.1", "ctu.0", + "dvc.0", "dvc.1", + "clk_a", "clk_b", "clk_c", "clk_i"; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 1005>, + <&cpg 1006>, <&cpg 1007>, + <&cpg 1008>, <&cpg 1009>, + <&cpg 1010>, <&cpg 1011>, + <&cpg 1012>, <&cpg 1013>, + <&cpg 1014>, <&cpg 1015>; + reset-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", + "ssi.5", "ssi.4", "ssi.3", "ssi.2", + "ssi.1", "ssi.0"; + status = "disabled"; rcar_sound,dvc { dvc0: dvc-0 { + dmas = <&audma1 0xbc>; + dma-names = "tx"; }; dvc1: dvc-1 { + dmas = <&audma1 0xbe>; + dma-names = "tx"; }; }; + rcar_sound,mix { + mix0: mix-0 { }; + mix1: mix-1 { }; + }; + + rcar_sound,ctu { + ctu00: ctu-0 { }; + ctu01: ctu-1 { }; + ctu02: ctu-2 { }; + ctu03: ctu-3 { }; + ctu10: ctu-4 { }; + ctu11: ctu-5 { }; + ctu12: ctu-6 { }; + ctu13: ctu-7 { }; + }; + rcar_sound,src { src0: src-0 { + interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x85>, <&audma1 0x9a>; + dma-names = "rx", "tx"; }; src1: src-1 { + interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x87>, <&audma1 0x9c>; + dma-names = "rx", "tx"; + }; + src2: src-2 { + interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x89>, <&audma1 0x9e>; + dma-names = "rx", "tx"; + }; + src3: src-3 { + interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8b>, <&audma1 0xa0>; + dma-names = "rx", "tx"; + }; + src4: src-4 { + interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8d>, <&audma1 0xb0>; + dma-names = "rx", "tx"; + }; + src5: src-5 { + interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8f>, <&audma1 0xb2>; + dma-names = "rx", "tx"; + }; + src6: src-6 { + interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x91>, <&audma1 0xb4>; + dma-names = "rx", "tx"; + }; + src7: src-7 { + interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x93>, <&audma1 0xb6>; + dma-names = "rx", "tx"; + }; + src8: src-8 { + interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x95>, <&audma1 0xb8>; + dma-names = "rx", "tx"; + }; + src9: src-9 { + interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x97>, <&audma1 0xba>; + dma-names = "rx", "tx"; }; }; rcar_sound,ssi { ssi0: ssi-0 { + interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi1: ssi-1 { + interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>; + dma-names = "rx", "tx", "rxu", "txu"; }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; + ssi2: ssi-2 { + interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>; + dma-names = "rx", "tx", "rxu", "txu"; }; - port@1 { - reg = <1>; + ssi3: ssi-3 { + interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi4: ssi-4 { + interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi5: ssi-5 { + interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi6: ssi-6 { + interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi7: ssi-7 { + interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi8: ssi-8 { + interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>; + dma-names = "rx", "tx", "rxu", "txu"; + }; + ssi9: ssi-9 { + interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>; + dma-names = "rx", "tx", "rxu", "txu"; }; }; }; + audma0: dma-controller@ec700000 { + compatible = "renesas,dmac-r8a77965", + "renesas,rcar-dmac"; + reg = <0 0xec700000 0 0x10000>; + interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 502>; + clock-names = "fck"; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 502>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + audma1: dma-controller@ec720000 { + compatible = "renesas,dmac-r8a77965", + "renesas,rcar-dmac"; + reg = <0 0xec720000 0 0x10000>; + interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 501>; + clock-names = "fck"; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 501>; + #dma-cells = <1>; + dma-channels = <16>; + }; + xhci0: usb@ee000000 { compatible = "renesas,xhci-r8a77965", "renesas,rcar-gen3-xhci"; @@ -1390,11 +1690,11 @@ compatible = "generic-ohci"; reg = <0 0xee080000 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -1414,12 +1714,12 @@ compatible = "generic-ehci"; reg = <0 0xee080100 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; companion = <&ohci0>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -1441,9 +1741,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee080200 0 0x700>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; #phy-cells = <0>; status = "disabled"; }; @@ -1452,9 +1752,9 @@ compatible = "renesas,usb2-phy-r8a77965", "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee0a0200 0 0x700>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 702>; power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 702>; #phy-cells = <0>; status = "disabled"; }; @@ -1507,6 +1807,17 @@ status = "disabled"; }; + sata: sata@ee300000 { + compatible = "renesas,sata-r8a77965", + "renesas,rcar-gen3-sata"; + reg = <0 0xee300000 0 0x200000>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 815>; + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 815>; + status = "disabled"; + }; + gic: interrupt-controller@f1010000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; @@ -1578,6 +1889,16 @@ status = "disabled"; }; + fdp1@fe940000 { + compatible = "renesas,fdp1"; + reg = <0 0xfe940000 0 0x2400>; + interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 119>; + power-domains = <&sysc R8A77965_PD_A3VP>; + resets = <&cpg 119>; + renesas,fcp = <&fcpf0>; + }; + fcpf0: fcp@fe950000 { compatible = "renesas,fcpf"; reg = <0 0xfe950000 0 0x200>; @@ -1843,14 +2164,6 @@ }; }; - timer { - compatible = "arm,armv8-timer"; - interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, - <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, - <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, - <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; - }; - thermal-zones { sensor_thermal1: sensor-thermal1 { polling-delay-passive = <250>; @@ -1895,6 +2208,14 @@ }; }; + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; + }; + /* External USB clocks - can be overridden by the board */ usb3s0_clk: usb3s0 { compatible = "fixed-clock"; diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts index 8eac8ca6550b..0dbcb4cccc18 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts @@ -51,6 +51,15 @@ regulator-always-on; }; + vcc_vddq_vin0: regulator-2 { + compatible = "regulator-fixed"; + regulator-name = "VCC_VDDQ_VIN0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + lvds-decoder { compatible = "thine,thc63lvd1024"; vcc-supply = <&vcc_d3_3v>; @@ -128,6 +137,12 @@ function = "i2c0"; }; + mmc_pins: mmc_3_3v { + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; + power-source = <3300>; + }; + scif0_pins: scif0 { groups = "scif0_data"; function = "scif0"; @@ -192,6 +207,17 @@ }; }; +&mmc0 { + pinctrl-0 = <&mmc_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&vcc_d3_3v>; + vqmmc-supply = <&vcc_vddq_vin0>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + &scif0 { pinctrl-0 = <&scif0_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi index 954168858fed..cba7885cf7c3 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a77970 SoC + * Device Tree Source for the R-Car V3M (R8A77970) SoC * * Copyright (C) 2016-2017 Renesas Electronics Corp. * Copyright (C) 2017 Cogent Embedded, Inc. @@ -24,6 +24,13 @@ i2c4 = &i2c4; }; + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -82,13 +89,6 @@ method = "smc"; }; - /* External CAN clock - to be overridden by boards that provide it */ - can_clk: can { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <0>; - }; - /* External SCIF clock - to be overridden by boards that provide it */ scif_clk: scif { compatible = "fixed-clock"; @@ -209,6 +209,76 @@ reg = <0 0xe6060000 0 0x504>; }; + cmt0: timer@e60f0000 { + compatible = "renesas,r8a77970-cmt0", + "renesas,rcar-gen3-cmt0"; + reg = <0 0xe60f0000 0 0x1004>; + interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 303>; + clock-names = "fck"; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 303>; + status = "disabled"; + }; + + cmt1: timer@e6130000 { + compatible = "renesas,r8a77970-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6130000 0 0x1004>; + interrupts = <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>, + <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 302>; + clock-names = "fck"; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 302>; + status = "disabled"; + }; + + cmt2: timer@e6140000 { + compatible = "renesas,r8a77970-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6140000 0 0x1004>; + interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 301>; + clock-names = "fck"; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 301>; + status = "disabled"; + }; + + cmt3: timer@e6148000 { + compatible = "renesas,r8a77970-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6148000 0 0x1004>; + interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 300>; + clock-names = "fck"; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 300>; + status = "disabled"; + }; + cpg: clock-controller@e6150000 { compatible = "renesas,r8a77970-cpg-mssr"; reg = <0 0xe6150000 0 0x1000>; @@ -544,6 +614,16 @@ status = "disabled"; }; + tpu: pwm@e6e80000 { + compatible = "renesas,tpu-r8a77970", "renesas,tpu"; + reg = <0 0xe6e80000 0 0x148>; + interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 304>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 304>; + #pwm-cells = <3>; + status = "disabled"; + }; vin0: video@e6ef0000 { compatible = "renesas,vin-r8a77970"; @@ -567,7 +647,7 @@ vin0csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin0>; + remote-endpoint = <&csi40vin0>; }; }; }; @@ -595,7 +675,7 @@ vin1csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin1>; + remote-endpoint = <&csi40vin1>; }; }; }; @@ -623,7 +703,7 @@ vin2csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin2>; + remote-endpoint = <&csi40vin2>; }; }; }; @@ -651,7 +731,7 @@ vin3csi40: endpoint@2 { reg = <2>; - remote-endpoint= <&csi40vin3>; + remote-endpoint = <&csi40vin3>; }; }; }; @@ -754,6 +834,18 @@ #iommu-cells = <1>; }; + mmc0: mmc@ee140000 { + compatible = "renesas,sdhi-r8a77970", + "renesas,rcar-gen3-sdhi"; + reg = <0 0xee140000 0 0x2000>; + interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 314>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 314>; + max-frequency = <200000000>; + status = "disabled"; + }; + gic: interrupt-controller@f1010000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts index 9f25c407dfd7..fe2e2c051cc9 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts @@ -45,6 +45,56 @@ regulator-boot-on; regulator-always-on; }; + + d1_8v: regulator-2 { + compatible = "regulator-fixed"; + regulator-name = "D1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7511_out>; + }; + }; + }; + + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <&d3_3v>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + thc63lvd1024_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + + port@2 { + reg = <2>; + thc63lvd1024_out: endpoint { + remote-endpoint = <&adv7511_in>; + }; + }; + }; + }; + + x1_clk: x1-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <148500000>; + }; }; &avb { @@ -74,6 +124,13 @@ }; }; +&du { + clocks = <&cpg CPG_MOD 724>, + <&x1_clk>; + clock-names = "du.0", "dclkin.0"; + status = "okay"; +}; + &extal_clk { clock-frequency = <16666666>; }; @@ -102,6 +159,55 @@ gpio-controller; #gpio-cells = <2>; }; + + hdmi@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + avdd-supply = <&d1_8v>; + dvdd-supply = <&d1_8v>; + pvdd-supply = <&d1_8v>; + bgvdd-supply = <&d1_8v>; + dvdd-3v-supply = <&d3_3v>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&thc63lvd1024_out>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&lvds0 { + status = "okay"; + + ports { + port@1 { + lvds0_out: endpoint { + remote-endpoint = <&thc63lvd1024_in>; + }; + }; + }; }; &mmc0 { @@ -117,6 +223,18 @@ status = "okay"; }; +&pciec { + status = "okay"; +}; + +&pcie_bus_clk { + clock-frequency = <100000000>; +}; + +&pcie_phy { + status = "okay"; +}; + &pfc { avb_pins: avb { groups = "avb_mdio", "avb_rgmii"; @@ -156,6 +274,11 @@ }; }; +&rwdt { + timeout-sec = <60>; + status = "okay"; +}; + &scif0 { pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts index 9dac42f8f804..dd14a41b32cd 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts @@ -27,6 +27,72 @@ /* first 128MB is reserved for secure area. */ reg = <0 0x48000000 0 0x78000000>; }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7511_out>; + }; + }; + }; + + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <&vcc3v3_d5>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + thc63lvd1024_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + + port@2 { + reg = <2>; + thc63lvd1024_out: endpoint { + remote-endpoint = <&adv7511_in>; + }; + }; + }; + }; + + osc1_clk: osc1-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <148500000>; + }; + + vcc1v8_d4: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "VCC1V8_D4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + vcc3v3_d5: regulator-1 { + compatible = "regulator-fixed"; + regulator-name = "VCC3V3_D5"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&du { + clocks = <&cpg CPG_MOD 724>, + <&osc1_clk>; + clock-names = "du.0", "dclkin.0"; + status = "okay"; }; &extal_clk { @@ -53,6 +119,64 @@ }; }; +&i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + + status = "okay"; + clock-frequency = <400000>; + + hdmi@39 { + compatible = "adi,adv7511w"; + #sound-dai-cells = <0>; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + avdd-supply = <&vcc1v8_d4>; + dvdd-supply = <&vcc1v8_d4>; + pvdd-supply = <&vcc1v8_d4>; + bgvdd-supply = <&vcc1v8_d4>; + dvdd-3v-supply = <&vcc3v3_d5>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&thc63lvd1024_out>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&lvds0 { + status = "okay"; + + ports { + port@1 { + lvds0_out: endpoint { + remote-endpoint = <&thc63lvd1024_in>; + }; + }; + }; +}; + &pfc { gether_pins: gether { groups = "gether_mdio_a", "gether_rgmii", @@ -60,6 +184,11 @@ function = "gether"; }; + i2c0_pins: i2c0 { + groups = "i2c0"; + function = "i2c0"; + }; + scif0_pins: scif0 { groups = "scif0_data"; function = "scif0"; @@ -71,6 +200,11 @@ }; }; +&rwdt { + timeout-sec = <60>; + status = "okay"; +}; + &scif0 { pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi index b8c9a56562f2..d4952b527d14 100644 --- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a77980 SoC + * Device Tree Source for the R-Car V3H (R8A77980) SoC * * Copyright (C) 2018 Renesas Electronics Corp. * Copyright (C) 2018 Cogent Embedded, Inc. @@ -25,6 +25,13 @@ i2c5 = &i2c5; }; + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -77,27 +84,36 @@ }; }; - /* External CAN clock - to be overridden by boards that provide it */ - can_clk: can { + extal_clk: extal { compatible = "fixed-clock"; #clock-cells = <0>; + /* This value must be overridden by the board */ clock-frequency = <0>; }; - extal_clk: extal { + extalr_clk: extalr { compatible = "fixed-clock"; #clock-cells = <0>; /* This value must be overridden by the board */ clock-frequency = <0>; }; - extalr_clk: extalr { + /* External PCIe clock - can be overridden by the board */ + pcie_bus_clk: pcie_bus { compatible = "fixed-clock"; #clock-cells = <0>; - /* This value must be overridden by the board */ clock-frequency = <0>; }; + pmu_a53 { + compatible = "arm,cortex-a53-pmu"; + interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>; + }; + psci { compatible = "arm,psci-1.0", "arm,psci-0.2"; method = "smc"; @@ -118,6 +134,16 @@ #size-cells = <2>; ranges; + rwdt: watchdog@e6020000 { + compatible = "renesas,r8a77980-wdt", + "renesas,rcar-gen3-wdt"; + reg = <0 0xe6020000 0 0x0c>; + clocks = <&cpg CPG_MOD 402>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 402>; + status = "disabled"; + }; + gpio0: gpio@e6050000 { compatible = "renesas,gpio-r8a77980", "renesas,rcar-gen3-gpio"; @@ -213,6 +239,76 @@ reg = <0 0xe6060000 0 0x50c>; }; + cmt0: timer@e60f0000 { + compatible = "renesas,r8a77980-cmt0", + "renesas,rcar-gen3-cmt0"; + reg = <0 0xe60f0000 0 0x1004>; + interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 303>; + clock-names = "fck"; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 303>; + status = "disabled"; + }; + + cmt1: timer@e6130000 { + compatible = "renesas,r8a77980-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6130000 0 0x1004>; + interrupts = <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>, + <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 302>; + clock-names = "fck"; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 302>; + status = "disabled"; + }; + + cmt2: timer@e6140000 { + compatible = "renesas,r8a77980-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6140000 0 0x1004>; + interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 301>; + clock-names = "fck"; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 301>; + status = "disabled"; + }; + + cmt3: timer@e6148000 { + compatible = "renesas,r8a77980-cmt1", + "renesas,rcar-gen3-cmt1"; + reg = <0 0xe6148000 0 0x1004>; + interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 300>; + clock-names = "fck"; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 300>; + status = "disabled"; + }; + cpg: clock-controller@e6150000 { compatible = "renesas,r8a77980-cpg-mssr"; reg = <0 0xe6150000 0 0x1000>; @@ -418,6 +514,16 @@ status = "disabled"; }; + pcie_phy: pcie-phy@e65d0000 { + compatible = "renesas,r8a77980-pcie-phy"; + reg = <0 0xe65d0000 0 0x8000>; + #phy-cells = <0>; + clocks = <&cpg CPG_MOD 319>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 319>; + status = "disabled"; + }; + canfd: can@e66c0000 { compatible = "renesas,r8a77980-canfd", "renesas,rcar-gen3-canfd"; @@ -443,69 +549,6 @@ }; }; - ipmmu_ds1: mmu@e7740000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xe7740000 0 0x1000>; - renesas,ipmmu-main = <&ipmmu_mm 0>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_vip0: mmu@e7b00000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xe7b00000 0 0x1000>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_vip1: mmu@e7960000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xe7960000 0 0x1000>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_ir: mmu@ff8b0000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xff8b0000 0 0x1000>; - renesas,ipmmu-main = <&ipmmu_mm 3>; - power-domains = <&sysc R8A77980_PD_A3IR>; - #iommu-cells = <1>; - }; - - ipmmu_mm: mmu@e67b0000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xe67b0000 0 0x1000>; - interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_rt: mmu@ffc80000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xffc80000 0 0x1000>; - renesas,ipmmu-main = <&ipmmu_mm 10>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_vc0: mmu@fe6b0000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xfe6b0000 0 0x1000>; - renesas,ipmmu-main = <&ipmmu_mm 12>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - - ipmmu_vi0: mmu@febd0000 { - compatible = "renesas,ipmmu-r8a77980"; - reg = <0 0xfebd0000 0 0x1000>; - renesas,ipmmu-main = <&ipmmu_mm 14>; - power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; - #iommu-cells = <1>; - }; - avb: ethernet@e6800000 { compatible = "renesas,etheravb-r8a77980", "renesas,etheravb-rcar-gen3"; @@ -623,6 +666,313 @@ status = "disabled"; }; + tpu: pwm@e6e80000 { + compatible = "renesas,tpu-r8a77980", "renesas,tpu"; + reg = <0 0xe6e80000 0 0x148>; + interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 304>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 304>; + #pwm-cells = <3>; + status = "disabled"; + }; + + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef0000 0 0x1000>; + interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 811>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin0csi40: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi40vin0>; + }; + }; + }; + }; + + vin1: video@e6ef1000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef1000 0 0x1000>; + interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + status = "disabled"; + resets = <&cpg 810>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin1csi40: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi40vin1>; + }; + }; + }; + }; + + vin2: video@e6ef2000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef2000 0 0x1000>; + interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 809>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin2csi40: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi40vin2>; + }; + }; + }; + }; + + vin3: video@e6ef3000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef3000 0 0x1000>; + interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 808>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 808>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin3csi40: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi40vin3>; + }; + }; + }; + }; + + vin4: video@e6ef4000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef4000 0 0x1000>; + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 807>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin4csi41: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi41vin4>; + }; + }; + }; + }; + + vin5: video@e6ef5000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef5000 0 0x1000>; + interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 806>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin5csi41: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi41vin5>; + }; + }; + }; + }; + + vin6: video@e6ef6000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef6000 0 0x1000>; + interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 805>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 805>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin6csi41: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi41vin6>; + }; + }; + }; + }; + + vin7: video@e6ef7000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef7000 0 0x1000>; + interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 804>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 804>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + vin7csi41: endpoint@2 { + reg = <2>; + remote-endpoint = <&csi41vin7>; + }; + }; + }; + }; + + vin8: video@e6ef8000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef8000 0 0x1000>; + interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 628>; + status = "disabled"; + }; + + vin9: video@e6ef9000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef9000 0 0x1000>; + interrupts = <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 627>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 627>; + status = "disabled"; + }; + + vin10: video@e6efa000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6efa000 0 0x1000>; + interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 625>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 625>; + status = "disabled"; + }; + + vin11: video@e6efb000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6efb000 0 0x1000>; + interrupts = <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 618>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 618>; + status = "disabled"; + }; + + vin12: video@e6efc000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6efc000 0 0x1000>; + interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 612>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 612>; + status = "disabled"; + }; + + vin13: video@e6efd000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6efd000 0 0x1000>; + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 608>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 608>; + status = "disabled"; + }; + + vin14: video@e6efe000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6efe000 0 0x1000>; + interrupts = <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 605>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 605>; + status = "disabled"; + }; + + vin15: video@e6eff000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6eff000 0 0x1000>; + interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 604>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 604>; + status = "disabled"; + }; + dmac1: dma-controller@e7300000 { compatible = "renesas,dmac-r8a77980", "renesas,rcar-dmac"; @@ -655,6 +1005,14 @@ resets = <&cpg 218>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>, + <&ipmmu_ds1 2>, <&ipmmu_ds1 3>, + <&ipmmu_ds1 4>, <&ipmmu_ds1 5>, + <&ipmmu_ds1 6>, <&ipmmu_ds1 7>, + <&ipmmu_ds1 8>, <&ipmmu_ds1 9>, + <&ipmmu_ds1 10>, <&ipmmu_ds1 11>, + <&ipmmu_ds1 12>, <&ipmmu_ds1 13>, + <&ipmmu_ds1 14>, <&ipmmu_ds1 15>; }; dmac2: dma-controller@e7310000 { @@ -689,6 +1047,14 @@ resets = <&cpg 217>; #dma-cells = <1>; dma-channels = <16>; + iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>, + <&ipmmu_ds1 18>, <&ipmmu_ds1 19>, + <&ipmmu_ds1 20>, <&ipmmu_ds1 21>, + <&ipmmu_ds1 22>, <&ipmmu_ds1 23>, + <&ipmmu_ds1 24>, <&ipmmu_ds1 25>, + <&ipmmu_ds1 26>, <&ipmmu_ds1 27>, + <&ipmmu_ds1 28>, <&ipmmu_ds1 29>, + <&ipmmu_ds1 30>, <&ipmmu_ds1 31>; }; gether: ethernet@e7400000 { @@ -703,6 +1069,69 @@ status = "disabled"; }; + ipmmu_ds1: mmu@e7740000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xe7740000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 0>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_ir: mmu@ff8b0000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xff8b0000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 3>; + power-domains = <&sysc R8A77980_PD_A3IR>; + #iommu-cells = <1>; + }; + + ipmmu_mm: mmu@e67b0000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xe67b0000 0 0x1000>; + interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_rt: mmu@ffc80000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xffc80000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 10>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_vc0: mmu@fe6b0000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xfe6b0000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 12>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_vi0: mmu@febd0000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xfebd0000 0 0x1000>; + renesas,ipmmu-main = <&ipmmu_mm 14>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_vip0: mmu@e7b00000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xe7b00000 0 0x1000>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + + ipmmu_vip1: mmu@e7960000 { + compatible = "renesas,ipmmu-r8a77980"; + reg = <0 0xe7960000 0 0x1000>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + #iommu-cells = <1>; + }; + mmc0: mmc@ee140000 { compatible = "renesas,sdhi-r8a77980", "renesas,rcar-gen3-sdhi"; @@ -732,6 +1161,38 @@ resets = <&cpg 408>; }; + pciec: pcie@fe000000 { + compatible = "renesas,pcie-r8a77980", + "renesas,pcie-rcar-gen3"; + reg = <0 0xfe000000 0 0x80000>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + device_type = "pci"; + ranges = < + 0x01000000 0 0x00000000 0 0xfe100000 0 0x0100000 + 0x02000000 0 0xfe200000 0 0xfe200000 0 0x0200000 + 0x02000000 0 0x30000000 0 0x30000000 0 0x8000000 + 0x42000000 0 0x38000000 0 0x38000000 0 0x8000000 + >; + dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 + 0 0x80000000>; + interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 148 + IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; + clock-names = "pcie", "pcie_bus"; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 319>; + phys = <&pcie_phy>; + phy-names = "pcie"; + status = "disabled"; + }; + vspd0: vsp@fea20000 { compatible = "renesas,vsp2"; reg = <0 0xfea20000 0 0x5000>; @@ -750,6 +1211,84 @@ resets = <&cpg 603>; }; + csi40: csi2@feaa0000 { + compatible = "renesas,r8a77980-csi2"; + reg = <0 0xfeaa0000 0 0x10000>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 716>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + csi40vin0: endpoint@0 { + reg = <0>; + remote-endpoint = <&vin0csi40>; + }; + csi40vin1: endpoint@1 { + reg = <1>; + remote-endpoint = <&vin1csi40>; + }; + csi40vin2: endpoint@2 { + reg = <2>; + remote-endpoint = <&vin2csi40>; + }; + csi40vin3: endpoint@3 { + reg = <3>; + remote-endpoint = <&vin3csi40>; + }; + }; + }; + }; + + csi41: csi2@feab0000 { + compatible = "renesas,r8a77980-csi2"; + reg = <0 0xfeab0000 0 0x10000>; + interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 715>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 715>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + csi41vin4: endpoint@0 { + reg = <0>; + remote-endpoint = <&vin4csi41>; + }; + csi41vin5: endpoint@1 { + reg = <1>; + remote-endpoint = <&vin5csi41>; + }; + csi41vin6: endpoint@2 { + reg = <2>; + remote-endpoint = <&vin6csi41>; + }; + csi41vin7: endpoint@3 { + reg = <3>; + remote-endpoint = <&vin7csi41>; + }; + }; + }; + }; + du: display@feb00000 { compatible = "renesas,du-r8a77980", "renesas,du-r8a77970"; diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts index 2bc3a4884b00..f342dd85b152 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts @@ -28,6 +28,111 @@ /* first 128MB is reserved for secure area. */ reg = <0x0 0x48000000 0x0 0x38000000>; }; + + cvbs-in { + compatible = "composite-video-connector"; + label = "CVBS IN"; + + port { + cvbs_con: endpoint { + remote-endpoint = <&adv7482_ain7>; + }; + }; + }; + + hdmi-in { + compatible = "hdmi-connector"; + label = "HDMI IN"; + type = "a"; + + port { + hdmi_in_con: endpoint { + remote-endpoint = <&adv7482_hdmi>; + }; + }; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_out: endpoint { + remote-endpoint = <&adv7511_out>; + }; + }; + }; + + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <®_3p3v>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + thc63lvd1024_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + + port@2 { + reg = <2>; + thc63lvd1024_out: endpoint { + remote-endpoint = <&adv7511_in>; + }; + }; + }; + }; + + vga { + compatible = "vga-connector"; + + port { + vga_in: endpoint { + remote-endpoint = <&adv7123_out>; + }; + }; + }; + + vga-encoder { + compatible = "adi,adv7123"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7123_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + port@1 { + reg = <1>; + adv7123_out: endpoint { + remote-endpoint = <&vga_in>; + }; + }; + }; + }; + + 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; + }; + + x13_clk: x13 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <74250000>; + }; }; &avb { @@ -47,6 +152,41 @@ }; }; +&csi40 { + status = "okay"; + + ports { + port@0 { + reg = <0>; + + csi40_in: endpoint { + clock-lanes = <0>; + data-lanes = <1 2>; + remote-endpoint = <&adv7482_txa>; + }; + }; + }; +}; + +&du { + pinctrl-0 = <&du_pins>; + pinctrl-names = "default"; + status = "okay"; + + clocks = <&cpg CPG_MOD 724>, + <&cpg CPG_MOD 723>, + <&x13_clk>; + clock-names = "du.0", "du.1", "dclkin.0"; + + ports { + port@0 { + endpoint { + remote-endpoint = <&adv7123_in>; + }; + }; + }; +}; + &ehci0 { status = "okay"; }; @@ -55,6 +195,105 @@ clock-frequency = <48000000>; }; +&i2c0 { + status = "okay"; + + hdmi-encoder@39 { + compatible = "adi,adv7511w"; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&thc63lvd1024_out>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; + + video-receiver@70 { + compatible = "adi,adv7482"; + reg = <0x70>; + + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&gpio0>; + interrupt-names = "intrq1", "intrq2"; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>, + <17 IRQ_TYPE_LEVEL_LOW>; + + port@7 { + reg = <7>; + + adv7482_ain7: endpoint { + remote-endpoint = <&cvbs_con>; + }; + }; + + port@8 { + reg = <8>; + + adv7482_hdmi: endpoint { + remote-endpoint = <&hdmi_in_con>; + }; + }; + + port@a { + reg = <0xa>; + + adv7482_txa: endpoint { + clock-lanes = <0>; + data-lanes = <1 2>; + remote-endpoint = <&csi40_in>; + }; + }; + }; +}; + +&lvds0 { + status = "okay"; + + clocks = <&cpg CPG_MOD 727>, + <&x13_clk>, + <&extal_clk>; + clock-names = "fck", "dclkin.0", "extal"; + + ports { + port@1 { + lvds0_out: endpoint { + remote-endpoint = <&thc63lvd1024_in>; + }; + }; + }; +}; + +&lvds1 { + clocks = <&cpg CPG_MOD 727>, + <&x13_clk>, + <&extal_clk>; + clock-names = "fck", "dclkin.0", "extal"; +}; + &ohci0 { status = "okay"; }; @@ -67,6 +306,21 @@ }; }; + du_pins: du { + groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; + function = "du"; + }; + + pwm3_pins: pwm3 { + groups = "pwm3_b"; + function = "pwm3"; + }; + + pwm5_pins: pwm5 { + groups = "pwm5_a"; + function = "pwm5"; + }; + usb0_pins: usb { groups = "usb0_b"; function = "usb0"; @@ -78,6 +332,20 @@ }; }; +&pwm3 { + pinctrl-0 = <&pwm3_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pwm5 { + pinctrl-0 = <&pwm5_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + &rwdt { timeout-sec = <60>; status = "okay"; @@ -94,6 +362,10 @@ status = "okay"; }; +&vin4 { + status = "okay"; +}; + &xhci0 { pinctrl-0 = <&usb30_pins>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi index ae89260baad9..9509dc05665f 100644 --- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi @@ -1,11 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Device Tree Source for the r8a77990 SoC + * Device Tree Source for the R-Car E3 (R8A77990) SoC * * Copyright (C) 2018 Renesas Electronics Corp. */ -#include <dt-bindings/clock/renesas-cpg-mssr.h> +#include <dt-bindings/clock/r8a77990-cpg-mssr.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/power/r8a77990-sysc.h> @@ -14,6 +14,17 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + i2c7 = &i2c7; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -22,7 +33,7 @@ compatible = "arm,cortex-a53", "arm,armv8"; reg = <0>; device_type = "cpu"; - power-domains = <&sysc 5>; + power-domains = <&sysc R8A77990_PD_CA53_CPU0>; next-level-cache = <&L2_CA53>; enable-method = "psci"; }; @@ -31,14 +42,14 @@ compatible = "arm,cortex-a53", "arm,armv8"; reg = <1>; device_type = "cpu"; - power-domains = <&sysc 6>; + power-domains = <&sysc R8A77990_PD_CA53_CPU1>; next-level-cache = <&L2_CA53>; enable-method = "psci"; }; L2_CA53: cache-controller-0 { compatible = "cache"; - power-domains = <&sysc 21>; + power-domains = <&sysc R8A77990_PD_CA53_SCU>; cache-unified; cache-level = <2>; }; @@ -63,6 +74,13 @@ method = "smc"; }; + /* External SCIF clock - to be overridden by boards that provide it */ + scif_clk: scif { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + soc: soc { compatible = "simple-bus"; interrupt-parent = <&gic>; @@ -75,7 +93,7 @@ "renesas,rcar-gen3-wdt"; reg = <0 0xe6020000 0 0x0c>; clocks = <&cpg CPG_MOD 402>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 402>; status = "disabled"; }; @@ -91,7 +109,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 912>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 912>; }; @@ -106,7 +124,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 911>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 911>; }; @@ -121,7 +139,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 910>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 910>; }; @@ -136,7 +154,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 909>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 909>; }; @@ -151,7 +169,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 908>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 908>; }; @@ -166,7 +184,7 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 907>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 907>; }; @@ -181,10 +199,122 @@ #interrupt-cells = <2>; interrupt-controller; clocks = <&cpg CPG_MOD 906>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 906>; }; + i2c0: i2c@e6500000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6500000 0 0x40>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 931>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 931>; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c1: i2c@e6508000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6508000 0 0x40>; + interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 930>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 930>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c2: i2c@e6510000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6510000 0 0x40>; + interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 929>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 929>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c3: i2c@e66d0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66d0000 0 0x40>; + interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 928>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 928>; + i2c-scl-internal-delay-ns = <110>; + status = "disabled"; + }; + + i2c4: i2c@e66d8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66d8000 0 0x40>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 927>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 927>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c5: i2c@e66e0000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66e0000 0 0x40>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 919>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 919>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c6: i2c@e66e8000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe66e8000 0 0x40>; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 918>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 918>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + + i2c7: i2c@e6690000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a77990", + "renesas,rcar-gen3-i2c"; + reg = <0 0xe6690000 0 0x40>; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 1003>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 1003>; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + pfc: pin-controller@e6060000 { compatible = "renesas,pfc-r8a77990"; reg = <0 0xe6060000 0 0x508>; @@ -211,6 +341,132 @@ #power-domain-cells = <1>; }; + dmac0: dma-controller@e6700000 { + compatible = "renesas,dmac-r8a77990", + "renesas,rcar-dmac"; + reg = <0 0xe6700000 0 0x10000>; + interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 219>; + clock-names = "fck"; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 219>; + #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>; + }; + + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77990", + "renesas,rcar-dmac"; + reg = <0 0xe7300000 0 0x10000>; + interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 218>; + clock-names = "fck"; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 218>; + #dma-cells = <1>; + dma-channels = <16>; + iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>, + <&ipmmu_ds1 2>, <&ipmmu_ds1 3>, + <&ipmmu_ds1 4>, <&ipmmu_ds1 5>, + <&ipmmu_ds1 6>, <&ipmmu_ds1 7>, + <&ipmmu_ds1 8>, <&ipmmu_ds1 9>, + <&ipmmu_ds1 10>, <&ipmmu_ds1 11>, + <&ipmmu_ds1 12>, <&ipmmu_ds1 13>, + <&ipmmu_ds1 14>, <&ipmmu_ds1 15>; + }; + + dmac2: dma-controller@e7310000 { + compatible = "renesas,dmac-r8a77990", + "renesas,rcar-dmac"; + reg = <0 0xe7310000 0 0x10000>; + interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 418 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 397 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15"; + clocks = <&cpg CPG_MOD 217>; + clock-names = "fck"; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 217>; + #dma-cells = <1>; + dma-channels = <16>; + iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>, + <&ipmmu_ds1 18>, <&ipmmu_ds1 19>, + <&ipmmu_ds1 20>, <&ipmmu_ds1 21>, + <&ipmmu_ds1 22>, <&ipmmu_ds1 23>, + <&ipmmu_ds1 24>, <&ipmmu_ds1 25>, + <&ipmmu_ds1 26>, <&ipmmu_ds1 27>, + <&ipmmu_ds1 28>, <&ipmmu_ds1 29>, + <&ipmmu_ds1 30>, <&ipmmu_ds1 31>; + }; + ipmmu_ds0: mmu@e6740000 { compatible = "renesas,ipmmu-r8a77990"; reg = <0 0xe6740000 0 0x1000>; @@ -329,7 +585,7 @@ "ch20", "ch21", "ch22", "ch23", "ch24"; clocks = <&cpg CPG_MOD 812>; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 812>; phy-mode = "rgmii"; #address-cells = <1>; @@ -337,18 +593,191 @@ status = "disabled"; }; + pwm0: pwm@e6e30000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e30000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm1: pwm@e6e31000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e31000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm2: pwm@e6e32000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e32000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm3: pwm@e6e33000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e33000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm4: pwm@e6e34000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e34000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm5: pwm@e6e35000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e35000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pwm6: pwm@e6e36000 { + compatible = "renesas,pwm-r8a77990", "renesas,pwm-rcar"; + reg = <0 0xe6e36000 0 0x8>; + clocks = <&cpg CPG_MOD 523>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 523>; + #pwm-cells = <2>; + status = "disabled"; + }; + scif2: serial@e6e88000 { compatible = "renesas,scif-r8a77990", "renesas,rcar-gen3-scif", "renesas,scif"; reg = <0 0xe6e88000 0 64>; interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 310>; - clock-names = "fck"; - power-domains = <&sysc 32>; + clocks = <&cpg CPG_MOD 310>, + <&cpg CPG_CORE R8A77990_CLK_S3D1C>, + <&scif_clk>; + clock-names = "fck", "brg_int", "scif_clk"; + + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 310>; status = "disabled"; }; + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a77990", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6e90000 0 0x0064>; + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 211>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 211>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof1: spi@e6ea0000 { + compatible = "renesas,msiof-r8a77990", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6ea0000 0 0x0064>; + interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 210>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 210>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof2: spi@e6c00000 { + compatible = "renesas,msiof-r8a77990", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6c00000 0 0x0064>; + interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 209>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 209>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + msiof3: spi@e6c10000 { + compatible = "renesas,msiof-r8a77990", + "renesas,rcar-gen3-msiof"; + reg = <0 0xe6c10000 0 0x0064>; + interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 208>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 208>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + vin4: video@e6ef4000 { + compatible = "renesas,vin-r8a77990"; + reg = <0 0xe6ef4000 0 0x1000>; + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 807>; + renesas,id = <4>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + vin4csi40: endpoint { + remote-endpoint= <&csi40vin4>; + }; + }; + }; + }; + + vin5: video@e6ef5000 { + compatible = "renesas,vin-r8a77990"; + reg = <0 0xe6ef5000 0 0x1000>; + interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 806>; + renesas,id = <5>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + vin5csi40: endpoint { + remote-endpoint= <&csi40vin5>; + }; + }; + }; + }; + xhci0: usb@ee000000 { compatible = "renesas,xhci-r8a77990", "renesas,rcar-gen3-xhci"; @@ -364,11 +793,11 @@ compatible = "generic-ohci"; reg = <0 0xee080000 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; - power-domains = <&sysc 32>; - resets = <&cpg 703>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -376,12 +805,12 @@ compatible = "generic-ehci"; reg = <0 0xee080100 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; companion = <&ohci0>; - power-domains = <&sysc 32>; - resets = <&cpg 703>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -390,9 +819,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee080200 0 0x700>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; - power-domains = <&sysc 32>; - resets = <&cpg 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 703>, <&cpg 704>; #phy-cells = <0>; status = "disabled"; }; @@ -410,10 +839,208 @@ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; clocks = <&cpg CPG_MOD 408>; clock-names = "clk"; - power-domains = <&sysc 32>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; resets = <&cpg 408>; }; + vspb0: vsp@fe960000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe960000 0 0x8000>; + interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 626>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 626>; + renesas,fcp = <&fcpvb0>; + }; + + fcpvb0: fcp@fe96f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe96f000 0 0x200>; + clocks = <&cpg CPG_MOD 607>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 607>; + iommus = <&ipmmu_vp0 5>; + }; + + vspi0: vsp@fe9a0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9a0000 0 0x8000>; + interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 631>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 631>; + renesas,fcp = <&fcpvi0>; + }; + + fcpvi0: fcp@fe9af000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9af000 0 0x200>; + clocks = <&cpg CPG_MOD 611>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 611>; + iommus = <&ipmmu_vp0 8>; + }; + + vspd0: vsp@fea20000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea20000 0 0x7000>; + interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 623>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 623>; + renesas,fcp = <&fcpvd0>; + }; + + fcpvd0: fcp@fea27000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea27000 0 0x200>; + clocks = <&cpg CPG_MOD 603>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 603>; + iommus = <&ipmmu_vi0 8>; + }; + + vspd1: vsp@fea28000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea28000 0 0x7000>; + interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 622>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 622>; + renesas,fcp = <&fcpvd1>; + }; + + fcpvd1: fcp@fea2f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea2f000 0 0x200>; + clocks = <&cpg CPG_MOD 602>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 602>; + iommus = <&ipmmu_vi0 9>; + }; + + csi40: csi2@feaa0000 { + compatible = "renesas,r8a77990-csi2", "renesas,rcar-gen3-csi2"; + reg = <0 0xfeaa0000 0 0x10000>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 716>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <1>; + + csi40vin4: endpoint@0 { + reg = <0>; + remote-endpoint = <&vin4csi40>; + }; + csi40vin5: endpoint@1 { + reg = <1>; + remote-endpoint = <&vin5csi40>; + }; + }; + }; + }; + + du: display@feb00000 { + compatible = "renesas,du-r8a77990"; + reg = <0 0xfeb00000 0 0x80000>; + interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 724>, + <&cpg CPG_MOD 723>; + clock-names = "du.0", "du.1"; + vsps = <&vspd0 0 &vspd1 0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + du_out_rgb: endpoint { + }; + }; + + port@1 { + reg = <1>; + du_out_lvds0: endpoint { + remote-endpoint = <&lvds0_in>; + }; + }; + + port@2 { + reg = <2>; + du_out_lvds1: endpoint { + remote-endpoint = <&lvds1_in>; + }; + }; + }; + }; + + lvds0: lvds-encoder@feb90000 { + compatible = "renesas,r8a77990-lvds"; + reg = <0 0xfeb90000 0 0x20>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 727>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds0_in: endpoint { + remote-endpoint = <&du_out_lvds0>; + }; + }; + + port@1 { + reg = <1>; + lvds0_out: endpoint { + }; + }; + }; + }; + + lvds1: lvds-encoder@feb90100 { + compatible = "renesas,r8a77990-lvds"; + reg = <0 0xfeb90100 0 0x20>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A77990_PD_ALWAYS_ON>; + resets = <&cpg 726>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds1_in: endpoint { + remote-endpoint = <&du_out_lvds1>; + }; + }; + + port@1 { + reg = <1>; + lvds1_out: endpoint { + }; + }; + }; + }; + prr: chipid@fff00044 { compatible = "renesas,prr"; reg = <0 0xfff00044 0 4>; diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts index a8e8f2669d4c..2405eaad0296 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts +++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts @@ -2,7 +2,7 @@ /* * Device Tree Source for the Draak board * - * Copyright (C) 2016 Renesas Electronics Corp. + * Copyright (C) 2016-2018 Renesas Electronics Corp. * Copyright (C) 2017 Glider bvba */ @@ -24,55 +24,58 @@ stdout-path = "serial0:115200n8"; }; - vga { - compatible = "vga-connector"; + composite-in { + compatible = "composite-video-connector"; port { - vga_in: endpoint { - remote-endpoint = <&adv7123_out>; + composite_con_in: endpoint { + remote-endpoint = <&adv7180_in>; }; }; }; - vga-encoder { - compatible = "adi,adv7123"; - - ports { - #address-cells = <1>; - #size-cells = <0>; + hdmi-in { + compatible = "hdmi-connector"; + type = "a"; - port@0 { - reg = <0>; - adv7123_in: endpoint { - remote-endpoint = <&du_out_rgb>; - }; - }; - port@1 { - reg = <1>; - adv7123_out: endpoint { - remote-endpoint = <&vga_in>; - }; + port { + hdmi_con_in: endpoint { + remote-endpoint = <&adv7612_in>; }; }; }; - composite-in { - compatible = "composite-video-connector"; + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; port { - composite_con_in: endpoint { - remote-endpoint = <&adv7180_in>; + hdmi_con_out: endpoint { + remote-endpoint = <&adv7511_out>; }; }; }; - hdmi-in { - compatible = "hdmi-connector"; - type = "a"; + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <®_3p3v>; - port { - hdmi_con_in: endpoint { - remote-endpoint = <&adv7612_in>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + thc63lvd1024_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + + port@2 { + reg = <2>; + thc63lvd1024_out: endpoint { + remote-endpoint = <&adv7511_in>; + }; }; }; }; @@ -101,76 +104,86 @@ regulator-always-on; }; - x12_clk: x12 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <74250000>; - }; -}; - -&extal_clk { - clock-frequency = <48000000>; -}; + vga { + compatible = "vga-connector"; -&pfc { - avb0_pins: avb { - mux { - groups = "avb0_link", "avb0_mdio", "avb0_mii"; - function = "avb0"; + port { + vga_in: endpoint { + remote-endpoint = <&adv7123_out>; + }; }; }; - du_pins: du { - groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; - function = "du"; - }; + vga-encoder { + compatible = "adi,adv7123"; - i2c0_pins: i2c0 { - groups = "i2c0"; - function = "i2c0"; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; - i2c1_pins: i2c1 { - groups = "i2c1"; - function = "i2c1"; + port@0 { + reg = <0>; + adv7123_in: endpoint { + remote-endpoint = <&du_out_rgb>; + }; + }; + port@1 { + reg = <1>; + adv7123_out: endpoint { + remote-endpoint = <&vga_in>; + }; + }; + }; }; - pwm0_pins: pwm0 { - groups = "pwm0_c"; - function = "pwm0"; + x12_clk: x12 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <74250000>; }; +}; - pwm1_pins: pwm1 { - groups = "pwm1_c"; - function = "pwm1"; - }; +&avb { + pinctrl-0 = <&avb0_pins>; + pinctrl-names = "default"; + renesas,no-ether-link; + phy-handle = <&phy0>; + phy-mode = "rgmii-txid"; + status = "okay"; - scif2_pins: scif2 { - groups = "scif2_data"; - function = "scif2"; + phy0: ethernet-phy@0 { + rxc-skew-ps = <1500>; + reg = <0>; + interrupt-parent = <&gpio5>; + interrupts = <19 IRQ_TYPE_LEVEL_LOW>; }; +}; - sdhi2_pins: sd2 { - groups = "mmc_data8", "mmc_ctrl"; - function = "mmc"; - power-source = <1800>; - }; +&du { + pinctrl-0 = <&du_pins>; + pinctrl-names = "default"; + status = "okay"; - sdhi2_pins_uhs: sd2_uhs { - groups = "mmc_data8", "mmc_ctrl"; - function = "mmc"; - power-source = <1800>; - }; + clocks = <&cpg CPG_MOD 724>, + <&cpg CPG_MOD 723>, + <&x12_clk>; + clock-names = "du.0", "du.1", "dclkin.0"; - usb0_pins: usb0 { - groups = "usb0"; - function = "usb0"; + ports { + port@0 { + endpoint { + remote-endpoint = <&adv7123_in>; + }; + }; }; +}; - vin4_pins_cvbs: vin4 { - groups = "vin4_data8", "vin4_sync", "vin4_clk"; - function = "vin4"; - }; +&ehci0 { + status = "okay"; +}; + +&extal_clk { + clock-frequency = <48000000>; }; &i2c0 { @@ -178,12 +191,6 @@ pinctrl-names = "default"; status = "okay"; - eeprom@50 { - compatible = "rohm,br24t01", "atmel,24c01"; - reg = <0x50>; - pagesize = <8>; - }; - composite-in@20 { compatible = "adi,adv7180cp"; reg = <0x20>; @@ -218,6 +225,43 @@ }; + hdmi-encoder@39 { + compatible = "adi,adv7511w"; + reg = <0x39>, <0x3f>, <0x38>, <0x3c>; + reg-names = "main", "edid", "packet", "cec"; + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_LEVEL_LOW>; + + /* Depends on LVDS */ + max-clock = <135000000>; + min-vrefresh = <50>; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + adi,input-style = <1>; + adi,input-justification = "evenly"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7511_in: endpoint { + remote-endpoint = <&thc63lvd1024_out>; + }; + }; + + port@1 { + reg = <1>; + adv7511_out: endpoint { + remote-endpoint = <&hdmi_con_out>; + }; + }; + }; + }; + hdmi-decoder@4c { compatible = "adi,adv7612"; reg = <0x4c>; @@ -254,6 +298,12 @@ }; }; }; + + eeprom@50 { + compatible = "rohm,br24t01", "atmel,24c01"; + reg = <0x50>; + pagesize = <8>; + }; }; &i2c1 { @@ -262,47 +312,112 @@ status = "okay"; }; -&du { - pinctrl-0 = <&du_pins>; - pinctrl-names = "default"; +&lvds0 { status = "okay"; - clocks = <&cpg CPG_MOD 724>, - <&cpg CPG_MOD 723>, - <&x12_clk>; - clock-names = "du.0", "du.1", "dclkin.0"; + clocks = <&cpg CPG_MOD 727>, + <&x12_clk>, + <&extal_clk>; + clock-names = "fck", "dclkin.0", "extal"; ports { - port@0 { - endpoint { - remote-endpoint = <&adv7123_in>; + port@1 { + lvds0_out: endpoint { + remote-endpoint = <&thc63lvd1024_in>; }; }; }; }; -&ehci0 { - status = "okay"; +&lvds1 { + clocks = <&cpg CPG_MOD 727>, + <&x12_clk>, + <&extal_clk>; + clock-names = "fck", "dclkin.0", "extal"; }; &ohci0 { status = "okay"; }; -&avb { - pinctrl-0 = <&avb0_pins>; +&pfc { + avb0_pins: avb { + mux { + groups = "avb0_link", "avb0_mdio", "avb0_mii"; + function = "avb0"; + }; + }; + + du_pins: du { + groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0"; + function = "du"; + }; + + i2c0_pins: i2c0 { + groups = "i2c0"; + function = "i2c0"; + }; + + i2c1_pins: i2c1 { + groups = "i2c1"; + function = "i2c1"; + }; + + pwm0_pins: pwm0 { + groups = "pwm0_c"; + function = "pwm0"; + }; + + pwm1_pins: pwm1 { + groups = "pwm1_c"; + function = "pwm1"; + }; + + scif2_pins: scif2 { + groups = "scif2_data"; + function = "scif2"; + }; + + sdhi2_pins: sd2 { + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; + power-source = <1800>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "mmc_data8", "mmc_ctrl"; + function = "mmc"; + power-source = <1800>; + }; + + usb0_pins: usb0 { + groups = "usb0"; + function = "usb0"; + }; + + vin4_pins_cvbs: vin4 { + groups = "vin4_data8", "vin4_sync", "vin4_clk"; + function = "vin4"; + }; +}; + +&pwm0 { + pinctrl-0 = <&pwm0_pins>; pinctrl-names = "default"; - renesas,no-ether-link; - phy-handle = <&phy0>; - phy-mode = "rgmii-txid"; + status = "okay"; +}; - phy0: ethernet-phy@0 { - rxc-skew-ps = <1500>; - reg = <0>; - interrupt-parent = <&gpio5>; - interrupts = <19 IRQ_TYPE_LEVEL_LOW>; - }; +&pwm1 { + pinctrl-0 = <&pwm1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&rwdt { + timeout-sec = <60>; + status = "okay"; }; &scif2 { @@ -333,25 +448,6 @@ status = "okay"; }; -&pwm0 { - pinctrl-0 = <&pwm0_pins>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pwm1 { - pinctrl-0 = <&pwm1_pins>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&rwdt { - timeout-sec = <60>; - status = "okay"; -}; - &vin4 { pinctrl-0 = <&vin4_pins_cvbs>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi index fe77bc43c447..214f4954b321 100644 --- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Device Tree Source for the r8a77995 SoC + * Device Tree Source for the R-Car D3 (R8A77995) SoC * * Copyright (C) 2016 Renesas Electronics Corp. * Copyright (C) 2017 Glider bvba @@ -391,6 +391,10 @@ resets = <&cpg 219>; #dma-cells = <1>; dma-channels = <8>; + 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>; }; dmac1: dma-controller@e7300000 { @@ -415,6 +419,10 @@ resets = <&cpg 218>; #dma-cells = <1>; dma-channels = <8>; + iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>, + <&ipmmu_ds1 2>, <&ipmmu_ds1 3>, + <&ipmmu_ds1 4>, <&ipmmu_ds1 5>, + <&ipmmu_ds1 6>, <&ipmmu_ds1 7>; }; dmac2: dma-controller@e7310000 { @@ -439,6 +447,10 @@ resets = <&cpg 217>; #dma-cells = <1>; dma-channels = <8>; + iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>, + <&ipmmu_ds1 18>, <&ipmmu_ds1 19>, + <&ipmmu_ds1 20>, <&ipmmu_ds1 21>, + <&ipmmu_ds1 22>, <&ipmmu_ds1 23>; }; ipmmu_ds0: mmu@e6740000 { @@ -817,11 +829,11 @@ compatible = "generic-ohci"; reg = <0 0xee080000 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -829,12 +841,12 @@ compatible = "generic-ehci"; reg = <0 0xee080100 0 0x100>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; phys = <&usb2_phy0>; phy-names = "usb"; companion = <&ohci0>; power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; status = "disabled"; }; @@ -843,9 +855,9 @@ "renesas,rcar-gen3-usb2-phy"; reg = <0 0xee080200 0 0x700>; interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg CPG_MOD 703>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; - resets = <&cpg 703>; + resets = <&cpg 703>, <&cpg 704>; #phy-cells = <0>; status = "disabled"; }; @@ -960,12 +972,68 @@ port@1 { reg = <1>; du_out_lvds0: endpoint { + remote-endpoint = <&lvds0_in>; }; }; port@2 { reg = <2>; du_out_lvds1: endpoint { + remote-endpoint = <&lvds1_in>; + }; + }; + }; + }; + + lvds0: lvds-encoder@feb90000 { + compatible = "renesas,r8a77995-lvds"; + reg = <0 0xfeb90000 0 0x20>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; + resets = <&cpg 727>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds0_in: endpoint { + remote-endpoint = <&du_out_lvds0>; + }; + }; + + port@1 { + reg = <1>; + lvds0_out: endpoint { + }; + }; + }; + }; + + lvds1: lvds-encoder@feb90100 { + compatible = "renesas,r8a77995-lvds"; + reg = <0 0xfeb90100 0 0x20>; + clocks = <&cpg CPG_MOD 727>; + power-domains = <&sysc R8A77995_PD_ALWAYS_ON>; + resets = <&cpg 726>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lvds1_in: endpoint { + remote-endpoint = <&du_out_lvds1>; + }; + }; + + port@1 { + reg = <1>; + lvds1_out: endpoint { }; }; }; diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi index 7d3d866a0063..7f91ff524109 100644 --- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi +++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi @@ -420,7 +420,10 @@ video-receiver@70 { compatible = "adi,adv7482"; - reg = <0x70>; + reg = <0x70 0x71 0x72 0x73 0x74 0x75 + 0x60 0x61 0x62 0x63 0x64 0x65>; + reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater", + "infoframe", "cbus", "cec", "sdp", "txa", "txb" ; #address-cells = <1>; #size-cells = <0>; @@ -471,6 +474,8 @@ &i2c_dvfs { status = "okay"; + clock-frequency = <400000>; + pmic: pmic@30 { pinctrl-0 = <&irq0_pins>; pinctrl-names = "default"; @@ -748,6 +753,7 @@ wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; bus-width = <4>; sd-uhs-sdr50; + sd-uhs-sdr104; status = "okay"; }; @@ -777,6 +783,7 @@ wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; bus-width = <4>; sd-uhs-sdr50; + sd-uhs-sdr104; status = "okay"; }; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi index 8bf3091a899c..1b316d79df88 100644 --- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -127,7 +127,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x71>; - reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi index 0ead552d7eae..89daca7356df 100644 --- a/arch/arm64/boot/dts/renesas/ulcb.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi @@ -18,6 +18,7 @@ }; chosen { + bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; stdout-path = "serial0:115200n8"; }; @@ -241,6 +242,8 @@ &i2c_dvfs { status = "okay"; + clock-frequency = <400000>; + pmic: pmic@30 { pinctrl-0 = <&irq0_pins>; pinctrl-names = "default"; @@ -416,6 +419,7 @@ cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; bus-width = <4>; sd-uhs-sdr50; + sd-uhs-sdr104; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index b0092d95b574..49042c477870 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb @@ -14,5 +15,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-firefly.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-bob.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock960.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb diff --git a/arch/arm64/boot/dts/rockchip/px30-evb.dts b/arch/arm64/boot/dts/rockchip/px30-evb.dts new file mode 100644 index 000000000000..263d7f3dbc44 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-evb.dts @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + */ + +/dts-v1/; +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pinctrl/rockchip.h> +#include "px30.dtsi" + +/ { + model = "Rockchip PX30 EVB"; + compatible = "rockchip,px30-evb", "rockchip,px30"; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 2>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + esc-key { + label = "esc"; + linux,code = <KEY_ESC>; + press-threshold-microvolt = <1310000>; + }; + + home-key { + label = "home"; + linux,code = <KEY_HOME>; + press-threshold-microvolt = <624000>; + }; + + menu-key { + label = "menu"; + linux,code = <KEY_MENU>; + press-threshold-microvolt = <987000>; + }; + + vol-down-key { + label = "volume down"; + linux,code = <KEY_VOLUMEDOWN>; + press-threshold-microvolt = <300000>; + }; + + vol-up-key { + label = "volume up"; + linux,code = <KEY_VOLUMEUP>; + press-threshold-microvolt = <17000>; + }; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 25000 0>; + }; + + 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 */ + }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + + vcc5v0_sys: vccsys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; +}; + +&display_subsystem { + status = "okay"; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&gmac { + clock_in_out = "output"; + phy-supply = <&vcc_phy>; + snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 50000 50000>; + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&i2s1_2ch { + status = "okay"; +}; + +&io_domains { + status = "okay"; +}; + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = + <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + pmic { + pmic_int: pmic_int { + rockchip,pins = + <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + soc_slppin_gpio: soc_slppin_gpio { + rockchip,pins = + <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; + }; + + soc_slppin_slp: soc_slppin_slp { + rockchip,pins = + <0 RK_PA4 RK_FUNC_1 &pcfg_pull_none>; + }; + + soc_slppin_rst: soc_slppin_rst { + rockchip,pins = + <0 RK_PA4 RK_FUNC_2 &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = + <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pmu_io_domains { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&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; + status = "okay"; +}; + +&sdio { + bus-width = <4>; + cap-sd-highspeed; + keep-power-in-suspend; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + sd-uhs-sdr104; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi new file mode 100644 index 000000000000..9aa8d5ef9e45 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -0,0 +1,2047 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include <dt-bindings/clock/px30-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/px30-power.h> +#include <dt-bindings/soc/rockchip,boot-mode.h> + +/ { + compatible = "rockchip,px30"; + + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + ethernet0 = &gmac; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + spi0 = &spi0; + spi1 = &spi1; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a35", "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <90>; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a35", "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <90>; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a35", "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <90>; + operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a35", "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + clocks = <&cru ARMCLK>; + #cooling-cells = <2>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + dynamic-power-coefficient = <90>; + operating-points-v2 = <&cpu0_opp_table>; + }; + + 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>; + }; + }; + }; + + cpu0_opp_table: cpu0-opp-table { + compatible = "operating-points-v2"; + opp-shared; + + opp-408000000 { + opp-hz = /bits/ 64 <408000000>; + opp-microvolt = <950000 950000 1350000>; + clock-latency-ns = <40000>; + opp-suspend; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <950000 950000 1350000>; + clock-latency-ns = <40000>; + }; + opp-816000000 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <1050000 1050000 1350000>; + clock-latency-ns = <40000>; + }; + opp-1008000000 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <1175000 1175000 1350000>; + clock-latency-ns = <40000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1300000 1300000 1350000>; + clock-latency-ns = <40000>; + }; + opp-1296000000 { + opp-hz = /bits/ 64 <1296000000>; + opp-microvolt = <1350000 1350000 1350000>; + clock-latency-ns = <40000>; + }; + }; + + arm-pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <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>; + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + + display_subsystem: display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vopb_out>, <&vopl_out>; + status = "disabled"; + }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; + + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <50000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + xin24m: xin24m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "xin24m"; + }; + + xin32k: xin32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + }; + + pmu: power-management@ff000000 { + compatible = "rockchip,px30-pmu", "syscon", "simple-mfd"; + reg = <0x0 0xff000000 0x0 0x1000>; + + power: power-controller { + compatible = "rockchip,px30-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + /* These power domains are grouped by VD_LOGIC */ + pd_usb@PX30_PD_USB { + reg = <PX30_PD_USB>; + clocks = <&cru HCLK_HOST>, + <&cru HCLK_OTG>, + <&cru SCLK_OTG_ADP>; + pm_qos = <&qos_usb_host>, <&qos_usb_otg>; + }; + pd_sdcard@PX30_PD_SDCARD { + reg = <PX30_PD_SDCARD>; + clocks = <&cru HCLK_SDMMC>, + <&cru SCLK_SDMMC>; + pm_qos = <&qos_sdmmc>; + }; + pd_gmac@PX30_PD_GMAC { + reg = <PX30_PD_GMAC>; + clocks = <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>, + <&cru SCLK_MAC_REF>, + <&cru SCLK_GMAC_RX_TX>; + pm_qos = <&qos_gmac>; + }; + pd_mmc_nand@PX30_PD_MMC_NAND { + reg = <PX30_PD_MMC_NAND>; + clocks = <&cru HCLK_NANDC>, + <&cru HCLK_EMMC>, + <&cru HCLK_SDIO>, + <&cru HCLK_SFC>, + <&cru SCLK_EMMC>, + <&cru SCLK_NANDC>, + <&cru SCLK_SDIO>, + <&cru SCLK_SFC>; + pm_qos = <&qos_emmc>, <&qos_nand>, + <&qos_sdio>, <&qos_sfc>; + }; + pd_vpu@PX30_PD_VPU { + reg = <PX30_PD_VPU>; + clocks = <&cru ACLK_VPU>, + <&cru HCLK_VPU>, + <&cru SCLK_CORE_VPU>; + pm_qos = <&qos_vpu>, <&qos_vpu_r128>; + }; + pd_vo@PX30_PD_VO { + reg = <PX30_PD_VO>; + clocks = <&cru ACLK_RGA>, + <&cru ACLK_VOPB>, + <&cru ACLK_VOPL>, + <&cru DCLK_VOPB>, + <&cru DCLK_VOPL>, + <&cru HCLK_RGA>, + <&cru HCLK_VOPB>, + <&cru HCLK_VOPL>, + <&cru PCLK_MIPI_DSI>, + <&cru SCLK_RGA_CORE>, + <&cru SCLK_VOPB_PWM>; + pm_qos = <&qos_rga_rd>, <&qos_rga_wr>, + <&qos_vop_m0>, <&qos_vop_m1>; + }; + pd_vi@PX30_PD_VI { + reg = <PX30_PD_VI>; + clocks = <&cru ACLK_CIF>, + <&cru ACLK_ISP>, + <&cru HCLK_CIF>, + <&cru HCLK_ISP>, + <&cru SCLK_ISP>; + pm_qos = <&qos_isp_128>, <&qos_isp_rd>, + <&qos_isp_wr>, <&qos_isp_m1>, + <&qos_vip>; + }; + pd_gpu@PX30_PD_GPU { + reg = <PX30_PD_GPU>; + clocks = <&cru SCLK_GPU>; + pm_qos = <&qos_gpu>; + }; + }; + }; + + pmugrf: syscon@ff010000 { + compatible = "rockchip,px30-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xff010000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + pmu_io_domains: io-domains { + compatible = "rockchip,px30-pmu-io-voltage-domain"; + status = "disabled"; + }; + + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x200>; + mode-bootloader = <BOOT_BL_DOWNLOAD>; + mode-fastboot = <BOOT_FASTBOOT>; + mode-loader = <BOOT_BL_DOWNLOAD>; + mode-normal = <BOOT_NORMAL>; + mode-recovery = <BOOT_RECOVERY>; + }; + }; + + uart0: serial@ff030000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff030000 0x0 0x100>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 0>, <&dmac 1>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>; + status = "disabled"; + }; + + i2s1_2ch: i2s@ff070000 { + compatible = "rockchip,px30-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff070000 0x0 0x1000>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_I2S1>, <&cru HCLK_I2S1>; + clock-names = "i2s_clk", "i2s_hclk"; + dmas = <&dmac 18>, <&dmac 19>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_sclk &i2s1_2ch_lrck + &i2s1_2ch_sdi &i2s1_2ch_sdo>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s2_2ch: i2s@ff080000 { + compatible = "rockchip,px30-i2s", "rockchip,rk3066-i2s"; + reg = <0x0 0xff080000 0x0 0x1000>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_I2S2>, <&cru HCLK_I2S2>; + clock-names = "i2s_clk", "i2s_hclk"; + dmas = <&dmac 20>, <&dmac 21>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s2_2ch_sclk &i2s2_2ch_lrck + &i2s2_2ch_sdi &i2s2_2ch_sdo>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + gic: interrupt-controller@ff131000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xff131000 0 0x1000>, + <0x0 0xff132000 0 0x2000>, + <0x0 0xff134000 0 0x2000>, + <0x0 0xff136000 0 0x2000>; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + grf: syscon@ff140000 { + compatible = "rockchip,px30-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff140000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + io_domains: io-domains { + compatible = "rockchip,px30-io-voltage-domain"; + status = "disabled"; + }; + }; + + uart1: serial@ff158000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff158000 0x0 0x100>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 2>, <&dmac 3>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_xfer &uart1_cts &uart1_rts>; + status = "disabled"; + }; + + uart2: serial@ff160000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff160000 0x0 0x100>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 4>, <&dmac 5>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer>; + status = "disabled"; + }; + + uart3: serial@ff168000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff168000 0x0 0x100>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 6>, <&dmac 7>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart3m1_xfer &uart3m1_cts &uart3m1_rts>; + status = "disabled"; + }; + + uart4: serial@ff170000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff170000 0x0 0x100>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 8>, <&dmac 9>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_xfer &uart4_cts &uart4_rts>; + status = "disabled"; + }; + + uart5: serial@ff178000 { + compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; + reg = <0x0 0xff178000 0x0 0x100>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; + clock-names = "baudclk", "apb_pclk"; + dmas = <&dmac 10>, <&dmac 11>; + dma-names = "tx", "rx"; + reg-shift = <2>; + reg-io-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&uart5_xfer &uart5_cts &uart5_rts>; + status = "disabled"; + }; + + i2c0: i2c@ff180000 { + compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xff180000 0x0 0x1000>; + clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@ff190000 { + compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xff190000 0x0 0x1000>; + clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@ff1a0000 { + compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xff1a0000 0x0 0x1000>; + clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c3: i2c@ff1b0000 { + compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c"; + reg = <0x0 0xff1b0000 0x0 0x1000>; + clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>; + clock-names = "i2c", "pclk"; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_xfer>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi0: spi@ff1d0000 { + compatible = "rockchip,px30-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1d0000 0x0 0x1000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac 12>, <&dmac 13>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_clk &spi0_csn &spi0_miso &spi0_mosi>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@ff1d8000 { + compatible = "rockchip,px30-spi", "rockchip,rk3066-spi"; + reg = <0x0 0xff1d8000 0x0 0x1000>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>; + clock-names = "spiclk", "apb_pclk"; + dmas = <&dmac 14>, <&dmac 15>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + wdt: watchdog@ff1e0000 { + compatible = "snps,dw-wdt"; + reg = <0x0 0xff1e0000 0x0 0x100>; + clocks = <&cru PCLK_WDT_NS>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pwm0: pwm@ff200000 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff200000 0x0 0x10>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm1: pwm@ff200010 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff200010 0x0 0x10>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm1_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm2: pwm@ff200020 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff200020 0x0 0x10>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm2_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm3: pwm@ff200030 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff200030 0x0 0x10>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm3_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm4: pwm@ff208000 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff208000 0x0 0x10>; + clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm4_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm5: pwm@ff208010 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff208010 0x0 0x10>; + clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm5_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm6: pwm@ff208020 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff208020 0x0 0x10>; + clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm6_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm7: pwm@ff208030 { + compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; + reg = <0x0 0xff208030 0x0 0x10>; + clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; + clock-names = "pwm", "pclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm7_pin>; + #pwm-cells = <3>; + status = "disabled"; + }; + + rktimer: timer@ff210000 { + compatible = "rockchip,px30-timer", "rockchip,rk3288-timer"; + reg = <0x0 0xff210000 0x0 0x1000>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru PCLK_TIMER>, <&cru SCLK_TIMER0>; + clock-names = "pclk", "timer"; + }; + + amba { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + dmac: dmac@ff240000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff240000 0x0 0x4000>; + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + }; + }; + + saradc: saradc@ff288000 { + compatible = "rockchip,px30-saradc", "rockchip,rk3399-saradc"; + reg = <0x0 0xff288000 0x0 0x100>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; + #io-channel-cells = <1>; + clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_SARADC_P>; + reset-names = "saradc-apb"; + status = "disabled"; + }; + + cru: clock-controller@ff2b0000 { + compatible = "rockchip,px30-cru"; + reg = <0x0 0xff2b0000 0x0 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + + assigned-clocks = <&cru PLL_NPLL>; + assigned-clock-rates = <1188000000>; + }; + + pmucru: clock-controller@ff2bc000 { + compatible = "rockchip,px30-pmucru"; + reg = <0x0 0xff2bc000 0x0 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + + assigned-clocks = + <&pmucru PLL_GPLL>, <&pmucru PCLK_PMU_PRE>, + <&pmucru SCLK_WIFI_PMU>, <&cru ARMCLK>, + <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>, + <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>, + <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>; + assigned-clock-rates = + <1200000000>, <100000000>, + <26000000>, <600000000>, + <200000000>, <200000000>, + <150000000>, <150000000>, + <100000000>, <200000000>; + }; + + usb20_otg: usb@ff300000 { + compatible = "rockchip,px30-usb", "rockchip,rk3066-usb", + "snps,dwc2"; + reg = <0x0 0xff300000 0x0 0x40000>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_OTG>; + clock-names = "otg"; + dr_mode = "otg"; + g-np-tx-fifo-size = <16>; + g-rx-fifo-size = <280>; + g-tx-fifo-size = <256 128 128 64 32 16>; + g-use-dma; + power-domains = <&power PX30_PD_USB>; + status = "disabled"; + }; + + usb_host0_ehci: usb@ff340000 { + compatible = "generic-ehci"; + reg = <0x0 0xff340000 0x0 0x10000>; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_HOST>; + clock-names = "usbhost"; + power-domains = <&power PX30_PD_USB>; + status = "disabled"; + }; + + usb_host0_ohci: usb@ff350000 { + compatible = "generic-ohci"; + reg = <0x0 0xff350000 0x0 0x10000>; + interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_HOST>; + clock-names = "usbhost"; + power-domains = <&power PX30_PD_USB>; + status = "disabled"; + }; + + gmac: ethernet@ff360000 { + compatible = "rockchip,px30-gmac"; + reg = <0x0 0xff360000 0x0 0x10000>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + clocks = <&cru SCLK_GMAC>, <&cru SCLK_GMAC_RX_TX>, + <&cru SCLK_GMAC_RX_TX>, <&cru SCLK_MAC_REF>, + <&cru SCLK_MAC_REFOUT>, <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>, <&cru SCLK_GMAC_RMII>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_ref", + "clk_mac_refout", "aclk_mac", + "pclk_mac", "clk_mac_speed"; + rockchip,grf = <&grf>; + phy-mode = "rmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rmii_pins &mac_refclk_12ma>; + power-domains = <&power PX30_PD_GMAC>; + resets = <&cru SRST_GMAC_A>; + reset-names = "stmmaceth"; + status = "disabled"; + }; + + sdmmc: dwmmc@ff370000 { + compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff370000 0x0 0x4000>; + interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>; + power-domains = <&power PX30_PD_SDCARD>; + status = "disabled"; + }; + + sdio: dwmmc@ff380000 { + compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff380000 0x0 0x4000>; + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdio_bus4 &sdio_cmd &sdio_clk>; + power-domains = <&power PX30_PD_MMC_NAND>; + status = "disabled"; + }; + + emmc: dwmmc@ff390000 { + compatible = "rockchip,px30-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff390000 0x0 0x4000>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; + fifo-depth = <0x100>; + max-frequency = <150000000>; + power-domains = <&power PX30_PD_MMC_NAND>; + status = "disabled"; + }; + + vopb: vop@ff460000 { + compatible = "rockchip,px30-vop-big"; + reg = <0x0 0xff460000 0x0 0xefc>; + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_VOPB>, <&cru DCLK_VOPB>, + <&cru HCLK_VOPB>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_VOPB_A>, <&cru SRST_VOPB_H>, <&cru SRST_VOPB>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vopb_mmu>; + power-domains = <&power PX30_PD_VO>; + rockchip,grf = <&grf>; + status = "disabled"; + + vopb_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + vopb_mmu: iommu@ff460f00 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff460f00 0x0 0x100>; + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "vopb_mmu"; + clocks = <&cru ACLK_VOPB>, <&cru HCLK_VOPB>; + clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VO>; + #iommu-cells = <0>; + status = "disabled"; + }; + + vopl: vop@ff470000 { + compatible = "rockchip,px30-vop-lit"; + reg = <0x0 0xff470000 0x0 0xefc>; + interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_VOPL>, <&cru DCLK_VOPL>, + <&cru HCLK_VOPL>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_VOPL_A>, <&cru SRST_VOPL_H>, <&cru SRST_VOPL>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vopl_mmu>; + power-domains = <&power PX30_PD_VO>; + rockchip,grf = <&grf>; + status = "disabled"; + + vopl_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + vopl_mmu: iommu@ff470f00 { + compatible = "rockchip,iommu"; + reg = <0x0 0xff470f00 0x0 0x100>; + interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "vopl_mmu"; + clocks = <&cru ACLK_VOPL>, <&cru HCLK_VOPL>; + clock-names = "aclk", "hclk"; + power-domains = <&power PX30_PD_VO>; + #iommu-cells = <0>; + status = "disabled"; + }; + + qos_gmac: qos@ff518000 { + compatible = "syscon"; + reg = <0x0 0xff518000 0x0 0x20>; + }; + + qos_gpu: qos@ff520000 { + compatible = "syscon"; + reg = <0x0 0xff520000 0x0 0x20>; + }; + + qos_sdmmc: qos@ff52c000 { + compatible = "syscon"; + reg = <0x0 0xff52c000 0x0 0x20>; + }; + + qos_emmc: qos@ff538000 { + compatible = "syscon"; + reg = <0x0 0xff538000 0x0 0x20>; + }; + + qos_nand: qos@ff538080 { + compatible = "syscon"; + reg = <0x0 0xff538080 0x0 0x20>; + }; + + qos_sdio: qos@ff538100 { + compatible = "syscon"; + reg = <0x0 0xff538100 0x0 0x20>; + }; + + qos_sfc: qos@ff538180 { + compatible = "syscon"; + reg = <0x0 0xff538180 0x0 0x20>; + }; + + qos_usb_host: qos@ff540000 { + compatible = "syscon"; + reg = <0x0 0xff540000 0x0 0x20>; + }; + + qos_usb_otg: qos@ff540080 { + compatible = "syscon"; + reg = <0x0 0xff540080 0x0 0x20>; + }; + + qos_isp_128: qos@ff548000 { + compatible = "syscon"; + reg = <0x0 0xff548000 0x0 0x20>; + }; + + qos_isp_rd: qos@ff548080 { + compatible = "syscon"; + reg = <0x0 0xff548080 0x0 0x20>; + }; + + qos_isp_wr: qos@ff548100 { + compatible = "syscon"; + reg = <0x0 0xff548100 0x0 0x20>; + }; + + qos_isp_m1: qos@ff548180 { + compatible = "syscon"; + reg = <0x0 0xff548180 0x0 0x20>; + }; + + qos_vip: qos@ff548200 { + compatible = "syscon"; + reg = <0x0 0xff548200 0x0 0x20>; + }; + + qos_rga_rd: qos@ff550000 { + compatible = "syscon"; + reg = <0x0 0xff550000 0x0 0x20>; + }; + + qos_rga_wr: qos@ff550080 { + compatible = "syscon"; + reg = <0x0 0xff550080 0x0 0x20>; + }; + + qos_vop_m0: qos@ff550100 { + compatible = "syscon"; + reg = <0x0 0xff550100 0x0 0x20>; + }; + + qos_vop_m1: qos@ff550180 { + compatible = "syscon"; + reg = <0x0 0xff550180 0x0 0x20>; + }; + + qos_vpu: qos@ff558000 { + compatible = "syscon"; + reg = <0x0 0xff558000 0x0 0x20>; + }; + + qos_vpu_r128: qos@ff558080 { + compatible = "syscon"; + reg = <0x0 0xff558080 0x0 0x20>; + }; + + pinctrl: pinctrl { + compatible = "rockchip,px30-pinctrl"; + rockchip,grf = <&grf>; + rockchip,pmu = <&pmugrf>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio0: gpio0@ff040000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff040000 0x0 0x100>; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&pmucru PCLK_GPIO0_PMU>; + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio1@ff250000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff250000 0x0 0x100>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru PCLK_GPIO1>; + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio2@ff260000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff260000 0x0 0x100>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru PCLK_GPIO2>; + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio3@ff270000 { + compatible = "rockchip,gpio-bank"; + reg = <0x0 0xff270000 0x0 0x100>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru PCLK_GPIO3>; + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + 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_2ma: pcfg-pull-none-2ma { + bias-disable; + drive-strength = <2>; + }; + + pcfg_pull_up_2ma: pcfg-pull-up-2ma { + bias-pull-up; + drive-strength = <2>; + }; + + pcfg_pull_up_4ma: pcfg-pull-up-4ma { + bias-pull-up; + drive-strength = <4>; + }; + + pcfg_pull_none_4ma: pcfg-pull-none-4ma { + bias-disable; + drive-strength = <4>; + }; + + pcfg_pull_down_4ma: pcfg-pull-down-4ma { + bias-pull-down; + drive-strength = <4>; + }; + + pcfg_pull_none_8ma: pcfg-pull-none-8ma { + bias-disable; + drive-strength = <8>; + }; + + pcfg_pull_up_8ma: pcfg-pull-up-8ma { + bias-pull-up; + drive-strength = <8>; + }; + + pcfg_pull_none_12ma: pcfg-pull-none-12ma { + bias-disable; + drive-strength = <12>; + }; + + pcfg_pull_up_12ma: pcfg-pull-up-12ma { + bias-pull-up; + drive-strength = <12>; + }; + + pcfg_pull_none_smt: pcfg-pull-none-smt { + bias-disable; + input-schmitt-enable; + }; + + pcfg_output_high: pcfg-output-high { + output-high; + }; + + pcfg_output_low: pcfg-output-low { + output-low; + }; + + pcfg_input_high: pcfg-input-high { + bias-pull-up; + input-enable; + }; + + pcfg_input: pcfg-input { + input-enable; + }; + + i2c0 { + i2c0_xfer: i2c0-xfer { + rockchip,pins = + <0 RK_PB0 1 &pcfg_pull_none_smt>, + <0 RK_PB1 1 &pcfg_pull_none_smt>; + }; + }; + + i2c1 { + i2c1_xfer: i2c1-xfer { + rockchip,pins = + <0 RK_PC2 1 &pcfg_pull_none_smt>, + <0 RK_PC3 1 &pcfg_pull_none_smt>; + }; + }; + + i2c2 { + i2c2_xfer: i2c2-xfer { + rockchip,pins = + <2 RK_PB7 2 &pcfg_pull_none_smt>, + <2 RK_PC0 2 &pcfg_pull_none_smt>; + }; + }; + + i2c3 { + i2c3_xfer: i2c3-xfer { + rockchip,pins = + <1 RK_PB4 4 &pcfg_pull_none_smt>, + <1 RK_PB5 4 &pcfg_pull_none_smt>; + }; + }; + + tsadc { + tsadc_otp_gpio: tsadc-otp-gpio { + rockchip,pins = + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + tsadc_otp_out: tsadc-otp-out { + rockchip,pins = + <0 RK_PA6 1 &pcfg_pull_none>; + }; + }; + + uart0 { + uart0_xfer: uart0-xfer { + rockchip,pins = + <0 RK_PB2 1 &pcfg_pull_up>, + <0 RK_PB3 1 &pcfg_pull_up>; + }; + + uart0_cts: uart0-cts { + rockchip,pins = + <0 RK_PB4 1 &pcfg_pull_none>; + }; + + uart0_rts: uart0-rts { + rockchip,pins = + <0 RK_PB5 1 &pcfg_pull_none>; + }; + + uart0_rts_gpio: uart0-rts-gpio { + rockchip,pins = + <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + uart1 { + uart1_xfer: uart1-xfer { + rockchip,pins = + <1 RK_PC1 1 &pcfg_pull_up>, + <1 RK_PC0 1 &pcfg_pull_up>; + }; + + uart1_cts: uart1-cts { + rockchip,pins = + <1 RK_PC2 1 &pcfg_pull_none>; + }; + + uart1_rts: uart1-rts { + rockchip,pins = + <1 RK_PC3 1 &pcfg_pull_none>; + }; + + uart1_rts_gpio: uart1-rts-gpio { + rockchip,pins = + <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + uart2-m0 { + uart2m0_xfer: uart2m0-xfer { + rockchip,pins = + <1 RK_PD2 2 &pcfg_pull_up>, + <1 RK_PD3 2 &pcfg_pull_up>; + }; + }; + + uart2-m1 { + uart2m1_xfer: uart2m1-xfer { + rockchip,pins = + <2 RK_PB4 2 &pcfg_pull_up>, + <2 RK_PB6 2 &pcfg_pull_up>; + }; + }; + + uart3-m0 { + uart3m0_xfer: uart3m0-xfer { + rockchip,pins = + <0 RK_PC0 2 &pcfg_pull_up>, + <0 RK_PC1 2 &pcfg_pull_up>; + }; + + uart3m0_cts: uart3m0-cts { + rockchip,pins = + <0 RK_PC2 2 &pcfg_pull_none>; + }; + + uart3m0_rts: uart3m0-rts { + rockchip,pins = + <0 RK_PC3 2 &pcfg_pull_none>; + }; + + uart3m0_rts_gpio: uart3m0-rts-gpio { + rockchip,pins = + <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + uart3-m1 { + uart3m1_xfer: uart3m1-xfer { + rockchip,pins = + <1 RK_PB6 2 &pcfg_pull_up>, + <1 RK_PB7 2 &pcfg_pull_up>; + }; + + uart3m1_cts: uart3m1-cts { + rockchip,pins = + <1 RK_PB4 2 &pcfg_pull_none>; + }; + + uart3m1_rts: uart3m1-rts { + rockchip,pins = + <1 RK_PB5 2 &pcfg_pull_none>; + }; + + uart3m1_rts_gpio: uart3m1-rts-gpio { + rockchip,pins = + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + uart4 { + uart4_xfer: uart4-xfer { + rockchip,pins = + <1 RK_PD4 2 &pcfg_pull_up>, + <1 RK_PD5 2 &pcfg_pull_up>; + }; + + uart4_cts: uart4-cts { + rockchip,pins = + <1 RK_PD6 2 &pcfg_pull_none>; + }; + + uart4_rts: uart4-rts { + rockchip,pins = + <1 RK_PD7 2 &pcfg_pull_none>; + }; + }; + + uart5 { + uart5_xfer: uart5-xfer { + rockchip,pins = + <3 RK_PA2 4 &pcfg_pull_up>, + <3 RK_PA1 4 &pcfg_pull_up>; + }; + + uart5_cts: uart5-cts { + rockchip,pins = + <3 RK_PA3 4 &pcfg_pull_none>; + }; + + uart5_rts: uart5-rts { + rockchip,pins = + <3 RK_PA5 4 &pcfg_pull_none>; + }; + }; + + spi0 { + spi0_clk: spi0-clk { + rockchip,pins = + <1 RK_PB7 3 &pcfg_pull_up_4ma>; + }; + + spi0_csn: spi0-csn { + rockchip,pins = + <1 RK_PB6 3 &pcfg_pull_up_4ma>; + }; + + spi0_miso: spi0-miso { + rockchip,pins = + <1 RK_PB5 3 &pcfg_pull_up_4ma>; + }; + + spi0_mosi: spi0-mosi { + rockchip,pins = + <1 RK_PB4 3 &pcfg_pull_up_4ma>; + }; + + spi0_clk_hs: spi0-clk-hs { + rockchip,pins = + <1 RK_PB7 3 &pcfg_pull_up_8ma>; + }; + + spi0_miso_hs: spi0-miso-hs { + rockchip,pins = + <1 RK_PB5 3 &pcfg_pull_up_8ma>; + }; + + spi0_mosi_hs: spi0-mosi-hs { + rockchip,pins = + <1 RK_PB4 3 &pcfg_pull_up_8ma>; + }; + }; + + spi1 { + spi1_clk: spi1-clk { + rockchip,pins = + <3 RK_PB7 4 &pcfg_pull_up_4ma>; + }; + + spi1_csn0: spi1-csn0 { + rockchip,pins = + <3 RK_PB1 4 &pcfg_pull_up_4ma>; + }; + + spi1_csn1: spi1-csn1 { + rockchip,pins = + <3 RK_PB2 2 &pcfg_pull_up_4ma>; + }; + + spi1_miso: spi1-miso { + rockchip,pins = + <3 RK_PB6 4 &pcfg_pull_up_4ma>; + }; + + spi1_mosi: spi1-mosi { + rockchip,pins = + <3 RK_PB4 4 &pcfg_pull_up_4ma>; + }; + + spi1_clk_hs: spi1-clk-hs { + rockchip,pins = + <3 RK_PB7 4 &pcfg_pull_up_8ma>; + }; + + spi1_miso_hs: spi1-miso-hs { + rockchip,pins = + <3 RK_PB6 4 &pcfg_pull_up_8ma>; + }; + + spi1_mosi_hs: spi1-mosi-hs { + rockchip,pins = + <3 RK_PB4 4 &pcfg_pull_up_8ma>; + }; + }; + + pdm { + pdm_clk0m0: pdm-clk0m0 { + rockchip,pins = + <3 RK_PC6 2 &pcfg_pull_none>; + }; + + pdm_clk0m1: pdm-clk0m1 { + rockchip,pins = + <2 RK_PC6 1 &pcfg_pull_none>; + }; + + pdm_clk1: pdm-clk1 { + rockchip,pins = + <3 RK_PC7 2 &pcfg_pull_none>; + }; + + pdm_sdi0m0: pdm-sdi0m0 { + rockchip,pins = + <3 RK_PD3 2 &pcfg_pull_none>; + }; + + pdm_sdi0m1: pdm-sdi0m1 { + rockchip,pins = + <2 RK_PC5 2 &pcfg_pull_none>; + }; + + pdm_sdi1: pdm-sdi1 { + rockchip,pins = + <3 RK_PD0 2 &pcfg_pull_none>; + }; + + pdm_sdi2: pdm-sdi2 { + rockchip,pins = + <3 RK_PD1 2 &pcfg_pull_none>; + }; + + pdm_sdi3: pdm-sdi3 { + rockchip,pins = + <3 RK_PD2 2 &pcfg_pull_none>; + }; + + pdm_clk0m0_sleep: pdm-clk0m0-sleep { + rockchip,pins = + <3 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_clk0m_sleep1: pdm-clk0m1-sleep { + rockchip,pins = + <2 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_clk1_sleep: pdm-clk1-sleep { + rockchip,pins = + <3 RK_PC7 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_sdi0m0_sleep: pdm-sdi0m0-sleep { + rockchip,pins = + <3 RK_PD3 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_sdi0m1_sleep: pdm-sdi0m1-sleep { + rockchip,pins = + <2 RK_PC5 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_sdi1_sleep: pdm-sdi1-sleep { + rockchip,pins = + <3 RK_PD0 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_sdi2_sleep: pdm-sdi2-sleep { + rockchip,pins = + <3 RK_PD1 RK_FUNC_GPIO &pcfg_input_high>; + }; + + pdm_sdi3_sleep: pdm-sdi3-sleep { + rockchip,pins = + <3 RK_PD2 RK_FUNC_GPIO &pcfg_input_high>; + }; + }; + + i2s0 { + i2s0_8ch_mclk: i2s0-8ch-mclk { + rockchip,pins = + <3 RK_PC1 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sclktx: i2s0-8ch-sclktx { + rockchip,pins = + <3 RK_PC3 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sclkrx: i2s0-8ch-sclkrx { + rockchip,pins = + <3 RK_PB4 2 &pcfg_pull_none>; + }; + + i2s0_8ch_lrcktx: i2s0-8ch-lrcktx { + rockchip,pins = + <3 RK_PC2 2 &pcfg_pull_none>; + }; + + i2s0_8ch_lrckrx: i2s0-8ch-lrckrx { + rockchip,pins = + <3 RK_PB5 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdo0: i2s0-8ch-sdo0 { + rockchip,pins = + <3 RK_PC4 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdo1: i2s0-8ch-sdo1 { + rockchip,pins = + <3 RK_PC0 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdo2: i2s0-8ch-sdo2 { + rockchip,pins = + <3 RK_PB7 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdo3: i2s0-8ch-sdo3 { + rockchip,pins = + <3 RK_PB6 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdi0: i2s0-8ch-sdi0 { + rockchip,pins = + <3 RK_PC5 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdi1: i2s0-8ch-sdi1 { + rockchip,pins = + <3 RK_PB3 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdi2: i2s0-8ch-sdi2 { + rockchip,pins = + <3 RK_PB1 2 &pcfg_pull_none>; + }; + + i2s0_8ch_sdi3: i2s0-8ch-sdi3 { + rockchip,pins = + <3 RK_PB0 2 &pcfg_pull_none>; + }; + }; + + i2s1 { + i2s1_2ch_mclk: i2s1-2ch-mclk { + rockchip,pins = + <2 RK_PC3 1 &pcfg_pull_none>; + }; + + i2s1_2ch_sclk: i2s1-2ch-sclk { + rockchip,pins = + <2 RK_PC2 1 &pcfg_pull_none>; + }; + + i2s1_2ch_lrck: i2s1-2ch-lrck { + rockchip,pins = + <2 RK_PC1 1 &pcfg_pull_none>; + }; + + i2s1_2ch_sdi: i2s1-2ch-sdi { + rockchip,pins = + <2 RK_PC5 1 &pcfg_pull_none>; + }; + + i2s1_2ch_sdo: i2s1-2ch-sdo { + rockchip,pins = + <2 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + i2s2 { + i2s2_2ch_mclk: i2s2-2ch-mclk { + rockchip,pins = + <3 RK_PA1 2 &pcfg_pull_none>; + }; + + i2s2_2ch_sclk: i2s2-2ch-sclk { + rockchip,pins = + <3 RK_PA2 2 &pcfg_pull_none>; + }; + + i2s2_2ch_lrck: i2s2-2ch-lrck { + rockchip,pins = + <3 RK_PA3 2 &pcfg_pull_none>; + }; + + i2s2_2ch_sdi: i2s2-2ch-sdi { + rockchip,pins = + <3 RK_PA5 2 &pcfg_pull_none>; + }; + + i2s2_2ch_sdo: i2s2-2ch-sdo { + rockchip,pins = + <3 RK_PA7 2 &pcfg_pull_none>; + }; + }; + + sdmmc { + sdmmc_clk: sdmmc-clk { + rockchip,pins = + <1 RK_PD6 1 &pcfg_pull_none_8ma>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = + <1 RK_PD7 1 &pcfg_pull_up_8ma>; + }; + + sdmmc_det: sdmmc-det { + rockchip,pins = + <0 RK_PA3 1 &pcfg_pull_up_8ma>; + }; + + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = + <1 RK_PD2 1 &pcfg_pull_up_8ma>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = + <1 RK_PD2 1 &pcfg_pull_up_8ma>, + <1 RK_PD3 1 &pcfg_pull_up_8ma>, + <1 RK_PD4 1 &pcfg_pull_up_8ma>, + <1 RK_PD5 1 &pcfg_pull_up_8ma>; + }; + + sdmmc_gpio: sdmmc-gpio { + rockchip,pins = + <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up_4ma>, + <1 RK_PD7 RK_FUNC_GPIO &pcfg_pull_up_4ma>; + }; + }; + + sdio { + sdio_clk: sdio-clk { + rockchip,pins = + <1 RK_PC5 1 &pcfg_pull_none>; + }; + + sdio_cmd: sdio-cmd { + rockchip,pins = + <1 RK_PC4 1 &pcfg_pull_up>; + }; + + sdio_bus4: sdio-bus4 { + rockchip,pins = + <1 RK_PC6 1 &pcfg_pull_up>, + <1 RK_PC7 1 &pcfg_pull_up>, + <1 RK_PD0 1 &pcfg_pull_up>, + <1 RK_PD1 1 &pcfg_pull_up>; + }; + + sdio_gpio: sdio-gpio { + rockchip,pins = + <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>, + <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + emmc { + emmc_clk: emmc-clk { + rockchip,pins = + <1 RK_PB1 2 &pcfg_pull_none_8ma>; + }; + + emmc_cmd: emmc-cmd { + rockchip,pins = + <1 RK_PB2 2 &pcfg_pull_up_8ma>; + }; + + emmc_pwren: emmc-pwren { + rockchip,pins = + <1 RK_PB0 2 &pcfg_pull_none>; + }; + + emmc_rstnout: emmc-rstnout { + rockchip,pins = + <1 RK_PB3 2 &pcfg_pull_none>; + }; + + emmc_bus1: emmc-bus1 { + rockchip,pins = + <1 RK_PA0 2 &pcfg_pull_up_8ma>; + }; + + emmc_bus4: emmc-bus4 { + rockchip,pins = + <1 RK_PA0 2 &pcfg_pull_up_8ma>, + <1 RK_PA1 2 &pcfg_pull_up_8ma>, + <1 RK_PA2 2 &pcfg_pull_up_8ma>, + <1 RK_PA3 2 &pcfg_pull_up_8ma>; + }; + + emmc_bus8: emmc-bus8 { + rockchip,pins = + <1 RK_PA0 2 &pcfg_pull_up_8ma>, + <1 RK_PA1 2 &pcfg_pull_up_8ma>, + <1 RK_PA2 2 &pcfg_pull_up_8ma>, + <1 RK_PA3 2 &pcfg_pull_up_8ma>, + <1 RK_PA4 2 &pcfg_pull_up_8ma>, + <1 RK_PA5 2 &pcfg_pull_up_8ma>, + <1 RK_PA6 2 &pcfg_pull_up_8ma>, + <1 RK_PA7 2 &pcfg_pull_up_8ma>; + }; + }; + + flash { + flash_cs0: flash-cs0 { + rockchip,pins = + <1 RK_PB0 1 &pcfg_pull_none>; + }; + + flash_rdy: flash-rdy { + rockchip,pins = + <1 RK_PB1 1 &pcfg_pull_none>; + }; + + flash_dqs: flash-dqs { + rockchip,pins = + <1 RK_PB2 1 &pcfg_pull_none>; + }; + + flash_ale: flash-ale { + rockchip,pins = + <1 RK_PB3 1 &pcfg_pull_none>; + }; + + flash_cle: flash-cle { + rockchip,pins = + <1 RK_PB4 1 &pcfg_pull_none>; + }; + + flash_wrn: flash-wrn { + rockchip,pins = + <1 RK_PB5 1 &pcfg_pull_none>; + }; + + flash_csl: flash-csl { + rockchip,pins = + <1 RK_PB6 1 &pcfg_pull_none>; + }; + + flash_rdn: flash-rdn { + rockchip,pins = + <1 RK_PB7 1 &pcfg_pull_none>; + }; + + flash_bus8: flash-bus8 { + rockchip,pins = + <1 RK_PA0 1 &pcfg_pull_up_12ma>, + <1 RK_PA1 1 &pcfg_pull_up_12ma>, + <1 RK_PA2 1 &pcfg_pull_up_12ma>, + <1 RK_PA3 1 &pcfg_pull_up_12ma>, + <1 RK_PA4 1 &pcfg_pull_up_12ma>, + <1 RK_PA5 1 &pcfg_pull_up_12ma>, + <1 RK_PA6 1 &pcfg_pull_up_12ma>, + <1 RK_PA7 1 &pcfg_pull_up_12ma>; + }; + }; + + lcdc { + lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { + rockchip,pins = + <3 RK_PA0 1 &pcfg_pull_none_12ma>; + }; + + lcdc_rgb_m0_hsync_pin: lcdc-rgb-m0-hsync-pin { + rockchip,pins = + <3 RK_PA1 1 &pcfg_pull_none_12ma>; + }; + + lcdc_rgb_m0_vsync_pin: lcdc-rgb-m0-vsync-pin { + rockchip,pins = + <3 RK_PA2 1 &pcfg_pull_none_12ma>; + }; + + lcdc_rgb_m0_den_pin: lcdc-rgb-m0-den-pin { + rockchip,pins = + <3 RK_PA3 1 &pcfg_pull_none_12ma>; + }; + + lcdc_rgb888_m0_data_pins: lcdc-rgb888-m0-data-pins { + rockchip,pins = + <3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */ + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */ + <3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */ + <3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */ + <3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */ + <3 RK_PC7 1 &pcfg_pull_none_8ma>, /* lcdc_d19 */ + <3 RK_PC6 1 &pcfg_pull_none_8ma>, /* lcdc_d18 */ + <3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */ + <3 RK_PC4 1 &pcfg_pull_none_8ma>, /* lcdc_d16 */ + <3 RK_PD3 1 &pcfg_pull_none_8ma>, /* lcdc_d23 */ + <3 RK_PD2 1 &pcfg_pull_none_8ma>, /* lcdc_d22 */ + <3 RK_PD1 1 &pcfg_pull_none_8ma>, /* lcdc_d21 */ + <3 RK_PD0 1 &pcfg_pull_none_8ma>; /* lcdc_d20 */ + }; + + lcdc_rgb666_m0_data_pins: lcdc-rgb666-m0-data-pins { + rockchip,pins = + <3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */ + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */ + <3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */ + <3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */ + <3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */ + <3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */ + <3 RK_PC4 1 &pcfg_pull_none_8ma>; /* lcdc_d16 */ + }; + + lcdc_rgb565_m0_data_pins: lcdc-rgb565-m0-data-pins { + rockchip,pins = + <3 RK_PA7 1 &pcfg_pull_none_8ma>, /* lcdc_d3 */ + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA5 1 &pcfg_pull_none_8ma>, /* lcdc_d1 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB1 1 &pcfg_pull_none_8ma>, /* lcdc_d5 */ + <3 RK_PB0 1 &pcfg_pull_none_8ma>, /* lcdc_d4 */ + <3 RK_PB7 1 &pcfg_pull_none_8ma>, /* lcdc_d11 */ + <3 RK_PB6 1 &pcfg_pull_none_8ma>, /* lcdc_d10 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PB4 1 &pcfg_pull_none_8ma>, /* lcdc_d8 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>; /* lcdc_d12 */ + }; + + lcdc_rgb888_m1_data_pins: lcdc-rgb888-m1-data-pins { + rockchip,pins = + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */ + <3 RK_PC7 1 &pcfg_pull_none_8ma>, /* lcdc_d19 */ + <3 RK_PC6 1 &pcfg_pull_none_8ma>, /* lcdc_d18 */ + <3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */ + <3 RK_PC4 1 &pcfg_pull_none_8ma>, /* lcdc_d16 */ + <3 RK_PD3 1 &pcfg_pull_none_8ma>, /* lcdc_d23 */ + <3 RK_PD2 1 &pcfg_pull_none_8ma>, /* lcdc_d22 */ + <3 RK_PD1 1 &pcfg_pull_none_8ma>, /* lcdc_d21 */ + <3 RK_PD0 1 &pcfg_pull_none_8ma>; /* lcdc_d20 */ + }; + + lcdc_rgb666_m1_data_pins: lcdc-rgb666-m1-data-pins { + rockchip,pins = + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>, /* lcdc_d12 */ + <3 RK_PC5 1 &pcfg_pull_none_8ma>, /* lcdc_d17 */ + <3 RK_PC4 1 &pcfg_pull_none_8ma>; /* lcdc_d16 */ + }; + + lcdc_rgb565_m1_data_pins: lcdc-rgb565-m1-data-pins { + rockchip,pins = + <3 RK_PA6 1 &pcfg_pull_none_8ma>, /* lcdc_d2 */ + <3 RK_PA4 1 &pcfg_pull_none_8ma>, /* lcdc_d0 */ + <3 RK_PB3 1 &pcfg_pull_none_8ma>, /* lcdc_d7 */ + <3 RK_PB2 1 &pcfg_pull_none_8ma>, /* lcdc_d6 */ + <3 RK_PB5 1 &pcfg_pull_none_8ma>, /* lcdc_d9 */ + <3 RK_PC3 1 &pcfg_pull_none_8ma>, /* lcdc_d15 */ + <3 RK_PC2 1 &pcfg_pull_none_8ma>, /* lcdc_d14 */ + <3 RK_PC1 1 &pcfg_pull_none_8ma>, /* lcdc_d13 */ + <3 RK_PC0 1 &pcfg_pull_none_8ma>; /* lcdc_d12 */ + }; + }; + + pwm0 { + pwm0_pin: pwm0-pin { + rockchip,pins = + <0 RK_PB7 1 &pcfg_pull_none>; + }; + }; + + pwm1 { + pwm1_pin: pwm1-pin { + rockchip,pins = + <0 RK_PC0 1 &pcfg_pull_none>; + }; + }; + + pwm2 { + pwm2_pin: pwm2-pin { + rockchip,pins = + <2 RK_PB5 1 &pcfg_pull_none>; + }; + }; + + pwm3 { + pwm3_pin: pwm3-pin { + rockchip,pins = + <0 RK_PC1 1 &pcfg_pull_none>; + }; + }; + + pwm4 { + pwm4_pin: pwm4-pin { + rockchip,pins = + <3 RK_PC2 3 &pcfg_pull_none>; + }; + }; + + pwm5 { + pwm5_pin: pwm5-pin { + rockchip,pins = + <3 RK_PC3 3 &pcfg_pull_none>; + }; + }; + + pwm6 { + pwm6_pin: pwm6-pin { + rockchip,pins = + <3 RK_PC4 3 &pcfg_pull_none>; + }; + }; + + pwm7 { + pwm7_pin: pwm7-pin { + rockchip,pins = + <3 RK_PC5 3 &pcfg_pull_none>; + }; + }; + + gmac { + rmii_pins: rmii-pins { + rockchip,pins = + <2 RK_PA0 2 &pcfg_pull_none_12ma>, /* mac_txen */ + <2 RK_PA1 2 &pcfg_pull_none_12ma>, /* mac_txd1 */ + <2 RK_PA2 2 &pcfg_pull_none_12ma>, /* mac_txd0 */ + <2 RK_PA3 2 &pcfg_pull_none>, /* mac_rxd0 */ + <2 RK_PA4 2 &pcfg_pull_none>, /* mac_rxd1 */ + <2 RK_PA5 2 &pcfg_pull_none>, /* mac_rxer */ + <2 RK_PA6 2 &pcfg_pull_none>, /* mac_rxdv */ + <2 RK_PA7 2 &pcfg_pull_none>, /* mac_mdio */ + <2 RK_PB1 2 &pcfg_pull_none>; /* mac_mdc */ + }; + + mac_refclk_12ma: mac-refclk-12ma { + rockchip,pins = + <2 RK_PB2 2 &pcfg_pull_none_12ma>; + }; + + mac_refclk: mac-refclk { + rockchip,pins = + <2 RK_PB2 2 &pcfg_pull_none>; + }; + }; + + cif-m0 { + cif_clkout_m0: cif-clkout-m0 { + rockchip,pins = + <2 RK_PB3 1 &pcfg_pull_none>; + }; + + dvp_d2d9_m0: dvp-d2d9-m0 { + rockchip,pins = + <2 RK_PA0 1 &pcfg_pull_none>, /* cif_data2 */ + <2 RK_PA1 1 &pcfg_pull_none>, /* cif_data3 */ + <2 RK_PA2 1 &pcfg_pull_none>, /* cif_data4 */ + <2 RK_PA3 1 &pcfg_pull_none>, /* cif_data5 */ + <2 RK_PA4 1 &pcfg_pull_none>, /* cif_data6 */ + <2 RK_PA5 1 &pcfg_pull_none>, /* cif_data7 */ + <2 RK_PA6 1 &pcfg_pull_none>, /* cif_data8 */ + <2 RK_PA7 1 &pcfg_pull_none>, /* cif_data9 */ + <2 RK_PB0 1 &pcfg_pull_none>, /* cif_sync */ + <2 RK_PB1 1 &pcfg_pull_none>, /* cif_href */ + <2 RK_PB2 1 &pcfg_pull_none>, /* cif_clkin */ + <2 RK_PB3 1 &pcfg_pull_none>; /* cif_clkout */ + }; + + dvp_d0d1_m0: dvp-d0d1-m0 { + rockchip,pins = + <2 RK_PB4 1 &pcfg_pull_none>, /* cif_data0 */ + <2 RK_PB6 1 &pcfg_pull_none>; /* cif_data1 */ + }; + + dvp_d10d11_m0:d10-d11-m0 { + rockchip,pins = + <2 RK_PB7 1 &pcfg_pull_none>, /* cif_data10 */ + <2 RK_PC0 1 &pcfg_pull_none>; /* cif_data11 */ + }; + }; + + cif-m1 { + cif_clkout_m1: cif-clkout-m1 { + rockchip,pins = + <3 RK_PD0 3 &pcfg_pull_none>; + }; + + dvp_d2d9_m1: dvp-d2d9-m1 { + rockchip,pins = + <3 RK_PA3 3 &pcfg_pull_none>, /* cif_data2 */ + <3 RK_PA5 3 &pcfg_pull_none>, /* cif_data3 */ + <3 RK_PA7 3 &pcfg_pull_none>, /* cif_data4 */ + <3 RK_PB0 3 &pcfg_pull_none>, /* cif_data5 */ + <3 RK_PB1 3 &pcfg_pull_none>, /* cif_data6 */ + <3 RK_PB4 3 &pcfg_pull_none>, /* cif_data7 */ + <3 RK_PB6 3 &pcfg_pull_none>, /* cif_data8 */ + <3 RK_PB7 3 &pcfg_pull_none>, /* cif_data9 */ + <3 RK_PD1 3 &pcfg_pull_none>, /* cif_sync */ + <3 RK_PD2 3 &pcfg_pull_none>, /* cif_href */ + <3 RK_PD3 3 &pcfg_pull_none>, /* cif_clkin */ + <3 RK_PD0 3 &pcfg_pull_none>; /* cif_clkout */ + }; + + dvp_d0d1_m1: dvp-d0d1-m1 { + rockchip,pins = + <3 RK_PA1 3 &pcfg_pull_none>, /* cif_data0 */ + <3 RK_PA2 3 &pcfg_pull_none>; /* cif_data1 */ + }; + + dvp_d10d11_m1:d10-d11-m1 { + rockchip,pins = + <3 RK_PC6 3 &pcfg_pull_none>, /* cif_data10 */ + <3 RK_PC7 3 &pcfg_pull_none>; /* cif_data11 */ + }; + }; + + isp { + isp_prelight: isp-prelight { + rockchip,pins = + <3 RK_PD1 4 &pcfg_pull_none>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts index 246c317f6a68..99d0d9912950 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts @@ -41,6 +41,19 @@ vin-supply = <&vcc_io>; }; + vcc_sdio: sdmmcio-regulator { + compatible = "regulator-gpio"; + gpios = <&grf_gpio 0 GPIO_ACTIVE_HIGH>; + states = <1800000 0x1 + 3300000 0x0>; + regulator-name = "vcc_sdio"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { compatible = "regulator-fixed"; enable-active-high; @@ -208,6 +221,18 @@ }; }; +&io_domains { + status = "okay"; + + vccio1-supply = <&vcc_io>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_sdio>; + vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io>; + vccio6-supply = <&vcc_io>; + pmuio-supply = <&vcc_io>; +}; + &pinctrl { pmic { pmic_int_l: pmic-int-l { @@ -230,7 +255,12 @@ max-frequency = <150000000>; pinctrl-names = "default"; pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vcc_sdio>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts index 5272e887a434..dc20145dd393 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts @@ -46,7 +46,7 @@ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { compatible = "regulator-fixed"; enable-active-high; - gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb20_host_drv>; regulator-name = "vcc_host1_5v"; @@ -62,6 +62,23 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; }; + + sound { + compatible = "audio-graph-card"; + label = "rockchip,rk3328"; + dais = <&spdif_p0>; + }; + + spdif-dit { + compatible = "linux,spdif-dit"; + #sound-dai-cells = <0>; + + port { + dit_p0_0: endpoint { + remote-endpoint = <&spdif_p0_0>; + }; + }; + }; }; &cpu0 { @@ -108,6 +125,14 @@ status = "okay"; }; +&hdmi { + status = "okay"; +}; + +&hdmiphy { + status = "okay"; +}; + &i2c1 { status = "okay"; @@ -238,7 +263,7 @@ usb2 { usb20_host_drv: usb20-host-drv { - rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; }; }; @@ -261,6 +286,30 @@ status = "okay"; }; +&spdif { + pinctrl-0 = <&spdifm0_tx>; + status = "okay"; + #sound-dai-cells = <0>; + + spdif_p0: port { + spdif_p0_0: endpoint { + remote-endpoint = <&dit_p0_0>; + }; + }; +}; + +&spi0 { + status = "okay"; + + spiflash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + /* maximum speed for Rockchip SPI */ + spi-max-frequency = <50000000>; + }; +}; + &tsadc { rockchip,hw-tshut-mode = <0>; rockchip,hw-tshut-polarity = <0>; @@ -295,3 +344,11 @@ &usb_host0_ohci { status = "okay"; }; + +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 3f5a2944300f..e1a33dd981e0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -151,6 +151,11 @@ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; }; + display_subsystem: display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vop_out>; + }; + psci { compatible = "arm,psci-1.0", "arm,psci-0.2"; method = "smc"; @@ -249,6 +254,12 @@ status = "disabled"; }; + grf_gpio: grf-gpio { + compatible = "rockchip,rk3328-grf-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + power: power-controller { compatible = "rockchip,rk3328-power-controller"; #power-domain-cells = <1>; @@ -274,7 +285,6 @@ mode-bootloader = <BOOT_FASTBOOT>; mode-loader = <BOOT_BL_DOWNLOAD>; }; - }; uart0: serial@ff110000 { @@ -600,6 +610,28 @@ status = "disabled"; }; + vop: vop@ff370000 { + compatible = "rockchip,rk3328-vop"; + reg = <0x0 0xff370000 0x0 0x3efc>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru ACLK_VOP>, <&cru DCLK_LCDC>, <&cru HCLK_VOP>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; + resets = <&cru SRST_VOP_A>, <&cru SRST_VOP_H>, <&cru SRST_VOP_D>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vop_mmu>; + status = "disabled"; + + vop_out: port { + #address-cells = <1>; + #size-cells = <0>; + + vop_out_hdmi: endpoint@0 { + reg = <0>; + remote-endpoint = <&hdmi_in_vop>; + }; + }; + }; + vop_mmu: iommu@ff373f00 { compatible = "rockchip,iommu"; reg = <0x0 0xff373f00 0x0 0x100>; @@ -611,6 +643,46 @@ status = "disabled"; }; + hdmi: hdmi@ff3c0000 { + 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>; + clocks = <&cru PCLK_HDMI>, + <&cru SCLK_HDMI_SFC>; + clock-names = "iahb", + "isfr"; + phys = <&hdmiphy>; + phy-names = "hdmi"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_cec &hdmii2c_xfer &hdmi_hpd>; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + hdmi_in: port { + hdmi_in_vop: endpoint { + remote-endpoint = <&vop_out_hdmi>; + }; + }; + }; + }; + + hdmiphy: phy@ff430000 { + compatible = "rockchip,rk3328-hdmi-phy"; + reg = <0x0 0xff430000 0x0 0x10000>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru PCLK_HDMIPHY>, <&xin24m>, <&cru DCLK_HDMIPHY>; + clock-names = "sysclk", "refoclk", "refpclk"; + clock-output-names = "hdmi_phy"; + #clock-cells = <0>; + nvmem-cells = <&efuse_cpu_version>; + nvmem-cell-names = "cpu-version"; + #phy-cells = <0>; + status = "disabled"; + }; + cru: clock-controller@ff440000 { compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon"; reg = <0x0 0xff440000 0x0 0x1000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts b/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts index 8978d924eb83..cce266da28cd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts @@ -7,8 +7,7 @@ */ /dts-v1/; -#include "rk3399.dtsi" -#include "rk3399-opp.dtsi" +#include "rk3399-rock960.dtsi" / { model = "96boards RK3399 Ficus"; @@ -24,97 +23,6 @@ clock-output-names = "clkin_gmac"; #clock-cells = <0>; }; - - vcc1v8_s0: vcc1v8-s0 { - compatible = "regulator-fixed"; - regulator-name = "vcc1v8_s0"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - }; - - vcc_sys: vcc-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - }; - - vcc3v3_sys: vcc3v3-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_sys"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - vin-supply = <&vcc_sys>; - }; - - vcc3v3_pcie: vcc3v3-pcie-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_drv>; - regulator-boot-on; - regulator-name = "vcc3v3_pcie"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc3v3_sys>; - }; - - vcc5v0_host: vcc5v0-host-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&host_vbus_drv>; - regulator-name = "vcc5v0_host"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-always-on; - vin-supply = <&vcc_sys>; - }; - - vdd_log: vdd-log { - compatible = "pwm-regulator"; - pwms = <&pwm2 0 25000 0>; - regulator-name = "vdd_log"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1400000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc_sys>; - }; - -}; - -&cpu_l0 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l1 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l2 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l3 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_b0 { - cpu-supply = <&vdd_cpu_b>; -}; - -&cpu_b1 { - cpu-supply = <&vdd_cpu_b>; -}; - -&emmc_phy { - status = "okay"; }; &gmac { @@ -133,279 +41,8 @@ status = "okay"; }; -&hdmi { - ddc-i2c-bus = <&i2c3>; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_cec>; - status = "okay"; -}; - -&i2c0 { - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <168>; - i2c-scl-falling-time-ns = <4>; - status = "okay"; - - vdd_cpu_b: regulator@40 { - compatible = "silergy,syr827"; - reg = <0x40>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_cpu_b"; - regulator-min-microvolt = <712500>; - regulator-max-microvolt = <1500000>; - regulator-ramp-delay = <1000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc_sys>; - status = "okay"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_gpu: regulator@41 { - compatible = "silergy,syr828"; - reg = <0x41>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_gpu"; - regulator-min-microvolt = <712500>; - regulator-max-microvolt = <1500000>; - regulator-ramp-delay = <1000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc_sys>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - rk808: pmic@1b { - compatible = "rockchip,rk808"; - reg = <0x1b>; - interrupt-parent = <&gpio1>; - interrupts = <21 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l>; - rockchip,system-power-controller; - wakeup-source; - #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; - - vcc1-supply = <&vcc_sys>; - vcc2-supply = <&vcc_sys>; - vcc3-supply = <&vcc_sys>; - vcc4-supply = <&vcc_sys>; - vcc6-supply = <&vcc_sys>; - vcc7-supply = <&vcc_sys>; - vcc8-supply = <&vcc3v3_sys>; - vcc9-supply = <&vcc_sys>; - vcc10-supply = <&vcc_sys>; - vcc11-supply = <&vcc_sys>; - vcc12-supply = <&vcc3v3_sys>; - vddio-supply = <&vcc_1v8>; - - regulators { - vdd_center: DCDC_REG1 { - regulator-name = "vdd_center"; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_l: DCDC_REG2 { - regulator-name = "vdd_cpu_l"; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-name = "vcc_ddr"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_1v8: DCDC_REG4 { - 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>; - }; - }; - - vcc1v8_dvp: LDO_REG1 { - regulator-name = "vcc1v8_dvp"; - 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>; - }; - }; - - vcca1v8_hdmi: LDO_REG2 { - regulator-name = "vcca1v8_hdmi"; - 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>; - }; - }; - - vcca_1v8: LDO_REG3 { - regulator-name = "vcca_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>; - }; - }; - - vcc_sd: LDO_REG4 { - regulator-name = "vcc_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>; - }; - }; - - vcc3v0_sd: LDO_REG5 { - regulator-name = "vcc3v0_sd"; - 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>; - }; - }; - - vcc_1v5: LDO_REG6 { - regulator-name = "vcc_1v5"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1500000>; - }; - }; - - vcca0v9_hdmi: LDO_REG7 { - regulator-name = "vcca0v9_hdmi"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <900000>; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <900000>; - }; - }; - - vcc_3v0: LDO_REG8 { - 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_s3: SWITCH_REG1 { - regulator-name = "vcc3v3_s3"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc3v3_s0: SWITCH_REG2 { - regulator-name = "vcc3v3_s0"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - }; - }; -}; - -&i2c1 { - status = "okay"; -}; - -&i2c2 { - status = "okay"; -}; - -&i2c3 { - status = "okay"; -}; - -&i2c4 { - status = "okay"; -}; - -&io_domains { - bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */ - audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */ - sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ - gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - &pcie0 { ep-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>; - num-lanes = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_clkreqn_cpm>; - vpcie3v3-supply = <&vcc3v3_pcie>; - status = "okay"; -}; - -&pmu_io_domains { - pmu1830-supply = <&vcc_1v8>; - status = "okay"; }; &pinctrl { @@ -416,31 +53,6 @@ }; }; - sdmmc { - sdmmc_bus1: sdmmc-bus1 { - rockchip,pins = - <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>; - }; - - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = - <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>, - <4 9 RK_FUNC_1 &pcfg_pull_up_8ma>, - <4 10 RK_FUNC_1 &pcfg_pull_up_8ma>, - <4 11 RK_FUNC_1 &pcfg_pull_up_8ma>; - }; - - sdmmc_clk: sdmmc-clk { - rockchip,pins = - <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = - <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>; - }; - }; - pcie { pcie_drv: pcie-drv { rockchip,pins = @@ -448,23 +60,6 @@ }; }; - pmic { - pmic_int_l: pmic-int-l { - rockchip,pins = - <1 21 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - vsel1_gpio: vsel1-gpio { - rockchip,pins = - <1 17 RK_FUNC_GPIO &pcfg_pull_down>; - }; - - vsel2_gpio: vsel2-gpio { - rockchip,pins = - <1 14 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - usb2 { host_vbus_drv: host-vbus-drv { rockchip,pins = @@ -473,127 +68,18 @@ }; }; -&pwm2 { - status = "okay"; -}; - -&pwm3 { - status = "okay"; -}; - -&sdhci { - bus-width = <8>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; - non-removable; - status = "okay"; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - clock-frequency = <100000000>; - clock-freq-min-max = <100000 100000000>; - disable-wp; - sd-uhs-sdr104; - vqmmc-supply = <&vcc_sd>; - card-detect-delay = <800>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; - status = "okay"; -}; - -&tcphy0 { - status = "okay"; -}; - -&tcphy1 { - status = "okay"; -}; - -&u2phy0 { - status = "okay"; -}; - -&u2phy1 { - status = "okay"; -}; - -&u2phy0_host { - phy-supply = <&vcc5v0_host>; - status = "okay"; -}; - -&u2phy1_host { - phy-supply = <&vcc5v0_host>; - status = "okay"; -}; - -&u2phy0_otg { - status = "okay"; -}; - -&u2phy1_otg { - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_xfer &uart0_cts>; - status = "okay"; -}; - -&uart2 { - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host0_ohci { - status = "okay"; -}; - -&usb_host1_ehci { - status = "okay"; -}; - -&usb_host1_ohci { - status = "okay"; -}; - -&usbdrd3_0 { - status = "okay"; -}; - &usbdrd_dwc3_0 { - status = "okay"; dr_mode = "host"; }; -&usbdrd3_1 { - status = "okay"; -}; - &usbdrd_dwc3_1 { - status = "okay"; dr_mode = "host"; }; -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; +&vcc3v3_pcie { + gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; }; -&vopl_mmu { - status = "okay"; +&vcc5v0_host { + gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts index 38336ab57cc4..c706db0ee9ec 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts @@ -622,6 +622,12 @@ }; }; + wifi { + wifi_host_wake_l: wifi-host-wake-l { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + leds { work_led_gpio: work_led-gpio { rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; @@ -646,6 +652,36 @@ status = "okay"; }; +&sdio0 { + /* WiFi & BT combo module Ampak AP6356S */ + bus-width = <4>; + cap-sdio-irq; + cap-sd-highspeed; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; + sd-uhs-sdr104; + + /* Power supply */ + vqmmc-supply = &vcc1v8_s3; /* IO line */ + vmmc-supply = &vcc_sdio; /* card's power */ + + status = "okay"; + + brcmf: wifi@1 { + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&gpio0>; + interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>; + interrupt-names = "host-wake"; + brcm,drive-strength = <5>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_l>; + }; +}; + &sdmmc { bus-width = <4>; cap-mmc-highspeed; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts index e0d64f862322..2dceeea29b83 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts @@ -131,7 +131,7 @@ status = "okay"; clock-frequency = <400000>; - sgtl5000: codec@0a { + sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; clocks = <&sgtl5000_clk>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dts new file mode 100644 index 000000000000..19f7732d728c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dts @@ -0,0 +1,680 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 T-Chip Intelligent Technology Co., Ltd + */ + +/dts-v1/; +#include <dt-bindings/pwm/pwm.h> +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + model = "Firefly ROC-RK3399-PC Board"; + compatible = "firefly,roc-rk3399-pc", "rockchip,rk3399"; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm0 0 25000 0>; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + 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_PB2 GPIO_ACTIVE_LOW>; + }; + + vcc_vbus_typec0: vcc-vbus-typec0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_vbus_typec0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + /* + * should be placed inside mp8859, but not until mp8859 has + * its own dt-binding. + */ + vcc12v_sys: mp8859-dcdc1 { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <&vcc_vbus_typec0>; + }; + + /* switched by pmic_sleep */ + vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_1v8>; + }; + + vcc3v3_sys: 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 = <&vcc12v_sys>; + }; + + /* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */ + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en &hub_rst>; + regulator-name = "vcc5v0_host"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_vbus_typec1: vcc-vbus-typec1 { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_vbus_typec1_en>; + regulator-name = "vcc_vbus_typec1"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_sys>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + vin-supply = <&vcc3v3_sys>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c3>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_cec>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc3v3_sys>; + vcc2-supply = <&vcc3v3_sys>; + vcc3-supply = <&vcc3v3_sys>; + vcc4-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc3v3_sys>; + vcc10-supply = <&vcc3v3_sys>; + vcc11-supply = <&vcc3v3_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc1v8_pmu>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + 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-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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_codec: LDO_REG1 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc1v8_hdmi: LDO_REG2 { + regulator-name = "vcc1v8_hdmi"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_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>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca0v9_hdmi: LDO_REG7 { + regulator-name = "vcca0v9_hdmi"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: vcc_lan: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel1_gpio>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel2_gpio>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc3v3_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + fusb1: usb-typec@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&fusb1_int>; + vbus-supply = <&vcc_vbus_typec1>; + status = "okay"; + }; +}; + +&i2c7 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + fusb0: usb-typec@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&fusb0_int>; + vbus-supply = <&vcc_vbus_typec0>; + status = "okay"; + }; +}; + +&i2s0 { + rockchip,playback-channels = <8>; + rockchip,capture-channels = <8>; + status = "okay"; +}; + +&i2s1 { + rockchip,playback-channels = <2>; + rockchip,capture-channels = <2>; + status = "okay"; +}; + +&i2s2 { + status = "okay"; +}; + +&io_domains { + audio-supply = <&vcca1v8_codec>; + bt656-supply = <&vcc_3v0>; + gpio1830-supply = <&vcc_3v0>; + sdmmc-supply = <&vcc_sdio>; + status = "okay"; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + lcd-panel { + lcd_panel_reset: lcd-panel-reset { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pmic { + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + hub_rst: hub-rst { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_output_high>; + }; + }; + + usb-typec { + vcc_vbus_typec1_en: vcc-vbus-typec1-en { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + fusb30x { + fusb0_int: fusb0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + fusb1_int: fusb1-int { + rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca1v8_s3>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; + + u2phy0_otg: otg-port { + phy-supply = <&vcc_vbus_typec0>; + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + status = "okay"; + + u2phy1_otg: otg-port { + phy-supply = <&vcc_vbus_typec1>; + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; + dr_mode = "host"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts new file mode 100644 index 000000000000..3c3308daec98 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Linaro Ltd. + */ + +/dts-v1/; +#include "rk3399-rock960.dtsi" + +/ { + model = "96boards Rock960"; + compatible = "vamrs,rock960", "rockchip,rk3399"; + + chosen { + stdout-path = "serial2:1500000n8"; + }; +}; + +&pcie0 { + ep-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; +}; + +&pinctrl { + pcie { + pcie_drv: pcie-drv { + rockchip,pins = + <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb2 { + host_vbus_drv: host-vbus-drv { + rockchip,pins = + <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&usbdrd_dwc3_0 { + dr_mode = "otg"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "host"; +}; + +&vcc3v3_pcie { + gpio = <&gpio2 5 GPIO_ACTIVE_HIGH>; +}; + +&vcc5v0_host { + gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi new file mode 100644 index 000000000000..6c8c4ab044aa --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Collabora Ltd. + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (c) 2018 Linaro Ltd. + */ + +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + vcc1v8_s0: vcc1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s0"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc3v3_pcie: vcc3v3-pcie-regulator { + compatible = "regulator-fixed"; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_drv>; + regulator-boot-on; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc3v3_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 0>; + regulator-name = "vdd_log"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; + +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&emmc_phy { + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c3>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_cec>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + status = "okay"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + 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>; + }; + }; + + vcca1v8_hdmi: LDO_REG2 { + regulator-name = "vcca1v8_hdmi"; + 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>; + }; + }; + + vcca_1v8: LDO_REG3 { + regulator-name = "vcca_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>; + }; + }; + + vcc_sd: LDO_REG4 { + regulator-name = "vcc_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>; + }; + }; + + vcc3v0_sd: LDO_REG5 { + regulator-name = "vcc3v0_sd"; + 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>; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca0v9_hdmi: LDO_REG7 { + regulator-name = "vcca0v9_hdmi"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vcc_3v0: LDO_REG8 { + 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_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c4 { + status = "okay"; +}; + +&io_domains { + bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */ + audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */ + sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ + gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pcie0 { + num-lanes = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqn_cpm>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_1v8>; + status = "okay"; +}; + +&pinctrl { + sdmmc { + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = + <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = + <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>, + <4 9 RK_FUNC_1 &pcfg_pull_up_8ma>, + <4 10 RK_FUNC_1 &pcfg_pull_up_8ma>, + <4 11 RK_FUNC_1 &pcfg_pull_up_8ma>; + }; + + sdmmc_clk: sdmmc-clk { + rockchip,pins = + <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = + <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = + <1 21 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vsel1_gpio: vsel1-gpio { + rockchip,pins = + <1 17 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = + <1 14 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + +&pwm2 { + status = "okay"; +}; + +&pwm3 { + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + clock-frequency = <100000000>; + clock-freq-min-max = <100000 100000000>; + cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + disable-wp; + sd-uhs-sdr104; + vqmmc-supply = <&vcc_sd>; + card-detect-delay = <800>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy0_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy1_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts new file mode 100644 index 000000000000..1d35f5406b5e --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts @@ -0,0 +1,692 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (c) 2018 Akash Gajjar <Akash_Gajjar@mentor.com> + */ + +/dts-v1/; +#include <dt-bindings/input/linux-event-codes.h> +#include <dt-bindings/pwm/pwm.h> +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + model = "Pine64 RockPro64"; + compatible = "pine64,rockpro64", "rockchip,rk3399"; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + dc_12v: dc-12v { + compatible = "regulator-fixed"; + regulator-name = "dc_12v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-names = "default"; + pinctrl-0 = <&pwrbtn>; + + power { + debounce-interval = <100>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO Key Power"; + linux,code = <KEY_POWER>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>; + + work-led { + label = "work"; + default-state = "on"; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + diy-led { + label = "diy"; + default-state = "off"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + 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_PB2 GPIO_ACTIVE_LOW>; + }; + + /* switched by pmic_sleep */ + vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_1v8>; + }; + + vcc3v3_pcie: vcc3v3-pcie-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pwr_en>; + regulator-name = "vcc3v3_pcie"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&dc_12v>; + }; + + vcc3v3_sys: 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 = <&vcc_sys>; + }; + + /* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */ + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-name = "vcc5v0_host"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc5v0_typec: vcc5v0-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec_en>; + regulator-name = "vcc5v0_typec"; + regulator-always-on; + vin-supply = <&vcc_sys>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + vin-supply = <&vcc_sys>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio1>; + interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + vcc7-supply = <&vcc_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcc1v8_pmu>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + 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-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + 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>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc2v8_dvp: LDO_REG2 { + regulator-name = "vcc2v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc1v8_pmu: LDO_REG3 { + regulator-name = "vcc1v8_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>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: vcc_lan: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <0>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + fusb0: typec-portc@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = <RK_PA2 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&fusb0_int>; + vbus-supply = <&vcc5v0_typec>; + status = "okay"; + }; +}; + +&i2s0 { + rockchip,playback-channels = <8>; + rockchip,capture-channels = <8>; + status = "okay"; +}; + +&i2s1 { + rockchip,playback-channels = <2>; + rockchip,capture-channels = <2>; + status = "okay"; +}; + +&i2s2 { + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_dvp>; + audio-supply = <&vcca1v8_codec>; + sdmmc-supply = <&vcc_sdio>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + buttons { + pwrbtn: pwrbtn { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + fusb302x { + fusb0_int: fusb0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + work_led_gpio: work_led-gpio { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + diy_led_gpio: diy_led-gpio { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lcd-panel { + lcd_panel_reset: lcd-panel-reset { + rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pcie { + pcie_pwr_en: pcie-pwr-en { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + vcc5v0_typec_en: vcc5v0_typec_en { + rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca1v8_s3>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "otg"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; + dr_mode = "host"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi index 36b60791c156..5421e23760c3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi @@ -93,6 +93,19 @@ vin-supply = <&vcc_1v8>; }; + vcc3v0_sd: vcc3v0-sd { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_pwr_h>; + regulator-always-on; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + regulator-name = "vcc3v0_sd"; + vin-supply = <&vcc3v3_sys>; + }; + vcc3v3_sys: vcc3v3-sys { compatible = "regulator-fixed"; regulator-name = "vcc3v3_sys"; @@ -103,20 +116,10 @@ vin-supply = <&vcc_sys>; }; - vcc_sys: vcc-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&dc_12v>; - }; - vcc5v0_host: vcc5v0-host-regulator { compatible = "regulator-fixed"; enable-active-high; - gpio = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>; + gpio = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&vcc5v0_host_en>; regulator-name = "vcc5v0_host"; @@ -124,6 +127,26 @@ vin-supply = <&vcc_sys>; }; + vcc5v0_typec0: vcc5v0-typec0-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vcc5v0_typec0"; + vin-supply = <&vcc_sys>; + }; + + vcc_sys: vcc-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; + vdd_log: vdd-log { compatible = "pwm-regulator"; pwms = <&pwm2 0 25000 1>; @@ -208,7 +231,7 @@ #clock-cells = <1>; clock-output-names = "xin32k", "rk808-clkout2"; pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l &pmic_dvs2>; + pinctrl-0 = <&pmic_int_l>; rockchip,system-power-controller; wakeup-source; @@ -310,7 +333,7 @@ regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; @@ -455,11 +478,6 @@ <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; - pmic_dvs2: pmic-dvs2 { - rockchip,pins = - <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; - }; - vsel1_gpio: vsel1-gpio { rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; }; @@ -469,11 +487,22 @@ }; }; + sd { + sdmmc0_pwr_h: sdmmc0-pwr-h { + rockchip,pins = + <RK_GPIO0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb2 { vcc5v0_host_en: vcc5v0-host-en { rockchip,pins = <4 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; }; + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = + <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; }; }; @@ -499,6 +528,7 @@ }; &sdmmc { + broken-cd; bus-width = <4>; cap-mmc-highspeed; cap-sd-highspeed; @@ -507,6 +537,7 @@ max-frequency = <150000000>; pinctrl-names = "default"; pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + vmmc-supply = <&vcc3v0_sd>; vqmmc-supply = <&vcc_sdio>; status = "okay"; }; @@ -531,6 +562,7 @@ status = "okay"; u2phy0_otg: otg-port { + phy-supply = <&vcc5v0_typec0>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index c88e603396f6..99e7f65c1779 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -74,6 +74,7 @@ clocks = <&cru ARMCLKL>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu_l1: cpu@1 { @@ -84,6 +85,7 @@ clocks = <&cru ARMCLKL>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu_l2: cpu@2 { @@ -94,6 +96,7 @@ clocks = <&cru ARMCLKL>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu_l3: cpu@3 { @@ -104,6 +107,7 @@ clocks = <&cru ARMCLKL>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu_b0: cpu@100 { @@ -114,6 +118,7 @@ clocks = <&cru ARMCLKB>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <436>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; }; cpu_b1: cpu@101 { @@ -124,6 +129,29 @@ clocks = <&cru ARMCLKB>; #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <436>; + cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + }; + + 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>; + }; }; }; @@ -1720,6 +1748,8 @@ resets = <&cru SRST_P_MIPI_DSI0>; reset-names = "apb"; rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; ports { @@ -1754,6 +1784,8 @@ resets = <&cru SRST_P_MIPI_DSI1>; reset-names = "apb"; rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; ports { diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi index d63b56e944de..31ba52b14e99 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi @@ -116,6 +116,28 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi1: spi@54006100 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006100 0x100>; + interrupts = <0 216 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -432,6 +454,8 @@ <&mio_clk 12>; resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>; + phy-names = "usb"; + phys = <&usb_phy0>; has-transaction-translator; }; @@ -446,6 +470,8 @@ <&mio_clk 13>; resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>; + phy-names = "usb"; + phys = <&usb_phy1>; has-transaction-translator; }; @@ -460,6 +486,8 @@ <&mio_clk 14>; resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 10>, <&mio_rst 14>; + phy-names = "usb"; + phys = <&usb_phy2>; has-transaction-translator; }; @@ -488,6 +516,27 @@ pinctrl: pinctrl { compatible = "socionext,uniphier-ld11-pinctrl"; }; + + usb-phy { + compatible = "socionext,uniphier-ld11-usb2-phy"; + #address-cells = <1>; + #size-cells = <0>; + + usb_phy0: phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + usb_phy1: phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + + usb_phy2: phy@2 { + reg = <2>; + #phy-cells = <0>; + }; + }; }; soc-glue@5f900000 { @@ -571,7 +620,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20-global.dts b/arch/arm64/boot/dts/socionext/uniphier-ld20-global.dts index 1a5e7c24b901..d7ae28afef7d 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20-global.dts +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20-global.dts @@ -148,3 +148,7 @@ &nand { status = "okay"; }; + +&usb { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts b/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts index 440c2e6a638b..406244a5c8e8 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts @@ -75,3 +75,7 @@ drive-strength = <9>; }; }; + +&usb { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index caf112629caa..d7e2d8969601 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -224,6 +224,50 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi1: spi@54006100 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006100 0x100>; + interrupts = <0 216 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi2: spi@54006200 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006200 0x100>; + interrupts = <0 229 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi3: spi@54006300 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006300 0x100>; + interrupts = <0 230 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi3>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -528,6 +572,20 @@ cdns,phy-dll-delay-sdclk-hsmmc = <21>; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v3.1.1"; + status = "disabled"; + reg = <0x5a400000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd>; + clocks = <&sd_clk 0>; + reset-names = "host"; + resets = <&sd_rst 0>; + bus-width = <4>; + cap-sd-highspeed; + }; + soc_glue: soc-glue@5f800000 { compatible = "socionext,uniphier-ld20-soc-glue", "simple-mfd", "syscon"; @@ -553,6 +611,50 @@ efuse@200 { compatible = "socionext,uniphier-efuse"; reg = <0x200 0x68>; + #address-cells = <1>; + #size-cells = <1>; + + /* USB cells */ + usb_rterm0: trim@54,4 { + reg = <0x54 1>; + bits = <4 2>; + }; + usb_rterm1: trim@55,4 { + reg = <0x55 1>; + bits = <4 2>; + }; + usb_rterm2: trim@58,4 { + reg = <0x58 1>; + bits = <4 2>; + }; + usb_rterm3: trim@59,4 { + reg = <0x59 1>; + bits = <4 2>; + }; + usb_sel_t0: trim@54,0 { + reg = <0x54 1>; + bits = <0 4>; + }; + usb_sel_t1: trim@55,0 { + reg = <0x55 1>; + bits = <0 4>; + }; + usb_sel_t2: trim@58,0 { + reg = <0x58 1>; + bits = <0 4>; + }; + usb_sel_t3: trim@59,0 { + reg = <0x59 1>; + bits = <0 4>; + }; + usb_hs_i0: trim@56,0 { + reg = <0x56 1>; + bits = <0 4>; + }; + usb_hs_i2: trim@5a,0 { + reg = <0x5a 1>; + bits = <0 4>; + }; }; }; @@ -620,6 +722,156 @@ }; }; + usb: usb@65a00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; + interrupt-names = "host"; + interrupts = <0 134 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb1>, + <&pinctrl_usb2>, <&pinctrl_usb3>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 14>, <&sys_clk 14>, <&sys_clk 14>; + resets = <&usb_rst 15>; + phys = <&usb_hsphy0>, <&usb_hsphy1>, + <&usb_hsphy2>, <&usb_hsphy3>, + <&usb_ssphy0>, <&usb_ssphy1>; + dr_mode = "host"; + }; + + usb-glue@65b00000 { + compatible = "socionext,uniphier-ld20-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65b00000 0x400>; + + usb_rst: reset@0 { + compatible = "socionext,uniphier-ld20-usb3-reset"; + reg = <0x0 0x4>; + #reset-cells = <1>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb_vbus0: regulator@100 { + compatible = "socionext,uniphier-ld20-usb3-regulator"; + reg = <0x100 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb_vbus1: regulator@110 { + compatible = "socionext,uniphier-ld20-usb3-regulator"; + reg = <0x110 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb_vbus2: regulator@120 { + compatible = "socionext,uniphier-ld20-usb3-regulator"; + reg = <0x120 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb_vbus3: regulator@130 { + compatible = "socionext,uniphier-ld20-usb3-regulator"; + reg = <0x130 0x10>; + clock-names = "link"; + clocks = <&sys_clk 14>; + reset-names = "link"; + resets = <&sys_rst 14>; + }; + + usb_hsphy0: hs-phy@200 { + compatible = "socionext,uniphier-ld20-usb3-hsphy"; + reg = <0x200 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 16>; + vbus-supply = <&usb_vbus0>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm0>, <&usb_sel_t0>, + <&usb_hs_i0>; + }; + + usb_hsphy1: hs-phy@210 { + compatible = "socionext,uniphier-ld20-usb3-hsphy"; + reg = <0x210 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 16>; + vbus-supply = <&usb_vbus1>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm1>, <&usb_sel_t1>, + <&usb_hs_i0>; + }; + + usb_hsphy2: hs-phy@220 { + compatible = "socionext,uniphier-ld20-usb3-hsphy"; + reg = <0x220 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 17>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 17>; + vbus-supply = <&usb_vbus2>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm2>, <&usb_sel_t2>, + <&usb_hs_i2>; + }; + + usb_hsphy3: hs-phy@230 { + compatible = "socionext,uniphier-ld20-usb3-hsphy"; + reg = <0x230 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 17>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 17>; + vbus-supply = <&usb_vbus3>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm3>, <&usb_sel_t3>, + <&usb_hs_i2>; + }; + + usb_ssphy0: ss-phy@300 { + compatible = "socionext,uniphier-ld20-usb3-ssphy"; + reg = <0x300 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 18>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 18>; + vbus-supply = <&usb_vbus0>; + }; + + usb_ssphy1: ss-phy@310 { + compatible = "socionext,uniphier-ld20-usb3-ssphy"; + reg = <0x310 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 14>, <&sys_clk 19>; + reset-names = "link", "phy"; + resets = <&sys_rst 14>, <&sys_rst 19>; + vbus-supply = <&usb_vbus1>; + }; + }; + nand: nand@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; @@ -628,7 +880,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref.dts b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref.dts index c1bb607bd211..a41f7cac952a 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref.dts +++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref.dts @@ -75,6 +75,10 @@ status = "okay"; }; +&sd { + status = "okay"; +}; + ð0 { status = "okay"; phy-handle = <ðphy0>; @@ -100,3 +104,11 @@ &nand { status = "okay"; }; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi index 2a4cf427f5d3..4f57c9e9d7a8 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi @@ -144,6 +144,28 @@ #size-cells = <1>; ranges = <0 0 0 0xffffffff>; + spi0: spi@54006000 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006000 0x100>; + interrupts = <0 39 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + + spi1: spi@54006100 { + compatible = "socionext,uniphier-scssi"; + status = "disabled"; + reg = <0x54006100 0x100>; + interrupts = <0 216 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>; + clocks = <&peri_clk 11>; + resets = <&peri_rst 11>; + }; + serial0: serial@54006800 { compatible = "socionext,uniphier-uart"; status = "disabled"; @@ -341,6 +363,24 @@ cdns,phy-dll-delay-sdclk-hsmmc = <21>; }; + sd: sdhc@5a400000 { + compatible = "socionext,uniphier-sd-v3.1.1"; + status = "disabled"; + reg = <0x5a400000 0x800>; + interrupts = <0 76 4>; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&pinctrl_sd>; + pinctrl-1 = <&pinctrl_sd_uhs>; + clocks = <&sd_clk 0>; + reset-names = "host"; + resets = <&sd_rst 0>; + bus-width = <4>; + cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + }; + soc_glue: soc-glue@5f800000 { compatible = "socionext,uniphier-pxs3-soc-glue", "simple-mfd", "syscon"; @@ -366,6 +406,50 @@ efuse@200 { compatible = "socionext,uniphier-efuse"; reg = <0x200 0x68>; + #address-cells = <1>; + #size-cells = <1>; + + /* USB cells */ + usb_rterm0: trim@54,4 { + reg = <0x54 1>; + bits = <4 2>; + }; + usb_rterm1: trim@55,4 { + reg = <0x55 1>; + bits = <4 2>; + }; + usb_rterm2: trim@58,4 { + reg = <0x58 1>; + bits = <4 2>; + }; + usb_rterm3: trim@59,4 { + reg = <0x59 1>; + bits = <4 2>; + }; + usb_sel_t0: trim@54,0 { + reg = <0x54 1>; + bits = <0 4>; + }; + usb_sel_t1: trim@55,0 { + reg = <0x55 1>; + bits = <0 4>; + }; + usb_sel_t2: trim@58,0 { + reg = <0x58 1>; + bits = <0 4>; + }; + usb_sel_t3: trim@59,0 { + reg = <0x59 1>; + bits = <0 4>; + }; + usb_hs_i0: trim@56,0 { + reg = <0x56 1>; + bits = <0 4>; + }; + usb_hs_i2: trim@5a,0 { + reg = <0x5a 1>; + bits = <0 4>; + }; }; }; @@ -447,6 +531,202 @@ }; }; + usb0: usb@65a00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65a00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 134 4>, <0 135 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 12>, <&sys_clk 12>, <&sys_clk 12>; + resets = <&usb0_rst 15>; + phys = <&usb0_hsphy0>, <&usb0_hsphy1>, + <&usb0_ssphy0>, <&usb0_ssphy1>; + dr_mode = "host"; + }; + + usb-glue@65b00000 { + compatible = "socionext,uniphier-pxs3-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65b00000 0x400>; + + usb0_rst: reset@0 { + compatible = "socionext,uniphier-pxs3-usb3-reset"; + reg = <0x0 0x4>; + #reset-cells = <1>; + clock-names = "link"; + clocks = <&sys_clk 12>; + reset-names = "link"; + resets = <&sys_rst 12>; + }; + + usb0_vbus0: regulator@100 { + compatible = "socionext,uniphier-pxs3-usb3-regulator"; + reg = <0x100 0x10>; + clock-names = "link"; + clocks = <&sys_clk 12>; + reset-names = "link"; + resets = <&sys_rst 12>; + }; + + usb0_vbus1: regulator@110 { + compatible = "socionext,uniphier-pxs3-usb3-regulator"; + reg = <0x110 0x10>; + clock-names = "link"; + clocks = <&sys_clk 12>; + reset-names = "link"; + resets = <&sys_rst 12>; + }; + + usb0_hsphy0: hs-phy@200 { + compatible = "socionext,uniphier-pxs3-usb3-hsphy"; + reg = <0x200 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 12>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 12>, <&sys_rst 16>; + vbus-supply = <&usb0_vbus0>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm0>, <&usb_sel_t0>, + <&usb_hs_i0>; + }; + + usb0_hsphy1: hs-phy@210 { + compatible = "socionext,uniphier-pxs3-usb3-hsphy"; + reg = <0x210 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 12>, <&sys_clk 16>; + reset-names = "link", "phy"; + resets = <&sys_rst 12>, <&sys_rst 16>; + vbus-supply = <&usb0_vbus1>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm1>, <&usb_sel_t1>, + <&usb_hs_i0>; + }; + + usb0_ssphy0: ss-phy@300 { + compatible = "socionext,uniphier-pxs3-usb3-ssphy"; + reg = <0x300 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 12>, <&sys_clk 17>; + reset-names = "link", "phy"; + resets = <&sys_rst 12>, <&sys_rst 17>; + vbus-supply = <&usb0_vbus0>; + }; + + usb0_ssphy1: ss-phy@310 { + compatible = "socionext,uniphier-pxs3-usb3-ssphy"; + reg = <0x310 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy"; + clocks = <&sys_clk 12>, <&sys_clk 18>; + reset-names = "link", "phy"; + resets = <&sys_rst 12>, <&sys_rst 18>; + vbus-supply = <&usb0_vbus1>; + }; + }; + + usb1: usb@65c00000 { + compatible = "socionext,uniphier-dwc3", "snps,dwc3"; + status = "disabled"; + reg = <0x65c00000 0xcd00>; + interrupt-names = "host", "peripheral"; + interrupts = <0 137 4>, <0 138 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>; + clock-names = "ref", "bus_early", "suspend"; + clocks = <&sys_clk 13>, <&sys_clk 13>, <&sys_clk 13>; + resets = <&usb1_rst 15>; + phys = <&usb1_hsphy0>, <&usb1_hsphy1>, + <&usb1_ssphy0>; + dr_mode = "host"; + }; + + usb-glue@65d00000 { + compatible = "socionext,uniphier-pxs3-dwc3-glue", + "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x65d00000 0x400>; + + usb1_rst: reset@0 { + compatible = "socionext,uniphier-pxs3-usb3-reset"; + reg = <0x0 0x4>; + #reset-cells = <1>; + clock-names = "link"; + clocks = <&sys_clk 13>; + reset-names = "link"; + resets = <&sys_rst 13>; + }; + + usb1_vbus0: regulator@100 { + compatible = "socionext,uniphier-pxs3-usb3-regulator"; + reg = <0x100 0x10>; + clock-names = "link"; + clocks = <&sys_clk 13>; + reset-names = "link"; + resets = <&sys_rst 13>; + }; + + usb1_vbus1: regulator@110 { + compatible = "socionext,uniphier-pxs3-usb3-regulator"; + reg = <0x110 0x10>; + clock-names = "link"; + clocks = <&sys_clk 13>; + reset-names = "link"; + resets = <&sys_rst 13>; + }; + + usb1_hsphy0: hs-phy@200 { + compatible = "socionext,uniphier-pxs3-usb3-hsphy"; + reg = <0x200 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy", "phy-ext"; + clocks = <&sys_clk 13>, <&sys_clk 20>, + <&sys_clk 14>; + reset-names = "link", "phy"; + resets = <&sys_rst 13>, <&sys_rst 20>; + vbus-supply = <&usb1_vbus0>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm2>, <&usb_sel_t2>, + <&usb_hs_i2>; + }; + + usb1_hsphy1: hs-phy@210 { + compatible = "socionext,uniphier-pxs3-usb3-hsphy"; + reg = <0x210 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy", "phy-ext"; + clocks = <&sys_clk 13>, <&sys_clk 20>, + <&sys_clk 14>; + reset-names = "link", "phy"; + resets = <&sys_rst 13>, <&sys_rst 20>; + vbus-supply = <&usb1_vbus1>; + nvmem-cell-names = "rterm", "sel_t", "hs_i"; + nvmem-cells = <&usb_rterm3>, <&usb_sel_t3>, + <&usb_hs_i2>; + }; + + usb1_ssphy0: ss-phy@300 { + compatible = "socionext,uniphier-pxs3-usb3-ssphy"; + reg = <0x300 0x10>; + #phy-cells = <0>; + clock-names = "link", "phy", "phy-ext"; + clocks = <&sys_clk 13>, <&sys_clk 21>, + <&sys_clk 14>; + reset-names = "link", "phy"; + resets = <&sys_rst 13>, <&sys_rst 21>; + vbus-supply = <&usb1_vbus0>; + }; + }; + nand: nand@68000000 { compatible = "socionext,uniphier-denali-nand-v5b"; status = "disabled"; @@ -455,7 +735,8 @@ interrupts = <0 65 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nand>; - clocks = <&sys_clk 2>; + clock-names = "nand", "nand_x", "ecc"; + clocks = <&sys_clk 2>, <&sys_clk 3>, <&sys_clk 3>; resets = <&sys_rst 2>; }; }; diff --git a/arch/arm64/boot/dts/synaptics/as370.dtsi b/arch/arm64/boot/dts/synaptics/as370.dtsi new file mode 100644 index 000000000000..7331acf3874e --- /dev/null +++ b/arch/arm64/boot/dts/synaptics/as370.dtsi @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2018 Synaptics Incorporated + * + * Author: Jisheng Zhang <jszhang@kernel.org> + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "syna,as370"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x0>; + enable-method = "psci"; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_SLEEP_0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x1>; + enable-method = "psci"; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_SLEEP_0>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x2>; + enable-method = "psci"; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_SLEEP_0>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0x3>; + enable-method = "psci"; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_SLEEP_0>; + }; + + l2: cache { + compatible = "cache"; + }; + + idle-states { + entry-method = "psci"; + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <75>; + exit-latency-us = <155>; + min-residency-us = <1000>; + }; + }; + }; + + osc: osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <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>; + interrupt-affinity = <&cpu0>, + <&cpu1>, + <&cpu2>, + <&cpu3>; + }; + + 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)>; + }; + + soc@f7000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0xf7000000 0x1000000>; + + gic: interrupt-controller@901000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x901000 0x1000>, + <0x902000 0x2000>, + <0x904000 0x2000>, + <0x906000 0x2000>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + apb@e80000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xe80000 0x10000>; + + uart0: serial@c00 { + compatible = "snps,dw-apb-uart"; + reg = <0xc00 0x100>; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc>; + reg-shift = <2>; + status = "disabled"; + }; + + gpio0: gpio@1800 { + compatible = "snps,dw-apb-gpio"; + reg = <0x1800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-port@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@2000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x2000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + + portb: gpio-port@1 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi index 2409344df4fa..adcd6341e40c 100644 --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi @@ -8,13 +8,13 @@ &cbass_main { gic500: interrupt-controller@1800000 { compatible = "arm,gic-v3"; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; ranges; #interrupt-cells = <3>; interrupt-controller; - reg = <0x01800000 0x10000>, /* GICD */ - <0x01880000 0x90000>; /* GICR */ + reg = <0x00 0x01800000 0x00 0x10000>, /* GICD */ + <0x00 0x01880000 0x00 0x90000>; /* GICR */ /* * vcpumntirq: * virtual CPU interface maintenance interrupt @@ -23,9 +23,50 @@ gic_its: gic-its@18200000 { compatible = "arm,gic-v3-its"; - reg = <0x01820000 0x10000>; + reg = <0x00 0x01820000 0x00 0x10000>; msi-controller; #msi-cells = <1>; }; }; + + secure_proxy_main: mailbox@32c00000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x00 0x32c00000 0x00 0x100000>, + <0x00 0x32400000 0x00 0x100000>, + <0x00 0x32800000 0x00 0x100000>; + interrupt-names = "rx_011"; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + }; + + main_uart0: serial@2800000 { + compatible = "ti,am654-uart"; + reg = <0x00 0x02800000 0x00 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <48000000>; + current-speed = <115200>; + }; + + main_uart1: serial@2810000 { + compatible = "ti,am654-uart"; + reg = <0x00 0x02810000 0x00 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <48000000>; + current-speed = <115200>; + }; + + main_uart2: serial@2820000 { + compatible = "ti,am654-uart"; + reg = <0x00 0x02820000 0x00 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <48000000>; + current-speed = <115200>; + }; }; diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi new file mode 100644 index 000000000000..8c611d16df44 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for AM6 SoC Family MCU Domain peripherals + * + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +&cbass_mcu { + mcu_uart0: serial@40a00000 { + compatible = "ti,am654-uart"; + reg = <0x00 0x40a00000 0x00 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <96000000>; + current-speed = <115200>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi new file mode 100644 index 000000000000..affc3c309353 --- /dev/null +++ b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for AM6 SoC Family Wakeup Domain peripherals + * + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +&cbass_wakeup { + dmsc: dmsc { + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mbox-names = "rx", "tx"; + + mboxes= <&secure_proxy_main 11>, + <&secure_proxy_main 13>; + + k3_pds: power-controller { + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <1>; + }; + + k3_clks: clocks { + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; + }; + + k3_reset: reset-controller { + compatible = "ti,sci-reset"; + #reset-cells = <2>; + }; + }; + + wkup_uart0: serial@42300000 { + compatible = "ti,am654-uart"; + reg = <0x00 0x42300000 0x00 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 697 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <48000000>; + current-speed = <115200>; + }; +}; diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi index cede1fa0983c..3d4bf369d030 100644 --- a/arch/arm64/boot/dts/ti/k3-am65.dtsi +++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi @@ -16,6 +16,14 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + serial0 = &wkup_uart0; + serial1 = &mcu_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; + serial4 = &main_uart2; + }; + chosen { }; firmware { @@ -46,38 +54,38 @@ cbass_main: interconnect@100000 { compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x00100000 0x00 0x00100000 0x00020000>, /* ctrl mmr */ - <0x00600000 0x00 0x00600000 0x00001100>, /* GPIO */ - <0x00900000 0x00 0x00900000 0x00012000>, /* serdes */ - <0x01000000 0x00 0x01000000 0x0af02400>, /* Most peripherals */ - <0x30800000 0x00 0x30800000 0x0bc00000>, /* MAIN NAVSS */ + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */ + <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */ + <0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */ + <0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */ + <0x00 0x30800000 0x00 0x30800000 0x00 0x0bc00000>, /* MAIN NAVSS */ /* MCUSS Range */ - <0x28380000 0x00 0x28380000 0x03880000>, - <0x40200000 0x00 0x40200000 0x00900100>, - <0x42040000 0x00 0x42040000 0x03ac2400>, - <0x45100000 0x00 0x45100000 0x00c24000>, - <0x46000000 0x00 0x46000000 0x00200000>, - <0x47000000 0x00 0x47000000 0x00068400>; + <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, + <0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>, + <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, + <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, + <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, + <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>; cbass_mcu: interconnect@28380000 { compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x28380000 0x28380000 0x03880000>, /* MCU NAVSS*/ - <0x40200000 0x40200000 0x00900100>, /* First peripheral window */ - <0x42040000 0x42040000 0x03ac2400>, /* WKUP */ - <0x45100000 0x45100000 0x00c24000>, /* MMRs, remaining NAVSS */ - <0x46000000 0x46000000 0x00200000>, /* CPSW */ - <0x47000000 0x47000000 0x00068400>; /* OSPI space 1 */ + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/ + <0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>, /* First peripheral window */ + <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP */ + <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 */ cbass_wakeup: interconnect@42040000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; /* WKUP Basic peripherals */ - ranges = <0x42040000 0x42040000 0x03ac2400>; + ranges = <0x42040000 0x00 0x42040000 0x03ac2400>; }; }; }; @@ -85,3 +93,5 @@ /* Now include the peripherals for each bus segments */ #include "k3-am65-main.dtsi" +#include "k3-am65-mcu.dtsi" +#include "k3-am65-wakeup.dtsi" diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts index af6956fdc13f..e146ac2ad781 100644 --- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts +++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts @@ -34,3 +34,8 @@ }; }; }; + +&wkup_uart0 { + /* Wakeup UART is used by System firmware */ + status = "disabled"; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index db8d364f8476..3cb995606e60 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -50,6 +50,8 @@ CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SEATTLE=y CONFIG_ARCH_SYNQUACER=y CONFIG_ARCH_RENESAS=y +CONFIG_ARCH_R8A774A1=y +CONFIG_ARCH_R8A774C0=y CONFIG_ARCH_R8A7795=y CONFIG_ARCH_R8A7796=y CONFIG_ARCH_R8A77965=y @@ -68,6 +70,7 @@ CONFIG_ARCH_XGENE=y CONFIG_ARCH_ZX=y CONFIG_ARCH_ZYNQMP=y CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y CONFIG_PCI_IOV=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_ACPI=y @@ -115,6 +118,7 @@ CONFIG_ARM_ARMADA_37XX_CPUFREQ=y CONFIG_ARM_BIG_LITTLE_CPUFREQ=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_TEGRA186_CPUFREQ=y +CONFIG_TI_SCI_PROTOCOL=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -150,6 +154,9 @@ CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y CONFIG_VLAN_8021Q_MVRP=y +CONFIG_QRTR=m +CONFIG_QRTR_SMD=m +CONFIG_QRTR_TUN=m CONFIG_BPF_JIT=y CONFIG_BT=m CONFIG_BT_HIDP=m @@ -222,6 +229,9 @@ CONFIG_THUNDER_NIC_PF=y CONFIG_HIX5HD2_GMAC=y CONFIG_HNS_DSAF=y CONFIG_HNS_ENET=y +CONFIG_HNS3=y +CONFIG_HNS3_HCLGE=y +CONFIG_HNS3_ENET=y CONFIG_E1000E=y CONFIG_IGB=y CONFIG_IGBVF=y @@ -279,6 +289,7 @@ CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_OMAP=y CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_8250_UNIPHIER=y CONFIG_SERIAL_OF_PLATFORM=y @@ -434,6 +445,7 @@ CONFIG_DRM_EXYNOS_DSI=y CONFIG_DRM_EXYNOS_HDMI=y CONFIG_DRM_EXYNOS_MIC=y CONFIG_DRM_ROCKCHIP=m +CONFIG_DRM_SUN4I=m CONFIG_ROCKCHIP_ANALOGIX_DP=y CONFIG_ROCKCHIP_CDN_DP=y CONFIG_ROCKCHIP_DW_HDMI=y @@ -520,6 +532,7 @@ CONFIG_MMC_MESON_GX=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SPI=y CONFIG_MMC_SDHI=y +CONFIG_MMC_UNIPHIER=y CONFIG_MMC_DW=y CONFIG_MMC_DW_EXYNOS=y CONFIG_MMC_DW_HI3798CV200=y @@ -577,6 +590,7 @@ CONFIG_COMMON_CLK_CS2000_CP=y CONFIG_COMMON_CLK_S2MPS11=y CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_PWM=y +CONFIG_TI_SCI_CLK=y CONFIG_COMMON_CLK_QCOM=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_IPQ_GCC_8074=y @@ -588,6 +602,7 @@ CONFIG_HWSPINLOCK_QCOM=y CONFIG_ARM_MHU=y CONFIG_PLATFORM_MHU=y CONFIG_BCM2835_MBOX=y +CONFIG_TI_MESSAGE_MANAGER=y CONFIG_QCOM_APCS_IPC=y CONFIG_ROCKCHIP_IOMMU=y CONFIG_TEGRA_IOMMU_SMMU=y @@ -608,6 +623,7 @@ CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_ARCH_TEGRA_194_SOC=y CONFIG_ARCH_K3_AM6_SOC=y CONFIG_SOC_TI=y +CONFIG_TI_SCI_PM_DOMAINS=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_EXTCON_USB_GPIO=y CONFIG_EXTCON_USBC_CROS_EC=y @@ -627,6 +643,7 @@ CONFIG_PWM_RCAR=m CONFIG_PWM_ROCKCHIP=y CONFIG_PWM_SAMSUNG=y CONFIG_PWM_TEGRA=m +CONFIG_RESET_TI_SCI=y CONFIG_PHY_XGENE=y CONFIG_PHY_SUN4I_USB=y CONFIG_PHY_HI6220_USB=y @@ -638,10 +655,13 @@ CONFIG_PHY_QCOM_USB_HS=y CONFIG_PHY_RCAR_GEN3_USB2=y CONFIG_PHY_RCAR_GEN3_USB3=m CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_INNO_HDMI=m CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_PCIE=m CONFIG_PHY_ROCKCHIP_TYPEC=y CONFIG_PHY_TEGRA_XUSB=y +CONFIG_PHY_UNIPHIER_USB3=y +CONFIG_PHY_UNIPHIER_USB2=y CONFIG_HISI_PMU=y CONFIG_QCOM_L2_PMU=y CONFIG_QCOM_L3_PMU=y @@ -698,6 +718,7 @@ CONFIG_MEMTEST=y CONFIG_SECURITY=y CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=y CONFIG_ARM64_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA2_ARM64_CE=y @@ -706,7 +727,6 @@ CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m -CONFIG_CRYPTO_CRC32_ARM64_CE=m CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_CHACHA20_NEON=m diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index e3fdb0fd6f70..a5606823ed4d 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -66,11 +66,6 @@ config CRYPTO_CRCT10DIF_ARM64_CE depends on KERNEL_MODE_NEON && CRC_T10DIF select CRYPTO_HASH -config CRYPTO_CRC32_ARM64_CE - tristate "CRC32 and CRC32C digest algorithms using ARMv8 extensions" - depends on CRC32 - select CRYPTO_HASH - config CRYPTO_AES_ARM64 tristate "AES core cipher using scalar instructions" select CRYPTO_AES @@ -119,10 +114,4 @@ config CRYPTO_AES_ARM64_BS select CRYPTO_AES_ARM64 select CRYPTO_SIMD -config CRYPTO_SPECK_NEON - tristate "NEON accelerated Speck cipher algorithms" - depends on KERNEL_MODE_NEON - select CRYPTO_BLKCIPHER - select CRYPTO_SPECK - endif diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index bcafd016618e..f476fede09ba 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -32,9 +32,6 @@ ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM64_CE) += crct10dif-ce.o crct10dif-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o -obj-$(CONFIG_CRYPTO_CRC32_ARM64_CE) += crc32-ce.o -crc32-ce-y:= crc32-ce-core.o crc32-ce-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o aes-ce-cipher-y := aes-ce-core.o aes-ce-glue.o @@ -56,9 +53,6 @@ sha512-arm64-y := sha512-glue.o sha512-core.o obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o -obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o -speck-neon-y := speck-neon-core.o speck-neon-glue.o - obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o diff --git a/arch/arm64/crypto/aes-ce.S b/arch/arm64/crypto/aes-ce.S index 623e74ed1c67..143070510809 100644 --- a/arch/arm64/crypto/aes-ce.S +++ b/arch/arm64/crypto/aes-ce.S @@ -17,6 +17,11 @@ .arch armv8-a+crypto + xtsmask .req v16 + + .macro xts_reload_mask, tmp + .endm + /* preload all round keys */ .macro load_round_keys, rounds, rk cmp \rounds, #12 diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index adcb83eb683c..1e676625ef33 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -15,6 +15,7 @@ #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> #include <linux/module.h> #include <linux/cpufeature.h> #include <crypto/xts.h> @@ -31,6 +32,8 @@ #define aes_ecb_decrypt ce_aes_ecb_decrypt #define aes_cbc_encrypt ce_aes_cbc_encrypt #define aes_cbc_decrypt ce_aes_cbc_decrypt +#define aes_cbc_cts_encrypt ce_aes_cbc_cts_encrypt +#define aes_cbc_cts_decrypt ce_aes_cbc_cts_decrypt #define aes_ctr_encrypt ce_aes_ctr_encrypt #define aes_xts_encrypt ce_aes_xts_encrypt #define aes_xts_decrypt ce_aes_xts_decrypt @@ -45,6 +48,8 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); #define aes_ecb_decrypt neon_aes_ecb_decrypt #define aes_cbc_encrypt neon_aes_cbc_encrypt #define aes_cbc_decrypt neon_aes_cbc_decrypt +#define aes_cbc_cts_encrypt neon_aes_cbc_cts_encrypt +#define aes_cbc_cts_decrypt neon_aes_cbc_cts_decrypt #define aes_ctr_encrypt neon_aes_ctr_encrypt #define aes_xts_encrypt neon_aes_xts_encrypt #define aes_xts_decrypt neon_aes_xts_decrypt @@ -63,30 +68,41 @@ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_LICENSE("GPL v2"); /* defined in aes-modes.S */ -asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], +asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, int blocks); -asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], +asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, int blocks); -asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], +asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, int blocks, u8 iv[]); -asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], +asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, int blocks, u8 iv[]); -asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], +asmlinkage void aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[], + int rounds, int bytes, u8 const iv[]); +asmlinkage void aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[], + int rounds, int bytes, u8 const iv[]); + +asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], int rounds, int blocks, u8 ctr[]); -asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u8 const rk1[], - int rounds, int blocks, u8 const rk2[], u8 iv[], +asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u32 const rk1[], + int rounds, int blocks, u32 const rk2[], u8 iv[], int first); -asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], - int rounds, int blocks, u8 const rk2[], u8 iv[], +asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u32 const rk1[], + int rounds, int blocks, u32 const rk2[], u8 iv[], int first); asmlinkage void aes_mac_update(u8 const in[], u32 const rk[], int rounds, int blocks, u8 dg[], int enc_before, int enc_after); +struct cts_cbc_req_ctx { + struct scatterlist sg_src[2]; + struct scatterlist sg_dst[2]; + struct skcipher_request subreq; +}; + struct crypto_aes_xts_ctx { struct crypto_aes_ctx key1; struct crypto_aes_ctx __aligned(8) key2; @@ -142,7 +158,7 @@ static int ecb_encrypt(struct skcipher_request *req) while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { kernel_neon_begin(); aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key_enc, rounds, blocks); + ctx->key_enc, rounds, blocks); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -162,7 +178,7 @@ static int ecb_decrypt(struct skcipher_request *req) while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { kernel_neon_begin(); aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key_dec, rounds, blocks); + ctx->key_dec, rounds, blocks); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -182,7 +198,7 @@ static int cbc_encrypt(struct skcipher_request *req) while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { kernel_neon_begin(); aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key_enc, rounds, blocks, walk.iv); + ctx->key_enc, rounds, blocks, walk.iv); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -202,13 +218,149 @@ static int cbc_decrypt(struct skcipher_request *req) while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { kernel_neon_begin(); aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key_dec, rounds, blocks, walk.iv); + ctx->key_dec, rounds, blocks, walk.iv); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } return err; } +static int cts_cbc_init_tfm(struct crypto_skcipher *tfm) +{ + crypto_skcipher_set_reqsize(tfm, sizeof(struct cts_cbc_req_ctx)); + return 0; +} + +static int cts_cbc_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + struct cts_cbc_req_ctx *rctx = skcipher_request_ctx(req); + int err, rounds = 6 + ctx->key_length / 4; + int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2; + struct scatterlist *src = req->src, *dst = req->dst; + struct skcipher_walk walk; + + skcipher_request_set_tfm(&rctx->subreq, tfm); + + if (req->cryptlen <= AES_BLOCK_SIZE) { + if (req->cryptlen < AES_BLOCK_SIZE) + return -EINVAL; + cbc_blocks = 1; + } + + if (cbc_blocks > 0) { + unsigned int blocks; + + skcipher_request_set_crypt(&rctx->subreq, req->src, req->dst, + cbc_blocks * AES_BLOCK_SIZE, + req->iv); + + err = skcipher_walk_virt(&walk, &rctx->subreq, false); + + while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { + kernel_neon_begin(); + aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, + ctx->key_enc, rounds, blocks, walk.iv); + kernel_neon_end(); + err = skcipher_walk_done(&walk, + walk.nbytes % AES_BLOCK_SIZE); + } + if (err) + return err; + + if (req->cryptlen == AES_BLOCK_SIZE) + return 0; + + dst = src = scatterwalk_ffwd(rctx->sg_src, req->src, + rctx->subreq.cryptlen); + if (req->dst != req->src) + dst = scatterwalk_ffwd(rctx->sg_dst, req->dst, + rctx->subreq.cryptlen); + } + + /* handle ciphertext stealing */ + skcipher_request_set_crypt(&rctx->subreq, src, dst, + req->cryptlen - cbc_blocks * AES_BLOCK_SIZE, + req->iv); + + err = skcipher_walk_virt(&walk, &rctx->subreq, false); + if (err) + return err; + + kernel_neon_begin(); + aes_cbc_cts_encrypt(walk.dst.virt.addr, walk.src.virt.addr, + ctx->key_enc, rounds, walk.nbytes, walk.iv); + kernel_neon_end(); + + return skcipher_walk_done(&walk, 0); +} + +static int cts_cbc_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); + struct cts_cbc_req_ctx *rctx = skcipher_request_ctx(req); + int err, rounds = 6 + ctx->key_length / 4; + int cbc_blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2; + struct scatterlist *src = req->src, *dst = req->dst; + struct skcipher_walk walk; + + skcipher_request_set_tfm(&rctx->subreq, tfm); + + if (req->cryptlen <= AES_BLOCK_SIZE) { + if (req->cryptlen < AES_BLOCK_SIZE) + return -EINVAL; + cbc_blocks = 1; + } + + if (cbc_blocks > 0) { + unsigned int blocks; + + skcipher_request_set_crypt(&rctx->subreq, req->src, req->dst, + cbc_blocks * AES_BLOCK_SIZE, + req->iv); + + err = skcipher_walk_virt(&walk, &rctx->subreq, false); + + while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { + kernel_neon_begin(); + aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, + ctx->key_dec, rounds, blocks, walk.iv); + kernel_neon_end(); + err = skcipher_walk_done(&walk, + walk.nbytes % AES_BLOCK_SIZE); + } + if (err) + return err; + + if (req->cryptlen == AES_BLOCK_SIZE) + return 0; + + dst = src = scatterwalk_ffwd(rctx->sg_src, req->src, + rctx->subreq.cryptlen); + if (req->dst != req->src) + dst = scatterwalk_ffwd(rctx->sg_dst, req->dst, + rctx->subreq.cryptlen); + } + + /* handle ciphertext stealing */ + skcipher_request_set_crypt(&rctx->subreq, src, dst, + req->cryptlen - cbc_blocks * AES_BLOCK_SIZE, + req->iv); + + err = skcipher_walk_virt(&walk, &rctx->subreq, false); + if (err) + return err; + + kernel_neon_begin(); + aes_cbc_cts_decrypt(walk.dst.virt.addr, walk.src.virt.addr, + ctx->key_dec, rounds, walk.nbytes, walk.iv); + kernel_neon_end(); + + return skcipher_walk_done(&walk, 0); +} + static int ctr_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -222,7 +374,7 @@ static int ctr_encrypt(struct skcipher_request *req) while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { kernel_neon_begin(); aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key_enc, rounds, blocks, walk.iv); + ctx->key_enc, rounds, blocks, walk.iv); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -238,7 +390,7 @@ static int ctr_encrypt(struct skcipher_request *req) blocks = -1; kernel_neon_begin(); - aes_ctr_encrypt(tail, NULL, (u8 *)ctx->key_enc, rounds, + aes_ctr_encrypt(tail, NULL, ctx->key_enc, rounds, blocks, walk.iv); kernel_neon_end(); crypto_xor_cpy(tdst, tsrc, tail, nbytes); @@ -272,8 +424,8 @@ static int xts_encrypt(struct skcipher_request *req) for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { kernel_neon_begin(); aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key1.key_enc, rounds, blocks, - (u8 *)ctx->key2.key_enc, walk.iv, first); + ctx->key1.key_enc, rounds, blocks, + ctx->key2.key_enc, walk.iv, first); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -294,8 +446,8 @@ static int xts_decrypt(struct skcipher_request *req) for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { kernel_neon_begin(); aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr, - (u8 *)ctx->key1.key_dec, rounds, blocks, - (u8 *)ctx->key2.key_enc, walk.iv, first); + ctx->key1.key_dec, rounds, blocks, + ctx->key2.key_enc, walk.iv, first); kernel_neon_end(); err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } @@ -336,6 +488,24 @@ static struct skcipher_alg aes_algs[] = { { .decrypt = cbc_decrypt, }, { .base = { + .cra_name = "__cts(cbc(aes))", + .cra_driver_name = "__cts-cbc-aes-" MODE, + .cra_priority = PRIO, + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto_aes_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .walksize = 2 * AES_BLOCK_SIZE, + .setkey = skcipher_aes_setkey, + .encrypt = cts_cbc_encrypt, + .decrypt = cts_cbc_decrypt, + .init = cts_cbc_init_tfm, +}, { + .base = { .cra_name = "__ctr(aes)", .cra_driver_name = "__ctr-aes-" MODE, .cra_priority = PRIO, @@ -412,7 +582,6 @@ static int cmac_setkey(struct crypto_shash *tfm, const u8 *in_key, { struct mac_tfm_ctx *ctx = crypto_shash_ctx(tfm); be128 *consts = (be128 *)ctx->consts; - u8 *rk = (u8 *)ctx->key.key_enc; int rounds = 6 + key_len / 4; int err; @@ -422,7 +591,8 @@ static int cmac_setkey(struct crypto_shash *tfm, const u8 *in_key, /* encrypt the zero vector */ kernel_neon_begin(); - aes_ecb_encrypt(ctx->consts, (u8[AES_BLOCK_SIZE]){}, rk, rounds, 1); + aes_ecb_encrypt(ctx->consts, (u8[AES_BLOCK_SIZE]){}, ctx->key.key_enc, + rounds, 1); kernel_neon_end(); cmac_gf128_mul_by_x(consts, consts); @@ -441,7 +611,6 @@ static int xcbc_setkey(struct crypto_shash *tfm, const u8 *in_key, }; struct mac_tfm_ctx *ctx = crypto_shash_ctx(tfm); - u8 *rk = (u8 *)ctx->key.key_enc; int rounds = 6 + key_len / 4; u8 key[AES_BLOCK_SIZE]; int err; @@ -451,8 +620,8 @@ static int xcbc_setkey(struct crypto_shash *tfm, const u8 *in_key, return err; kernel_neon_begin(); - aes_ecb_encrypt(key, ks[0], rk, rounds, 1); - aes_ecb_encrypt(ctx->consts, ks[1], rk, rounds, 2); + aes_ecb_encrypt(key, ks[0], ctx->key.key_enc, rounds, 1); + aes_ecb_encrypt(ctx->consts, ks[1], ctx->key.key_enc, rounds, 2); kernel_neon_end(); return cbcmac_setkey(tfm, key, sizeof(key)); diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S index 483a7130cf0e..67700045a0e0 100644 --- a/arch/arm64/crypto/aes-modes.S +++ b/arch/arm64/crypto/aes-modes.S @@ -14,12 +14,12 @@ .align 4 aes_encrypt_block4x: - encrypt_block4x v0, v1, v2, v3, w22, x21, x8, w7 + encrypt_block4x v0, v1, v2, v3, w3, x2, x8, w7 ret ENDPROC(aes_encrypt_block4x) aes_decrypt_block4x: - decrypt_block4x v0, v1, v2, v3, w22, x21, x8, w7 + decrypt_block4x v0, v1, v2, v3, w3, x2, x8, w7 ret ENDPROC(aes_decrypt_block4x) @@ -31,71 +31,57 @@ ENDPROC(aes_decrypt_block4x) */ AES_ENTRY(aes_ecb_encrypt) - frame_push 5 + stp x29, x30, [sp, #-16]! + mov x29, sp - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - -.Lecbencrestart: - enc_prepare w22, x21, x5 + enc_prepare w3, x2, x5 .LecbencloopNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lecbenc1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 pt blocks */ + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ bl aes_encrypt_block4x - st1 {v0.16b-v3.16b}, [x19], #64 - cond_yield_neon .Lecbencrestart + st1 {v0.16b-v3.16b}, [x0], #64 b .LecbencloopNx .Lecbenc1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lecbencout .Lecbencloop: - ld1 {v0.16b}, [x20], #16 /* get next pt block */ - encrypt_block v0, w22, x21, x5, w6 - st1 {v0.16b}, [x19], #16 - subs w23, w23, #1 + ld1 {v0.16b}, [x1], #16 /* get next pt block */ + encrypt_block v0, w3, x2, x5, w6 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 bne .Lecbencloop .Lecbencout: - frame_pop + ldp x29, x30, [sp], #16 ret AES_ENDPROC(aes_ecb_encrypt) AES_ENTRY(aes_ecb_decrypt) - frame_push 5 + stp x29, x30, [sp, #-16]! + mov x29, sp - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - -.Lecbdecrestart: - dec_prepare w22, x21, x5 + dec_prepare w3, x2, x5 .LecbdecloopNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lecbdec1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 ct blocks */ + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ bl aes_decrypt_block4x - st1 {v0.16b-v3.16b}, [x19], #64 - cond_yield_neon .Lecbdecrestart + st1 {v0.16b-v3.16b}, [x0], #64 b .LecbdecloopNx .Lecbdec1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lecbdecout .Lecbdecloop: - ld1 {v0.16b}, [x20], #16 /* get next ct block */ - decrypt_block v0, w22, x21, x5, w6 - st1 {v0.16b}, [x19], #16 - subs w23, w23, #1 + ld1 {v0.16b}, [x1], #16 /* get next ct block */ + decrypt_block v0, w3, x2, x5, w6 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 bne .Lecbdecloop .Lecbdecout: - frame_pop + ldp x29, x30, [sp], #16 ret AES_ENDPROC(aes_ecb_decrypt) @@ -108,162 +94,211 @@ AES_ENDPROC(aes_ecb_decrypt) */ AES_ENTRY(aes_cbc_encrypt) - frame_push 6 - - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - mov x24, x5 - -.Lcbcencrestart: - ld1 {v4.16b}, [x24] /* get iv */ - enc_prepare w22, x21, x6 + ld1 {v4.16b}, [x5] /* get iv */ + enc_prepare w3, x2, x6 .Lcbcencloop4x: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lcbcenc1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 pt blocks */ + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ eor v0.16b, v0.16b, v4.16b /* ..and xor with iv */ - encrypt_block v0, w22, x21, x6, w7 + encrypt_block v0, w3, x2, x6, w7 eor v1.16b, v1.16b, v0.16b - encrypt_block v1, w22, x21, x6, w7 + encrypt_block v1, w3, x2, x6, w7 eor v2.16b, v2.16b, v1.16b - encrypt_block v2, w22, x21, x6, w7 + encrypt_block v2, w3, x2, x6, w7 eor v3.16b, v3.16b, v2.16b - encrypt_block v3, w22, x21, x6, w7 - st1 {v0.16b-v3.16b}, [x19], #64 + encrypt_block v3, w3, x2, x6, w7 + st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v3.16b - st1 {v4.16b}, [x24] /* return iv */ - cond_yield_neon .Lcbcencrestart b .Lcbcencloop4x .Lcbcenc1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lcbcencout .Lcbcencloop: - ld1 {v0.16b}, [x20], #16 /* get next pt block */ + ld1 {v0.16b}, [x1], #16 /* get next pt block */ eor v4.16b, v4.16b, v0.16b /* ..and xor with iv */ - encrypt_block v4, w22, x21, x6, w7 - st1 {v4.16b}, [x19], #16 - subs w23, w23, #1 + encrypt_block v4, w3, x2, x6, w7 + st1 {v4.16b}, [x0], #16 + subs w4, w4, #1 bne .Lcbcencloop .Lcbcencout: - st1 {v4.16b}, [x24] /* return iv */ - frame_pop + st1 {v4.16b}, [x5] /* return iv */ ret AES_ENDPROC(aes_cbc_encrypt) AES_ENTRY(aes_cbc_decrypt) - frame_push 6 - - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - mov x24, x5 + stp x29, x30, [sp, #-16]! + mov x29, sp -.Lcbcdecrestart: - ld1 {v7.16b}, [x24] /* get iv */ - dec_prepare w22, x21, x6 + ld1 {v7.16b}, [x5] /* get iv */ + dec_prepare w3, x2, x6 .LcbcdecloopNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lcbcdec1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 ct blocks */ + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ mov v4.16b, v0.16b mov v5.16b, v1.16b mov v6.16b, v2.16b bl aes_decrypt_block4x - sub x20, x20, #16 + sub x1, x1, #16 eor v0.16b, v0.16b, v7.16b eor v1.16b, v1.16b, v4.16b - ld1 {v7.16b}, [x20], #16 /* reload 1 ct block */ + ld1 {v7.16b}, [x1], #16 /* reload 1 ct block */ eor v2.16b, v2.16b, v5.16b eor v3.16b, v3.16b, v6.16b - st1 {v0.16b-v3.16b}, [x19], #64 - st1 {v7.16b}, [x24] /* return iv */ - cond_yield_neon .Lcbcdecrestart + st1 {v0.16b-v3.16b}, [x0], #64 b .LcbcdecloopNx .Lcbcdec1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lcbcdecout .Lcbcdecloop: - ld1 {v1.16b}, [x20], #16 /* get next ct block */ + ld1 {v1.16b}, [x1], #16 /* get next ct block */ mov v0.16b, v1.16b /* ...and copy to v0 */ - decrypt_block v0, w22, x21, x6, w7 + decrypt_block v0, w3, x2, x6, w7 eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */ mov v7.16b, v1.16b /* ct is next iv */ - st1 {v0.16b}, [x19], #16 - subs w23, w23, #1 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 bne .Lcbcdecloop .Lcbcdecout: - st1 {v7.16b}, [x24] /* return iv */ - frame_pop + st1 {v7.16b}, [x5] /* return iv */ + ldp x29, x30, [sp], #16 ret AES_ENDPROC(aes_cbc_decrypt) /* + * aes_cbc_cts_encrypt(u8 out[], u8 const in[], u32 const rk[], + * int rounds, int bytes, u8 const iv[]) + * aes_cbc_cts_decrypt(u8 out[], u8 const in[], u32 const rk[], + * int rounds, int bytes, u8 const iv[]) + */ + +AES_ENTRY(aes_cbc_cts_encrypt) + adr_l x8, .Lcts_permute_table + sub x4, x4, #16 + add x9, x8, #32 + add x8, x8, x4 + sub x9, x9, x4 + ld1 {v3.16b}, [x8] + ld1 {v4.16b}, [x9] + + ld1 {v0.16b}, [x1], x4 /* overlapping loads */ + ld1 {v1.16b}, [x1] + + ld1 {v5.16b}, [x5] /* get iv */ + enc_prepare w3, x2, x6 + + eor v0.16b, v0.16b, v5.16b /* xor with iv */ + tbl v1.16b, {v1.16b}, v4.16b + encrypt_block v0, w3, x2, x6, w7 + + eor v1.16b, v1.16b, v0.16b + tbl v0.16b, {v0.16b}, v3.16b + encrypt_block v1, w3, x2, x6, w7 + + add x4, x0, x4 + st1 {v0.16b}, [x4] /* overlapping stores */ + st1 {v1.16b}, [x0] + ret +AES_ENDPROC(aes_cbc_cts_encrypt) + +AES_ENTRY(aes_cbc_cts_decrypt) + adr_l x8, .Lcts_permute_table + sub x4, x4, #16 + add x9, x8, #32 + add x8, x8, x4 + sub x9, x9, x4 + ld1 {v3.16b}, [x8] + ld1 {v4.16b}, [x9] + + ld1 {v0.16b}, [x1], x4 /* overlapping loads */ + ld1 {v1.16b}, [x1] + + ld1 {v5.16b}, [x5] /* get iv */ + dec_prepare w3, x2, x6 + + tbl v2.16b, {v1.16b}, v4.16b + decrypt_block v0, w3, x2, x6, w7 + eor v2.16b, v2.16b, v0.16b + + tbx v0.16b, {v1.16b}, v4.16b + tbl v2.16b, {v2.16b}, v3.16b + decrypt_block v0, w3, x2, x6, w7 + eor v0.16b, v0.16b, v5.16b /* xor with iv */ + + add x4, x0, x4 + st1 {v2.16b}, [x4] /* overlapping stores */ + st1 {v0.16b}, [x0] + ret +AES_ENDPROC(aes_cbc_cts_decrypt) + + .section ".rodata", "a" + .align 6 +.Lcts_permute_table: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 + .byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + .previous + + + /* * aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, * int blocks, u8 ctr[]) */ AES_ENTRY(aes_ctr_encrypt) - frame_push 6 + stp x29, x30, [sp, #-16]! + mov x29, sp - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - mov x24, x5 - -.Lctrrestart: - enc_prepare w22, x21, x6 - ld1 {v4.16b}, [x24] + enc_prepare w3, x2, x6 + ld1 {v4.16b}, [x5] umov x6, v4.d[1] /* keep swabbed ctr in reg */ rev x6, x6 + cmn w6, w4 /* 32 bit overflow? */ + bcs .Lctrloop .LctrloopNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lctr1x - cmn w6, #4 /* 32 bit overflow? */ - bcs .Lctr1x - ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */ - dup v7.4s, w6 + add w7, w6, #1 mov v0.16b, v4.16b - add v7.4s, v7.4s, v8.4s + add w8, w6, #2 mov v1.16b, v4.16b - rev32 v8.16b, v7.16b + add w9, w6, #3 mov v2.16b, v4.16b + rev w7, w7 mov v3.16b, v4.16b - mov v1.s[3], v8.s[0] - mov v2.s[3], v8.s[1] - mov v3.s[3], v8.s[2] - ld1 {v5.16b-v7.16b}, [x20], #48 /* get 3 input blocks */ + rev w8, w8 + mov v1.s[3], w7 + rev w9, w9 + mov v2.s[3], w8 + mov v3.s[3], w9 + ld1 {v5.16b-v7.16b}, [x1], #48 /* get 3 input blocks */ bl aes_encrypt_block4x eor v0.16b, v5.16b, v0.16b - ld1 {v5.16b}, [x20], #16 /* get 1 input block */ + ld1 {v5.16b}, [x1], #16 /* get 1 input block */ eor v1.16b, v6.16b, v1.16b eor v2.16b, v7.16b, v2.16b eor v3.16b, v5.16b, v3.16b - st1 {v0.16b-v3.16b}, [x19], #64 + st1 {v0.16b-v3.16b}, [x0], #64 add x6, x6, #4 rev x7, x6 ins v4.d[1], x7 - cbz w23, .Lctrout - st1 {v4.16b}, [x24] /* return next CTR value */ - cond_yield_neon .Lctrrestart + cbz w4, .Lctrout b .LctrloopNx .Lctr1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lctrout .Lctrloop: mov v0.16b, v4.16b - encrypt_block v0, w22, x21, x8, w7 + encrypt_block v0, w3, x2, x8, w7 adds x6, x6, #1 /* increment BE ctr */ rev x7, x6 @@ -271,22 +306,22 @@ AES_ENTRY(aes_ctr_encrypt) bcs .Lctrcarry /* overflow? */ .Lctrcarrydone: - subs w23, w23, #1 + subs w4, w4, #1 bmi .Lctrtailblock /* blocks <0 means tail block */ - ld1 {v3.16b}, [x20], #16 + ld1 {v3.16b}, [x1], #16 eor v3.16b, v0.16b, v3.16b - st1 {v3.16b}, [x19], #16 + st1 {v3.16b}, [x0], #16 bne .Lctrloop .Lctrout: - st1 {v4.16b}, [x24] /* return next CTR value */ -.Lctrret: - frame_pop + st1 {v4.16b}, [x5] /* return next CTR value */ + ldp x29, x30, [sp], #16 ret .Lctrtailblock: - st1 {v0.16b}, [x19] - b .Lctrret + st1 {v0.16b}, [x0] + ldp x29, x30, [sp], #16 + ret .Lctrcarry: umov x7, v4.d[0] /* load upper word of ctr */ @@ -296,7 +331,6 @@ AES_ENTRY(aes_ctr_encrypt) ins v4.d[0], x7 b .Lctrcarrydone AES_ENDPROC(aes_ctr_encrypt) - .ltorg /* @@ -306,150 +340,132 @@ AES_ENDPROC(aes_ctr_encrypt) * int blocks, u8 const rk2[], u8 iv[], int first) */ - .macro next_tweak, out, in, const, tmp + .macro next_tweak, out, in, tmp sshr \tmp\().2d, \in\().2d, #63 - and \tmp\().16b, \tmp\().16b, \const\().16b + and \tmp\().16b, \tmp\().16b, xtsmask.16b add \out\().2d, \in\().2d, \in\().2d ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 eor \out\().16b, \out\().16b, \tmp\().16b .endm -.Lxts_mul_x: -CPU_LE( .quad 1, 0x87 ) -CPU_BE( .quad 0x87, 1 ) + .macro xts_load_mask, tmp + movi xtsmask.2s, #0x1 + movi \tmp\().2s, #0x87 + uzp1 xtsmask.4s, xtsmask.4s, \tmp\().4s + .endm AES_ENTRY(aes_xts_encrypt) - frame_push 6 + stp x29, x30, [sp, #-16]! + mov x29, sp - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - mov x24, x6 - - ld1 {v4.16b}, [x24] + ld1 {v4.16b}, [x6] + xts_load_mask v8 cbz w7, .Lxtsencnotfirst enc_prepare w3, x5, x8 encrypt_block v4, w3, x5, x8, w7 /* first tweak */ enc_switch_key w3, x2, x8 - ldr q7, .Lxts_mul_x b .LxtsencNx -.Lxtsencrestart: - ld1 {v4.16b}, [x24] .Lxtsencnotfirst: - enc_prepare w22, x21, x8 + enc_prepare w3, x2, x8 .LxtsencloopNx: - ldr q7, .Lxts_mul_x - next_tweak v4, v4, v7, v8 + next_tweak v4, v4, v8 .LxtsencNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lxtsenc1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 pt blocks */ - next_tweak v5, v4, v7, v8 + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ + next_tweak v5, v4, v8 eor v0.16b, v0.16b, v4.16b - next_tweak v6, v5, v7, v8 + next_tweak v6, v5, v8 eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b - next_tweak v7, v6, v7, v8 + next_tweak v7, v6, v8 eor v3.16b, v3.16b, v7.16b bl aes_encrypt_block4x eor v3.16b, v3.16b, v7.16b eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b - st1 {v0.16b-v3.16b}, [x19], #64 + st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v7.16b - cbz w23, .Lxtsencout - st1 {v4.16b}, [x24] - cond_yield_neon .Lxtsencrestart + cbz w4, .Lxtsencout + xts_reload_mask v8 b .LxtsencloopNx .Lxtsenc1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lxtsencout .Lxtsencloop: - ld1 {v1.16b}, [x20], #16 + ld1 {v1.16b}, [x1], #16 eor v0.16b, v1.16b, v4.16b - encrypt_block v0, w22, x21, x8, w7 + encrypt_block v0, w3, x2, x8, w7 eor v0.16b, v0.16b, v4.16b - st1 {v0.16b}, [x19], #16 - subs w23, w23, #1 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 beq .Lxtsencout - next_tweak v4, v4, v7, v8 + next_tweak v4, v4, v8 b .Lxtsencloop .Lxtsencout: - st1 {v4.16b}, [x24] - frame_pop + st1 {v4.16b}, [x6] + ldp x29, x30, [sp], #16 ret AES_ENDPROC(aes_xts_encrypt) AES_ENTRY(aes_xts_decrypt) - frame_push 6 + stp x29, x30, [sp, #-16]! + mov x29, sp - mov x19, x0 - mov x20, x1 - mov x21, x2 - mov x22, x3 - mov x23, x4 - mov x24, x6 - - ld1 {v4.16b}, [x24] + ld1 {v4.16b}, [x6] + xts_load_mask v8 cbz w7, .Lxtsdecnotfirst enc_prepare w3, x5, x8 encrypt_block v4, w3, x5, x8, w7 /* first tweak */ dec_prepare w3, x2, x8 - ldr q7, .Lxts_mul_x b .LxtsdecNx -.Lxtsdecrestart: - ld1 {v4.16b}, [x24] .Lxtsdecnotfirst: - dec_prepare w22, x21, x8 + dec_prepare w3, x2, x8 .LxtsdecloopNx: - ldr q7, .Lxts_mul_x - next_tweak v4, v4, v7, v8 + next_tweak v4, v4, v8 .LxtsdecNx: - subs w23, w23, #4 + subs w4, w4, #4 bmi .Lxtsdec1x - ld1 {v0.16b-v3.16b}, [x20], #64 /* get 4 ct blocks */ - next_tweak v5, v4, v7, v8 + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ + next_tweak v5, v4, v8 eor v0.16b, v0.16b, v4.16b - next_tweak v6, v5, v7, v8 + next_tweak v6, v5, v8 eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b - next_tweak v7, v6, v7, v8 + next_tweak v7, v6, v8 eor v3.16b, v3.16b, v7.16b bl aes_decrypt_block4x eor v3.16b, v3.16b, v7.16b eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b - st1 {v0.16b-v3.16b}, [x19], #64 + st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v7.16b - cbz w23, .Lxtsdecout - st1 {v4.16b}, [x24] - cond_yield_neon .Lxtsdecrestart + cbz w4, .Lxtsdecout + xts_reload_mask v8 b .LxtsdecloopNx .Lxtsdec1x: - adds w23, w23, #4 + adds w4, w4, #4 beq .Lxtsdecout .Lxtsdecloop: - ld1 {v1.16b}, [x20], #16 + ld1 {v1.16b}, [x1], #16 eor v0.16b, v1.16b, v4.16b - decrypt_block v0, w22, x21, x8, w7 + decrypt_block v0, w3, x2, x8, w7 eor v0.16b, v0.16b, v4.16b - st1 {v0.16b}, [x19], #16 - subs w23, w23, #1 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 beq .Lxtsdecout - next_tweak v4, v4, v7, v8 + next_tweak v4, v4, v8 b .Lxtsdecloop .Lxtsdecout: - st1 {v4.16b}, [x24] - frame_pop + st1 {v4.16b}, [x6] + ldp x29, x30, [sp], #16 ret AES_ENDPROC(aes_xts_decrypt) diff --git a/arch/arm64/crypto/aes-neon.S b/arch/arm64/crypto/aes-neon.S index 1c7b45b7268e..29100f692e8a 100644 --- a/arch/arm64/crypto/aes-neon.S +++ b/arch/arm64/crypto/aes-neon.S @@ -14,6 +14,12 @@ #define AES_ENTRY(func) ENTRY(neon_ ## func) #define AES_ENDPROC(func) ENDPROC(neon_ ## func) + xtsmask .req v7 + + .macro xts_reload_mask, tmp + xts_load_mask \tmp + .endm + /* multiply by polynomial 'x' in GF(2^8) */ .macro mul_by_x, out, in, temp, const sshr \temp, \in, #7 diff --git a/arch/arm64/crypto/crc32-ce-core.S b/arch/arm64/crypto/crc32-ce-core.S deleted file mode 100644 index 8061bf0f9c66..000000000000 --- a/arch/arm64/crypto/crc32-ce-core.S +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Accelerated CRC32(C) using arm64 CRC, NEON and Crypto Extensions instructions - * - * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org> - * - * 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 - * published by the Free Software Foundation. - */ - -/* GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see http://www.gnu.org/licenses - * - * Please visit http://www.xyratex.com/contact if you need additional - * information or have any questions. - * - * GPL HEADER END - */ - -/* - * Copyright 2012 Xyratex Technology Limited - * - * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32 - * calculation. - * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE) - * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found - * at: - * http://www.intel.com/products/processor/manuals/ - * Intel(R) 64 and IA-32 Architectures Software Developer's Manual - * Volume 2B: Instruction Set Reference, N-Z - * - * Authors: Gregory Prestas <Gregory_Prestas@us.xyratex.com> - * Alexander Boyko <Alexander_Boyko@xyratex.com> - */ - -#include <linux/linkage.h> -#include <asm/assembler.h> - - .section ".rodata", "a" - .align 6 - .cpu generic+crypto+crc - -.Lcrc32_constants: - /* - * [x4*128+32 mod P(x) << 32)]' << 1 = 0x154442bd4 - * #define CONSTANT_R1 0x154442bd4LL - * - * [(x4*128-32 mod P(x) << 32)]' << 1 = 0x1c6e41596 - * #define CONSTANT_R2 0x1c6e41596LL - */ - .octa 0x00000001c6e415960000000154442bd4 - - /* - * [(x128+32 mod P(x) << 32)]' << 1 = 0x1751997d0 - * #define CONSTANT_R3 0x1751997d0LL - * - * [(x128-32 mod P(x) << 32)]' << 1 = 0x0ccaa009e - * #define CONSTANT_R4 0x0ccaa009eLL - */ - .octa 0x00000000ccaa009e00000001751997d0 - - /* - * [(x64 mod P(x) << 32)]' << 1 = 0x163cd6124 - * #define CONSTANT_R5 0x163cd6124LL - */ - .quad 0x0000000163cd6124 - .quad 0x00000000FFFFFFFF - - /* - * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL - * - * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))` - * = 0x1F7011641LL - * #define CONSTANT_RU 0x1F7011641LL - */ - .octa 0x00000001F701164100000001DB710641 - -.Lcrc32c_constants: - .octa 0x000000009e4addf800000000740eef02 - .octa 0x000000014cd00bd600000000f20c0dfe - .quad 0x00000000dd45aab8 - .quad 0x00000000FFFFFFFF - .octa 0x00000000dea713f10000000105ec76f0 - - vCONSTANT .req v0 - dCONSTANT .req d0 - qCONSTANT .req q0 - - BUF .req x19 - LEN .req x20 - CRC .req x21 - CONST .req x22 - - vzr .req v9 - - /** - * Calculate crc32 - * BUF - buffer - * LEN - sizeof buffer (multiple of 16 bytes), LEN should be > 63 - * CRC - initial crc32 - * return %eax crc32 - * uint crc32_pmull_le(unsigned char const *buffer, - * size_t len, uint crc32) - */ - .text -ENTRY(crc32_pmull_le) - adr_l x3, .Lcrc32_constants - b 0f - -ENTRY(crc32c_pmull_le) - adr_l x3, .Lcrc32c_constants - -0: frame_push 4, 64 - - mov BUF, x0 - mov LEN, x1 - mov CRC, x2 - mov CONST, x3 - - bic LEN, LEN, #15 - ld1 {v1.16b-v4.16b}, [BUF], #0x40 - movi vzr.16b, #0 - fmov dCONSTANT, CRC - eor v1.16b, v1.16b, vCONSTANT.16b - sub LEN, LEN, #0x40 - cmp LEN, #0x40 - b.lt less_64 - - ldr qCONSTANT, [CONST] - -loop_64: /* 64 bytes Full cache line folding */ - sub LEN, LEN, #0x40 - - pmull2 v5.1q, v1.2d, vCONSTANT.2d - pmull2 v6.1q, v2.2d, vCONSTANT.2d - pmull2 v7.1q, v3.2d, vCONSTANT.2d - pmull2 v8.1q, v4.2d, vCONSTANT.2d - - pmull v1.1q, v1.1d, vCONSTANT.1d - pmull v2.1q, v2.1d, vCONSTANT.1d - pmull v3.1q, v3.1d, vCONSTANT.1d - pmull v4.1q, v4.1d, vCONSTANT.1d - - eor v1.16b, v1.16b, v5.16b - ld1 {v5.16b}, [BUF], #0x10 - eor v2.16b, v2.16b, v6.16b - ld1 {v6.16b}, [BUF], #0x10 - eor v3.16b, v3.16b, v7.16b - ld1 {v7.16b}, [BUF], #0x10 - eor v4.16b, v4.16b, v8.16b - ld1 {v8.16b}, [BUF], #0x10 - - eor v1.16b, v1.16b, v5.16b - eor v2.16b, v2.16b, v6.16b - eor v3.16b, v3.16b, v7.16b - eor v4.16b, v4.16b, v8.16b - - cmp LEN, #0x40 - b.lt less_64 - - if_will_cond_yield_neon - stp q1, q2, [sp, #.Lframe_local_offset] - stp q3, q4, [sp, #.Lframe_local_offset + 32] - do_cond_yield_neon - ldp q1, q2, [sp, #.Lframe_local_offset] - ldp q3, q4, [sp, #.Lframe_local_offset + 32] - ldr qCONSTANT, [CONST] - movi vzr.16b, #0 - endif_yield_neon - b loop_64 - -less_64: /* Folding cache line into 128bit */ - ldr qCONSTANT, [CONST, #16] - - pmull2 v5.1q, v1.2d, vCONSTANT.2d - pmull v1.1q, v1.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v5.16b - eor v1.16b, v1.16b, v2.16b - - pmull2 v5.1q, v1.2d, vCONSTANT.2d - pmull v1.1q, v1.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v5.16b - eor v1.16b, v1.16b, v3.16b - - pmull2 v5.1q, v1.2d, vCONSTANT.2d - pmull v1.1q, v1.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v5.16b - eor v1.16b, v1.16b, v4.16b - - cbz LEN, fold_64 - -loop_16: /* Folding rest buffer into 128bit */ - subs LEN, LEN, #0x10 - - ld1 {v2.16b}, [BUF], #0x10 - pmull2 v5.1q, v1.2d, vCONSTANT.2d - pmull v1.1q, v1.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v5.16b - eor v1.16b, v1.16b, v2.16b - - b.ne loop_16 - -fold_64: - /* perform the last 64 bit fold, also adds 32 zeroes - * to the input stream */ - ext v2.16b, v1.16b, v1.16b, #8 - pmull2 v2.1q, v2.2d, vCONSTANT.2d - ext v1.16b, v1.16b, vzr.16b, #8 - eor v1.16b, v1.16b, v2.16b - - /* final 32-bit fold */ - ldr dCONSTANT, [CONST, #32] - ldr d3, [CONST, #40] - - ext v2.16b, v1.16b, vzr.16b, #4 - and v1.16b, v1.16b, v3.16b - pmull v1.1q, v1.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v2.16b - - /* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */ - ldr qCONSTANT, [CONST, #48] - - and v2.16b, v1.16b, v3.16b - ext v2.16b, vzr.16b, v2.16b, #8 - pmull2 v2.1q, v2.2d, vCONSTANT.2d - and v2.16b, v2.16b, v3.16b - pmull v2.1q, v2.1d, vCONSTANT.1d - eor v1.16b, v1.16b, v2.16b - mov w0, v1.s[1] - - frame_pop - ret -ENDPROC(crc32_pmull_le) -ENDPROC(crc32c_pmull_le) - - .macro __crc32, c -0: subs x2, x2, #16 - b.mi 8f - ldp x3, x4, [x1], #16 -CPU_BE( rev x3, x3 ) -CPU_BE( rev x4, x4 ) - crc32\c\()x w0, w0, x3 - crc32\c\()x w0, w0, x4 - b.ne 0b - ret - -8: tbz x2, #3, 4f - ldr x3, [x1], #8 -CPU_BE( rev x3, x3 ) - crc32\c\()x w0, w0, x3 -4: tbz x2, #2, 2f - ldr w3, [x1], #4 -CPU_BE( rev w3, w3 ) - crc32\c\()w w0, w0, w3 -2: tbz x2, #1, 1f - ldrh w3, [x1], #2 -CPU_BE( rev16 w3, w3 ) - crc32\c\()h w0, w0, w3 -1: tbz x2, #0, 0f - ldrb w3, [x1] - crc32\c\()b w0, w0, w3 -0: ret - .endm - - .align 5 -ENTRY(crc32_armv8_le) - __crc32 -ENDPROC(crc32_armv8_le) - - .align 5 -ENTRY(crc32c_armv8_le) - __crc32 c -ENDPROC(crc32c_armv8_le) diff --git a/arch/arm64/crypto/crc32-ce-glue.c b/arch/arm64/crypto/crc32-ce-glue.c deleted file mode 100644 index 34b4e3d46aab..000000000000 --- a/arch/arm64/crypto/crc32-ce-glue.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Accelerated CRC32(C) using arm64 NEON and Crypto Extensions instructions - * - * Copyright (C) 2016 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org> - * - * 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 - * published by the Free Software Foundation. - */ - -#include <linux/cpufeature.h> -#include <linux/crc32.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/string.h> - -#include <crypto/internal/hash.h> - -#include <asm/hwcap.h> -#include <asm/neon.h> -#include <asm/simd.h> -#include <asm/unaligned.h> - -#define PMULL_MIN_LEN 64L /* minimum size of buffer - * for crc32_pmull_le_16 */ -#define SCALE_F 16L /* size of NEON register */ - -asmlinkage u32 crc32_pmull_le(const u8 buf[], u64 len, u32 init_crc); -asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], size_t len); - -asmlinkage u32 crc32c_pmull_le(const u8 buf[], u64 len, u32 init_crc); -asmlinkage u32 crc32c_armv8_le(u32 init_crc, const u8 buf[], size_t len); - -static u32 (*fallback_crc32)(u32 init_crc, const u8 buf[], size_t len); -static u32 (*fallback_crc32c)(u32 init_crc, const u8 buf[], size_t len); - -static int crc32_pmull_cra_init(struct crypto_tfm *tfm) -{ - u32 *key = crypto_tfm_ctx(tfm); - - *key = 0; - return 0; -} - -static int crc32c_pmull_cra_init(struct crypto_tfm *tfm) -{ - u32 *key = crypto_tfm_ctx(tfm); - - *key = ~0; - return 0; -} - -static int crc32_pmull_setkey(struct crypto_shash *hash, const u8 *key, - unsigned int keylen) -{ - u32 *mctx = crypto_shash_ctx(hash); - - if (keylen != sizeof(u32)) { - crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - *mctx = le32_to_cpup((__le32 *)key); - return 0; -} - -static int crc32_pmull_init(struct shash_desc *desc) -{ - u32 *mctx = crypto_shash_ctx(desc->tfm); - u32 *crc = shash_desc_ctx(desc); - - *crc = *mctx; - return 0; -} - -static int crc32_update(struct shash_desc *desc, const u8 *data, - unsigned int length) -{ - u32 *crc = shash_desc_ctx(desc); - - *crc = crc32_armv8_le(*crc, data, length); - return 0; -} - -static int crc32c_update(struct shash_desc *desc, const u8 *data, - unsigned int length) -{ - u32 *crc = shash_desc_ctx(desc); - - *crc = crc32c_armv8_le(*crc, data, length); - return 0; -} - -static int crc32_pmull_update(struct shash_desc *desc, const u8 *data, - unsigned int length) -{ - u32 *crc = shash_desc_ctx(desc); - unsigned int l; - - if ((u64)data % SCALE_F) { - l = min_t(u32, length, SCALE_F - ((u64)data % SCALE_F)); - - *crc = fallback_crc32(*crc, data, l); - - data += l; - length -= l; - } - - if (length >= PMULL_MIN_LEN && may_use_simd()) { - l = round_down(length, SCALE_F); - - kernel_neon_begin(); - *crc = crc32_pmull_le(data, l, *crc); - kernel_neon_end(); - - data += l; - length -= l; - } - - if (length > 0) - *crc = fallback_crc32(*crc, data, length); - - return 0; -} - -static int crc32c_pmull_update(struct shash_desc *desc, const u8 *data, - unsigned int length) -{ - u32 *crc = shash_desc_ctx(desc); - unsigned int l; - - if ((u64)data % SCALE_F) { - l = min_t(u32, length, SCALE_F - ((u64)data % SCALE_F)); - - *crc = fallback_crc32c(*crc, data, l); - - data += l; - length -= l; - } - - if (length >= PMULL_MIN_LEN && may_use_simd()) { - l = round_down(length, SCALE_F); - - kernel_neon_begin(); - *crc = crc32c_pmull_le(data, l, *crc); - kernel_neon_end(); - - data += l; - length -= l; - } - - if (length > 0) { - *crc = fallback_crc32c(*crc, data, length); - } - - return 0; -} - -static int crc32_pmull_final(struct shash_desc *desc, u8 *out) -{ - u32 *crc = shash_desc_ctx(desc); - - put_unaligned_le32(*crc, out); - return 0; -} - -static int crc32c_pmull_final(struct shash_desc *desc, u8 *out) -{ - u32 *crc = shash_desc_ctx(desc); - - put_unaligned_le32(~*crc, out); - return 0; -} - -static struct shash_alg crc32_pmull_algs[] = { { - .setkey = crc32_pmull_setkey, - .init = crc32_pmull_init, - .update = crc32_update, - .final = crc32_pmull_final, - .descsize = sizeof(u32), - .digestsize = sizeof(u32), - - .base.cra_ctxsize = sizeof(u32), - .base.cra_init = crc32_pmull_cra_init, - .base.cra_name = "crc32", - .base.cra_driver_name = "crc32-arm64-ce", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, - .base.cra_blocksize = 1, - .base.cra_module = THIS_MODULE, -}, { - .setkey = crc32_pmull_setkey, - .init = crc32_pmull_init, - .update = crc32c_update, - .final = crc32c_pmull_final, - .descsize = sizeof(u32), - .digestsize = sizeof(u32), - - .base.cra_ctxsize = sizeof(u32), - .base.cra_init = crc32c_pmull_cra_init, - .base.cra_name = "crc32c", - .base.cra_driver_name = "crc32c-arm64-ce", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, - .base.cra_blocksize = 1, - .base.cra_module = THIS_MODULE, -} }; - -static int __init crc32_pmull_mod_init(void) -{ - if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_PMULL)) { - crc32_pmull_algs[0].update = crc32_pmull_update; - crc32_pmull_algs[1].update = crc32c_pmull_update; - - if (elf_hwcap & HWCAP_CRC32) { - fallback_crc32 = crc32_armv8_le; - fallback_crc32c = crc32c_armv8_le; - } else { - fallback_crc32 = crc32_le; - fallback_crc32c = __crc32c_le; - } - } else if (!(elf_hwcap & HWCAP_CRC32)) { - return -ENODEV; - } - return crypto_register_shashes(crc32_pmull_algs, - ARRAY_SIZE(crc32_pmull_algs)); -} - -static void __exit crc32_pmull_mod_exit(void) -{ - crypto_unregister_shashes(crc32_pmull_algs, - ARRAY_SIZE(crc32_pmull_algs)); -} - -static const struct cpu_feature crc32_cpu_feature[] = { - { cpu_feature(CRC32) }, { cpu_feature(PMULL) }, { } -}; -MODULE_DEVICE_TABLE(cpu, crc32_cpu_feature); - -module_init(crc32_pmull_mod_init); -module_exit(crc32_pmull_mod_exit); - -MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); -MODULE_LICENSE("GPL v2"); diff --git a/arch/arm64/crypto/crct10dif-ce-core.S b/arch/arm64/crypto/crct10dif-ce-core.S index 663ea71cdb38..9e82e8e8ed05 100644 --- a/arch/arm64/crypto/crct10dif-ce-core.S +++ b/arch/arm64/crypto/crct10dif-ce-core.S @@ -80,7 +80,186 @@ vzr .req v13 -ENTRY(crc_t10dif_pmull) + ad .req v14 + bd .req v10 + + 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 + + .macro __pmull_pre_p64, bd + .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 + .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 + +__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, bd.8b // F = A1*B + pmull t8.8h, ad.8b, bd1.8b // E = A*B1 + pmull t5.8h, t5.8b, bd.8b // H = A2*B + pmull t7.8h, ad.8b, bd2.8b // G = A*B2 + pmull t6.8h, t6.8b, bd.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, bd.16b // F = A1*B + pmull2 t8.8h, ad.16b, bd1.16b // E = A*B1 + pmull2 t5.8h, t5.16b, bd.16b // H = A2*B + pmull2 t7.8h, ad.16b, bd2.16b // G = A*B2 + pmull2 t6.8h, t6.16b, bd.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 + 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 +ENDPROC(__pmull_p8_core) + + .macro __pmull_p8, rq, ad, bd, i + .ifnc \bd, v10 + .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 + + .macro fold64, p, reg1, reg2 + ldp q11, q12, [arg2], #0x20 + + __pmull_\p v8, \reg1, v10, 2 + __pmull_\p \reg1, \reg1, v10 + +CPU_LE( rev64 v11.16b, v11.16b ) +CPU_LE( rev64 v12.16b, v12.16b ) + + __pmull_\p v9, \reg2, v10, 2 + __pmull_\p \reg2, \reg2, v10 + +CPU_LE( ext v11.16b, v11.16b, v11.16b, #8 ) +CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 ) + + eor \reg1\().16b, \reg1\().16b, v8.16b + eor \reg2\().16b, \reg2\().16b, v9.16b + eor \reg1\().16b, \reg1\().16b, v11.16b + eor \reg2\().16b, \reg2\().16b, v12.16b + .endm + + .macro fold16, p, reg, rk + __pmull_\p v8, \reg, v10 + __pmull_\p \reg, \reg, v10, 2 + .ifnb \rk + ldr_l q10, \rk, x8 + __pmull_pre_\p v10 + .endif + eor v7.16b, v7.16b, v8.16b + eor v7.16b, v7.16b, \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 frame_push 3, 128 mov arg1_low32, w0 @@ -89,6 +268,8 @@ ENTRY(crc_t10dif_pmull) movi vzr.16b, #0 // init zero register + __pmull_init_\p + // adjust the 16-bit initial_crc value, scale it to 32 bits lsl arg1_low32, arg1_low32, #16 @@ -96,7 +277,7 @@ ENTRY(crc_t10dif_pmull) cmp arg3, #256 // for sizes less than 128, we can't fold 64B at a time... - b.lt _less_than_128 + b.lt .L_less_than_128_\@ // load the initial crc value // crc value does not need to be byte-reflected, but it needs @@ -137,6 +318,7 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) ldr_l q10, rk3, x8 // xmm10 has rk3 and rk4 // type of pmull instruction // will determine which constant to use + __pmull_pre_\p v10 // // we subtract 256 instead of 128 to save one instruction from the loop @@ -147,41 +329,19 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) // buffer. The _fold_64_B_loop will fold 64B at a time // until we have 64+y Bytes of buffer - // fold 64B at a time. This section of the code folds 4 vector // registers in parallel -_fold_64_B_loop: +.L_fold_64_B_loop_\@: - .macro fold64, reg1, reg2 - ldp q11, q12, [arg2], #0x20 - - pmull2 v8.1q, \reg1\().2d, v10.2d - pmull \reg1\().1q, \reg1\().1d, v10.1d - -CPU_LE( rev64 v11.16b, v11.16b ) -CPU_LE( rev64 v12.16b, v12.16b ) - - pmull2 v9.1q, \reg2\().2d, v10.2d - pmull \reg2\().1q, \reg2\().1d, v10.1d - -CPU_LE( ext v11.16b, v11.16b, v11.16b, #8 ) -CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 ) - - eor \reg1\().16b, \reg1\().16b, v8.16b - eor \reg2\().16b, \reg2\().16b, v9.16b - eor \reg1\().16b, \reg1\().16b, v11.16b - eor \reg2\().16b, \reg2\().16b, v12.16b - .endm - - fold64 v0, v1 - fold64 v2, v3 - fold64 v4, v5 - fold64 v6, v7 + fold64 \p, v0, v1 + fold64 \p, v2, v3 + fold64 \p, v4, v5 + fold64 \p, v6, v7 subs arg3, arg3, #128 // check if there is another 64B in the buffer to be able to fold - b.lt _fold_64_B_end + b.lt .L_fold_64_B_end_\@ if_will_cond_yield_neon stp q0, q1, [sp, #.Lframe_local_offset] @@ -195,11 +355,13 @@ CPU_LE( ext v12.16b, v12.16b, v12.16b, #8 ) ldp q6, q7, [sp, #.Lframe_local_offset + 96] ldr_l q10, rk3, x8 movi vzr.16b, #0 // init zero register + __pmull_init_\p + __pmull_pre_\p v10 endif_yield_neon - b _fold_64_B_loop + b .L_fold_64_B_loop_\@ -_fold_64_B_end: +.L_fold_64_B_end_\@: // at this point, the buffer pointer is pointing at the last y Bytes // of the buffer the 64B of folded data is in 4 of the vector // registers: v0, v1, v2, v3 @@ -208,38 +370,29 @@ _fold_64_B_end: // constants ldr_l q10, rk9, x8 + __pmull_pre_\p v10 - .macro fold16, reg, rk - pmull v8.1q, \reg\().1d, v10.1d - pmull2 \reg\().1q, \reg\().2d, v10.2d - .ifnb \rk - ldr_l q10, \rk, x8 - .endif - eor v7.16b, v7.16b, v8.16b - eor v7.16b, v7.16b, \reg\().16b - .endm - - fold16 v0, rk11 - fold16 v1, rk13 - fold16 v2, rk15 - fold16 v3, rk17 - fold16 v4, rk19 - fold16 v5, rk1 - fold16 v6 + fold16 \p, v0, rk11 + fold16 \p, v1, rk13 + fold16 \p, v2, rk15 + fold16 \p, v3, rk17 + fold16 \p, v4, rk19 + fold16 \p, v5, rk1 + fold16 \p, v6 // instead of 64, we add 48 to the loop counter to save 1 instruction // from the loop instead of a cmp instruction, we use the negative // flag with the jl instruction adds arg3, arg3, #(128-16) - b.lt _final_reduction_for_128 + b.lt .L_final_reduction_for_128_\@ // now we have 16+y bytes left to reduce. 16 Bytes is in register v7 // and the rest is in memory. We can fold 16 bytes at a time if y>=16 // continue folding 16B at a time -_16B_reduction_loop: - pmull v8.1q, v7.1d, v10.1d - pmull2 v7.1q, v7.2d, v10.2d +.L_16B_reduction_loop_\@: + __pmull_\p v8, v7, v10 + __pmull_\p v7, v7, v10, 2 eor v7.16b, v7.16b, v8.16b ldr q0, [arg2], #16 @@ -251,22 +404,22 @@ CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 ) // instead of a cmp instruction, we utilize the flags with the // jge instruction equivalent of: cmp arg3, 16-16 // check if there is any more 16B in the buffer to be able to fold - b.ge _16B_reduction_loop + b.ge .L_16B_reduction_loop_\@ // now we have 16+z bytes left to reduce, where 0<= z < 16. // first, we reduce the data in the xmm7 register -_final_reduction_for_128: +.L_final_reduction_for_128_\@: // check if any more data to fold. If not, compute the CRC of // the final 128 bits adds arg3, arg3, #16 - b.eq _128_done + b.eq .L_128_done_\@ // here we are getting data that is less than 16 bytes. // since we know that there was data before the pointer, we can // offset the input pointer before the actual point, to receive // exactly 16 bytes. after that the registers need to be adjusted. -_get_last_two_regs: +.L_get_last_two_regs_\@: add arg2, arg2, arg3 ldr q1, [arg2, #-16] CPU_LE( rev64 v1.16b, v1.16b ) @@ -291,47 +444,48 @@ CPU_LE( ext v1.16b, v1.16b, v1.16b, #8 ) bsl v0.16b, v2.16b, v1.16b // fold 16 Bytes - pmull v8.1q, v7.1d, v10.1d - pmull2 v7.1q, v7.2d, v10.2d + __pmull_\p v8, v7, v10 + __pmull_\p v7, v7, v10, 2 eor v7.16b, v7.16b, v8.16b eor v7.16b, v7.16b, v0.16b -_128_done: +.L_128_done_\@: // compute crc of a 128-bit value ldr_l q10, rk5, x8 // rk5 and rk6 in xmm10 + __pmull_pre_\p v10 // 64b fold ext v0.16b, vzr.16b, v7.16b, #8 mov v7.d[0], v7.d[1] - pmull v7.1q, v7.1d, v10.1d + __pmull_\p v7, v7, v10 eor v7.16b, v7.16b, v0.16b // 32b fold ext v0.16b, v7.16b, vzr.16b, #4 mov v7.s[3], vzr.s[0] - pmull2 v0.1q, v0.2d, v10.2d + __pmull_\p v0, v0, v10, 2 eor v7.16b, v7.16b, v0.16b // barrett reduction -_barrett: ldr_l q10, rk7, x8 + __pmull_pre_\p v10 mov v0.d[0], v7.d[1] - pmull v0.1q, v0.1d, v10.1d + __pmull_\p v0, v0, v10 ext v0.16b, vzr.16b, v0.16b, #12 - pmull2 v0.1q, v0.2d, v10.2d + __pmull_\p v0, v0, v10, 2 ext v0.16b, vzr.16b, v0.16b, #12 eor v7.16b, v7.16b, v0.16b mov w0, v7.s[1] -_cleanup: +.L_cleanup_\@: // scale the result back to 16 bits lsr x0, x0, #16 frame_pop ret -_less_than_128: - cbz arg3, _cleanup +.L_less_than_128_\@: + cbz arg3, .L_cleanup_\@ movi v0.16b, #0 mov v0.s[3], arg1_low32 // get the initial crc value @@ -342,20 +496,21 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) eor v7.16b, v7.16b, v0.16b // xor the initial crc value cmp arg3, #16 - b.eq _128_done // exactly 16 left - b.lt _less_than_16_left + b.eq .L_128_done_\@ // exactly 16 left + b.lt .L_less_than_16_left_\@ ldr_l q10, rk1, x8 // rk1 and rk2 in xmm10 + __pmull_pre_\p v10 // update the counter. subtract 32 instead of 16 to save one // instruction from the loop subs arg3, arg3, #32 - b.ge _16B_reduction_loop + b.ge .L_16B_reduction_loop_\@ add arg3, arg3, #16 - b _get_last_two_regs + b .L_get_last_two_regs_\@ -_less_than_16_left: +.L_less_than_16_left_\@: // shl r9, 4 adr_l x0, tbl_shf_table + 16 sub x0, x0, arg3 @@ -363,8 +518,17 @@ _less_than_16_left: movi v9.16b, #0x80 eor v0.16b, v0.16b, v9.16b tbl v7.16b, {v7.16b}, v0.16b - b _128_done -ENDPROC(crc_t10dif_pmull) + b .L_128_done_\@ + .endm + +ENTRY(crc_t10dif_pmull_p8) + crc_t10dif_pmull p8 +ENDPROC(crc_t10dif_pmull_p8) + + .align 5 +ENTRY(crc_t10dif_pmull_p64) + crc_t10dif_pmull p64 +ENDPROC(crc_t10dif_pmull_p64) // precomputed constants // these constants are precomputed from the poly: diff --git a/arch/arm64/crypto/crct10dif-ce-glue.c b/arch/arm64/crypto/crct10dif-ce-glue.c index 96f0cae4a022..b461d62023f2 100644 --- a/arch/arm64/crypto/crct10dif-ce-glue.c +++ b/arch/arm64/crypto/crct10dif-ce-glue.c @@ -22,7 +22,10 @@ #define CRC_T10DIF_PMULL_CHUNK_SIZE 16U -asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 buf[], u64 len); +asmlinkage u16 crc_t10dif_pmull_p64(u16 init_crc, const u8 buf[], u64 len); +asmlinkage u16 crc_t10dif_pmull_p8(u16 init_crc, const u8 buf[], u64 len); + +static u16 (*crc_t10dif_pmull)(u16 init_crc, const u8 buf[], u64 len); static int crct10dif_init(struct shash_desc *desc) { @@ -85,6 +88,11 @@ static struct shash_alg crc_t10dif_alg = { static int __init crc_t10dif_mod_init(void) { + if (elf_hwcap & HWCAP_PMULL) + crc_t10dif_pmull = crc_t10dif_pmull_p64; + else + crc_t10dif_pmull = crc_t10dif_pmull_p8; + return crypto_register_shash(&crc_t10dif_alg); } @@ -93,8 +101,10 @@ static void __exit crc_t10dif_mod_exit(void) crypto_unregister_shash(&crc_t10dif_alg); } -module_cpu_feature_match(PMULL, crc_t10dif_mod_init); +module_cpu_feature_match(ASIMD, crc_t10dif_mod_init); module_exit(crc_t10dif_mod_exit); MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("crct10dif"); +MODULE_ALIAS_CRYPTO("crct10dif-arm64-ce"); diff --git a/arch/arm64/crypto/speck-neon-core.S b/arch/arm64/crypto/speck-neon-core.S deleted file mode 100644 index b14463438b09..000000000000 --- a/arch/arm64/crypto/speck-neon-core.S +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * ARM64 NEON-accelerated implementation of Speck128-XTS and Speck64-XTS - * - * Copyright (c) 2018 Google, Inc - * - * Author: Eric Biggers <ebiggers@google.com> - */ - -#include <linux/linkage.h> - - .text - - // arguments - ROUND_KEYS .req x0 // const {u64,u32} *round_keys - NROUNDS .req w1 // int nrounds - NROUNDS_X .req x1 - DST .req x2 // void *dst - SRC .req x3 // const void *src - NBYTES .req w4 // unsigned int nbytes - TWEAK .req x5 // void *tweak - - // registers which hold the data being encrypted/decrypted - // (underscores avoid a naming collision with ARM64 registers x0-x3) - X_0 .req v0 - Y_0 .req v1 - X_1 .req v2 - Y_1 .req v3 - X_2 .req v4 - Y_2 .req v5 - X_3 .req v6 - Y_3 .req v7 - - // the round key, duplicated in all lanes - ROUND_KEY .req v8 - - // index vector for tbl-based 8-bit rotates - ROTATE_TABLE .req v9 - ROTATE_TABLE_Q .req q9 - - // temporary registers - TMP0 .req v10 - TMP1 .req v11 - TMP2 .req v12 - TMP3 .req v13 - - // multiplication table for updating XTS tweaks - GFMUL_TABLE .req v14 - GFMUL_TABLE_Q .req q14 - - // next XTS tweak value(s) - TWEAKV_NEXT .req v15 - - // XTS tweaks for the blocks currently being encrypted/decrypted - TWEAKV0 .req v16 - TWEAKV1 .req v17 - TWEAKV2 .req v18 - TWEAKV3 .req v19 - TWEAKV4 .req v20 - TWEAKV5 .req v21 - TWEAKV6 .req v22 - TWEAKV7 .req v23 - - .align 4 -.Lror64_8_table: - .octa 0x080f0e0d0c0b0a090007060504030201 -.Lror32_8_table: - .octa 0x0c0f0e0d080b0a090407060500030201 -.Lrol64_8_table: - .octa 0x0e0d0c0b0a09080f0605040302010007 -.Lrol32_8_table: - .octa 0x0e0d0c0f0a09080b0605040702010003 -.Lgf128mul_table: - .octa 0x00000000000000870000000000000001 -.Lgf64mul_table: - .octa 0x0000000000000000000000002d361b00 - -/* - * _speck_round_128bytes() - Speck encryption round on 128 bytes at a time - * - * Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for - * Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes - * of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64. - * 'lanes' is the lane specifier: "2d" for Speck128 or "4s" for Speck64. - */ -.macro _speck_round_128bytes n, lanes - - // x = ror(x, 8) - tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b - tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b - tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b - tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b - - // x += y - add X_0.\lanes, X_0.\lanes, Y_0.\lanes - add X_1.\lanes, X_1.\lanes, Y_1.\lanes - add X_2.\lanes, X_2.\lanes, Y_2.\lanes - add X_3.\lanes, X_3.\lanes, Y_3.\lanes - - // x ^= k - eor X_0.16b, X_0.16b, ROUND_KEY.16b - eor X_1.16b, X_1.16b, ROUND_KEY.16b - eor X_2.16b, X_2.16b, ROUND_KEY.16b - eor X_3.16b, X_3.16b, ROUND_KEY.16b - - // y = rol(y, 3) - shl TMP0.\lanes, Y_0.\lanes, #3 - shl TMP1.\lanes, Y_1.\lanes, #3 - shl TMP2.\lanes, Y_2.\lanes, #3 - shl TMP3.\lanes, Y_3.\lanes, #3 - sri TMP0.\lanes, Y_0.\lanes, #(\n - 3) - sri TMP1.\lanes, Y_1.\lanes, #(\n - 3) - sri TMP2.\lanes, Y_2.\lanes, #(\n - 3) - sri TMP3.\lanes, Y_3.\lanes, #(\n - 3) - - // y ^= x - eor Y_0.16b, TMP0.16b, X_0.16b - eor Y_1.16b, TMP1.16b, X_1.16b - eor Y_2.16b, TMP2.16b, X_2.16b - eor Y_3.16b, TMP3.16b, X_3.16b -.endm - -/* - * _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time - * - * This is the inverse of _speck_round_128bytes(). - */ -.macro _speck_unround_128bytes n, lanes - - // y ^= x - eor TMP0.16b, Y_0.16b, X_0.16b - eor TMP1.16b, Y_1.16b, X_1.16b - eor TMP2.16b, Y_2.16b, X_2.16b - eor TMP3.16b, Y_3.16b, X_3.16b - - // y = ror(y, 3) - ushr Y_0.\lanes, TMP0.\lanes, #3 - ushr Y_1.\lanes, TMP1.\lanes, #3 - ushr Y_2.\lanes, TMP2.\lanes, #3 - ushr Y_3.\lanes, TMP3.\lanes, #3 - sli Y_0.\lanes, TMP0.\lanes, #(\n - 3) - sli Y_1.\lanes, TMP1.\lanes, #(\n - 3) - sli Y_2.\lanes, TMP2.\lanes, #(\n - 3) - sli Y_3.\lanes, TMP3.\lanes, #(\n - 3) - - // x ^= k - eor X_0.16b, X_0.16b, ROUND_KEY.16b - eor X_1.16b, X_1.16b, ROUND_KEY.16b - eor X_2.16b, X_2.16b, ROUND_KEY.16b - eor X_3.16b, X_3.16b, ROUND_KEY.16b - - // x -= y - sub X_0.\lanes, X_0.\lanes, Y_0.\lanes - sub X_1.\lanes, X_1.\lanes, Y_1.\lanes - sub X_2.\lanes, X_2.\lanes, Y_2.\lanes - sub X_3.\lanes, X_3.\lanes, Y_3.\lanes - - // x = rol(x, 8) - tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b - tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b - tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b - tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b -.endm - -.macro _next_xts_tweak next, cur, tmp, n -.if \n == 64 - /* - * Calculate the next tweak by multiplying the current one by x, - * modulo p(x) = x^128 + x^7 + x^2 + x + 1. - */ - sshr \tmp\().2d, \cur\().2d, #63 - and \tmp\().16b, \tmp\().16b, GFMUL_TABLE.16b - shl \next\().2d, \cur\().2d, #1 - ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 - eor \next\().16b, \next\().16b, \tmp\().16b -.else - /* - * Calculate the next two tweaks by multiplying the current ones by x^2, - * modulo p(x) = x^64 + x^4 + x^3 + x + 1. - */ - ushr \tmp\().2d, \cur\().2d, #62 - shl \next\().2d, \cur\().2d, #2 - tbl \tmp\().16b, {GFMUL_TABLE.16b}, \tmp\().16b - eor \next\().16b, \next\().16b, \tmp\().16b -.endif -.endm - -/* - * _speck_xts_crypt() - Speck-XTS encryption/decryption - * - * Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer - * using Speck-XTS, specifically the variant with a block size of '2n' and round - * count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and - * the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a - * nonzero multiple of 128. - */ -.macro _speck_xts_crypt n, lanes, decrypting - - /* - * If decrypting, modify the ROUND_KEYS parameter to point to the last - * round key rather than the first, since for decryption the round keys - * are used in reverse order. - */ -.if \decrypting - mov NROUNDS, NROUNDS /* zero the high 32 bits */ -.if \n == 64 - add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #3 - sub ROUND_KEYS, ROUND_KEYS, #8 -.else - add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #2 - sub ROUND_KEYS, ROUND_KEYS, #4 -.endif -.endif - - // Load the index vector for tbl-based 8-bit rotates -.if \decrypting - ldr ROTATE_TABLE_Q, .Lrol\n\()_8_table -.else - ldr ROTATE_TABLE_Q, .Lror\n\()_8_table -.endif - - // One-time XTS preparation -.if \n == 64 - // Load first tweak - ld1 {TWEAKV0.16b}, [TWEAK] - - // Load GF(2^128) multiplication table - ldr GFMUL_TABLE_Q, .Lgf128mul_table -.else - // Load first tweak - ld1 {TWEAKV0.8b}, [TWEAK] - - // Load GF(2^64) multiplication table - ldr GFMUL_TABLE_Q, .Lgf64mul_table - - // Calculate second tweak, packing it together with the first - ushr TMP0.2d, TWEAKV0.2d, #63 - shl TMP1.2d, TWEAKV0.2d, #1 - tbl TMP0.8b, {GFMUL_TABLE.16b}, TMP0.8b - eor TMP0.8b, TMP0.8b, TMP1.8b - mov TWEAKV0.d[1], TMP0.d[0] -.endif - -.Lnext_128bytes_\@: - - // Calculate XTS tweaks for next 128 bytes - _next_xts_tweak TWEAKV1, TWEAKV0, TMP0, \n - _next_xts_tweak TWEAKV2, TWEAKV1, TMP0, \n - _next_xts_tweak TWEAKV3, TWEAKV2, TMP0, \n - _next_xts_tweak TWEAKV4, TWEAKV3, TMP0, \n - _next_xts_tweak TWEAKV5, TWEAKV4, TMP0, \n - _next_xts_tweak TWEAKV6, TWEAKV5, TMP0, \n - _next_xts_tweak TWEAKV7, TWEAKV6, TMP0, \n - _next_xts_tweak TWEAKV_NEXT, TWEAKV7, TMP0, \n - - // Load the next source blocks into {X,Y}[0-3] - ld1 {X_0.16b-Y_1.16b}, [SRC], #64 - ld1 {X_2.16b-Y_3.16b}, [SRC], #64 - - // XOR the source blocks with their XTS tweaks - eor TMP0.16b, X_0.16b, TWEAKV0.16b - eor Y_0.16b, Y_0.16b, TWEAKV1.16b - eor TMP1.16b, X_1.16b, TWEAKV2.16b - eor Y_1.16b, Y_1.16b, TWEAKV3.16b - eor TMP2.16b, X_2.16b, TWEAKV4.16b - eor Y_2.16b, Y_2.16b, TWEAKV5.16b - eor TMP3.16b, X_3.16b, TWEAKV6.16b - eor Y_3.16b, Y_3.16b, TWEAKV7.16b - - /* - * De-interleave the 'x' and 'y' elements of each block, i.e. make it so - * that the X[0-3] registers contain only the second halves of blocks, - * and the Y[0-3] registers contain only the first halves of blocks. - * (Speck uses the order (y, x) rather than the more intuitive (x, y).) - */ - uzp2 X_0.\lanes, TMP0.\lanes, Y_0.\lanes - uzp1 Y_0.\lanes, TMP0.\lanes, Y_0.\lanes - uzp2 X_1.\lanes, TMP1.\lanes, Y_1.\lanes - uzp1 Y_1.\lanes, TMP1.\lanes, Y_1.\lanes - uzp2 X_2.\lanes, TMP2.\lanes, Y_2.\lanes - uzp1 Y_2.\lanes, TMP2.\lanes, Y_2.\lanes - uzp2 X_3.\lanes, TMP3.\lanes, Y_3.\lanes - uzp1 Y_3.\lanes, TMP3.\lanes, Y_3.\lanes - - // Do the cipher rounds - mov x6, ROUND_KEYS - mov w7, NROUNDS -.Lnext_round_\@: -.if \decrypting - ld1r {ROUND_KEY.\lanes}, [x6] - sub x6, x6, #( \n / 8 ) - _speck_unround_128bytes \n, \lanes -.else - ld1r {ROUND_KEY.\lanes}, [x6], #( \n / 8 ) - _speck_round_128bytes \n, \lanes -.endif - subs w7, w7, #1 - bne .Lnext_round_\@ - - // Re-interleave the 'x' and 'y' elements of each block - zip1 TMP0.\lanes, Y_0.\lanes, X_0.\lanes - zip2 Y_0.\lanes, Y_0.\lanes, X_0.\lanes - zip1 TMP1.\lanes, Y_1.\lanes, X_1.\lanes - zip2 Y_1.\lanes, Y_1.\lanes, X_1.\lanes - zip1 TMP2.\lanes, Y_2.\lanes, X_2.\lanes - zip2 Y_2.\lanes, Y_2.\lanes, X_2.\lanes - zip1 TMP3.\lanes, Y_3.\lanes, X_3.\lanes - zip2 Y_3.\lanes, Y_3.\lanes, X_3.\lanes - - // XOR the encrypted/decrypted blocks with the tweaks calculated earlier - eor X_0.16b, TMP0.16b, TWEAKV0.16b - eor Y_0.16b, Y_0.16b, TWEAKV1.16b - eor X_1.16b, TMP1.16b, TWEAKV2.16b - eor Y_1.16b, Y_1.16b, TWEAKV3.16b - eor X_2.16b, TMP2.16b, TWEAKV4.16b - eor Y_2.16b, Y_2.16b, TWEAKV5.16b - eor X_3.16b, TMP3.16b, TWEAKV6.16b - eor Y_3.16b, Y_3.16b, TWEAKV7.16b - mov TWEAKV0.16b, TWEAKV_NEXT.16b - - // Store the ciphertext in the destination buffer - st1 {X_0.16b-Y_1.16b}, [DST], #64 - st1 {X_2.16b-Y_3.16b}, [DST], #64 - - // Continue if there are more 128-byte chunks remaining - subs NBYTES, NBYTES, #128 - bne .Lnext_128bytes_\@ - - // Store the next tweak and return -.if \n == 64 - st1 {TWEAKV_NEXT.16b}, [TWEAK] -.else - st1 {TWEAKV_NEXT.8b}, [TWEAK] -.endif - ret -.endm - -ENTRY(speck128_xts_encrypt_neon) - _speck_xts_crypt n=64, lanes=2d, decrypting=0 -ENDPROC(speck128_xts_encrypt_neon) - -ENTRY(speck128_xts_decrypt_neon) - _speck_xts_crypt n=64, lanes=2d, decrypting=1 -ENDPROC(speck128_xts_decrypt_neon) - -ENTRY(speck64_xts_encrypt_neon) - _speck_xts_crypt n=32, lanes=4s, decrypting=0 -ENDPROC(speck64_xts_encrypt_neon) - -ENTRY(speck64_xts_decrypt_neon) - _speck_xts_crypt n=32, lanes=4s, decrypting=1 -ENDPROC(speck64_xts_decrypt_neon) diff --git a/arch/arm64/crypto/speck-neon-glue.c b/arch/arm64/crypto/speck-neon-glue.c deleted file mode 100644 index 6e233aeb4ff4..000000000000 --- a/arch/arm64/crypto/speck-neon-glue.c +++ /dev/null @@ -1,282 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS - * (64-bit version; based on the 32-bit version) - * - * Copyright (c) 2018 Google, Inc - */ - -#include <asm/hwcap.h> -#include <asm/neon.h> -#include <asm/simd.h> -#include <crypto/algapi.h> -#include <crypto/gf128mul.h> -#include <crypto/internal/skcipher.h> -#include <crypto/speck.h> -#include <crypto/xts.h> -#include <linux/kernel.h> -#include <linux/module.h> - -/* The assembly functions only handle multiples of 128 bytes */ -#define SPECK_NEON_CHUNK_SIZE 128 - -/* Speck128 */ - -struct speck128_xts_tfm_ctx { - struct speck128_tfm_ctx main_key; - struct speck128_tfm_ctx tweak_key; -}; - -asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *, - u8 *, const u8 *); -typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *, - const void *, unsigned int, void *); - -static __always_inline int -__speck128_xts_crypt(struct skcipher_request *req, - speck128_crypt_one_t crypt_one, - speck128_xts_crypt_many_t crypt_many) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - le128 tweak; - int err; - - err = skcipher_walk_virt(&walk, req, true); - - crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); - - while (walk.nbytes > 0) { - unsigned int nbytes = walk.nbytes; - u8 *dst = walk.dst.virt.addr; - const u8 *src = walk.src.virt.addr; - - if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { - unsigned int count; - - count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); - kernel_neon_begin(); - (*crypt_many)(ctx->main_key.round_keys, - ctx->main_key.nrounds, - dst, src, count, &tweak); - kernel_neon_end(); - dst += count; - src += count; - nbytes -= count; - } - - /* Handle any remainder with generic code */ - while (nbytes >= sizeof(tweak)) { - le128_xor((le128 *)dst, (const le128 *)src, &tweak); - (*crypt_one)(&ctx->main_key, dst, dst); - le128_xor((le128 *)dst, (const le128 *)dst, &tweak); - gf128mul_x_ble(&tweak, &tweak); - - dst += sizeof(tweak); - src += sizeof(tweak); - nbytes -= sizeof(tweak); - } - err = skcipher_walk_done(&walk, nbytes); - } - - return err; -} - -static int speck128_xts_encrypt(struct skcipher_request *req) -{ - return __speck128_xts_crypt(req, crypto_speck128_encrypt, - speck128_xts_encrypt_neon); -} - -static int speck128_xts_decrypt(struct skcipher_request *req) -{ - return __speck128_xts_crypt(req, crypto_speck128_decrypt, - speck128_xts_decrypt_neon); -} - -static int speck128_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - int err; - - err = xts_verify_key(tfm, key, keylen); - if (err) - return err; - - keylen /= 2; - - err = crypto_speck128_setkey(&ctx->main_key, key, keylen); - if (err) - return err; - - return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen); -} - -/* Speck64 */ - -struct speck64_xts_tfm_ctx { - struct speck64_tfm_ctx main_key; - struct speck64_tfm_ctx tweak_key; -}; - -asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds, - void *dst, const void *src, - unsigned int nbytes, void *tweak); - -typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *, - u8 *, const u8 *); -typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *, - const void *, unsigned int, void *); - -static __always_inline int -__speck64_xts_crypt(struct skcipher_request *req, speck64_crypt_one_t crypt_one, - speck64_xts_crypt_many_t crypt_many) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - const struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - struct skcipher_walk walk; - __le64 tweak; - int err; - - err = skcipher_walk_virt(&walk, req, true); - - crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); - - while (walk.nbytes > 0) { - unsigned int nbytes = walk.nbytes; - u8 *dst = walk.dst.virt.addr; - const u8 *src = walk.src.virt.addr; - - if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { - unsigned int count; - - count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); - kernel_neon_begin(); - (*crypt_many)(ctx->main_key.round_keys, - ctx->main_key.nrounds, - dst, src, count, &tweak); - kernel_neon_end(); - dst += count; - src += count; - nbytes -= count; - } - - /* Handle any remainder with generic code */ - while (nbytes >= sizeof(tweak)) { - *(__le64 *)dst = *(__le64 *)src ^ tweak; - (*crypt_one)(&ctx->main_key, dst, dst); - *(__le64 *)dst ^= tweak; - tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^ - ((tweak & cpu_to_le64(1ULL << 63)) ? - 0x1B : 0)); - dst += sizeof(tweak); - src += sizeof(tweak); - nbytes -= sizeof(tweak); - } - err = skcipher_walk_done(&walk, nbytes); - } - - return err; -} - -static int speck64_xts_encrypt(struct skcipher_request *req) -{ - return __speck64_xts_crypt(req, crypto_speck64_encrypt, - speck64_xts_encrypt_neon); -} - -static int speck64_xts_decrypt(struct skcipher_request *req) -{ - return __speck64_xts_crypt(req, crypto_speck64_decrypt, - speck64_xts_decrypt_neon); -} - -static int speck64_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, - unsigned int keylen) -{ - struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); - int err; - - err = xts_verify_key(tfm, key, keylen); - if (err) - return err; - - keylen /= 2; - - err = crypto_speck64_setkey(&ctx->main_key, key, keylen); - if (err) - return err; - - return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen); -} - -static struct skcipher_alg speck_algs[] = { - { - .base.cra_name = "xts(speck128)", - .base.cra_driver_name = "xts-speck128-neon", - .base.cra_priority = 300, - .base.cra_blocksize = SPECK128_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx), - .base.cra_alignmask = 7, - .base.cra_module = THIS_MODULE, - .min_keysize = 2 * SPECK128_128_KEY_SIZE, - .max_keysize = 2 * SPECK128_256_KEY_SIZE, - .ivsize = SPECK128_BLOCK_SIZE, - .walksize = SPECK_NEON_CHUNK_SIZE, - .setkey = speck128_xts_setkey, - .encrypt = speck128_xts_encrypt, - .decrypt = speck128_xts_decrypt, - }, { - .base.cra_name = "xts(speck64)", - .base.cra_driver_name = "xts-speck64-neon", - .base.cra_priority = 300, - .base.cra_blocksize = SPECK64_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx), - .base.cra_alignmask = 7, - .base.cra_module = THIS_MODULE, - .min_keysize = 2 * SPECK64_96_KEY_SIZE, - .max_keysize = 2 * SPECK64_128_KEY_SIZE, - .ivsize = SPECK64_BLOCK_SIZE, - .walksize = SPECK_NEON_CHUNK_SIZE, - .setkey = speck64_xts_setkey, - .encrypt = speck64_xts_encrypt, - .decrypt = speck64_xts_decrypt, - } -}; - -static int __init speck_neon_module_init(void) -{ - if (!(elf_hwcap & HWCAP_ASIMD)) - return -ENODEV; - return crypto_register_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); -} - -static void __exit speck_neon_module_exit(void) -{ - crypto_unregister_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); -} - -module_init(speck_neon_module_init); -module_exit(speck_neon_module_exit); - -MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); -MODULE_ALIAS_CRYPTO("xts(speck128)"); -MODULE_ALIAS_CRYPTO("xts-speck128-neon"); -MODULE_ALIAS_CRYPTO("xts(speck64)"); -MODULE_ALIAS_CRYPTO("xts-speck64-neon"); diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index cee28a05ee98..93ce86d5dae1 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -25,6 +25,8 @@ #include <linux/sched.h> #include <linux/sched/task_stack.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #ifdef __AARCH64EB__ #define COMPAT_UTS_MACHINE "armv8b\0\0" @@ -32,10 +34,6 @@ #define COMPAT_UTS_MACHINE "armv8l\0\0" #endif -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u16 __compat_uid16_t; @@ -43,27 +41,13 @@ typedef u16 __compat_gid16_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s32 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s16 compat_short_t; -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u16 compat_ushort_t; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { #ifdef __AARCH64EB__ @@ -86,11 +70,11 @@ struct compat_stat { compat_off_t st_size; compat_off_t st_blksize; compat_off_t st_blocks; - compat_time_t st_atime; + old_time32_t st_atime; compat_ulong_t st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; compat_ulong_t st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; compat_ulong_t st_ctime_nsec; compat_ulong_t __unused4[2]; }; diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 6db48d90ad63..7e2ec64aa414 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -537,6 +537,27 @@ static inline void arm64_set_ssbd_mitigation(bool state) {} #endif extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); + +static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange) +{ + switch (parange) { + case 0: return 32; + case 1: return 36; + case 2: return 40; + case 3: return 42; + case 4: return 44; + case 5: return 48; + case 6: return 52; + /* + * A future PE could use a value unknown to the kernel. + * However, by the "D10.1.4 Principles of the ID scheme + * for fields in ID registers", ARM DDI 0487C.a, any new + * value is guaranteed to be higher than what we know already. + * As a safe limit, we return the limit supported by the kernel. + */ + default: return CONFIG_ARM64_PA_BITS; + } +} #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index 5a5fa47a6b18..3dd3d664c5c5 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h @@ -23,7 +23,6 @@ struct dev_archdata { #ifdef CONFIG_XEN const struct dma_map_ops *dev_dma_ops; #endif - bool dma_coherent; }; struct pdev_archdata { diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index b7847eb8a7bb..c41f3fb1446c 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h @@ -44,10 +44,13 @@ void arch_teardown_dma_ops(struct device *dev); #define arch_teardown_dma_ops arch_teardown_dma_ops #endif -/* do not use this function in a driver */ +/* + * Do not use this function in a driver, it is only provided for + * arch/arm/mm/xen.c, which is used by arm64 as well. + */ static inline bool is_device_dma_coherent(struct device *dev) { - return dev->archdata.dma_coherent; + return dev->dma_coherent; } #endif /* __KERNEL__ */ diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h index e73f68569624..fb6609875455 100644 --- a/arch/arm64/include/asm/hugetlb.h +++ b/arch/arm64/include/asm/hugetlb.h @@ -20,48 +20,18 @@ #include <asm/page.h> +#define __HAVE_ARCH_HUGE_PTEP_GET static inline pte_t huge_ptep_get(pte_t *ptep) { return READ_ONCE(*ptep); } - - -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, unsigned long len) { return 0; } -static inline int prepare_hugepage_range(struct file *file, - unsigned long addr, unsigned long len) -{ - struct hstate *h = hstate_file(file); - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (addr & ~huge_page_mask(h)) - return -EINVAL; - return 0; -} - -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - static inline void arch_clear_hugepage_flags(struct page *page) { clear_bit(PG_dcache_clean, &page->flags); @@ -70,20 +40,25 @@ static inline void arch_clear_hugepage_flags(struct page *page) extern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma, struct page *page, int writable); #define arch_make_huge_pte arch_make_huge_pte +#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); +#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty); +#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT extern void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH extern void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep); +#define __HAVE_ARCH_HUGE_PTE_CLEAR extern void huge_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long sz); -#define huge_pte_clear huge_pte_clear extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte, unsigned long sz); #define set_huge_swap_pte_at set_huge_swap_pte_at diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index b476bc46f0ab..6f602af5263c 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -107,6 +107,7 @@ #define VTCR_EL2_RES1 (1 << 31) #define VTCR_EL2_HD (1 << 22) #define VTCR_EL2_HA (1 << 21) +#define VTCR_EL2_PS_SHIFT TCR_EL2_PS_SHIFT #define VTCR_EL2_PS_MASK TCR_EL2_PS_MASK #define VTCR_EL2_TG0_MASK TCR_TG0_MASK #define VTCR_EL2_TG0_4K TCR_TG0_4K @@ -120,63 +121,150 @@ #define VTCR_EL2_IRGN0_WBWA TCR_IRGN0_WBWA #define VTCR_EL2_SL0_SHIFT 6 #define VTCR_EL2_SL0_MASK (3 << VTCR_EL2_SL0_SHIFT) -#define VTCR_EL2_SL0_LVL1 (1 << VTCR_EL2_SL0_SHIFT) #define VTCR_EL2_T0SZ_MASK 0x3f -#define VTCR_EL2_T0SZ_40B 24 #define VTCR_EL2_VS_SHIFT 19 #define VTCR_EL2_VS_8BIT (0 << VTCR_EL2_VS_SHIFT) #define VTCR_EL2_VS_16BIT (1 << VTCR_EL2_VS_SHIFT) +#define VTCR_EL2_T0SZ(x) TCR_T0SZ(x) + /* * We configure the Stage-2 page tables to always restrict the IPA space to be * 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are * not known to exist and will break with this configuration. * - * VTCR_EL2.PS is extracted from ID_AA64MMFR0_EL1.PARange at boot time - * (see hyp-init.S). + * The VTCR_EL2 is configured per VM and is initialised in kvm_arm_setup_stage2(). * * Note that when using 4K pages, we concatenate two first level page tables * together. With 16K pages, we concatenate 16 first level page tables. * - * The magic numbers used for VTTBR_X in this patch can be found in Tables - * D4-23 and D4-25 in ARM DDI 0487A.b. */ -#define VTCR_EL2_T0SZ_IPA VTCR_EL2_T0SZ_40B #define VTCR_EL2_COMMON_BITS (VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \ VTCR_EL2_IRGN0_WBWA | VTCR_EL2_RES1) -#ifdef CONFIG_ARM64_64K_PAGES /* - * Stage2 translation configuration: - * 64kB pages (TG0 = 1) - * 2 level page tables (SL = 1) + * VTCR_EL2:SL0 indicates the entry level for Stage2 translation. + * Interestingly, it depends on the page size. + * See D.10.2.121, VTCR_EL2, in ARM DDI 0487C.a + * + * ----------------------------------------- + * | Entry level | 4K | 16K/64K | + * ------------------------------------------ + * | Level: 0 | 2 | - | + * ------------------------------------------ + * | Level: 1 | 1 | 2 | + * ------------------------------------------ + * | Level: 2 | 0 | 1 | + * ------------------------------------------ + * | Level: 3 | - | 0 | + * ------------------------------------------ + * + * The table roughly translates to : + * + * SL0(PAGE_SIZE, Entry_level) = TGRAN_SL0_BASE - Entry_Level + * + * Where TGRAN_SL0_BASE is a magic number depending on the page size: + * TGRAN_SL0_BASE(4K) = 2 + * TGRAN_SL0_BASE(16K) = 3 + * TGRAN_SL0_BASE(64K) = 3 + * provided we take care of ruling out the unsupported cases and + * Entry_Level = 4 - Number_of_levels. + * */ -#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1) -#define VTTBR_X_TGRAN_MAGIC 38 +#ifdef CONFIG_ARM64_64K_PAGES + +#define VTCR_EL2_TGRAN VTCR_EL2_TG0_64K +#define VTCR_EL2_TGRAN_SL0_BASE 3UL + #elif defined(CONFIG_ARM64_16K_PAGES) -/* - * Stage2 translation configuration: - * 16kB pages (TG0 = 2) - * 2 level page tables (SL = 1) - */ -#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_16K | VTCR_EL2_SL0_LVL1) -#define VTTBR_X_TGRAN_MAGIC 42 + +#define VTCR_EL2_TGRAN VTCR_EL2_TG0_16K +#define VTCR_EL2_TGRAN_SL0_BASE 3UL + #else /* 4K */ -/* - * Stage2 translation configuration: - * 4kB pages (TG0 = 0) - * 3 level page tables (SL = 1) - */ -#define VTCR_EL2_TGRAN_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SL0_LVL1) -#define VTTBR_X_TGRAN_MAGIC 37 + +#define VTCR_EL2_TGRAN VTCR_EL2_TG0_4K +#define VTCR_EL2_TGRAN_SL0_BASE 2UL + #endif -#define VTCR_EL2_FLAGS (VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN_FLAGS) -#define VTTBR_X (VTTBR_X_TGRAN_MAGIC - VTCR_EL2_T0SZ_IPA) +#define VTCR_EL2_LVLS_TO_SL0(levels) \ + ((VTCR_EL2_TGRAN_SL0_BASE - (4 - (levels))) << VTCR_EL2_SL0_SHIFT) +#define VTCR_EL2_SL0_TO_LVLS(sl0) \ + ((sl0) + 4 - VTCR_EL2_TGRAN_SL0_BASE) +#define VTCR_EL2_LVLS(vtcr) \ + VTCR_EL2_SL0_TO_LVLS(((vtcr) & VTCR_EL2_SL0_MASK) >> VTCR_EL2_SL0_SHIFT) + +#define VTCR_EL2_FLAGS (VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN) +#define VTCR_EL2_IPA(vtcr) (64 - ((vtcr) & VTCR_EL2_T0SZ_MASK)) + +/* + * ARM VMSAv8-64 defines an algorithm for finding the translation table + * descriptors in section D4.2.8 in ARM DDI 0487C.a. + * + * The algorithm defines the expectations on the translation table + * addresses for each level, based on PAGE_SIZE, entry level + * and the translation table size (T0SZ). The variable "x" in the + * algorithm determines the alignment of a table base address at a given + * level and thus determines the alignment of VTTBR:BADDR for stage2 + * page table entry level. + * Since the number of bits resolved at the entry level could vary + * depending on the T0SZ, the value of "x" is defined based on a + * Magic constant for a given PAGE_SIZE and Entry Level. The + * intermediate levels must be always aligned to the PAGE_SIZE (i.e, + * x = PAGE_SHIFT). + * + * The value of "x" for entry level is calculated as : + * x = Magic_N - T0SZ + * + * where Magic_N is an integer depending on the page size and the entry + * level of the page table as below: + * + * -------------------------------------------- + * | Entry level | 4K 16K 64K | + * -------------------------------------------- + * | Level: 0 (4 levels) | 28 | - | - | + * -------------------------------------------- + * | Level: 1 (3 levels) | 37 | 31 | 25 | + * -------------------------------------------- + * | Level: 2 (2 levels) | 46 | 42 | 38 | + * -------------------------------------------- + * | Level: 3 (1 level) | - | 53 | 51 | + * -------------------------------------------- + * + * We have a magic formula for the Magic_N below: + * + * Magic_N(PAGE_SIZE, Level) = 64 - ((PAGE_SHIFT - 3) * Number_of_levels) + * + * where Number_of_levels = (4 - Level). We are only interested in the + * value for Entry_Level for the stage2 page table. + * + * So, given that T0SZ = (64 - IPA_SHIFT), we can compute 'x' as follows: + * + * x = (64 - ((PAGE_SHIFT - 3) * Number_of_levels)) - (64 - IPA_SHIFT) + * = IPA_SHIFT - ((PAGE_SHIFT - 3) * Number of levels) + * + * Here is one way to explain the Magic Formula: + * + * x = log2(Size_of_Entry_Level_Table) + * + * Since, we can resolve (PAGE_SHIFT - 3) bits at each level, and another + * PAGE_SHIFT bits in the PTE, we have : + * + * Bits_Entry_level = IPA_SHIFT - ((PAGE_SHIFT - 3) * (n - 1) + PAGE_SHIFT) + * = IPA_SHIFT - (PAGE_SHIFT - 3) * n - 3 + * where n = number of levels, and since each pointer is 8bytes, we have: + * + * x = Bits_Entry_Level + 3 + * = IPA_SHIFT - (PAGE_SHIFT - 3) * n + * + * The only constraint here is that, we have to find the number of page table + * levels for a given IPA size (which we do, see stage2_pt_levels()) + */ +#define ARM64_VTTBR_X(ipa, levels) ((ipa) - ((levels) * (PAGE_SHIFT - 3))) #define VTTBR_CNP_BIT (UL(1)) -#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_X) #define VTTBR_VMID_SHIFT (UL(48)) #define VTTBR_VMID_MASK(size) (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT) @@ -224,6 +312,13 @@ /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ #define HPFAR_MASK (~UL(0xf)) +/* + * We have + * PAR [PA_Shift - 1 : 12] = PA [PA_Shift - 1 : 12] + * HPFAR [PA_Shift - 9 : 4] = FIPA [PA_Shift - 1 : 12] + */ +#define PAR_TO_HPFAR(par) \ + (((par) & GENMASK_ULL(PHYS_MASK_SHIFT - 1, 12)) >> 8) #define kvm_arm_exception_type \ {0, "IRQ" }, \ diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 102b5a5c47b6..aea01a09eb94 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -30,6 +30,7 @@ #define ARM_EXCEPTION_IRQ 0 #define ARM_EXCEPTION_EL1_SERROR 1 #define ARM_EXCEPTION_TRAP 2 +#define ARM_EXCEPTION_IL 3 /* The hyp-stub will return this for any kvm_call_hyp() call */ #define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR @@ -72,8 +73,6 @@ extern void __vgic_v3_init_lrs(void); extern u32 __kvm_get_mdcr_el2(void); -extern u32 __init_stage2_translation(void); - /* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */ #define __hyp_this_cpu_ptr(sym) \ ({ \ diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2842bf149029..52fbc823ff8c 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -53,7 +53,7 @@ DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use); int __attribute_const__ kvm_target_cpu(void); int kvm_reset_vcpu(struct kvm_vcpu *vcpu); -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext); +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext); void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start); struct kvm_arch { @@ -61,11 +61,13 @@ struct kvm_arch { u64 vmid_gen; u32 vmid; - /* 1-level 2nd stage table, protected by kvm->mmu_lock */ + /* stage2 entry level table */ pgd_t *pgd; /* VTTBR value associated with above pgd and vmid */ u64 vttbr; + /* VTCR_EL2 value for this VM */ + u64 vtcr; /* The last vcpu id that ran on each physical CPU */ int __percpu *last_vcpu_ran; @@ -451,13 +453,7 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu, int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); -static inline void __cpu_init_stage2(void) -{ - u32 parange = kvm_call_hyp(__init_stage2_translation); - - WARN_ONCE(parange < 40, - "PARange is %d bits, unsupported configuration!", parange); -} +static inline void __cpu_init_stage2(void) {} /* Guest/host FPSIMD coordination helpers */ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu); @@ -520,8 +516,12 @@ static inline int kvm_arm_have_ssbd(void) void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu); void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu); +void kvm_set_ipa_limit(void); + #define __KVM_HAVE_ARCH_VM_ALLOC struct kvm *kvm_arch_alloc_vm(void); void kvm_arch_free_vm(struct kvm *kvm); +int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type); + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 384c34397619..23aca66767f9 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -155,5 +155,15 @@ void deactivate_traps_vhe_put(void); u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt); void __noreturn __hyp_do_panic(unsigned long, ...); +/* + * Must be called from hyp code running at EL2 with an updated VTTBR + * and interrupts disabled. + */ +static __always_inline void __hyp_text __load_guest_stage2(struct kvm *kvm) +{ + write_sysreg(kvm->arch.vtcr, vtcr_el2); + write_sysreg(kvm->arch.vttbr, vttbr_el2); +} + #endif /* __ARM64_KVM_HYP_H__ */ diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 64337afbf124..658657367f2f 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -141,8 +141,16 @@ static inline unsigned long __kern_hyp_va(unsigned long v) * We currently only support a 40bit IPA. */ #define KVM_PHYS_SHIFT (40) -#define KVM_PHYS_SIZE (1UL << KVM_PHYS_SHIFT) -#define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1UL) + +#define kvm_phys_shift(kvm) VTCR_EL2_IPA(kvm->arch.vtcr) +#define kvm_phys_size(kvm) (_AC(1, ULL) << kvm_phys_shift(kvm)) +#define kvm_phys_mask(kvm) (kvm_phys_size(kvm) - _AC(1, ULL)) + +static inline bool kvm_page_empty(void *ptr) +{ + struct page *ptr_page = virt_to_page(ptr); + return page_count(ptr_page) == 1; +} #include <asm/stage2_pgtable.h> @@ -238,12 +246,6 @@ static inline bool kvm_s2pmd_exec(pmd_t *pmdp) return !(READ_ONCE(pmd_val(*pmdp)) & PMD_S2_XN); } -static inline bool kvm_page_empty(void *ptr) -{ - struct page *ptr_page = virt_to_page(ptr); - return page_count(ptr_page) == 1; -} - #define hyp_pte_table_empty(ptep) kvm_page_empty(ptep) #ifdef __PAGETABLE_PMD_FOLDED @@ -517,6 +519,30 @@ static inline int hyp_map_aux_data(void) #define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr) +/* + * Get the magic number 'x' for VTTBR:BADDR of this KVM instance. + * With v8.2 LVA extensions, 'x' should be a minimum of 6 with + * 52bit IPS. + */ +static inline int arm64_vttbr_x(u32 ipa_shift, u32 levels) +{ + int x = ARM64_VTTBR_X(ipa_shift, levels); + + return (IS_ENABLED(CONFIG_ARM64_PA_BITS_52) && x < 6) ? 6 : x; +} + +static inline u64 vttbr_baddr_mask(u32 ipa_shift, u32 levels) +{ + unsigned int x = arm64_vttbr_x(ipa_shift, levels); + + return GENMASK_ULL(PHYS_MASK_SHIFT - 1, x); +} + +static inline u64 kvm_vttbr_baddr_mask(struct kvm *kvm) +{ + return vttbr_baddr_mask(kvm_phys_shift(kvm), kvm_stage2_levels(kvm)); +} + static inline bool kvm_cpu_has_cnp(void) { return system_supports_cnp(); diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index 6bc43889d11e..fce22c4b2f73 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -25,6 +25,9 @@ #define CurrentEL_EL1 (1 << 2) #define CurrentEL_EL2 (2 << 2) +/* Additional SPSR bits not exposed in the UABI */ +#define PSR_IL_BIT (1 << 20) + /* AArch32-specific ptrace requests */ #define COMPAT_PTRACE_GETREGS 12 #define COMPAT_PTRACE_SETREGS 13 diff --git a/arch/arm64/include/asm/stage2_pgtable-nopmd.h b/arch/arm64/include/asm/stage2_pgtable-nopmd.h deleted file mode 100644 index 2656a0fd05a6..000000000000 --- a/arch/arm64/include/asm/stage2_pgtable-nopmd.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2016 - ARM Ltd - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __ARM64_S2_PGTABLE_NOPMD_H_ -#define __ARM64_S2_PGTABLE_NOPMD_H_ - -#include <asm/stage2_pgtable-nopud.h> - -#define __S2_PGTABLE_PMD_FOLDED - -#define S2_PMD_SHIFT S2_PUD_SHIFT -#define S2_PTRS_PER_PMD 1 -#define S2_PMD_SIZE (1UL << S2_PMD_SHIFT) -#define S2_PMD_MASK (~(S2_PMD_SIZE-1)) - -#define stage2_pud_none(pud) (0) -#define stage2_pud_present(pud) (1) -#define stage2_pud_clear(pud) do { } while (0) -#define stage2_pud_populate(pud, pmd) do { } while (0) -#define stage2_pmd_offset(pud, address) ((pmd_t *)(pud)) - -#define stage2_pmd_free(pmd) do { } while (0) - -#define stage2_pmd_addr_end(addr, end) (end) - -#define stage2_pud_huge(pud) (0) -#define stage2_pmd_table_empty(pmdp) (0) - -#endif diff --git a/arch/arm64/include/asm/stage2_pgtable-nopud.h b/arch/arm64/include/asm/stage2_pgtable-nopud.h deleted file mode 100644 index 5ee87b54ebf3..000000000000 --- a/arch/arm64/include/asm/stage2_pgtable-nopud.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2016 - ARM Ltd - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __ARM64_S2_PGTABLE_NOPUD_H_ -#define __ARM64_S2_PGTABLE_NOPUD_H_ - -#define __S2_PGTABLE_PUD_FOLDED - -#define S2_PUD_SHIFT S2_PGDIR_SHIFT -#define S2_PTRS_PER_PUD 1 -#define S2_PUD_SIZE (_AC(1, UL) << S2_PUD_SHIFT) -#define S2_PUD_MASK (~(S2_PUD_SIZE-1)) - -#define stage2_pgd_none(pgd) (0) -#define stage2_pgd_present(pgd) (1) -#define stage2_pgd_clear(pgd) do { } while (0) -#define stage2_pgd_populate(pgd, pud) do { } while (0) - -#define stage2_pud_offset(pgd, address) ((pud_t *)(pgd)) - -#define stage2_pud_free(x) do { } while (0) - -#define stage2_pud_addr_end(addr, end) (end) -#define stage2_pud_table_empty(pmdp) (0) - -#endif diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h index 8b68099348e5..d352f6df8d2c 100644 --- a/arch/arm64/include/asm/stage2_pgtable.h +++ b/arch/arm64/include/asm/stage2_pgtable.h @@ -19,9 +19,17 @@ #ifndef __ARM64_S2_PGTABLE_H_ #define __ARM64_S2_PGTABLE_H_ +#include <linux/hugetlb.h> #include <asm/pgtable.h> /* + * PGDIR_SHIFT determines the size a top-level page table entry can map + * and depends on the number of levels in the page table. Compute the + * PGDIR_SHIFT for a given number of levels. + */ +#define pt_levels_pgdir_shift(lvls) ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (lvls)) + +/* * The hardware supports concatenation of up to 16 tables at stage2 entry level * and we use the feature whenever possible. * @@ -29,112 +37,208 @@ * On arm64, the smallest PAGE_SIZE supported is 4k, which means * (PAGE_SHIFT - 3) > 4 holds for all page sizes. * This implies, the total number of page table levels at stage2 expected - * by the hardware is actually the number of levels required for (KVM_PHYS_SHIFT - 4) + * by the hardware is actually the number of levels required for (IPA_SHIFT - 4) * in normal translations(e.g, stage1), since we cannot have another level in - * the range (KVM_PHYS_SHIFT, KVM_PHYS_SHIFT - 4). + * the range (IPA_SHIFT, IPA_SHIFT - 4). */ -#define STAGE2_PGTABLE_LEVELS ARM64_HW_PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4) +#define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4) +#define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr) -/* - * With all the supported VA_BITs and 40bit guest IPA, the following condition - * is always true: - * - * STAGE2_PGTABLE_LEVELS <= CONFIG_PGTABLE_LEVELS - * - * We base our stage-2 page table walker helpers on this assumption and - * fall back to using the host version of the helper wherever possible. - * i.e, if a particular level is not folded (e.g, PUD) at stage2, we fall back - * to using the host version, since it is guaranteed it is not folded at host. - * - * If the condition breaks in the future, we can rearrange the host level - * definitions and reuse them for stage2. Till then... - */ -#if STAGE2_PGTABLE_LEVELS > CONFIG_PGTABLE_LEVELS -#error "Unsupported combination of guest IPA and host VA_BITS." -#endif - -/* S2_PGDIR_SHIFT is the size mapped by top-level stage2 entry */ -#define S2_PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - STAGE2_PGTABLE_LEVELS) -#define S2_PGDIR_SIZE (_AC(1, UL) << S2_PGDIR_SHIFT) -#define S2_PGDIR_MASK (~(S2_PGDIR_SIZE - 1)) +/* stage2_pgdir_shift() is the size mapped by top-level stage2 entry for the VM */ +#define stage2_pgdir_shift(kvm) pt_levels_pgdir_shift(kvm_stage2_levels(kvm)) +#define stage2_pgdir_size(kvm) (1ULL << stage2_pgdir_shift(kvm)) +#define stage2_pgdir_mask(kvm) ~(stage2_pgdir_size(kvm) - 1) /* * The number of PTRS across all concatenated stage2 tables given by the * number of bits resolved at the initial level. + * If we force more levels than necessary, we may have (stage2_pgdir_shift > IPA), + * in which case, stage2_pgd_ptrs will have one entry. */ -#define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - S2_PGDIR_SHIFT)) +#define pgd_ptrs_shift(ipa, pgdir_shift) \ + ((ipa) > (pgdir_shift) ? ((ipa) - (pgdir_shift)) : 0) +#define __s2_pgd_ptrs(ipa, lvls) \ + (1 << (pgd_ptrs_shift((ipa), pt_levels_pgdir_shift(lvls)))) +#define __s2_pgd_size(ipa, lvls) (__s2_pgd_ptrs((ipa), (lvls)) * sizeof(pgd_t)) + +#define stage2_pgd_ptrs(kvm) __s2_pgd_ptrs(kvm_phys_shift(kvm), kvm_stage2_levels(kvm)) +#define stage2_pgd_size(kvm) __s2_pgd_size(kvm_phys_shift(kvm), kvm_stage2_levels(kvm)) /* - * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation - * levels in addition to the PGD. + * kvm_mmmu_cache_min_pages() is the number of pages required to install + * a stage-2 translation. We pre-allocate the entry level page table at + * the VM creation. */ -#define KVM_MMU_CACHE_MIN_PAGES (STAGE2_PGTABLE_LEVELS - 1) +#define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1) - -#if STAGE2_PGTABLE_LEVELS > 3 +/* Stage2 PUD definitions when the level is present */ +static inline bool kvm_stage2_has_pud(struct kvm *kvm) +{ + return (CONFIG_PGTABLE_LEVELS > 3) && (kvm_stage2_levels(kvm) > 3); +} #define S2_PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1) -#define S2_PUD_SIZE (_AC(1, UL) << S2_PUD_SHIFT) +#define S2_PUD_SIZE (1UL << S2_PUD_SHIFT) #define S2_PUD_MASK (~(S2_PUD_SIZE - 1)) -#define stage2_pgd_none(pgd) pgd_none(pgd) -#define stage2_pgd_clear(pgd) pgd_clear(pgd) -#define stage2_pgd_present(pgd) pgd_present(pgd) -#define stage2_pgd_populate(pgd, pud) pgd_populate(NULL, pgd, pud) -#define stage2_pud_offset(pgd, address) pud_offset(pgd, address) -#define stage2_pud_free(pud) pud_free(NULL, pud) +static inline bool stage2_pgd_none(struct kvm *kvm, pgd_t pgd) +{ + if (kvm_stage2_has_pud(kvm)) + return pgd_none(pgd); + else + return 0; +} -#define stage2_pud_table_empty(pudp) kvm_page_empty(pudp) +static inline void stage2_pgd_clear(struct kvm *kvm, pgd_t *pgdp) +{ + if (kvm_stage2_has_pud(kvm)) + pgd_clear(pgdp); +} -static inline phys_addr_t stage2_pud_addr_end(phys_addr_t addr, phys_addr_t end) +static inline bool stage2_pgd_present(struct kvm *kvm, pgd_t pgd) { - phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK; + if (kvm_stage2_has_pud(kvm)) + return pgd_present(pgd); + else + return 1; +} - return (boundary - 1 < end - 1) ? boundary : end; +static inline void stage2_pgd_populate(struct kvm *kvm, pgd_t *pgd, pud_t *pud) +{ + if (kvm_stage2_has_pud(kvm)) + pgd_populate(NULL, pgd, pud); +} + +static inline pud_t *stage2_pud_offset(struct kvm *kvm, + pgd_t *pgd, unsigned long address) +{ + if (kvm_stage2_has_pud(kvm)) + return pud_offset(pgd, address); + else + return (pud_t *)pgd; } -#endif /* STAGE2_PGTABLE_LEVELS > 3 */ +static inline void stage2_pud_free(struct kvm *kvm, pud_t *pud) +{ + if (kvm_stage2_has_pud(kvm)) + pud_free(NULL, pud); +} +static inline bool stage2_pud_table_empty(struct kvm *kvm, pud_t *pudp) +{ + if (kvm_stage2_has_pud(kvm)) + return kvm_page_empty(pudp); + else + return false; +} -#if STAGE2_PGTABLE_LEVELS > 2 +static inline phys_addr_t +stage2_pud_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) +{ + if (kvm_stage2_has_pud(kvm)) { + phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK; + + return (boundary - 1 < end - 1) ? boundary : end; + } else { + return end; + } +} + +/* Stage2 PMD definitions when the level is present */ +static inline bool kvm_stage2_has_pmd(struct kvm *kvm) +{ + return (CONFIG_PGTABLE_LEVELS > 2) && (kvm_stage2_levels(kvm) > 2); +} #define S2_PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2) -#define S2_PMD_SIZE (_AC(1, UL) << S2_PMD_SHIFT) +#define S2_PMD_SIZE (1UL << S2_PMD_SHIFT) #define S2_PMD_MASK (~(S2_PMD_SIZE - 1)) -#define stage2_pud_none(pud) pud_none(pud) -#define stage2_pud_clear(pud) pud_clear(pud) -#define stage2_pud_present(pud) pud_present(pud) -#define stage2_pud_populate(pud, pmd) pud_populate(NULL, pud, pmd) -#define stage2_pmd_offset(pud, address) pmd_offset(pud, address) -#define stage2_pmd_free(pmd) pmd_free(NULL, pmd) +static inline bool stage2_pud_none(struct kvm *kvm, pud_t pud) +{ + if (kvm_stage2_has_pmd(kvm)) + return pud_none(pud); + else + return 0; +} + +static inline void stage2_pud_clear(struct kvm *kvm, pud_t *pud) +{ + if (kvm_stage2_has_pmd(kvm)) + pud_clear(pud); +} -#define stage2_pud_huge(pud) pud_huge(pud) -#define stage2_pmd_table_empty(pmdp) kvm_page_empty(pmdp) +static inline bool stage2_pud_present(struct kvm *kvm, pud_t pud) +{ + if (kvm_stage2_has_pmd(kvm)) + return pud_present(pud); + else + return 1; +} -static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end) +static inline void stage2_pud_populate(struct kvm *kvm, pud_t *pud, pmd_t *pmd) { - phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK; + if (kvm_stage2_has_pmd(kvm)) + pud_populate(NULL, pud, pmd); +} - return (boundary - 1 < end - 1) ? boundary : end; +static inline pmd_t *stage2_pmd_offset(struct kvm *kvm, + pud_t *pud, unsigned long address) +{ + if (kvm_stage2_has_pmd(kvm)) + return pmd_offset(pud, address); + else + return (pmd_t *)pud; } -#endif /* STAGE2_PGTABLE_LEVELS > 2 */ +static inline void stage2_pmd_free(struct kvm *kvm, pmd_t *pmd) +{ + if (kvm_stage2_has_pmd(kvm)) + pmd_free(NULL, pmd); +} + +static inline bool stage2_pud_huge(struct kvm *kvm, pud_t pud) +{ + if (kvm_stage2_has_pmd(kvm)) + return pud_huge(pud); + else + return 0; +} + +static inline bool stage2_pmd_table_empty(struct kvm *kvm, pmd_t *pmdp) +{ + if (kvm_stage2_has_pmd(kvm)) + return kvm_page_empty(pmdp); + else + return 0; +} -#define stage2_pte_table_empty(ptep) kvm_page_empty(ptep) +static inline phys_addr_t +stage2_pmd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) +{ + if (kvm_stage2_has_pmd(kvm)) { + phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK; -#if STAGE2_PGTABLE_LEVELS == 2 -#include <asm/stage2_pgtable-nopmd.h> -#elif STAGE2_PGTABLE_LEVELS == 3 -#include <asm/stage2_pgtable-nopud.h> -#endif + return (boundary - 1 < end - 1) ? boundary : end; + } else { + return end; + } +} +static inline bool stage2_pte_table_empty(struct kvm *kvm, pte_t *ptep) +{ + return kvm_page_empty(ptep); +} -#define stage2_pgd_index(addr) (((addr) >> S2_PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) +static inline unsigned long stage2_pgd_index(struct kvm *kvm, phys_addr_t addr) +{ + return (((addr) >> stage2_pgdir_shift(kvm)) & (stage2_pgd_ptrs(kvm) - 1)); +} -static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end) +static inline phys_addr_t +stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) { - phys_addr_t boundary = (addr + S2_PGDIR_SIZE) & S2_PGDIR_MASK; + phys_addr_t boundary = (addr + stage2_pgdir_size(kvm)) & stage2_pgdir_mask(kvm); return (boundary - 1 < end - 1) ? boundary : end; } diff --git a/arch/arm64/include/asm/stat.h b/arch/arm64/include/asm/stat.h index eab738019707..397c6ccd04e7 100644 --- a/arch/arm64/include/asm/stat.h +++ b/arch/arm64/include/asm/stat.h @@ -20,7 +20,7 @@ #ifdef CONFIG_COMPAT -#include <linux/compat_time.h> +#include <linux/time.h> #include <asm/compat.h> /* diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h index dd95d33a5bd5..03a6c256b7ec 100644 --- a/arch/arm64/include/asm/string.h +++ b/arch/arm64/include/asm/string.h @@ -16,6 +16,7 @@ #ifndef __ASM_STRING_H #define __ASM_STRING_H +#ifndef CONFIG_KASAN #define __HAVE_ARCH_STRRCHR extern char *strrchr(const char *, int c); @@ -34,6 +35,13 @@ extern __kernel_size_t strlen(const char *); #define __HAVE_ARCH_STRNLEN extern __kernel_size_t strnlen(const char *, __kernel_size_t); +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *, const void *, size_t); + +#define __HAVE_ARCH_MEMCHR +extern void *memchr(const void *, int, __kernel_size_t); +#endif + #define __HAVE_ARCH_MEMCPY extern void *memcpy(void *, const void *, __kernel_size_t); extern void *__memcpy(void *, const void *, __kernel_size_t); @@ -42,16 +50,10 @@ extern void *__memcpy(void *, const void *, __kernel_size_t); extern void *memmove(void *, const void *, __kernel_size_t); extern void *__memmove(void *, const void *, __kernel_size_t); -#define __HAVE_ARCH_MEMCHR -extern void *memchr(const void *, int, __kernel_size_t); - #define __HAVE_ARCH_MEMSET extern void *memset(void *, int, __kernel_size_t); extern void *__memset(void *, int, __kernel_size_t); -#define __HAVE_ARCH_MEMCMP -extern int memcmp(const void *, const void *, size_t); - #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE void memcpy_flushcache(void *dst, const void *src, size_t cnt); diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 28893a0b141d..0e2a0ecaf484 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -33,7 +33,8 @@ void die(const char *msg, struct pt_regs *regs, int err); struct siginfo; void arm64_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, int err); + int signo, int sicode, void __user *addr, + int err); void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *), diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index c320f3bf6c57..f9c1aa6167d2 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -37,8 +37,9 @@ void register_undef_hook(struct undef_hook *hook); void unregister_undef_hook(struct undef_hook *hook); void force_signal_inject(int signal, int code, unsigned long address); void arm64_notify_segfault(unsigned long addr); -void arm64_force_sig_info(struct siginfo *info, const char *str, - struct task_struct *tsk); +void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str); +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str); +void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str); /* * Move regs->pc to next instruction and do necessary setup before it diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index e0d0f5b856e7..b13ca091f833 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -18,11 +18,11 @@ #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild index 198afbf0688f..6c5adf458690 100644 --- a/arch/arm64/include/uapi/asm/Kbuild +++ b/arch/arm64/include/uapi/asm/Kbuild @@ -19,3 +19,4 @@ generic-y += swab.h generic-y += termbits.h generic-y += termios.h generic-y += types.h +generic-y += siginfo.h diff --git a/arch/arm64/include/uapi/asm/siginfo.h b/arch/arm64/include/uapi/asm/siginfo.h deleted file mode 100644 index 574d12f86039..000000000000 --- a/arch/arm64/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * Copyright (C) 2012 ARM Ltd. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef __ASM_SIGINFO_H -#define __ASM_SIGINFO_H - -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h index 5072cbd15c82..dae1584cf017 100644 --- a/arch/arm64/include/uapi/asm/unistd.h +++ b/arch/arm64/include/uapi/asm/unistd.h @@ -16,5 +16,6 @@ */ #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_NEW_STAT #include <asm-generic/unistd.h> diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index d894a20b70b2..72f63a59b008 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -44,20 +44,23 @@ EXPORT_SYMBOL(__arch_copy_in_user); EXPORT_SYMBOL(memstart_addr); /* string / mem functions */ +#ifndef CONFIG_KASAN EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memchr); +#endif + EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memmove); -EXPORT_SYMBOL(memchr); -EXPORT_SYMBOL(memcmp); /* atomic bitops */ EXPORT_SYMBOL(set_bit); diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 06ca574495af..d7bb6aefae0a 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -210,13 +210,6 @@ NOKPROBE_SYMBOL(call_step_hook); static void send_user_sigtrap(int si_code) { struct pt_regs *regs = current_pt_regs(); - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = si_code; - info.si_addr = (void __user *)instruction_pointer(regs); if (WARN_ON(!user_mode(regs))) return; @@ -224,7 +217,9 @@ static void send_user_sigtrap(int si_code) if (interrupts_enabled(regs)) local_irq_enable(); - arm64_force_sig_info(&info, "User debug trap", current); + arm64_force_sig_fault(SIGTRAP, si_code, + (void __user *)instruction_pointer(regs), + "User debug trap"); } static int single_step_handler(unsigned long addr, unsigned int esr, diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 58c53bc96928..5ebe73b69961 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -842,7 +842,6 @@ asmlinkage void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) */ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) { - siginfo_t info; unsigned int si_code = FPE_FLTUNK; if (esr & ESR_ELx_FP_EXC_TFV) { @@ -858,12 +857,9 @@ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) si_code = FPE_FLTRES; } - clear_siginfo(&info); - info.si_signo = SIGFPE; - info.si_code = si_code; - info.si_addr = (void __user *)instruction_pointer(regs); - - send_sig_info(SIGFPE, &info, current); + send_sig_fault(SIGFPE, si_code, + (void __user *)instruction_pointer(regs), + current); } void fpsimd_thread_switch(struct task_struct *next) diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index 0e2ea1c78542..bb85e2f4603f 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -165,16 +165,15 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) /* Interface called from ACPI code to setup PCI host controller */ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) { - int node = acpi_get_node(root->device->handle); struct acpi_pci_generic_root_info *ri; struct pci_bus *bus, *child; struct acpi_pci_root_ops *root_ops; - ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node); + ri = kzalloc(sizeof(*ri), GFP_KERNEL); if (!ri) return NULL; - root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node); + root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL); if (!root_ops) { kfree(ri); return NULL; diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 6219486fa25f..1710a2d01669 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -182,13 +182,7 @@ static void ptrace_hbptriggered(struct perf_event *bp, struct pt_regs *regs) { struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_HWBKPT; - info.si_addr = (void __user *)(bkpt->trigger); + const char *desc = "Hardware breakpoint trap (ptrace)"; #ifdef CONFIG_COMPAT if (is_compat_task()) { @@ -208,10 +202,14 @@ static void ptrace_hbptriggered(struct perf_event *bp, break; } } - force_sig_ptrace_errno_trap(si_errno, (void __user *)bkpt->trigger); + arm64_force_sig_ptrace_errno_trap(si_errno, + (void __user *)bkpt->trigger, + desc); } #endif - arm64_force_sig_info(&info, "Hardware breakpoint trap (ptrace)", current); + arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, + (void __user *)(bkpt->trigger), + desc); } /* diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 25fcd22a4bb2..96b8f2f51ab2 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -602,7 +602,7 @@ static void __init of_parse_and_init_cpus(void) { struct device_node *dn; - for_each_node_by_type(dn, "cpu") { + for_each_of_cpu_node(dn) { u64 hwid = of_get_cpu_mpidr(dn); if (hwid == INVALID_HWID) diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index a6109825eeb9..32653d156747 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -68,8 +68,8 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags) */ long compat_arm_syscall(struct pt_regs *regs) { - siginfo_t info; unsigned int no = regs->regs[7]; + void __user *addr; switch (no) { /* @@ -112,13 +112,10 @@ long compat_arm_syscall(struct pt_regs *regs) break; } - clear_siginfo(&info); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - - (compat_thumb_mode(regs) ? 2 : 4); + addr = (void __user *)instruction_pointer(regs) - + (compat_thumb_mode(regs) ? 2 : 4); - arm64_notify_die("Oops - bad compat syscall(2)", regs, &info, no); + arm64_notify_die("Oops - bad compat syscall(2)", regs, + SIGILL, ILL_ILLTRP, addr, no); return 0; } diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4066da7f1e5e..5f4d9acb32f5 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -224,24 +224,19 @@ void die(const char *str, struct pt_regs *regs, int err) do_exit(SIGSEGV); } -static bool show_unhandled_signals_ratelimited(void) +static void arm64_show_signal(int signo, const char *str) { static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); - return show_unhandled_signals && __ratelimit(&rs); -} - -void arm64_force_sig_info(struct siginfo *info, const char *str, - struct task_struct *tsk) -{ + struct task_struct *tsk = current; unsigned int esr = tsk->thread.fault_code; struct pt_regs *regs = task_pt_regs(tsk); - if (!unhandled_signal(tsk, info->si_signo)) - goto send_sig; - - if (!show_unhandled_signals_ratelimited()) - goto send_sig; + /* Leave if the signal won't be shown */ + if (!show_unhandled_signals || + !unhandled_signal(tsk, signo) || + !__ratelimit(&rs)) + return; pr_info("%s[%d]: unhandled exception: ", tsk->comm, task_pid_nr(tsk)); if (esr) @@ -251,19 +246,39 @@ void arm64_force_sig_info(struct siginfo *info, const char *str, print_vma_addr(KERN_CONT " in ", regs->pc); pr_cont("\n"); __show_regs(regs); +} + +void arm64_force_sig_fault(int signo, int code, void __user *addr, + const char *str) +{ + arm64_show_signal(signo, str); + force_sig_fault(signo, code, addr, current); +} -send_sig: - force_sig_info(info->si_signo, info, tsk); +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, + const char *str) +{ + arm64_show_signal(SIGBUS, str); + force_sig_mceerr(code, addr, lsb, current); +} + +void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, + const char *str) +{ + arm64_show_signal(SIGTRAP, str); + force_sig_ptrace_errno_trap(errno, addr); } void arm64_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, int err) + int signo, int sicode, void __user *addr, + int err) { if (user_mode(regs)) { WARN_ON(regs != current_pt_regs()); current->thread.fault_address = 0; current->thread.fault_code = err; - arm64_force_sig_info(info, str, current); + + arm64_force_sig_fault(signo, sicode, addr, str); } else { die(str, regs, err); } @@ -350,15 +365,12 @@ exit: void force_signal_inject(int signal, int code, unsigned long address) { - siginfo_t info; const char *desc; struct pt_regs *regs = current_pt_regs(); if (WARN_ON(!user_mode(regs))) return; - clear_siginfo(&info); - switch (signal) { case SIGILL: desc = "undefined instruction"; @@ -377,12 +389,7 @@ void force_signal_inject(int signal, int code, unsigned long address) signal = SIGKILL; } - info.si_signo = signal; - info.si_errno = 0; - info.si_code = code; - info.si_addr = (void __user *)address; - - arm64_notify_die(desc, regs, &info, 0); + arm64_notify_die(desc, regs, signal, code, (void __user *)address, 0); } /* @@ -799,19 +806,13 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) */ asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) { - siginfo_t info; void __user *pc = (void __user *)instruction_pointer(regs); - clear_siginfo(&info); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = pc; - current->thread.fault_address = 0; current->thread.fault_code = esr; - arm64_force_sig_info(&info, "Bad EL0 synchronous exception", current); + arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, + "Bad EL0 synchronous exception"); } #ifdef CONFIG_VMAP_STACK diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index ab29c06a7d4b..03b00007553d 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -183,7 +183,6 @@ SECTIONS INIT_SETUP(16) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS *(.init.rodata.* .init.bss) /* from the EFI stub */ } diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index a6c9fbaeaefc..dd436a50fce7 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -391,15 +391,15 @@ int __attribute_const__ kvm_target_cpu(void) return KVM_ARM_TARGET_CORTEX_A53; case ARM_CPU_PART_CORTEX_A57: return KVM_ARM_TARGET_CORTEX_A57; - }; + } break; case ARM_CPU_IMP_APM: switch (part_number) { case APM_CPU_PART_POTENZA: return KVM_ARM_TARGET_XGENE_POTENZA; - }; + } break; - }; + } /* Return a default generic target */ return KVM_ARM_TARGET_GENERIC_V8; diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index e5e741bfffe1..35a81bebd02b 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -284,6 +284,13 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, */ run->exit_reason = KVM_EXIT_FAIL_ENTRY; return 0; + case ARM_EXCEPTION_IL: + /* + * We attempted an illegal exception return. Guest state must + * have been corrupted somehow. Give up. + */ + run->exit_reason = KVM_EXIT_FAIL_ENTRY; + return -EINVAL; default: kvm_pr_unimpl("Unsupported exception type: %d", exception_index); diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 2fabc2dc1966..82d1904328ad 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_KVM_ARM_HOST) += switch.o obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o obj-$(CONFIG_KVM_ARM_HOST) += tlb.o obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o -obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o # KVM code is run at a different exception code with a different map, so # compiler instrumentation that inserts callbacks or checks into the code may diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 24b4fbafe3e4..b1f14f736962 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -162,6 +162,20 @@ el1_error: mov x0, #ARM_EXCEPTION_EL1_SERROR b __guest_exit +el2_sync: + /* Check for illegal exception return, otherwise panic */ + mrs x0, spsr_el2 + + /* if this was something else, then panic! */ + tst x0, #PSR_IL_BIT + b.eq __hyp_panic + + /* Let's attempt a recovery from the illegal exception return */ + get_vcpu_ptr x1, x0 + mov x0, #ARM_EXCEPTION_IL + b __guest_exit + + el2_error: ldp x0, x1, [sp], #16 @@ -240,7 +254,7 @@ ENTRY(__kvm_hyp_vector) invalid_vect el2t_fiq_invalid // FIQ EL2t invalid_vect el2t_error_invalid // Error EL2t - invalid_vect el2h_sync_invalid // Synchronous EL2h + valid_vect el2_sync // Synchronous EL2h invalid_vect el2h_irq_invalid // IRQ EL2h invalid_vect el2h_fiq_invalid // FIQ EL2h valid_vect el2_error // Error EL2h diff --git a/arch/arm64/kvm/hyp/s2-setup.c b/arch/arm64/kvm/hyp/s2-setup.c deleted file mode 100644 index 603e1ee83e89..000000000000 --- a/arch/arm64/kvm/hyp/s2-setup.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2016 - ARM Ltd - * Author: Marc Zyngier <marc.zyngier@arm.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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/types.h> -#include <asm/kvm_arm.h> -#include <asm/kvm_asm.h> -#include <asm/kvm_hyp.h> - -u32 __hyp_text __init_stage2_translation(void) -{ - u64 val = VTCR_EL2_FLAGS; - u64 parange; - u64 tmp; - - /* - * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS - * bits in VTCR_EL2. Amusingly, the PARange is 4 bits, while - * PS is only 3. Fortunately, bit 19 is RES0 in VTCR_EL2... - */ - parange = read_sysreg(id_aa64mmfr0_el1) & 7; - if (parange > ID_AA64MMFR0_PARANGE_MAX) - parange = ID_AA64MMFR0_PARANGE_MAX; - val |= parange << 16; - - /* Compute the actual PARange... */ - switch (parange) { - case 0: - parange = 32; - break; - case 1: - parange = 36; - break; - case 2: - parange = 40; - break; - case 3: - parange = 42; - break; - case 4: - parange = 44; - break; - case 5: - default: - parange = 48; - break; - } - - /* - * ... and clamp it to 40 bits, unless we have some braindead - * HW that implements less than that. In all cases, we'll - * return that value for the rest of the kernel to decide what - * to do. - */ - val |= 64 - (parange > 40 ? 40 : parange); - - /* - * Check the availability of Hardware Access Flag / Dirty Bit - * Management in ID_AA64MMFR1_EL1 and enable the feature in VTCR_EL2. - */ - tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_HADBS_SHIFT) & 0xf; - if (tmp) - val |= VTCR_EL2_HA; - - /* - * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS - * bit in VTCR_EL2. - */ - tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_VMIDBITS_SHIFT) & 0xf; - val |= (tmp == ID_AA64MMFR1_VMIDBITS_16) ? - VTCR_EL2_VS_16BIT : - VTCR_EL2_VS_8BIT; - - write_sysreg(val, vtcr_el2); - - return parange; -} diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index ca46153d7915..7cc175c88a37 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -198,7 +198,7 @@ void deactivate_traps_vhe_put(void) static void __hyp_text __activate_vm(struct kvm *kvm) { - write_sysreg(kvm->arch.vttbr, vttbr_el2); + __load_guest_stage2(kvm); } static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu) @@ -263,7 +263,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) return false; /* Translation failed, back to guest */ /* Convert PAR to HPFAR format */ - *hpfar = ((tmp >> 12) & ((1UL << 36) - 1)) << 4; + *hpfar = PAR_TO_HPFAR(tmp); return true; } diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c index 76d016b446b2..68d6f7c3b237 100644 --- a/arch/arm64/kvm/hyp/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/sysreg-sr.c @@ -152,8 +152,25 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) static void __hyp_text __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) { + u64 pstate = ctxt->gp_regs.regs.pstate; + u64 mode = pstate & PSR_AA32_MODE_MASK; + + /* + * Safety check to ensure we're setting the CPU up to enter the guest + * in a less privileged mode. + * + * If we are attempting a return to EL2 or higher in AArch64 state, + * program SPSR_EL2 with M=EL2h and the IL bit set which ensures that + * we'll take an illegal exception state exception immediately after + * the ERET to the guest. Attempts to return to AArch32 Hyp will + * result in an illegal exception return because EL2's execution state + * is determined by SCR_EL3.RW. + */ + if (!(mode & PSR_MODE32_BIT) && mode >= PSR_MODE_EL2t) + pstate = PSR_MODE_EL2h | PSR_IL_BIT; + write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); - write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); + write_sysreg_el2(pstate, spsr); if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) write_sysreg_s(ctxt->sys_regs[DISR_EL1], SYS_VDISR_EL2); diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c index 131c7772703c..4dbd9c69a96d 100644 --- a/arch/arm64/kvm/hyp/tlb.c +++ b/arch/arm64/kvm/hyp/tlb.c @@ -30,7 +30,7 @@ static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm) * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so * let's flip TGE before executing the TLB operation. */ - write_sysreg(kvm->arch.vttbr, vttbr_el2); + __load_guest_stage2(kvm); val = read_sysreg(hcr_el2); val &= ~HCR_TGE; write_sysreg(val, hcr_el2); @@ -39,7 +39,7 @@ static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm) static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm) { - write_sysreg(kvm->arch.vttbr, vttbr_el2); + __load_guest_stage2(kvm); isb(); } diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78bbe1ca..b72a3dd56204 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -26,6 +26,7 @@ #include <kvm/arm_arch_timer.h> +#include <asm/cpufeature.h> #include <asm/cputype.h> #include <asm/ptrace.h> #include <asm/kvm_arm.h> @@ -33,6 +34,9 @@ #include <asm/kvm_coproc.h> #include <asm/kvm_mmu.h> +/* Maximum phys_shift supported for any VM on this host */ +static u32 kvm_ipa_limit; + /* * ARMv8 Reset Values */ @@ -55,12 +59,12 @@ static bool cpu_has_32bit_el1(void) } /** - * kvm_arch_dev_ioctl_check_extension + * kvm_arch_vm_ioctl_check_extension * * We currently assume that the number of HW registers is uniform * across all CPUs (see cpuinfo_sanity_check). */ -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; @@ -82,9 +86,11 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: - case KVM_CAP_VCPU_EVENTS: r = 1; break; + case KVM_CAP_ARM_VM_IPA_SIZE: + r = kvm_ipa_limit; + break; default: r = 0; } @@ -133,3 +139,99 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) /* Reset timer */ return kvm_timer_vcpu_reset(vcpu); } + +void kvm_set_ipa_limit(void) +{ + unsigned int ipa_max, pa_max, va_max, parange; + + parange = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1) & 0x7; + pa_max = id_aa64mmfr0_parange_to_phys_shift(parange); + + /* Clamp the IPA limit to the PA size supported by the kernel */ + ipa_max = (pa_max > PHYS_MASK_SHIFT) ? PHYS_MASK_SHIFT : pa_max; + /* + * Since our stage2 table is dependent on the stage1 page table code, + * we must always honor the following condition: + * + * Number of levels in Stage1 >= Number of levels in Stage2. + * + * So clamp the ipa limit further down to limit the number of levels. + * Since we can concatenate upto 16 tables at entry level, we could + * go upto 4bits above the maximum VA addressible with the current + * number of levels. + */ + va_max = PGDIR_SHIFT + PAGE_SHIFT - 3; + va_max += 4; + + if (va_max < ipa_max) + ipa_max = va_max; + + /* + * If the final limit is lower than the real physical address + * limit of the CPUs, report the reason. + */ + if (ipa_max < pa_max) + pr_info("kvm: Limiting the IPA size due to kernel %s Address limit\n", + (va_max < pa_max) ? "Virtual" : "Physical"); + + WARN(ipa_max < KVM_PHYS_SHIFT, + "KVM IPA limit (%d bit) is smaller than default size\n", ipa_max); + kvm_ipa_limit = ipa_max; + kvm_info("IPA Size Limit: %dbits\n", kvm_ipa_limit); +} + +/* + * Configure the VTCR_EL2 for this VM. The VTCR value is common + * across all the physical CPUs on the system. We use system wide + * sanitised values to fill in different fields, except for Hardware + * Management of Access Flags. HA Flag is set unconditionally on + * all CPUs, as it is safe to run with or without the feature and + * the bit is RES0 on CPUs that don't support it. + */ +int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type) +{ + u64 vtcr = VTCR_EL2_FLAGS; + u32 parange, phys_shift; + u8 lvls; + + if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK) + return -EINVAL; + + phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type); + if (phys_shift) { + if (phys_shift > kvm_ipa_limit || + phys_shift < 32) + return -EINVAL; + } else { + phys_shift = KVM_PHYS_SHIFT; + } + + parange = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1) & 7; + if (parange > ID_AA64MMFR0_PARANGE_MAX) + parange = ID_AA64MMFR0_PARANGE_MAX; + vtcr |= parange << VTCR_EL2_PS_SHIFT; + + vtcr |= VTCR_EL2_T0SZ(phys_shift); + /* + * Use a minimum 2 level page table to prevent splitting + * host PMD huge pages at stage2. + */ + lvls = stage2_pgtable_levels(phys_shift); + if (lvls < 2) + lvls = 2; + vtcr |= VTCR_EL2_LVLS_TO_SL0(lvls); + + /* + * Enable the Hardware Access Flag management, unconditionally + * on all CPUs. The features is RES0 on CPUs without the support + * and must be ignored by the CPUs. + */ + vtcr |= VTCR_EL2_HA; + + /* Set the vmid bits */ + vtcr |= (kvm_get_vmid_bits() == 16) ? + VTCR_EL2_VS_16BIT : + VTCR_EL2_VS_8BIT; + kvm->arch.vtcr = vtcr; + return 0; +} diff --git a/arch/arm64/lib/memchr.S b/arch/arm64/lib/memchr.S index 4444c1d25f4b..0f164a4baf52 100644 --- a/arch/arm64/lib/memchr.S +++ b/arch/arm64/lib/memchr.S @@ -30,7 +30,7 @@ * Returns: * x0 - address of first occurrence of 'c' or 0 */ -ENTRY(memchr) +WEAK(memchr) and w1, w1, #0xff 1: subs x2, x2, #1 b.mi 2f diff --git a/arch/arm64/lib/memcmp.S b/arch/arm64/lib/memcmp.S index 2a4e239bd17a..fb295f52e9f8 100644 --- a/arch/arm64/lib/memcmp.S +++ b/arch/arm64/lib/memcmp.S @@ -58,7 +58,7 @@ pos .req x11 limit_wd .req x12 mask .req x13 -ENTRY(memcmp) +WEAK(memcmp) cbz limit, .Lret0 eor tmp1, src1, src2 tst tmp1, #7 diff --git a/arch/arm64/lib/strchr.S b/arch/arm64/lib/strchr.S index dae0cf5591f9..7c83091d1bcd 100644 --- a/arch/arm64/lib/strchr.S +++ b/arch/arm64/lib/strchr.S @@ -29,7 +29,7 @@ * Returns: * x0 - address of first occurrence of 'c' or 0 */ -ENTRY(strchr) +WEAK(strchr) and w1, w1, #0xff 1: ldrb w2, [x0], #1 cmp w2, w1 diff --git a/arch/arm64/lib/strcmp.S b/arch/arm64/lib/strcmp.S index 471fe61760ef..7d5d15398bfb 100644 --- a/arch/arm64/lib/strcmp.S +++ b/arch/arm64/lib/strcmp.S @@ -60,7 +60,7 @@ tmp3 .req x9 zeroones .req x10 pos .req x11 -ENTRY(strcmp) +WEAK(strcmp) eor tmp1, src1, src2 mov zeroones, #REP8_01 tst tmp1, #7 diff --git a/arch/arm64/lib/strlen.S b/arch/arm64/lib/strlen.S index 55ccc8e24c08..8e0b14205dcb 100644 --- a/arch/arm64/lib/strlen.S +++ b/arch/arm64/lib/strlen.S @@ -56,7 +56,7 @@ pos .req x12 #define REP8_7f 0x7f7f7f7f7f7f7f7f #define REP8_80 0x8080808080808080 -ENTRY(strlen) +WEAK(strlen) mov zeroones, #REP8_01 bic src, srcin, #15 ands tmp1, srcin, #15 diff --git a/arch/arm64/lib/strncmp.S b/arch/arm64/lib/strncmp.S index e267044761c6..66bd145935d9 100644 --- a/arch/arm64/lib/strncmp.S +++ b/arch/arm64/lib/strncmp.S @@ -64,7 +64,7 @@ limit_wd .req x13 mask .req x14 endloop .req x15 -ENTRY(strncmp) +WEAK(strncmp) cbz limit, .Lret0 eor tmp1, src1, src2 mov zeroones, #REP8_01 diff --git a/arch/arm64/lib/strnlen.S b/arch/arm64/lib/strnlen.S index eae38da6e0bb..355be04441fe 100644 --- a/arch/arm64/lib/strnlen.S +++ b/arch/arm64/lib/strnlen.S @@ -59,7 +59,7 @@ limit_wd .req x14 #define REP8_7f 0x7f7f7f7f7f7f7f7f #define REP8_80 0x8080808080808080 -ENTRY(strnlen) +WEAK(strnlen) cbz limit, .Lhit_limit mov zeroones, #REP8_01 bic src, srcin, #15 diff --git a/arch/arm64/lib/strrchr.S b/arch/arm64/lib/strrchr.S index f8e2784d5752..ea84924d5990 100644 --- a/arch/arm64/lib/strrchr.S +++ b/arch/arm64/lib/strrchr.S @@ -29,7 +29,7 @@ * Returns: * x0 - address of last occurrence of 'c' or 0 */ -ENTRY(strrchr) +WEAK(strrchr) mov x3, #0 and w1, w1, #0xff 1: ldrb w2, [x0], #1 diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 072c51fb07d7..d190612b8f33 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -25,6 +25,7 @@ #include <linux/slab.h> #include <linux/genalloc.h> #include <linux/dma-direct.h> +#include <linux/dma-noncoherent.h> #include <linux/dma-contiguous.h> #include <linux/vmalloc.h> #include <linux/swiotlb.h> @@ -32,16 +33,6 @@ #include <asm/cacheflush.h> -static int swiotlb __ro_after_init; - -static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, - bool coherent) -{ - if (!coherent || (attrs & DMA_ATTR_WRITE_COMBINE)) - return pgprot_writecombine(prot); - return prot; -} - static struct gen_pool *atomic_pool __ro_after_init; #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K @@ -91,18 +82,16 @@ static int __free_from_pool(void *start, size_t size) return 1; } -static void *__dma_alloc(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flags, - unsigned long attrs) +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flags, unsigned long attrs) { struct page *page; void *ptr, *coherent_ptr; - bool coherent = is_device_dma_coherent(dev); - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false); + pgprot_t prot = pgprot_writecombine(PAGE_KERNEL); size = PAGE_ALIGN(size); - if (!coherent && !gfpflags_allow_blocking(flags)) { + if (!gfpflags_allow_blocking(flags)) { struct page *page = NULL; void *addr = __alloc_from_pool(size, &page, flags); @@ -112,14 +101,10 @@ static void *__dma_alloc(struct device *dev, size_t size, return addr; } - ptr = swiotlb_alloc(dev, size, dma_handle, flags, attrs); + ptr = dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs); if (!ptr) goto no_mem; - /* no need for non-cacheable mapping if coherent */ - if (coherent) - return ptr; - /* remove any dirty cache lines on the kernel alias */ __dma_flush_area(ptr, size); @@ -133,130 +118,57 @@ static void *__dma_alloc(struct device *dev, size_t size, return coherent_ptr; no_map: - swiotlb_free(dev, size, ptr, *dma_handle, attrs); + dma_direct_free_pages(dev, size, ptr, *dma_handle, attrs); no_mem: return NULL; } -static void __dma_free(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle, - unsigned long attrs) +void arch_dma_free(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, unsigned long attrs) { - void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle)); + if (!__free_from_pool(vaddr, PAGE_ALIGN(size))) { + void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle)); - size = PAGE_ALIGN(size); - - if (!is_device_dma_coherent(dev)) { - if (__free_from_pool(vaddr, size)) - return; vunmap(vaddr); + dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs); } - swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs); } -static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, - unsigned long attrs) +long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr, + dma_addr_t dma_addr) { - dma_addr_t dev_addr; - - dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs); - if (!is_device_dma_coherent(dev) && - (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); - - return dev_addr; -} - - -static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr, - size_t size, enum dma_data_direction dir, - unsigned long attrs) -{ - if (!is_device_dma_coherent(dev) && - (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); - swiotlb_unmap_page(dev, dev_addr, size, dir, attrs); + return __phys_to_pfn(dma_to_phys(dev, dma_addr)); } -static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl, - int nelems, enum dma_data_direction dir, - unsigned long attrs) +pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, + unsigned long attrs) { - struct scatterlist *sg; - int i, ret; - - ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs); - if (!is_device_dma_coherent(dev) && - (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - for_each_sg(sgl, sg, ret, i) - __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), - sg->length, dir); - - return ret; -} - -static void __swiotlb_unmap_sg_attrs(struct device *dev, - struct scatterlist *sgl, int nelems, - enum dma_data_direction dir, - unsigned long attrs) -{ - struct scatterlist *sg; - int i; - - if (!is_device_dma_coherent(dev) && - (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - for_each_sg(sgl, sg, nelems, i) - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), - sg->length, dir); - swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs); + if (!dev_is_dma_coherent(dev) || (attrs & DMA_ATTR_WRITE_COMBINE)) + return pgprot_writecombine(prot); + return prot; } -static void __swiotlb_sync_single_for_cpu(struct device *dev, - dma_addr_t dev_addr, size_t size, - enum dma_data_direction dir) +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) { - if (!is_device_dma_coherent(dev)) - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); - swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir); + __dma_map_area(phys_to_virt(paddr), size, dir); } -static void __swiotlb_sync_single_for_device(struct device *dev, - dma_addr_t dev_addr, size_t size, - enum dma_data_direction dir) +void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) { - swiotlb_sync_single_for_device(dev, dev_addr, size, dir); - if (!is_device_dma_coherent(dev)) - __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); + __dma_unmap_area(phys_to_virt(paddr), size, dir); } -static void __swiotlb_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) +static int __swiotlb_get_sgtable_page(struct sg_table *sgt, + struct page *page, size_t size) { - struct scatterlist *sg; - int i; - - if (!is_device_dma_coherent(dev)) - for_each_sg(sgl, sg, nelems, i) - __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), - sg->length, dir); - swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir); -} + int ret = sg_alloc_table(sgt, 1, GFP_KERNEL); -static void __swiotlb_sync_sg_for_device(struct device *dev, - struct scatterlist *sgl, int nelems, - enum dma_data_direction dir) -{ - struct scatterlist *sg; - int i; + if (!ret) + sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); - swiotlb_sync_sg_for_device(dev, sgl, nelems, dir); - if (!is_device_dma_coherent(dev)) - for_each_sg(sgl, sg, nelems, i) - __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), - sg->length, dir); + return ret; } static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, @@ -277,74 +189,6 @@ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, return ret; } -static int __swiotlb_mmap(struct device *dev, - struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t dma_addr, size_t size, - unsigned long attrs) -{ - int ret; - unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT; - - vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, - is_device_dma_coherent(dev)); - - if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) - return ret; - - return __swiotlb_mmap_pfn(vma, pfn, size); -} - -static int __swiotlb_get_sgtable_page(struct sg_table *sgt, - struct page *page, size_t size) -{ - int ret = sg_alloc_table(sgt, 1, GFP_KERNEL); - - if (!ret) - sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); - - return ret; -} - -static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size, - unsigned long attrs) -{ - struct page *page = phys_to_page(dma_to_phys(dev, handle)); - - return __swiotlb_get_sgtable_page(sgt, page, size); -} - -static int __swiotlb_dma_supported(struct device *hwdev, u64 mask) -{ - if (swiotlb) - return swiotlb_dma_supported(hwdev, mask); - return 1; -} - -static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr) -{ - if (swiotlb) - return swiotlb_dma_mapping_error(hwdev, addr); - return 0; -} - -static const struct dma_map_ops arm64_swiotlb_dma_ops = { - .alloc = __dma_alloc, - .free = __dma_free, - .mmap = __swiotlb_mmap, - .get_sgtable = __swiotlb_get_sgtable, - .map_page = __swiotlb_map_page, - .unmap_page = __swiotlb_unmap_page, - .map_sg = __swiotlb_map_sg_attrs, - .unmap_sg = __swiotlb_unmap_sg_attrs, - .sync_single_for_cpu = __swiotlb_sync_single_for_cpu, - .sync_single_for_device = __swiotlb_sync_single_for_device, - .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu, - .sync_sg_for_device = __swiotlb_sync_sg_for_device, - .dma_supported = __swiotlb_dma_supported, - .mapping_error = __swiotlb_dma_mapping_error, -}; - static int __init atomic_pool_init(void) { pgprot_t prot = __pgprot(PROT_NORMAL_NC); @@ -500,10 +344,6 @@ EXPORT_SYMBOL(dummy_dma_ops); static int __init arm64_dma_init(void) { - if (swiotlb_force == SWIOTLB_FORCE || - max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) - swiotlb = 1; - WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(), TAINT_CPU_OUT_OF_SPEC, "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", @@ -528,7 +368,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, unsigned long attrs) { - bool coherent = is_device_dma_coherent(dev); + bool coherent = dev_is_dma_coherent(dev); int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs); size_t iosize = size; void *addr; @@ -569,7 +409,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, addr = NULL; } } else if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) { - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent); + pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs); struct page *page; page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, @@ -596,7 +436,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, size >> PAGE_SHIFT); } } else { - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent); + pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs); struct page **pages; pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot, @@ -658,8 +498,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, struct vm_struct *area; int ret; - vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, - is_device_dma_coherent(dev)); + vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs); if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) return ret; @@ -709,11 +548,11 @@ static void __iommu_sync_single_for_cpu(struct device *dev, { phys_addr_t phys; - if (is_device_dma_coherent(dev)) + if (dev_is_dma_coherent(dev)) return; - phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); - __dma_unmap_area(phys_to_virt(phys), size, dir); + phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dev_addr); + arch_sync_dma_for_cpu(dev, phys, size, dir); } static void __iommu_sync_single_for_device(struct device *dev, @@ -722,11 +561,11 @@ static void __iommu_sync_single_for_device(struct device *dev, { phys_addr_t phys; - if (is_device_dma_coherent(dev)) + if (dev_is_dma_coherent(dev)) return; - phys = iommu_iova_to_phys(iommu_get_domain_for_dev(dev), dev_addr); - __dma_map_area(phys_to_virt(phys), size, dir); + phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dev_addr); + arch_sync_dma_for_device(dev, phys, size, dir); } static dma_addr_t __iommu_map_page(struct device *dev, struct page *page, @@ -734,13 +573,13 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page, enum dma_data_direction dir, unsigned long attrs) { - bool coherent = is_device_dma_coherent(dev); + bool coherent = dev_is_dma_coherent(dev); int prot = dma_info_to_prot(dir, coherent, attrs); dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot); - if (!iommu_dma_mapping_error(dev, dev_addr) && - (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) - __iommu_sync_single_for_device(dev, dev_addr, size, dir); + if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) && + !iommu_dma_mapping_error(dev, dev_addr)) + __dma_map_area(page_address(page) + offset, size, dir); return dev_addr; } @@ -762,11 +601,11 @@ static void __iommu_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg; int i; - if (is_device_dma_coherent(dev)) + if (dev_is_dma_coherent(dev)) return; for_each_sg(sgl, sg, nelems, i) - __dma_unmap_area(sg_virt(sg), sg->length, dir); + arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir); } static void __iommu_sync_sg_for_device(struct device *dev, @@ -776,18 +615,18 @@ static void __iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg; int i; - if (is_device_dma_coherent(dev)) + if (dev_is_dma_coherent(dev)) return; for_each_sg(sgl, sg, nelems, i) - __dma_map_area(sg_virt(sg), sg->length, dir); + arch_sync_dma_for_device(dev, sg_phys(sg), sg->length, dir); } static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nelems, enum dma_data_direction dir, unsigned long attrs) { - bool coherent = is_device_dma_coherent(dev); + bool coherent = dev_is_dma_coherent(dev); if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) __iommu_sync_sg_for_device(dev, sgl, nelems, dir); @@ -879,9 +718,9 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, const struct iommu_ops *iommu, bool coherent) { if (!dev->dma_ops) - dev->dma_ops = &arm64_swiotlb_dma_ops; + dev->dma_ops = &swiotlb_dma_ops; - dev->archdata.dma_coherent = coherent; + dev->dma_coherent = coherent; __iommu_setup_dma_ops(dev, dma_base, size, iommu); #ifdef CONFIG_XEN diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index d0e638ef3af6..7d9571f4ae3d 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -303,9 +303,9 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, die_kernel_fault(msg, addr, esr, regs); } -static void __do_user_fault(struct siginfo *info, unsigned int esr) +static void set_thread_esr(unsigned long address, unsigned int esr) { - current->thread.fault_address = (unsigned long)info->si_addr; + current->thread.fault_address = address; /* * If the faulting address is in the kernel, we must sanitize the ESR. @@ -358,7 +358,6 @@ static void __do_user_fault(struct siginfo *info, unsigned int esr) } current->thread.fault_code = esr; - arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current); } static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) @@ -369,14 +368,10 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re */ if (user_mode(regs)) { const struct fault_info *inf = esr_to_fault_info(esr); - struct siginfo si; - clear_siginfo(&si); - si.si_signo = inf->sig; - si.si_code = inf->code; - si.si_addr = (void __user *)addr; - - __do_user_fault(&si, esr); + set_thread_esr(addr, esr); + arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr, + inf->name); } else { __do_kernel_fault(addr, esr, regs); } @@ -430,9 +425,9 @@ static bool is_el0_instruction_abort(unsigned int esr) static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, struct pt_regs *regs) { + const struct fault_info *inf; struct task_struct *tsk; struct mm_struct *mm; - struct siginfo si; vm_fault_t fault, major = 0; unsigned long vm_flags = VM_READ | VM_WRITE; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; @@ -568,37 +563,35 @@ retry: return 0; } - clear_siginfo(&si); - si.si_addr = (void __user *)addr; - + inf = esr_to_fault_info(esr); + set_thread_esr(addr, esr); if (fault & VM_FAULT_SIGBUS) { /* * We had some memory, but were unable to successfully fix up * this page fault. */ - si.si_signo = SIGBUS; - si.si_code = BUS_ADRERR; - } else if (fault & VM_FAULT_HWPOISON_LARGE) { - unsigned int hindex = VM_FAULT_GET_HINDEX(fault); - - si.si_signo = SIGBUS; - si.si_code = BUS_MCEERR_AR; - si.si_addr_lsb = hstate_index_to_shift(hindex); - } else if (fault & VM_FAULT_HWPOISON) { - si.si_signo = SIGBUS; - si.si_code = BUS_MCEERR_AR; - si.si_addr_lsb = PAGE_SHIFT; + arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr, + inf->name); + } else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) { + unsigned int lsb; + + lsb = PAGE_SHIFT; + if (fault & VM_FAULT_HWPOISON_LARGE) + lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); + + arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb, + inf->name); } else { /* * Something tried to access memory that isn't in our memory * map. */ - si.si_signo = SIGSEGV; - si.si_code = fault == VM_FAULT_BADACCESS ? - SEGV_ACCERR : SEGV_MAPERR; + arm64_force_sig_fault(SIGSEGV, + fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR, + (void __user *)addr, + inf->name); } - __do_user_fault(&si, esr); return 0; no_context: @@ -631,8 +624,8 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - struct siginfo info; const struct fault_info *inf; + void __user *siaddr; inf = esr_to_fault_info(esr); @@ -651,15 +644,11 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) nmi_exit(); } - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; if (esr & ESR_ELx_FnV) - info.si_addr = NULL; + siaddr = NULL; else - info.si_addr = (void __user *)addr; - arm64_notify_die(inf->name, regs, &info, esr); + siaddr = (void __user *)addr; + arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr); return 0; } @@ -740,7 +729,6 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { const struct fault_info *inf = esr_to_fault_info(esr); - struct siginfo info; if (!inf->fn(addr, esr, regs)) return; @@ -751,12 +739,8 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, show_pte(addr); } - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm64_notify_die(inf->name, regs, &info, esr); + arm64_notify_die(inf->name, regs, + inf->sig, inf->code, (void __user *)addr, esr); } asmlinkage void __exception do_el0_irq_bp_hardening(void) @@ -786,20 +770,14 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - struct siginfo info; - if (user_mode(regs)) { if (instruction_pointer(regs) > TASK_SIZE) arm64_apply_bp_hardening(); local_daif_restore(DAIF_PROCCTX); } - clear_siginfo(&info); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)addr; - arm64_notify_die("SP/PC alignment exception", regs, &info, esr); + arm64_notify_die("SP/PC alignment exception", regs, + SIGBUS, BUS_ADRALN, (void __user *)addr, esr); } int __init early_brk64(unsigned long addr, unsigned int esr, @@ -853,14 +831,8 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, if (!inf->fn(addr, esr, regs)) { rv = 1; } else { - struct siginfo info; - - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - arm64_notify_die(inf->name, regs, &info, esr); + arm64_notify_die(inf->name, regs, + inf->sig, inf->code, (void __user *)addr, esr); rv = 0; } diff --git a/arch/c6x/Makefile b/arch/c6x/Makefile index 3fe8a948e94c..b7aa854f7008 100644 --- a/arch/c6x/Makefile +++ b/arch/c6x/Makefile @@ -40,9 +40,7 @@ boot := arch/$(ARCH)/boot DTB:=$(subst dtbImage.,,$(filter dtbImage.%, $(MAKECMDGOALS))) export DTB -ifneq ($(DTB),) core-y += $(boot)/dts/ -endif # With make 3.82 we cannot mix normal and wildcard targets diff --git a/arch/c6x/boot/dts/Makefile b/arch/c6x/boot/dts/Makefile index b212d278ebc4..f438285c3640 100644 --- a/arch/c6x/boot/dts/Makefile +++ b/arch/c6x/boot/dts/Makefile @@ -5,15 +5,12 @@ DTC_FLAGS ?= -p 1024 +dtb-$(CONFIG_SOC_TMS320C6455) += dsk6455.dtb +dtb-$(CONFIG_SOC_TMS320C6457) += evmc6457.dtb +dtb-$(CONFIG_SOC_TMS320C6472) += evmc6472.dtb +dtb-$(CONFIG_SOC_TMS320C6474) += evmc6474.dtb +dtb-$(CONFIG_SOC_TMS320C6678) += evmc6678.dtb + ifneq ($(DTB),) -obj-y += linked_dtb.o +obj-y += $(DTB).dtb.o endif - -quiet_cmd_cp = CP $< $@$2 - cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false) - -# Generate builtin.dtb from $(DTB).dtb -$(obj)/builtin.dtb: $(obj)/$(DTB).dtb - $(call if_changed,cp) - -$(obj)/linked_dtb.o: $(obj)/builtin.dtb diff --git a/arch/c6x/boot/dts/linked_dtb.S b/arch/c6x/boot/dts/linked_dtb.S deleted file mode 100644 index cf347f1d16ce..000000000000 --- a/arch/c6x/boot/dts/linked_dtb.S +++ /dev/null @@ -1,2 +0,0 @@ -.section __fdt_blob,"a" -.incbin "arch/c6x/boot/dts/builtin.dtb" diff --git a/arch/c6x/include/asm/sections.h b/arch/c6x/include/asm/sections.h index d6c591ab5b7e..dc2f15eb3bde 100644 --- a/arch/c6x/include/asm/sections.h +++ b/arch/c6x/include/asm/sections.h @@ -8,6 +8,5 @@ extern char _vectors_start[]; extern char _vectors_end[]; extern char _data_lma[]; -extern char _fdt_start[], _fdt_end[]; #endif /* _ASM_C6X_SECTIONS_H */ diff --git a/arch/c6x/include/uapi/asm/unistd.h b/arch/c6x/include/uapi/asm/unistd.h index 0d2daf7f9809..6b2fe792de9d 100644 --- a/arch/c6x/include/uapi/asm/unistd.h +++ b/arch/c6x/include/uapi/asm/unistd.h @@ -16,6 +16,7 @@ */ #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_CLONE /* Use the standard ABI for syscalls. */ diff --git a/arch/c6x/kernel/setup.c b/arch/c6x/kernel/setup.c index 786e36e2f61d..05d96a9541b5 100644 --- a/arch/c6x/kernel/setup.c +++ b/arch/c6x/kernel/setup.c @@ -96,7 +96,7 @@ static void __init get_cpuinfo(void) unsigned long core_khz; u64 tmp; struct cpuinfo_c6x *p; - struct device_node *node, *np; + struct device_node *node; p = &per_cpu(cpu_data, smp_processor_id()); @@ -190,13 +190,8 @@ static void __init get_cpuinfo(void) p->core_id = get_coreid(); - node = of_find_node_by_name(NULL, "cpus"); - if (node) { - for_each_child_of_node(node, np) - if (!strcmp("cpu", np->name)) - ++c6x_num_cores; - of_node_put(node); - } + for_each_of_cpu_node(node) + ++c6x_num_cores; node = of_find_node_by_name(NULL, "soc"); if (node) { @@ -270,7 +265,7 @@ int __init c6x_add_memory(phys_addr_t start, unsigned long size) notrace void __init machine_init(unsigned long dt_ptr) { void *dtb = __va(dt_ptr); - void *fdt = _fdt_start; + void *fdt = __dtb_start; /* interrupts must be masked */ set_creg(IER, 2); @@ -363,7 +358,7 @@ void __init setup_arch(char **cmdline_p) memory_end >> PAGE_SHIFT); memblock_reserve(memory_start, bootmap_size); - unflatten_device_tree(); + unflatten_and_copy_device_tree(); c6x_cache_init(); diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S index 1fba5b421eee..584bab2bace6 100644 --- a/arch/c6x/kernel/vmlinux.lds.S +++ b/arch/c6x/kernel/vmlinux.lds.S @@ -90,16 +90,6 @@ SECTIONS *(.switch) } - . = ALIGN (8) ; - __fdt_blob : AT(ADDR(__fdt_blob) - LOAD_OFFSET) - { - _fdt_start = . ; /* place for fdt blob */ - *(__fdt_blob) ; /* Any link-placed DTB */ - BYTE(0); /* section always has contents */ - . = _fdt_start + 0x4000; /* Pad up to 16kbyte */ - _fdt_end = . ; - } - _etext = .; /* diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig new file mode 100644 index 000000000000..0a0558567eaa --- /dev/null +++ b/arch/csky/Kconfig @@ -0,0 +1,205 @@ +config CSKY + def_bool y + select ARCH_HAS_SYNC_DMA_FOR_CPU + select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select ARCH_USE_BUILTIN_BSWAP + select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2 + select COMMON_CLK + select CLKSRC_MMIO + select CLKSRC_OF + select DMA_DIRECT_OPS + select DMA_NONCOHERENT_OPS + select IRQ_DOMAIN + select HANDLE_DOMAIN_IRQ + select DW_APB_TIMER_OF + select GENERIC_LIB_ASHLDI3 + select GENERIC_LIB_ASHRDI3 + select GENERIC_LIB_LSHRDI3 + select GENERIC_LIB_MULDI3 + select GENERIC_LIB_CMPDI2 + select GENERIC_LIB_UCMPDI2 + select GENERIC_ALLOCATOR + select GENERIC_ATOMIC64 + select GENERIC_CLOCKEVENTS + select GENERIC_CPU_DEVICES + select GENERIC_IRQ_CHIP + select GENERIC_IRQ_PROBE + select GENERIC_IRQ_SHOW + select GENERIC_IRQ_MULTI_HANDLER + select GENERIC_SCHED_CLOCK + select GENERIC_SMP_IDLE_THREAD + select HAVE_ARCH_TRACEHOOK + select HAVE_GENERIC_DMA_COHERENT + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZO + select HAVE_KERNEL_LZMA + select HAVE_C_RECORDMCOUNT + select HAVE_DMA_API_DEBUG + select HAVE_DMA_CONTIGUOUS + select HAVE_MEMBLOCK + select MAY_HAVE_SPARSE_IRQ + select MODULES_USE_ELF_RELA if MODULES + select NO_BOOTMEM + select OF + select OF_EARLY_FLATTREE + select OF_RESERVED_MEM + select PERF_USE_VMALLOC + select RTC_LIB + select TIMER_OF + select USB_ARCH_HAS_EHCI + select USB_ARCH_HAS_OHCI + +config CPU_HAS_CACHEV2 + bool + +config CPU_HAS_FPUV2 + bool + +config CPU_HAS_HILO + bool + +config CPU_HAS_TLBI + bool + +config CPU_HAS_LDSTEX + bool + help + For SMP, CPU needs "ldex&stex" instrcutions to atomic operations. + +config CPU_NEED_TLBSYNC + bool + +config CPU_NEED_SOFTALIGN + bool + +config CPU_NO_USER_BKPT + bool + help + For abiv2 we couldn't use "trap 1" as user space bkpt in gdbserver, because + abiv2 is 16/32bit instruction set and "trap 1" is 32bit. + So we need a 16bit instruction as user space bkpt, and it will cause an illegal + instruction exception. + In kernel we parse the *regs->pc to determine whether to send SIGTRAP or not. + +config GENERIC_CALIBRATE_DELAY + def_bool y + +config GENERIC_CSUM + def_bool y + +config GENERIC_HWEIGHT + def_bool y + +config MMU + def_bool y + +config RWSEM_GENERIC_SPINLOCK + def_bool y + +config TIME_LOW_RES + def_bool y + +config TRACE_IRQFLAGS_SUPPORT + def_bool y + +config CPU_TLB_SIZE + int + default "128" if (CPU_CK610 || CPU_CK807 || CPU_CK810) + default "1024" if (CPU_CK860) + +config CPU_ASID_BITS + int + default "8" if (CPU_CK610 || CPU_CK807 || CPU_CK810) + default "12" if (CPU_CK860) + +config L1_CACHE_SHIFT + int + default "4" if (CPU_CK610) + default "5" if (CPU_CK807 || CPU_CK810) + default "6" if (CPU_CK860) + +menu "Processor type and features" + +choice + prompt "CPU MODEL" + default CPU_CK807 + +config CPU_CK610 + bool "CSKY CPU ck610" + select CPU_NEED_TLBSYNC + select CPU_NEED_SOFTALIGN + select CPU_NO_USER_BKPT + +config CPU_CK810 + bool "CSKY CPU ck810" + select CPU_HAS_HILO + select CPU_NEED_TLBSYNC + +config CPU_CK807 + bool "CSKY CPU ck807" + select CPU_HAS_HILO + +config CPU_CK860 + bool "CSKY CPU ck860" + select CPU_HAS_TLBI + select CPU_HAS_CACHEV2 + select CPU_HAS_LDSTEX + select CPU_HAS_FPUV2 +endchoice + +choice + prompt "Power Manager Instruction (wait/doze/stop)" + default CPU_PM_NONE + +config CPU_PM_NONE + bool "None" + +config CPU_PM_WAIT + bool "wait" + +config CPU_PM_DOZE + bool "doze" + +config CPU_PM_STOP + bool "stop" +endchoice + +config CPU_HAS_VDSP + bool "CPU has VDSP coprocessor" + depends on CPU_HAS_FPU && CPU_HAS_FPUV2 + +config CPU_HAS_FPU + bool "CPU has FPU coprocessor" + depends on CPU_CK807 || CPU_CK810 || CPU_CK860 + +config CPU_HAS_TEE + bool "CPU has Trusted Execution Environment" + depends on CPU_CK810 + +config SMP + bool "Symmetric Multi-Processing (SMP) support for C-SKY" + depends on CPU_CK860 + default n + +config NR_CPUS + int "Maximum number of CPUs (2-32)" + range 2 32 + depends on SMP + default "2" + +config HIGHMEM + bool "High Memory Support" + depends on !CPU_CK610 + default y + +config FORCE_MAX_ZONEORDER + int "Maximum zone order" + default "11" + +config RAM_BASE + hex "DRAM start addr (the same with memory-section in dts)" + default 0x0 + +endmenu + +source "kernel/Kconfig.hz" diff --git a/arch/csky/Kconfig.debug b/arch/csky/Kconfig.debug new file mode 100644 index 000000000000..48cf6ff9df4a --- /dev/null +++ b/arch/csky/Kconfig.debug @@ -0,0 +1,9 @@ +menu "C-SKY Debug Options" +config CSKY_BUILTIN_DTB + string "Use kernel builtin dtb" + help + User could define the dtb instead of the one which is passed from + bootloader. + Sometimes for debug, we want to use a built-in dtb and then we needn't + modify bootloader at all. +endmenu diff --git a/arch/csky/Makefile b/arch/csky/Makefile new file mode 100644 index 000000000000..67a4ae1fba2b --- /dev/null +++ b/arch/csky/Makefile @@ -0,0 +1,93 @@ +OBJCOPYFLAGS :=-O binary +GZFLAGS :=-9 +KBUILD_DEFCONFIG := defconfig + +ifdef CONFIG_CPU_HAS_FPU +FPUEXT = f +endif + +ifdef CONFIG_CPU_HAS_VDSP +VDSPEXT = v +endif + +ifdef CONFIG_CPU_HAS_TEE +TEEEXT = t +endif + +ifdef CONFIG_CPU_CK610 +CPUTYPE = ck610 +CSKYABI = abiv1 +endif + +ifdef CONFIG_CPU_CK810 +CPUTYPE = ck810 +CSKYABI = abiv2 +endif + +ifdef CONFIG_CPU_CK807 +CPUTYPE = ck807 +CSKYABI = abiv2 +endif + +ifdef CONFIG_CPU_CK860 +CPUTYPE = ck860 +CSKYABI = abiv2 +endif + +ifneq ($(CSKYABI),) +MCPU_STR = $(CPUTYPE)$(FPUEXT)$(VDSPEXT)$(TEEEXT) +KBUILD_CFLAGS += -mcpu=$(MCPU_STR) +KBUILD_CFLAGS += -DCSKYCPU_DEF_NAME=\"$(MCPU_STR)\" +KBUILD_CFLAGS += -msoft-float -mdiv +KBUILD_CFLAGS += -fno-tree-vectorize +endif + +KBUILD_CFLAGS += -pipe +ifeq ($(CSKYABI),abiv2) +KBUILD_CFLAGS += -mno-stack-size +endif + +abidirs := $(patsubst %,arch/csky/%/,$(CSKYABI)) +KBUILD_CFLAGS += $(patsubst %,-I$(srctree)/%inc,$(abidirs)) + +KBUILD_CPPFLAGS += -mlittle-endian +LDFLAGS += -EL + +KBUILD_AFLAGS += $(KBUILD_CFLAGS) + +head-y := arch/csky/kernel/head.o + +core-y += arch/csky/kernel/ +core-y += arch/csky/mm/ +core-y += arch/csky/$(CSKYABI)/ + +libs-y += arch/csky/lib/ \ + $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name) + +boot := arch/csky/boot +ifneq '$(CONFIG_CSKY_BUILTIN_DTB)' '""' +core-y += $(boot)/dts/ +endif + +all: zImage + + +dtbs: scripts + $(Q)$(MAKE) $(build)=$(boot)/dts + +%.dtb %.dtb.S %.dtb.o: scripts + $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ + +zImage Image uImage: vmlinux dtbs + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +archclean: + $(Q)$(MAKE) $(clean)=$(boot) + $(Q)$(MAKE) $(clean)=$(boot)/dts + rm -rf arch/csky/include/generated + +define archhelp + echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' + echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' + echo ' uImage - U-Boot wrapped zImage' +endef diff --git a/arch/csky/abiv1/Makefile b/arch/csky/abiv1/Makefile new file mode 100644 index 000000000000..7c062768d44d --- /dev/null +++ b/arch/csky/abiv1/Makefile @@ -0,0 +1,8 @@ +obj-$(CONFIG_CPU_NEED_SOFTALIGN) += alignment.o +obj-y += bswapdi.o +obj-y += bswapsi.o +obj-y += cacheflush.o +obj-y += mmap.o +obj-y += memcpy.o +obj-y += memset.o +obj-y += strksyms.o diff --git a/arch/csky/abiv1/alignment.c b/arch/csky/abiv1/alignment.c new file mode 100644 index 000000000000..60205e98fb87 --- /dev/null +++ b/arch/csky/abiv1/alignment.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/kernel.h> +#include <linux/uaccess.h> +#include <linux/ptrace.h> + +static int align_enable = 1; +static int align_count; + +static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx) +{ + return rx == 15 ? regs->lr : *((uint32_t *)&(regs->a0) - 2 + rx); +} + +static inline void put_ptreg(struct pt_regs *regs, uint32_t rx, uint32_t val) +{ + if (rx == 15) + regs->lr = val; + else + *((uint32_t *)&(regs->a0) - 2 + rx) = val; +} + +/* + * Get byte-value from addr and set it to *valp. + * + * Success: return 0 + * Failure: return 1 + */ +static int ldb_asm(uint32_t addr, uint32_t *valp) +{ + uint32_t val; + int err; + + if (!access_ok(VERIFY_READ, (void *)addr, 1)) + return 1; + + asm volatile ( + "movi %0, 0\n" + "1:\n" + "ldb %1, (%2)\n" + "br 3f\n" + "2:\n" + "movi %0, 1\n" + "br 3f\n" + ".section __ex_table,\"a\"\n" + ".align 2\n" + ".long 1b, 2b\n" + ".previous\n" + "3:\n" + : "=&r"(err), "=r"(val) + : "r" (addr) + ); + + *valp = val; + + return err; +} + +/* + * Put byte-value to addr. + * + * Success: return 0 + * Failure: return 1 + */ +static int stb_asm(uint32_t addr, uint32_t val) +{ + int err; + + if (!access_ok(VERIFY_WRITE, (void *)addr, 1)) + return 1; + + asm volatile ( + "movi %0, 0\n" + "1:\n" + "stb %1, (%2)\n" + "br 3f\n" + "2:\n" + "movi %0, 1\n" + "br 3f\n" + ".section __ex_table,\"a\"\n" + ".align 2\n" + ".long 1b, 2b\n" + ".previous\n" + "3:\n" + : "=&r"(err) + : "r"(val), "r" (addr) + ); + + return err; +} + +/* + * Get half-word from [rx + imm] + * + * Success: return 0 + * Failure: return 1 + */ +static int ldh_c(struct pt_regs *regs, uint32_t rz, uint32_t addr) +{ + uint32_t byte0, byte1; + + if (ldb_asm(addr, &byte0)) + return 1; + addr += 1; + if (ldb_asm(addr, &byte1)) + return 1; + + byte0 |= byte1 << 8; + put_ptreg(regs, rz, byte0); + + return 0; +} + +/* + * Store half-word to [rx + imm] + * + * Success: return 0 + * Failure: return 1 + */ +static int sth_c(struct pt_regs *regs, uint32_t rz, uint32_t addr) +{ + uint32_t byte0, byte1; + + byte0 = byte1 = get_ptreg(regs, rz); + + byte0 &= 0xff; + + if (stb_asm(addr, byte0)) + return 1; + + addr += 1; + byte1 = (byte1 >> 8) & 0xff; + if (stb_asm(addr, byte1)) + return 1; + + return 0; +} + +/* + * Get word from [rx + imm] + * + * Success: return 0 + * Failure: return 1 + */ +static int ldw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr) +{ + uint32_t byte0, byte1, byte2, byte3; + + if (ldb_asm(addr, &byte0)) + return 1; + + addr += 1; + if (ldb_asm(addr, &byte1)) + return 1; + + addr += 1; + if (ldb_asm(addr, &byte2)) + return 1; + + addr += 1; + if (ldb_asm(addr, &byte3)) + return 1; + + byte0 |= byte1 << 8; + byte0 |= byte2 << 16; + byte0 |= byte3 << 24; + + put_ptreg(regs, rz, byte0); + + return 0; +} + +/* + * Store word to [rx + imm] + * + * Success: return 0 + * Failure: return 1 + */ +static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr) +{ + uint32_t byte0, byte1, byte2, byte3; + + byte0 = byte1 = byte2 = byte3 = get_ptreg(regs, rz); + + byte0 &= 0xff; + + if (stb_asm(addr, byte0)) + return 1; + + addr += 1; + byte1 = (byte1 >> 8) & 0xff; + if (stb_asm(addr, byte1)) + return 1; + + addr += 1; + byte2 = (byte2 >> 16) & 0xff; + if (stb_asm(addr, byte2)) + return 1; + + addr += 1; + byte3 = (byte3 >> 24) & 0xff; + if (stb_asm(addr, byte3)) + return 1; + + align_count++; + + return 0; +} + +extern int fixup_exception(struct pt_regs *regs); + +#define OP_LDH 0xc000 +#define OP_STH 0xd000 +#define OP_LDW 0x8000 +#define OP_STW 0x9000 + +void csky_alignment(struct pt_regs *regs) +{ + int ret; + uint16_t tmp; + uint32_t opcode = 0; + uint32_t rx = 0; + uint32_t rz = 0; + uint32_t imm = 0; + uint32_t addr = 0; + + if (!user_mode(regs)) + goto bad_area; + + ret = get_user(tmp, (uint16_t *)instruction_pointer(regs)); + if (ret) { + pr_err("%s get_user failed.\n", __func__); + goto bad_area; + } + + opcode = (uint32_t)tmp; + + rx = opcode & 0xf; + imm = (opcode >> 4) & 0xf; + rz = (opcode >> 8) & 0xf; + opcode &= 0xf000; + + if (rx == 0 || rx == 1 || rz == 0 || rz == 1) + goto bad_area; + + switch (opcode) { + case OP_LDH: + addr = get_ptreg(regs, rx) + (imm << 1); + ret = ldh_c(regs, rz, addr); + break; + case OP_LDW: + addr = get_ptreg(regs, rx) + (imm << 2); + ret = ldw_c(regs, rz, addr); + break; + case OP_STH: + addr = get_ptreg(regs, rx) + (imm << 1); + ret = sth_c(regs, rz, addr); + break; + case OP_STW: + addr = get_ptreg(regs, rx) + (imm << 2); + ret = stw_c(regs, rz, addr); + break; + } + + if (ret) + goto bad_area; + + regs->pc += 2; + + return; + +bad_area: + if (!user_mode(regs)) { + if (fixup_exception(regs)) + return; + + bust_spinlocks(1); + pr_alert("%s opcode: %x, rz: %d, rx: %d, imm: %d, addr: %x.\n", + __func__, opcode, rz, rx, imm, addr); + show_regs(regs); + bust_spinlocks(0); + do_exit(SIGKILL); + } + + force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr, current); +} + +static struct ctl_table alignment_tbl[4] = { + { + .procname = "enable", + .data = &align_enable, + .maxlen = sizeof(align_enable), + .mode = 0666, + .proc_handler = &proc_dointvec + }, + { + .procname = "count", + .data = &align_count, + .maxlen = sizeof(align_count), + .mode = 0666, + .proc_handler = &proc_dointvec + }, + {} +}; + +static struct ctl_table sysctl_table[2] = { + { + .procname = "csky_alignment", + .mode = 0555, + .child = alignment_tbl}, + {} +}; + +static struct ctl_path sysctl_path[2] = { + {.procname = "csky"}, + {} +}; + +static int __init csky_alignment_init(void) +{ + register_sysctl_paths(sysctl_path, sysctl_table); + return 0; +} + +arch_initcall(csky_alignment_init); diff --git a/arch/csky/abiv1/bswapdi.c b/arch/csky/abiv1/bswapdi.c new file mode 100644 index 000000000000..f50a1d6e337a --- /dev/null +++ b/arch/csky/abiv1/bswapdi.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/export.h> +#include <linux/compiler.h> +#include <uapi/linux/swab.h> + +unsigned long long notrace __bswapdi2(unsigned long long u) +{ + return ___constant_swab64(u); +} +EXPORT_SYMBOL(__bswapdi2); diff --git a/arch/csky/abiv1/bswapsi.c b/arch/csky/abiv1/bswapsi.c new file mode 100644 index 000000000000..0f79182e8a5b --- /dev/null +++ b/arch/csky/abiv1/bswapsi.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/export.h> +#include <linux/compiler.h> +#include <uapi/linux/swab.h> + +unsigned int notrace __bswapsi2(unsigned int u) +{ + return ___constant_swab32(u); +} +EXPORT_SYMBOL(__bswapsi2); diff --git a/arch/csky/abiv1/cacheflush.c b/arch/csky/abiv1/cacheflush.c new file mode 100644 index 000000000000..10af8b6fe322 --- /dev/null +++ b/arch/csky/abiv1/cacheflush.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/fs.h> +#include <linux/syscalls.h> +#include <linux/spinlock.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/cacheflush.h> +#include <asm/cachectl.h> + +void flush_dcache_page(struct page *page) +{ + struct address_space *mapping = page_mapping(page); + unsigned long addr; + + if (mapping && !mapping_mapped(mapping)) { + set_bit(PG_arch_1, &(page)->flags); + return; + } + + /* + * We could delay the flush for the !page_mapping case too. But that + * case is for exec env/arg pages and those are %99 certainly going to + * get faulted into the tlb (and thus flushed) anyways. + */ + addr = (unsigned long) page_address(page); + dcache_wb_range(addr, addr + PAGE_SIZE); +} + +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t *pte) +{ + unsigned long addr; + struct page *page; + unsigned long pfn; + + pfn = pte_pfn(*pte); + if (unlikely(!pfn_valid(pfn))) + return; + + page = pfn_to_page(pfn); + addr = (unsigned long) page_address(page); + + if (vma->vm_flags & VM_EXEC || + pages_do_alias(addr, address & PAGE_MASK)) + cache_wbinv_all(); + + clear_bit(PG_arch_1, &(page)->flags); +} diff --git a/arch/csky/abiv1/inc/abi/cacheflush.h b/arch/csky/abiv1/inc/abi/cacheflush.h new file mode 100644 index 000000000000..5f663aef9b1b --- /dev/null +++ b/arch/csky/abiv1/inc/abi/cacheflush.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ABI_CSKY_CACHEFLUSH_H +#define __ABI_CSKY_CACHEFLUSH_H + +#include <linux/compiler.h> +#include <asm/string.h> +#include <asm/cache.h> + +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +extern void flush_dcache_page(struct page *); + +#define flush_cache_mm(mm) cache_wbinv_all() +#define flush_cache_page(vma, page, pfn) cache_wbinv_all() +#define flush_cache_dup_mm(mm) cache_wbinv_all() + +/* + * if (current_mm != vma->mm) cache_wbinv_range(start, end) will be broken. + * Use cache_wbinv_all() here and need to be improved in future. + */ +#define flush_cache_range(vma, start, end) cache_wbinv_all() +#define flush_cache_vmap(start, end) cache_wbinv_range(start, end) +#define flush_cache_vunmap(start, end) cache_wbinv_range(start, end) + +#define flush_icache_page(vma, page) cache_wbinv_all() +#define flush_icache_range(start, end) cache_wbinv_range(start, end) + +#define flush_icache_user_range(vma, pg, adr, len) \ + cache_wbinv_range(adr, adr + len) + +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + cache_wbinv_all(); \ + memcpy(dst, src, len); \ + cache_wbinv_all(); \ +} while (0) + +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + cache_wbinv_all(); \ + memcpy(dst, src, len); \ + cache_wbinv_all(); \ +} while (0) + +#define flush_dcache_mmap_lock(mapping) do {} while (0) +#define flush_dcache_mmap_unlock(mapping) do {} while (0) + +#endif /* __ABI_CSKY_CACHEFLUSH_H */ diff --git a/arch/csky/abiv1/inc/abi/ckmmu.h b/arch/csky/abiv1/inc/abi/ckmmu.h new file mode 100644 index 000000000000..3a002017bebe --- /dev/null +++ b/arch/csky/abiv1/inc/abi/ckmmu.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_CKMMUV1_H +#define __ASM_CSKY_CKMMUV1_H +#include <abi/reg_ops.h> + +static inline int read_mmu_index(void) +{ + return cprcr("cpcr0"); +} + +static inline void write_mmu_index(int value) +{ + cpwcr("cpcr0", value); +} + +static inline int read_mmu_entrylo0(void) +{ + return cprcr("cpcr2") << 6; +} + +static inline int read_mmu_entrylo1(void) +{ + return cprcr("cpcr3") << 6; +} + +static inline void write_mmu_pagemask(int value) +{ + cpwcr("cpcr6", value); +} + +static inline int read_mmu_entryhi(void) +{ + return cprcr("cpcr4"); +} + +static inline void write_mmu_entryhi(int value) +{ + cpwcr("cpcr4", value); +} + +/* + * TLB operations. + */ +static inline void tlb_probe(void) +{ + cpwcr("cpcr8", 0x80000000); +} + +static inline void tlb_read(void) +{ + cpwcr("cpcr8", 0x40000000); +} + +static inline void tlb_invalid_all(void) +{ + cpwcr("cpcr8", 0x04000000); +} + +static inline void tlb_invalid_indexed(void) +{ + cpwcr("cpcr8", 0x02000000); +} + +static inline void setup_pgd(unsigned long pgd, bool kernel) +{ + cpwcr("cpcr29", pgd); +} + +static inline unsigned long get_pgd(void) +{ + return cprcr("cpcr29"); +} +#endif /* __ASM_CSKY_CKMMUV1_H */ diff --git a/arch/csky/abiv1/inc/abi/elf.h b/arch/csky/abiv1/inc/abi/elf.h new file mode 100644 index 000000000000..3058cc06b104 --- /dev/null +++ b/arch/csky/abiv1/inc/abi/elf.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ABI_CSKY_ELF_H +#define __ABI_CSKY_ELF_H + +#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ + pr_reg[0] = regs->pc; \ + pr_reg[1] = regs->regs[9]; \ + pr_reg[2] = regs->usp; \ + pr_reg[3] = regs->sr; \ + pr_reg[4] = regs->a0; \ + pr_reg[5] = regs->a1; \ + pr_reg[6] = regs->a2; \ + pr_reg[7] = regs->a3; \ + pr_reg[8] = regs->regs[0]; \ + pr_reg[9] = regs->regs[1]; \ + pr_reg[10] = regs->regs[2]; \ + pr_reg[11] = regs->regs[3]; \ + pr_reg[12] = regs->regs[4]; \ + pr_reg[13] = regs->regs[5]; \ + pr_reg[14] = regs->regs[6]; \ + pr_reg[15] = regs->regs[7]; \ + pr_reg[16] = regs->regs[8]; \ + pr_reg[17] = regs->lr; \ +} while (0); +#endif /* __ABI_CSKY_ELF_H */ diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h new file mode 100644 index 000000000000..3f3faab3d747 --- /dev/null +++ b/arch/csky/abiv1/inc/abi/entry.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_ENTRY_H +#define __ASM_CSKY_ENTRY_H + +#include <asm/setup.h> +#include <abi/regdef.h> + +#define LSAVE_PC 8 +#define LSAVE_PSR 12 +#define LSAVE_A0 24 +#define LSAVE_A1 28 +#define LSAVE_A2 32 +#define LSAVE_A3 36 +#define LSAVE_A4 40 +#define LSAVE_A5 44 + +#define EPC_INCREASE 2 +#define EPC_KEEP 0 + +.macro USPTOKSP + mtcr sp, ss1 + mfcr sp, ss0 +.endm + +.macro KSPTOUSP + mtcr sp, ss0 + mfcr sp, ss1 +.endm + +.macro INCTRAP rx + addi \rx, EPC_INCREASE +.endm + +.macro SAVE_ALL epc_inc + mtcr r13, ss2 + mfcr r13, epsr + btsti r13, 31 + bt 1f + USPTOKSP +1: + subi sp, 32 + subi sp, 32 + subi sp, 16 + stw r13, (sp, 12) + + stw lr, (sp, 4) + + mfcr lr, epc + movi r13, \epc_inc + add lr, r13 + stw lr, (sp, 8) + + mfcr lr, ss1 + stw lr, (sp, 16) + + stw a0, (sp, 20) + stw a0, (sp, 24) + stw a1, (sp, 28) + stw a2, (sp, 32) + stw a3, (sp, 36) + + addi sp, 32 + addi sp, 8 + mfcr r13, ss2 + stw r6, (sp) + stw r7, (sp, 4) + stw r8, (sp, 8) + stw r9, (sp, 12) + stw r10, (sp, 16) + stw r11, (sp, 20) + stw r12, (sp, 24) + stw r13, (sp, 28) + stw r14, (sp, 32) + stw r1, (sp, 36) + subi sp, 32 + subi sp, 8 +.endm + +.macro RESTORE_ALL + psrclr ie + ldw lr, (sp, 4) + ldw a0, (sp, 8) + mtcr a0, epc + ldw a0, (sp, 12) + mtcr a0, epsr + btsti a0, 31 + ldw a0, (sp, 16) + mtcr a0, ss1 + + ldw a0, (sp, 24) + ldw a1, (sp, 28) + ldw a2, (sp, 32) + ldw a3, (sp, 36) + + addi sp, 32 + addi sp, 8 + ldw r6, (sp) + ldw r7, (sp, 4) + ldw r8, (sp, 8) + ldw r9, (sp, 12) + ldw r10, (sp, 16) + ldw r11, (sp, 20) + ldw r12, (sp, 24) + ldw r13, (sp, 28) + ldw r14, (sp, 32) + ldw r1, (sp, 36) + addi sp, 32 + addi sp, 8 + + bt 1f + KSPTOUSP +1: + rte +.endm + +.macro SAVE_SWITCH_STACK + subi sp, 32 + stm r8-r15, (sp) +.endm + +.macro RESTORE_SWITCH_STACK + ldm r8-r15, (sp) + addi sp, 32 +.endm + +/* MMU registers operators. */ +.macro RD_MIR rx + cprcr \rx, cpcr0 +.endm + +.macro RD_MEH rx + cprcr \rx, cpcr4 +.endm + +.macro RD_MCIR rx + cprcr \rx, cpcr8 +.endm + +.macro RD_PGDR rx + cprcr \rx, cpcr29 +.endm + +.macro WR_MEH rx + cpwcr \rx, cpcr4 +.endm + +.macro WR_MCIR rx + cpwcr \rx, cpcr8 +.endm + +.macro SETUP_MMU rx + lrw \rx, PHYS_OFFSET | 0xe + cpwcr \rx, cpcr30 + lrw \rx, (PHYS_OFFSET + 0x20000000) | 0xe + cpwcr \rx, cpcr31 +.endm + +#endif /* __ASM_CSKY_ENTRY_H */ diff --git a/arch/csky/abiv1/inc/abi/page.h b/arch/csky/abiv1/inc/abi/page.h new file mode 100644 index 000000000000..6336e92a103a --- /dev/null +++ b/arch/csky/abiv1/inc/abi/page.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +extern unsigned long shm_align_mask; +extern void flush_dcache_page(struct page *page); + +static inline unsigned long pages_do_alias(unsigned long addr1, + unsigned long addr2) +{ + return (addr1 ^ addr2) & shm_align_mask; +} + +static inline void clear_user_page(void *addr, unsigned long vaddr, + struct page *page) +{ + clear_page(addr); + if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK)) + flush_dcache_page(page); +} + +static inline void copy_user_page(void *to, void *from, unsigned long vaddr, + struct page *page) +{ + copy_page(to, from); + if (pages_do_alias((unsigned long) to, vaddr & PAGE_MASK)) + flush_dcache_page(page); +} diff --git a/arch/csky/abiv1/inc/abi/pgtable-bits.h b/arch/csky/abiv1/inc/abi/pgtable-bits.h new file mode 100644 index 000000000000..455075b5db0d --- /dev/null +++ b/arch/csky/abiv1/inc/abi/pgtable-bits.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_PGTABLE_BITS_H +#define __ASM_CSKY_PGTABLE_BITS_H + +/* implemented in software */ +#define _PAGE_ACCESSED (1<<3) +#define PAGE_ACCESSED_BIT (3) + +#define _PAGE_READ (1<<1) +#define _PAGE_WRITE (1<<2) +#define _PAGE_PRESENT (1<<0) + +#define _PAGE_MODIFIED (1<<4) +#define PAGE_MODIFIED_BIT (4) + +/* implemented in hardware */ +#define _PAGE_GLOBAL (1<<6) + +#define _PAGE_VALID (1<<7) +#define PAGE_VALID_BIT (7) + +#define _PAGE_DIRTY (1<<8) +#define PAGE_DIRTY_BIT (8) + +#define _PAGE_CACHE (3<<9) +#define _PAGE_UNCACHE (2<<9) + +#define _CACHE_MASK (7<<9) + +#define _CACHE_CACHED (_PAGE_VALID | _PAGE_CACHE) +#define _CACHE_UNCACHED (_PAGE_VALID | _PAGE_UNCACHE) + +#define HAVE_ARCH_UNMAPPED_AREA + +#endif /* __ASM_CSKY_PGTABLE_BITS_H */ diff --git a/arch/csky/abiv1/inc/abi/reg_ops.h b/arch/csky/abiv1/inc/abi/reg_ops.h new file mode 100644 index 000000000000..a153bd3918f7 --- /dev/null +++ b/arch/csky/abiv1/inc/abi/reg_ops.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ABI_REG_OPS_H +#define __ABI_REG_OPS_H +#include <asm/reg_ops.h> + +#define cprcr(reg) \ +({ \ + unsigned int tmp; \ + asm volatile("cprcr %0, "reg"\n":"=b"(tmp)); \ + tmp; \ +}) + +#define cpwcr(reg, val) \ +({ \ + asm volatile("cpwcr %0, "reg"\n"::"b"(val)); \ +}) + +static inline unsigned int mfcr_hint(void) +{ + return mfcr("cr30"); +} + +static inline unsigned int mfcr_ccr2(void) { return 0; } + +#endif /* __ABI_REG_OPS_H */ diff --git a/arch/csky/abiv1/inc/abi/regdef.h b/arch/csky/abiv1/inc/abi/regdef.h new file mode 100644 index 000000000000..876689291b71 --- /dev/null +++ b/arch/csky/abiv1/inc/abi/regdef.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_REGDEF_H +#define __ASM_CSKY_REGDEF_H + +#define syscallid r1 +#define r11_sig r11 + +#define regs_syscallid(regs) regs->regs[9] + +/* + * PSR format: + * | 31 | 30-24 | 23-16 | 15 14 | 13-0 | + * S CPID VEC TM + * + * S: Super Mode + * CPID: Coprocessor id, only 15 for MMU + * VEC: Exception Number + * TM: Trace Mode + */ +#define DEFAULT_PSR_VALUE 0x8f000000 + +#define SYSTRACE_SAVENUM 2 + +#endif /* __ASM_CSKY_REGDEF_H */ diff --git a/arch/csky/abiv1/inc/abi/string.h b/arch/csky/abiv1/inc/abi/string.h new file mode 100644 index 000000000000..5abe80be044d --- /dev/null +++ b/arch/csky/abiv1/inc/abi/string.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ABI_CSKY_STRING_H +#define __ABI_CSKY_STRING_H + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +#endif /* __ABI_CSKY_STRING_H */ diff --git a/arch/csky/abiv1/inc/abi/vdso.h b/arch/csky/abiv1/inc/abi/vdso.h new file mode 100644 index 000000000000..14352f524f1d --- /dev/null +++ b/arch/csky/abiv1/inc/abi/vdso.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/uaccess.h> + +static inline int setup_vdso_page(unsigned short *ptr) +{ + int err = 0; + + /* movi r1, 127 */ + err |= __put_user(0x67f1, ptr + 0); + /* addi r1, (139 - 127) */ + err |= __put_user(0x20b1, ptr + 1); + /* trap 0 */ + err |= __put_user(0x0008, ptr + 2); + + return err; +} diff --git a/arch/csky/abiv1/memcpy.S b/arch/csky/abiv1/memcpy.S new file mode 100644 index 000000000000..5078eb5169fa --- /dev/null +++ b/arch/csky/abiv1/memcpy.S @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> + +.macro GET_FRONT_BITS rx y +#ifdef __cskyLE__ + lsri \rx, \y +#else + lsli \rx, \y +#endif +.endm + +.macro GET_AFTER_BITS rx y +#ifdef __cskyLE__ + lsli \rx, \y +#else + lsri \rx, \y +#endif +.endm + +/* void *memcpy(void *dest, const void *src, size_t n); */ +ENTRY(memcpy) + mov r7, r2 + cmplti r4, 4 + bt .L_copy_by_byte + mov r6, r2 + andi r6, 3 + cmpnei r6, 0 + jbt .L_dest_not_aligned + mov r6, r3 + andi r6, 3 + cmpnei r6, 0 + jbt .L_dest_aligned_but_src_not_aligned +.L0: + cmplti r4, 16 + jbt .L_aligned_and_len_less_16bytes + subi sp, 8 + stw r8, (sp, 0) +.L_aligned_and_len_larger_16bytes: + ldw r1, (r3, 0) + ldw r5, (r3, 4) + ldw r8, (r3, 8) + stw r1, (r7, 0) + ldw r1, (r3, 12) + stw r5, (r7, 4) + stw r8, (r7, 8) + stw r1, (r7, 12) + subi r4, 16 + addi r3, 16 + addi r7, 16 + cmplti r4, 16 + jbf .L_aligned_and_len_larger_16bytes + ldw r8, (sp, 0) + addi sp, 8 + cmpnei r4, 0 + jbf .L_return + +.L_aligned_and_len_less_16bytes: + cmplti r4, 4 + bt .L_copy_by_byte +.L1: + ldw r1, (r3, 0) + stw r1, (r7, 0) + subi r4, 4 + addi r3, 4 + addi r7, 4 + cmplti r4, 4 + jbf .L1 + br .L_copy_by_byte + +.L_return: + rts + +.L_copy_by_byte: /* len less than 4 bytes */ + cmpnei r4, 0 + jbf .L_return +.L4: + ldb r1, (r3, 0) + stb r1, (r7, 0) + addi r3, 1 + addi r7, 1 + decne r4 + jbt .L4 + rts + +/* + * If dest is not aligned, just copying some bytes makes the dest align. + * Afther that, we judge whether the src is aligned. + */ +.L_dest_not_aligned: + mov r5, r3 + rsub r5, r5, r7 + abs r5, r5 + cmplt r5, r4 + bt .L_copy_by_byte + mov r5, r7 + sub r5, r3 + cmphs r5, r4 + bf .L_copy_by_byte + mov r5, r6 +.L5: + ldb r1, (r3, 0) /* makes the dest align. */ + stb r1, (r7, 0) + addi r5, 1 + subi r4, 1 + addi r3, 1 + addi r7, 1 + cmpnei r5, 4 + jbt .L5 + cmplti r4, 4 + jbt .L_copy_by_byte + mov r6, r3 /* judge whether the src is aligned. */ + andi r6, 3 + cmpnei r6, 0 + jbf .L0 + +/* Judge the number of misaligned, 1, 2, 3? */ +.L_dest_aligned_but_src_not_aligned: + mov r5, r3 + rsub r5, r5, r7 + abs r5, r5 + cmplt r5, r4 + bt .L_copy_by_byte + bclri r3, 0 + bclri r3, 1 + ldw r1, (r3, 0) + addi r3, 4 + cmpnei r6, 2 + bf .L_dest_aligned_but_src_not_aligned_2bytes + cmpnei r6, 3 + bf .L_dest_aligned_but_src_not_aligned_3bytes + +.L_dest_aligned_but_src_not_aligned_1byte: + mov r5, r7 + sub r5, r3 + cmphs r5, r4 + bf .L_copy_by_byte + cmplti r4, 16 + bf .L11 +.L10: /* If the len is less than 16 bytes */ + GET_FRONT_BITS r1 8 + mov r5, r1 + ldw r6, (r3, 0) + mov r1, r6 + GET_AFTER_BITS r6 24 + or r5, r6 + stw r5, (r7, 0) + subi r4, 4 + addi r3, 4 + addi r7, 4 + cmplti r4, 4 + bf .L10 + subi r3, 3 + br .L_copy_by_byte +.L11: + subi sp, 16 + stw r8, (sp, 0) + stw r9, (sp, 4) + stw r10, (sp, 8) + stw r11, (sp, 12) +.L12: + ldw r5, (r3, 0) + ldw r11, (r3, 4) + ldw r8, (r3, 8) + ldw r9, (r3, 12) + + GET_FRONT_BITS r1 8 /* little or big endian? */ + mov r10, r5 + GET_AFTER_BITS r5 24 + or r5, r1 + + GET_FRONT_BITS r10 8 + mov r1, r11 + GET_AFTER_BITS r11 24 + or r11, r10 + + GET_FRONT_BITS r1 8 + mov r10, r8 + GET_AFTER_BITS r8 24 + or r8, r1 + + GET_FRONT_BITS r10 8 + mov r1, r9 + GET_AFTER_BITS r9 24 + or r9, r10 + + stw r5, (r7, 0) + stw r11, (r7, 4) + stw r8, (r7, 8) + stw r9, (r7, 12) + subi r4, 16 + addi r3, 16 + addi r7, 16 + cmplti r4, 16 + jbf .L12 + ldw r8, (sp, 0) + ldw r9, (sp, 4) + ldw r10, (sp, 8) + ldw r11, (sp, 12) + addi sp , 16 + cmplti r4, 4 + bf .L10 + subi r3, 3 + br .L_copy_by_byte + +.L_dest_aligned_but_src_not_aligned_2bytes: + cmplti r4, 16 + bf .L21 +.L20: + GET_FRONT_BITS r1 16 + mov r5, r1 + ldw r6, (r3, 0) + mov r1, r6 + GET_AFTER_BITS r6 16 + or r5, r6 + stw r5, (r7, 0) + subi r4, 4 + addi r3, 4 + addi r7, 4 + cmplti r4, 4 + bf .L20 + subi r3, 2 + br .L_copy_by_byte + rts + +.L21: /* n > 16 */ + subi sp, 16 + stw r8, (sp, 0) + stw r9, (sp, 4) + stw r10, (sp, 8) + stw r11, (sp, 12) + +.L22: + ldw r5, (r3, 0) + ldw r11, (r3, 4) + ldw r8, (r3, 8) + ldw r9, (r3, 12) + + GET_FRONT_BITS r1 16 + mov r10, r5 + GET_AFTER_BITS r5 16 + or r5, r1 + + GET_FRONT_BITS r10 16 + mov r1, r11 + GET_AFTER_BITS r11 16 + or r11, r10 + + GET_FRONT_BITS r1 16 + mov r10, r8 + GET_AFTER_BITS r8 16 + or r8, r1 + + GET_FRONT_BITS r10 16 + mov r1, r9 + GET_AFTER_BITS r9 16 + or r9, r10 + + stw r5, (r7, 0) + stw r11, (r7, 4) + stw r8, (r7, 8) + stw r9, (r7, 12) + subi r4, 16 + addi r3, 16 + addi r7, 16 + cmplti r4, 16 + jbf .L22 + ldw r8, (sp, 0) + ldw r9, (sp, 4) + ldw r10, (sp, 8) + ldw r11, (sp, 12) + addi sp, 16 + cmplti r4, 4 + bf .L20 + subi r3, 2 + br .L_copy_by_byte + + +.L_dest_aligned_but_src_not_aligned_3bytes: + cmplti r4, 16 + bf .L31 +.L30: + GET_FRONT_BITS r1 24 + mov r5, r1 + ldw r6, (r3, 0) + mov r1, r6 + GET_AFTER_BITS r6 8 + or r5, r6 + stw r5, (r7, 0) + subi r4, 4 + addi r3, 4 + addi r7, 4 + cmplti r4, 4 + bf .L30 + subi r3, 1 + br .L_copy_by_byte +.L31: + subi sp, 16 + stw r8, (sp, 0) + stw r9, (sp, 4) + stw r10, (sp, 8) + stw r11, (sp, 12) +.L32: + ldw r5, (r3, 0) + ldw r11, (r3, 4) + ldw r8, (r3, 8) + ldw r9, (r3, 12) + + GET_FRONT_BITS r1 24 + mov r10, r5 + GET_AFTER_BITS r5 8 + or r5, r1 + + GET_FRONT_BITS r10 24 + mov r1, r11 + GET_AFTER_BITS r11 8 + or r11, r10 + + GET_FRONT_BITS r1 24 + mov r10, r8 + GET_AFTER_BITS r8 8 + or r8, r1 + + GET_FRONT_BITS r10 24 + mov r1, r9 + GET_AFTER_BITS r9 8 + or r9, r10 + + stw r5, (r7, 0) + stw r11, (r7, 4) + stw r8, (r7, 8) + stw r9, (r7, 12) + subi r4, 16 + addi r3, 16 + addi r7, 16 + cmplti r4, 16 + jbf .L32 + ldw r8, (sp, 0) + ldw r9, (sp, 4) + ldw r10, (sp, 8) + ldw r11, (sp, 12) + addi sp, 16 + cmplti r4, 4 + bf .L30 + subi r3, 1 + br .L_copy_by_byte diff --git a/arch/csky/abiv1/memset.c b/arch/csky/abiv1/memset.c new file mode 100644 index 000000000000..b4aa75b99c5d --- /dev/null +++ b/arch/csky/abiv1/memset.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/types.h> + +void *memset(void *dest, int c, size_t l) +{ + char *d = dest; + int ch = c & 0xff; + int tmp = (ch | ch << 8 | ch << 16 | ch << 24); + + while (((uintptr_t)d & 0x3) && l--) + *d++ = ch; + + while (l >= 16) { + *(((u32 *)d)) = tmp; + *(((u32 *)d)+1) = tmp; + *(((u32 *)d)+2) = tmp; + *(((u32 *)d)+3) = tmp; + l -= 16; + d += 16; + } + + while (l > 3) { + *(((u32 *)d)) = tmp; + l -= 4; + d += 4; + } + + while (l) { + *d = ch; + l--; + d++; + } + + return dest; +} diff --git a/arch/csky/abiv1/mmap.c b/arch/csky/abiv1/mmap.c new file mode 100644 index 000000000000..b462fd50b23a --- /dev/null +++ b/arch/csky/abiv1/mmap.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/mman.h> +#include <linux/shm.h> +#include <linux/sched.h> +#include <linux/random.h> +#include <linux/io.h> + +unsigned long shm_align_mask = (0x4000 >> 1) - 1; /* Sane caches */ + +#define COLOUR_ALIGN(addr, pgoff) \ + ((((addr) + shm_align_mask) & ~shm_align_mask) + \ + (((pgoff) << PAGE_SHIFT) & shm_align_mask)) + +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct *vmm; + int do_color_align; + + if (flags & MAP_FIXED) { + /* + * We do not accept a shared mapping if it would violate + * cache aliasing constraints. + */ + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) + return -EINVAL; + return addr; + } + + if (len > TASK_SIZE) + return -ENOMEM; + do_color_align = 0; + if (filp || (flags & MAP_SHARED)) + do_color_align = 1; + if (addr) { + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + vmm = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && + (!vmm || addr + len <= vmm->vm_start)) + return addr; + } + addr = TASK_UNMAPPED_BASE; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vmm || addr + len <= vmm->vm_start) + return addr; + addr = vmm->vm_end; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + } +} diff --git a/arch/csky/abiv1/strksyms.c b/arch/csky/abiv1/strksyms.c new file mode 100644 index 000000000000..436995c9b75c --- /dev/null +++ b/arch/csky/abiv1/strksyms.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/module.h> + +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); diff --git a/arch/csky/abiv2/Makefile b/arch/csky/abiv2/Makefile new file mode 100644 index 000000000000..069ca7276b99 --- /dev/null +++ b/arch/csky/abiv2/Makefile @@ -0,0 +1,10 @@ +obj-y += cacheflush.o +obj-$(CONFIG_CPU_HAS_FPU) += fpu.o +obj-y += memcmp.o +obj-y += memcpy.o +obj-y += memmove.o +obj-y += memset.o +obj-y += strcmp.o +obj-y += strcpy.o +obj-y += strlen.o +obj-y += strksyms.o diff --git a/arch/csky/abiv2/cacheflush.c b/arch/csky/abiv2/cacheflush.c new file mode 100644 index 000000000000..d22c95ffc74d --- /dev/null +++ b/arch/csky/abiv2/cacheflush.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/cache.h> +#include <linux/highmem.h> +#include <linux/mm.h> +#include <asm/cache.h> + +void flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + unsigned long start; + + start = (unsigned long) kmap_atomic(page); + + cache_wbinv_range(start, start + PAGE_SIZE); + + kunmap_atomic((void *)start); +} + +void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, int len) +{ + unsigned long kaddr; + + kaddr = (unsigned long) kmap_atomic(page) + (vaddr & ~PAGE_MASK); + + cache_wbinv_range(kaddr, kaddr + len); + + kunmap_atomic((void *)kaddr); +} + +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t *pte) +{ + unsigned long addr, pfn; + struct page *page; + void *va; + + if (!(vma->vm_flags & VM_EXEC)) + return; + + pfn = pte_pfn(*pte); + if (unlikely(!pfn_valid(pfn))) + return; + + page = pfn_to_page(pfn); + if (page == ZERO_PAGE(0)) + return; + + va = page_address(page); + addr = (unsigned long) va; + + if (va == NULL && PageHighMem(page)) + addr = (unsigned long) kmap_atomic(page); + + cache_wbinv_range(addr, addr + PAGE_SIZE); + + if (va == NULL && PageHighMem(page)) + kunmap_atomic((void *) addr); +} diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c new file mode 100644 index 000000000000..e7e11344005a --- /dev/null +++ b/arch/csky/abiv2/fpu.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/ptrace.h> +#include <linux/uaccess.h> +#include <abi/reg_ops.h> + +#define MTCR_MASK 0xFC00FFE0 +#define MFCR_MASK 0xFC00FFE0 +#define MTCR_DIST 0xC0006420 +#define MFCR_DIST 0xC0006020 + +void __init init_fpu(void) +{ + mtcr("cr<1, 2>", 0); +} + +/* + * fpu_libc_helper() is to help libc to excute: + * - mfcr %a, cr<1, 2> + * - mfcr %a, cr<2, 2> + * - mtcr %a, cr<1, 2> + * - mtcr %a, cr<2, 2> + */ +int fpu_libc_helper(struct pt_regs *regs) +{ + int fault; + unsigned long instrptr, regx = 0; + unsigned long index = 0, tmp = 0; + unsigned long tinstr = 0; + u16 instr_hi, instr_low; + + instrptr = instruction_pointer(regs); + if (instrptr & 1) + return 0; + + fault = __get_user(instr_low, (u16 *)instrptr); + if (fault) + return 0; + + fault = __get_user(instr_hi, (u16 *)(instrptr + 2)); + if (fault) + return 0; + + tinstr = instr_hi | ((unsigned long)instr_low << 16); + + if (((tinstr >> 21) & 0x1F) != 2) + return 0; + + if ((tinstr & MTCR_MASK) == MTCR_DIST) { + index = (tinstr >> 16) & 0x1F; + if (index > 13) + return 0; + + tmp = tinstr & 0x1F; + if (tmp > 2) + return 0; + + regx = *(®s->a0 + index); + + if (tmp == 1) + mtcr("cr<1, 2>", regx); + else if (tmp == 2) + mtcr("cr<2, 2>", regx); + else + return 0; + + regs->pc += 4; + return 1; + } + + if ((tinstr & MFCR_MASK) == MFCR_DIST) { + index = tinstr & 0x1F; + if (index > 13) + return 0; + + tmp = ((tinstr >> 16) & 0x1F); + if (tmp > 2) + return 0; + + if (tmp == 1) + regx = mfcr("cr<1, 2>"); + else if (tmp == 2) + regx = mfcr("cr<2, 2>"); + else + return 0; + + *(®s->a0 + index) = regx; + + regs->pc += 4; + return 1; + } + + return 0; +} + +void fpu_fpe(struct pt_regs *regs) +{ + int sig, code; + unsigned int fesr; + + fesr = mfcr("cr<2, 2>"); + + sig = SIGFPE; + code = FPE_FLTUNK; + + if (fesr & FPE_ILLE) { + sig = SIGILL; + code = ILL_ILLOPC; + } else if (fesr & FPE_IDC) { + sig = SIGILL; + code = ILL_ILLOPN; + } else if (fesr & FPE_FEC) { + sig = SIGFPE; + if (fesr & FPE_IOC) + code = FPE_FLTINV; + else if (fesr & FPE_DZC) + code = FPE_FLTDIV; + else if (fesr & FPE_UFC) + code = FPE_FLTUND; + else if (fesr & FPE_OFC) + code = FPE_FLTOVF; + else if (fesr & FPE_IXC) + code = FPE_FLTRES; + } + + force_sig_fault(sig, code, (void __user *)regs->pc, current); +} + +#define FMFVR_FPU_REGS(vrx, vry) \ + "fmfvrl %0, "#vrx"\n" \ + "fmfvrh %1, "#vrx"\n" \ + "fmfvrl %2, "#vry"\n" \ + "fmfvrh %3, "#vry"\n" + +#define FMTVR_FPU_REGS(vrx, vry) \ + "fmtvrl "#vrx", %0\n" \ + "fmtvrh "#vrx", %1\n" \ + "fmtvrl "#vry", %2\n" \ + "fmtvrh "#vry", %3\n" + +#define STW_FPU_REGS(a, b, c, d) \ + "stw %0, (%4, "#a")\n" \ + "stw %1, (%4, "#b")\n" \ + "stw %2, (%4, "#c")\n" \ + "stw %3, (%4, "#d")\n" + +#define LDW_FPU_REGS(a, b, c, d) \ + "ldw %0, (%4, "#a")\n" \ + "ldw %1, (%4, "#b")\n" \ + "ldw %2, (%4, "#c")\n" \ + "ldw %3, (%4, "#d")\n" + +void save_to_user_fp(struct user_fp *user_fp) +{ + unsigned long flg; + unsigned long tmp1, tmp2; + unsigned long *fpregs; + + local_irq_save(flg); + + tmp1 = mfcr("cr<1, 2>"); + tmp2 = mfcr("cr<2, 2>"); + + user_fp->fcr = tmp1; + user_fp->fesr = tmp2; + + fpregs = &user_fp->vr[0]; +#ifdef CONFIG_CPU_HAS_FPUV2 +#ifdef CONFIG_CPU_HAS_VDSP + asm volatile( + "vstmu.32 vr0-vr3, (%0)\n" + "vstmu.32 vr4-vr7, (%0)\n" + "vstmu.32 vr8-vr11, (%0)\n" + "vstmu.32 vr12-vr15, (%0)\n" + "fstmu.64 vr16-vr31, (%0)\n" + : "+a"(fpregs) + ::"memory"); +#else + asm volatile( + "fstmu.64 vr0-vr31, (%0)\n" + : "+a"(fpregs) + ::"memory"); +#endif +#else + { + unsigned long tmp3, tmp4; + + asm volatile( + FMFVR_FPU_REGS(vr0, vr1) + STW_FPU_REGS(0, 4, 16, 20) + FMFVR_FPU_REGS(vr2, vr3) + STW_FPU_REGS(32, 36, 48, 52) + FMFVR_FPU_REGS(vr4, vr5) + STW_FPU_REGS(64, 68, 80, 84) + FMFVR_FPU_REGS(vr6, vr7) + STW_FPU_REGS(96, 100, 112, 116) + "addi %4, 128\n" + FMFVR_FPU_REGS(vr8, vr9) + STW_FPU_REGS(0, 4, 16, 20) + FMFVR_FPU_REGS(vr10, vr11) + STW_FPU_REGS(32, 36, 48, 52) + FMFVR_FPU_REGS(vr12, vr13) + STW_FPU_REGS(64, 68, 80, 84) + FMFVR_FPU_REGS(vr14, vr15) + STW_FPU_REGS(96, 100, 112, 116) + : "=a"(tmp1), "=a"(tmp2), "=a"(tmp3), + "=a"(tmp4), "+a"(fpregs) + ::"memory"); + } +#endif + + local_irq_restore(flg); +} + +void restore_from_user_fp(struct user_fp *user_fp) +{ + unsigned long flg; + unsigned long tmp1, tmp2; + unsigned long *fpregs; + + local_irq_save(flg); + + tmp1 = user_fp->fcr; + tmp2 = user_fp->fesr; + + mtcr("cr<1, 2>", tmp1); + mtcr("cr<2, 2>", tmp2); + + fpregs = &user_fp->vr[0]; +#ifdef CONFIG_CPU_HAS_FPUV2 +#ifdef CONFIG_CPU_HAS_VDSP + asm volatile( + "vldmu.32 vr0-vr3, (%0)\n" + "vldmu.32 vr4-vr7, (%0)\n" + "vldmu.32 vr8-vr11, (%0)\n" + "vldmu.32 vr12-vr15, (%0)\n" + "fldmu.64 vr16-vr31, (%0)\n" + : "+a"(fpregs) + ::"memory"); +#else + asm volatile( + "fldmu.64 vr0-vr31, (%0)\n" + : "+a"(fpregs) + ::"memory"); +#endif +#else + { + unsigned long tmp3, tmp4; + + asm volatile( + LDW_FPU_REGS(0, 4, 16, 20) + FMTVR_FPU_REGS(vr0, vr1) + LDW_FPU_REGS(32, 36, 48, 52) + FMTVR_FPU_REGS(vr2, vr3) + LDW_FPU_REGS(64, 68, 80, 84) + FMTVR_FPU_REGS(vr4, vr5) + LDW_FPU_REGS(96, 100, 112, 116) + FMTVR_FPU_REGS(vr6, vr7) + "addi %4, 128\n" + LDW_FPU_REGS(0, 4, 16, 20) + FMTVR_FPU_REGS(vr8, vr9) + LDW_FPU_REGS(32, 36, 48, 52) + FMTVR_FPU_REGS(vr10, vr11) + LDW_FPU_REGS(64, 68, 80, 84) + FMTVR_FPU_REGS(vr12, vr13) + LDW_FPU_REGS(96, 100, 112, 116) + FMTVR_FPU_REGS(vr14, vr15) + : "=a"(tmp1), "=a"(tmp2), "=a"(tmp3), + "=a"(tmp4), "+a"(fpregs) + ::"memory"); + } +#endif + local_irq_restore(flg); +} diff --git a/arch/csky/abiv2/inc/abi/cacheflush.h b/arch/csky/abiv2/inc/abi/cacheflush.h new file mode 100644 index 000000000000..b8db5e0b2fe3 --- /dev/null +++ b/arch/csky/abiv2/inc/abi/cacheflush.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ABI_CSKY_CACHEFLUSH_H +#define __ABI_CSKY_CACHEFLUSH_H + +/* Keep includes the same across arches. */ +#include <linux/mm.h> + +/* + * The cache doesn't need to be flushed when TLB entries change when + * the cache is mapped to physical memory, not virtual memory + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_dup_mm(mm) do { } while (0) + +#define flush_cache_range(vma, start, end) \ + do { \ + if (vma->vm_flags & VM_EXEC) \ + icache_inv_all(); \ + } while (0) + +#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 +#define flush_dcache_page(page) do { } while (0) +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +#define flush_icache_range(start, end) cache_wbinv_range(start, end) + +void flush_icache_page(struct vm_area_struct *vma, struct page *page); +void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, int len); + +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) + +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + memcpy(dst, src, len); \ + cache_wbinv_range((unsigned long)dst, (unsigned long)dst + len); \ +} while (0) +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ + memcpy(dst, src, len) + +#endif /* __ABI_CSKY_CACHEFLUSH_H */ diff --git a/arch/csky/abiv2/inc/abi/ckmmu.h b/arch/csky/abiv2/inc/abi/ckmmu.h new file mode 100644 index 000000000000..97230ad9427c --- /dev/null +++ b/arch/csky/abiv2/inc/abi/ckmmu.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_CKMMUV2_H +#define __ASM_CSKY_CKMMUV2_H + +#include <abi/reg_ops.h> +#include <asm/barrier.h> + +static inline int read_mmu_index(void) +{ + return mfcr("cr<0, 15>"); +} + +static inline void write_mmu_index(int value) +{ + mtcr("cr<0, 15>", value); +} + +static inline int read_mmu_entrylo0(void) +{ + return mfcr("cr<2, 15>"); +} + +static inline int read_mmu_entrylo1(void) +{ + return mfcr("cr<3, 15>"); +} + +static inline void write_mmu_pagemask(int value) +{ + mtcr("cr<6, 15>", value); +} + +static inline int read_mmu_entryhi(void) +{ + return mfcr("cr<4, 15>"); +} + +static inline void write_mmu_entryhi(int value) +{ + mtcr("cr<4, 15>", value); +} + +/* + * TLB operations. + */ +static inline void tlb_probe(void) +{ + mtcr("cr<8, 15>", 0x80000000); +} + +static inline void tlb_read(void) +{ + mtcr("cr<8, 15>", 0x40000000); +} + +static inline void tlb_invalid_all(void) +{ +#ifdef CONFIG_CPU_HAS_TLBI + asm volatile("tlbi.alls\n":::"memory"); + sync_is(); +#else + mtcr("cr<8, 15>", 0x04000000); +#endif +} + +static inline void tlb_invalid_indexed(void) +{ + mtcr("cr<8, 15>", 0x02000000); +} + +/* setup hardrefil pgd */ +static inline unsigned long get_pgd(void) +{ + return mfcr("cr<29, 15>"); +} + +static inline void setup_pgd(unsigned long pgd, bool kernel) +{ + if (kernel) + mtcr("cr<28, 15>", pgd); + else + mtcr("cr<29, 15>", pgd); +} + +#endif /* __ASM_CSKY_CKMMUV2_H */ diff --git a/arch/csky/abiv2/inc/abi/elf.h b/arch/csky/abiv2/inc/abi/elf.h new file mode 100644 index 000000000000..290f49ef4c48 --- /dev/null +++ b/arch/csky/abiv2/inc/abi/elf.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ABI_CSKY_ELF_H +#define __ABI_CSKY_ELF_H + +/* The member sort in array pr_reg[x] is defined by GDB. */ +#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ + pr_reg[0] = regs->pc; \ + pr_reg[1] = regs->a1; \ + pr_reg[2] = regs->a0; \ + pr_reg[3] = regs->sr; \ + pr_reg[4] = regs->a2; \ + pr_reg[5] = regs->a3; \ + pr_reg[6] = regs->regs[0]; \ + pr_reg[7] = regs->regs[1]; \ + pr_reg[8] = regs->regs[2]; \ + pr_reg[9] = regs->regs[3]; \ + pr_reg[10] = regs->regs[4]; \ + pr_reg[11] = regs->regs[5]; \ + pr_reg[12] = regs->regs[6]; \ + pr_reg[13] = regs->regs[7]; \ + pr_reg[14] = regs->regs[8]; \ + pr_reg[15] = regs->regs[9]; \ + pr_reg[16] = regs->usp; \ + pr_reg[17] = regs->lr; \ + pr_reg[18] = regs->exregs[0]; \ + pr_reg[19] = regs->exregs[1]; \ + pr_reg[20] = regs->exregs[2]; \ + pr_reg[21] = regs->exregs[3]; \ + pr_reg[22] = regs->exregs[4]; \ + pr_reg[23] = regs->exregs[5]; \ + pr_reg[24] = regs->exregs[6]; \ + pr_reg[25] = regs->exregs[7]; \ + pr_reg[26] = regs->exregs[8]; \ + pr_reg[27] = regs->exregs[9]; \ + pr_reg[28] = regs->exregs[10]; \ + pr_reg[29] = regs->exregs[11]; \ + pr_reg[30] = regs->exregs[12]; \ + pr_reg[31] = regs->exregs[13]; \ + pr_reg[32] = regs->exregs[14]; \ + pr_reg[33] = regs->tls; \ +} while (0); +#endif /* __ABI_CSKY_ELF_H */ diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h new file mode 100644 index 000000000000..acd05214d4e3 --- /dev/null +++ b/arch/csky/abiv2/inc/abi/entry.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_ENTRY_H +#define __ASM_CSKY_ENTRY_H + +#include <asm/setup.h> +#include <abi/regdef.h> + +#define LSAVE_PC 8 +#define LSAVE_PSR 12 +#define LSAVE_A0 24 +#define LSAVE_A1 28 +#define LSAVE_A2 32 +#define LSAVE_A3 36 + +#define EPC_INCREASE 4 +#define EPC_KEEP 0 + +#define KSPTOUSP +#define USPTOKSP + +#define usp cr<14, 1> + +.macro INCTRAP rx + addi \rx, EPC_INCREASE +.endm + +.macro SAVE_ALL epc_inc + subi sp, 152 + stw tls, (sp, 0) + stw lr, (sp, 4) + + mfcr lr, epc + movi tls, \epc_inc + add lr, tls + stw lr, (sp, 8) + + mfcr lr, epsr + stw lr, (sp, 12) + mfcr lr, usp + stw lr, (sp, 16) + + stw a0, (sp, 20) + stw a0, (sp, 24) + stw a1, (sp, 28) + stw a2, (sp, 32) + stw a3, (sp, 36) + + addi sp, 40 + stm r4-r13, (sp) + + addi sp, 40 + stm r16-r30, (sp) +#ifdef CONFIG_CPU_HAS_HILO + mfhi lr + stw lr, (sp, 60) + mflo lr + stw lr, (sp, 64) +#endif + subi sp, 80 +.endm + +.macro RESTORE_ALL + psrclr ie + ldw tls, (sp, 0) + ldw lr, (sp, 4) + ldw a0, (sp, 8) + mtcr a0, epc + ldw a0, (sp, 12) + mtcr a0, epsr + ldw a0, (sp, 16) + mtcr a0, usp + +#ifdef CONFIG_CPU_HAS_HILO + ldw a0, (sp, 140) + mthi a0 + ldw a0, (sp, 144) + mtlo a0 +#endif + + ldw a0, (sp, 24) + ldw a1, (sp, 28) + ldw a2, (sp, 32) + ldw a3, (sp, 36) + + addi sp, 40 + ldm r4-r13, (sp) + addi sp, 40 + ldm r16-r30, (sp) + addi sp, 72 + rte +.endm + +.macro SAVE_SWITCH_STACK + subi sp, 64 + stm r4-r11, (sp) + stw r15, (sp, 32) + stw r16, (sp, 36) + stw r17, (sp, 40) + stw r26, (sp, 44) + stw r27, (sp, 48) + stw r28, (sp, 52) + stw r29, (sp, 56) + stw r30, (sp, 60) +.endm + +.macro RESTORE_SWITCH_STACK + ldm r4-r11, (sp) + ldw r15, (sp, 32) + ldw r16, (sp, 36) + ldw r17, (sp, 40) + ldw r26, (sp, 44) + ldw r27, (sp, 48) + ldw r28, (sp, 52) + ldw r29, (sp, 56) + ldw r30, (sp, 60) + addi sp, 64 +.endm + +/* MMU registers operators. */ +.macro RD_MIR rx + mfcr \rx, cr<0, 15> +.endm + +.macro RD_MEH rx + mfcr \rx, cr<4, 15> +.endm + +.macro RD_MCIR rx + mfcr \rx, cr<8, 15> +.endm + +.macro RD_PGDR rx + mfcr \rx, cr<29, 15> +.endm + +.macro RD_PGDR_K rx + mfcr \rx, cr<28, 15> +.endm + +.macro WR_MEH rx + mtcr \rx, cr<4, 15> +.endm + +.macro WR_MCIR rx + mtcr \rx, cr<8, 15> +.endm + +.macro SETUP_MMU rx + lrw \rx, PHYS_OFFSET | 0xe + mtcr \rx, cr<30, 15> + lrw \rx, (PHYS_OFFSET + 0x20000000) | 0xe + mtcr \rx, cr<31, 15> +.endm +#endif /* __ASM_CSKY_ENTRY_H */ diff --git a/arch/csky/abiv2/inc/abi/fpu.h b/arch/csky/abiv2/inc/abi/fpu.h new file mode 100644 index 000000000000..22ca3cf2794a --- /dev/null +++ b/arch/csky/abiv2/inc/abi/fpu.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_FPU_H +#define __ASM_CSKY_FPU_H + +#include <asm/sigcontext.h> +#include <asm/ptrace.h> + +int fpu_libc_helper(struct pt_regs *regs); +void fpu_fpe(struct pt_regs *regs); +void __init init_fpu(void); + +void save_to_user_fp(struct user_fp *user_fp); +void restore_from_user_fp(struct user_fp *user_fp); + +/* + * Define the fesr bit for fpe handle. + */ +#define FPE_ILLE (1 << 16) /* Illegal instruction */ +#define FPE_FEC (1 << 7) /* Input float-point arithmetic exception */ +#define FPE_IDC (1 << 5) /* Input denormalized exception */ +#define FPE_IXC (1 << 4) /* Inexact exception */ +#define FPE_UFC (1 << 3) /* Underflow exception */ +#define FPE_OFC (1 << 2) /* Overflow exception */ +#define FPE_DZC (1 << 1) /* Divide by zero exception */ +#define FPE_IOC (1 << 0) /* Invalid operation exception */ +#define FPE_REGULAR_EXCEPTION (FPE_IXC | FPE_UFC | FPE_OFC | FPE_DZC | FPE_IOC) + +#ifdef CONFIG_OPEN_FPU_IDE +#define IDE_STAT (1 << 5) +#else +#define IDE_STAT 0 +#endif + +#ifdef CONFIG_OPEN_FPU_IXE +#define IXE_STAT (1 << 4) +#else +#define IXE_STAT 0 +#endif + +#ifdef CONFIG_OPEN_FPU_UFE +#define UFE_STAT (1 << 3) +#else +#define UFE_STAT 0 +#endif + +#ifdef CONFIG_OPEN_FPU_OFE +#define OFE_STAT (1 << 2) +#else +#define OFE_STAT 0 +#endif + +#ifdef CONFIG_OPEN_FPU_DZE +#define DZE_STAT (1 << 1) +#else +#define DZE_STAT 0 +#endif + +#ifdef CONFIG_OPEN_FPU_IOE +#define IOE_STAT (1 << 0) +#else +#define IOE_STAT 0 +#endif + +#endif /* __ASM_CSKY_FPU_H */ diff --git a/arch/csky/abiv2/inc/abi/page.h b/arch/csky/abiv2/inc/abi/page.h new file mode 100644 index 000000000000..0a70cb553dca --- /dev/null +++ b/arch/csky/abiv2/inc/abi/page.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +static inline void clear_user_page(void *addr, unsigned long vaddr, + struct page *page) +{ + clear_page(addr); +} + +static inline void copy_user_page(void *to, void *from, unsigned long vaddr, + struct page *page) +{ + copy_page(to, from); +} diff --git a/arch/csky/abiv2/inc/abi/pgtable-bits.h b/arch/csky/abiv2/inc/abi/pgtable-bits.h new file mode 100644 index 000000000000..b20ae19702e3 --- /dev/null +++ b/arch/csky/abiv2/inc/abi/pgtable-bits.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_PGTABLE_BITS_H +#define __ASM_CSKY_PGTABLE_BITS_H + +/* implemented in software */ +#define _PAGE_ACCESSED (1<<7) +#define PAGE_ACCESSED_BIT (7) + +#define _PAGE_READ (1<<8) +#define _PAGE_WRITE (1<<9) +#define _PAGE_PRESENT (1<<10) + +#define _PAGE_MODIFIED (1<<11) +#define PAGE_MODIFIED_BIT (11) + +/* implemented in hardware */ +#define _PAGE_GLOBAL (1<<0) + +#define _PAGE_VALID (1<<1) +#define PAGE_VALID_BIT (1) + +#define _PAGE_DIRTY (1<<2) +#define PAGE_DIRTY_BIT (2) + +#define _PAGE_SO (1<<5) +#define _PAGE_BUF (1<<6) + +#define _PAGE_CACHE (1<<3) + +#define _CACHE_MASK _PAGE_CACHE + +#define _CACHE_CACHED (_PAGE_VALID | _PAGE_CACHE | _PAGE_BUF) +#define _CACHE_UNCACHED (_PAGE_VALID | _PAGE_SO) + +#endif /* __ASM_CSKY_PGTABLE_BITS_H */ diff --git a/arch/csky/abiv2/inc/abi/reg_ops.h b/arch/csky/abiv2/inc/abi/reg_ops.h new file mode 100644 index 000000000000..ae82c3f26a6b --- /dev/null +++ b/arch/csky/abiv2/inc/abi/reg_ops.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ABI_REG_OPS_H +#define __ABI_REG_OPS_H +#include <asm/reg_ops.h> + +static inline unsigned int mfcr_hint(void) +{ + return mfcr("cr31"); +} + +static inline unsigned int mfcr_ccr2(void) +{ + return mfcr("cr23"); +} +#endif /* __ABI_REG_OPS_H */ diff --git a/arch/csky/abiv2/inc/abi/regdef.h b/arch/csky/abiv2/inc/abi/regdef.h new file mode 100644 index 000000000000..c72abb781bdc --- /dev/null +++ b/arch/csky/abiv2/inc/abi/regdef.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_REGDEF_H +#define __ASM_CSKY_REGDEF_H + +#define syscallid r7 +#define r11_sig r11 + +#define regs_syscallid(regs) regs->regs[3] + +/* + * PSR format: + * | 31 | 30-24 | 23-16 | 15 14 | 13-10 | 9 | 8-0 | + * S VEC TM MM + * + * S: Super Mode + * VEC: Exception Number + * TM: Trace Mode + * MM: Memory unaligned addr access + */ +#define DEFAULT_PSR_VALUE 0x80000200 + +#define SYSTRACE_SAVENUM 5 + +#endif /* __ASM_CSKY_REGDEF_H */ diff --git a/arch/csky/abiv2/inc/abi/string.h b/arch/csky/abiv2/inc/abi/string.h new file mode 100644 index 000000000000..f01bad2ac4fb --- /dev/null +++ b/arch/csky/abiv2/inc/abi/string.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ABI_CSKY_STRING_H +#define __ABI_CSKY_STRING_H + +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +#define __HAVE_ARCH_STRCMP +extern int strcmp(const char *, const char *); + +#define __HAVE_ARCH_STRCPY +extern char *strcpy(char *, const char *); + +#define __HAVE_ARCH_STRLEN +extern __kernel_size_t strlen(const char *); + +#endif /* __ABI_CSKY_STRING_H */ diff --git a/arch/csky/abiv2/inc/abi/vdso.h b/arch/csky/abiv2/inc/abi/vdso.h new file mode 100644 index 000000000000..b60d4a070326 --- /dev/null +++ b/arch/csky/abiv2/inc/abi/vdso.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ABI_CSKY_VDSO_H +#define __ABI_CSKY_VDSO_H + +#include <linux/uaccess.h> + +static inline int setup_vdso_page(unsigned short *ptr) +{ + int err = 0; + + /* movi r7, 173 */ + err |= __put_user(0xea07, ptr); + err |= __put_user(0x008b, ptr+1); + + /* trap 0 */ + err |= __put_user(0xc000, ptr+2); + err |= __put_user(0x2020, ptr+3); + + return err; +} + +#endif /* __ABI_CSKY_STRING_H */ diff --git a/arch/csky/abiv2/memcmp.S b/arch/csky/abiv2/memcmp.S new file mode 100644 index 000000000000..bf0d809f09e2 --- /dev/null +++ b/arch/csky/abiv2/memcmp.S @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + +ENTRY(memcmp) + /* Test if len less than 4 bytes. */ + mov r3, r0 + movi r0, 0 + mov r12, r4 + cmplti r2, 4 + bt .L_compare_by_byte + + andi r13, r0, 3 + movi r19, 4 + + /* Test if s1 is not 4 bytes aligned. */ + bnez r13, .L_s1_not_aligned + + LABLE_ALIGN +.L_s1_aligned: + /* If dest is aligned, then copy. */ + zext r18, r2, 31, 4 + /* Test if len less than 16 bytes. */ + bez r18, .L_compare_by_word + +.L_compare_by_4word: + /* If aligned, load word each time. */ + ldw r20, (r3, 0) + ldw r21, (r1, 0) + /* If s1[i] != s2[i], goto .L_byte_check. */ + cmpne r20, r21 + bt .L_byte_check + + ldw r20, (r3, 4) + ldw r21, (r1, 4) + cmpne r20, r21 + bt .L_byte_check + + ldw r20, (r3, 8) + ldw r21, (r1, 8) + cmpne r20, r21 + bt .L_byte_check + + ldw r20, (r3, 12) + ldw r21, (r1, 12) + cmpne r20, r21 + bt .L_byte_check + + PRE_BNEZAD (r18) + addi a3, 16 + addi a1, 16 + + BNEZAD (r18, .L_compare_by_4word) + +.L_compare_by_word: + zext r18, r2, 3, 2 + bez r18, .L_compare_by_byte +.L_compare_by_word_loop: + ldw r20, (r3, 0) + ldw r21, (r1, 0) + addi r3, 4 + PRE_BNEZAD (r18) + cmpne r20, r21 + addi r1, 4 + bt .L_byte_check + BNEZAD (r18, .L_compare_by_word_loop) + +.L_compare_by_byte: + zext r18, r2, 1, 0 + bez r18, .L_return +.L_compare_by_byte_loop: + ldb r0, (r3, 0) + ldb r4, (r1, 0) + addi r3, 1 + subu r0, r4 + PRE_BNEZAD (r18) + addi r1, 1 + bnez r0, .L_return + BNEZAD (r18, .L_compare_by_byte_loop) + +.L_return: + mov r4, r12 + rts + +# ifdef __CSKYBE__ +/* d[i] != s[i] in word, so we check byte 0. */ +.L_byte_check: + xtrb0 r0, r20 + xtrb0 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 1 */ + xtrb1 r0, r20 + xtrb1 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 2 */ + xtrb2 r0, r20 + xtrb2 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 3 */ + xtrb3 r0, r20 + xtrb3 r2, r21 + subu r0, r2 +# else +/* s1[i] != s2[i] in word, so we check byte 3. */ +.L_byte_check: + xtrb3 r0, r20 + xtrb3 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 2 */ + xtrb2 r0, r20 + xtrb2 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 1 */ + xtrb1 r0, r20 + xtrb1 r2, r21 + subu r0, r2 + bnez r0, .L_return + + /* check byte 0 */ + xtrb0 r0, r20 + xtrb0 r2, r21 + subu r0, r2 + br .L_return +# endif /* !__CSKYBE__ */ + +/* Compare when s1 is not aligned. */ +.L_s1_not_aligned: + sub r13, r19, r13 + sub r2, r13 +.L_s1_not_aligned_loop: + ldb r0, (r3, 0) + ldb r4, (r1, 0) + addi r3, 1 + subu r0, r4 + PRE_BNEZAD (r13) + addi r1, 1 + bnez r0, .L_return + BNEZAD (r13, .L_s1_not_aligned_loop) + br .L_s1_aligned +ENDPROC(memcmp) diff --git a/arch/csky/abiv2/memcpy.S b/arch/csky/abiv2/memcpy.S new file mode 100644 index 000000000000..987fec60ab97 --- /dev/null +++ b/arch/csky/abiv2/memcpy.S @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + +ENTRY(__memcpy) +ENTRY(memcpy) + /* Test if len less than 4 bytes. */ + mov r12, r0 + cmplti r2, 4 + bt .L_copy_by_byte + + andi r13, r0, 3 + movi r19, 4 + /* Test if dest is not 4 bytes aligned. */ + bnez r13, .L_dest_not_aligned + +/* Hardware can handle unaligned access directly. */ +.L_dest_aligned: + /* If dest is aligned, then copy. */ + zext r18, r2, 31, 4 + + /* Test if len less than 16 bytes. */ + bez r18, .L_len_less_16bytes + movi r19, 0 + + LABLE_ALIGN +.L_len_larger_16bytes: +#if defined(__CSKY_VDSPV2__) + vldx.8 vr0, (r1), r19 + PRE_BNEZAD (r18) + addi r1, 16 + vstx.8 vr0, (r0), r19 + addi r0, 16 +#elif defined(__CK860__) + ldw r3, (r1, 0) + stw r3, (r0, 0) + ldw r3, (r1, 4) + stw r3, (r0, 4) + ldw r3, (r1, 8) + stw r3, (r0, 8) + ldw r3, (r1, 12) + addi r1, 16 + stw r3, (r0, 12) + addi r0, 16 +#else + ldw r20, (r1, 0) + ldw r21, (r1, 4) + ldw r22, (r1, 8) + ldw r23, (r1, 12) + stw r20, (r0, 0) + stw r21, (r0, 4) + stw r22, (r0, 8) + stw r23, (r0, 12) + PRE_BNEZAD (r18) + addi r1, 16 + addi r0, 16 +#endif + BNEZAD (r18, .L_len_larger_16bytes) + +.L_len_less_16bytes: + zext r18, r2, 3, 2 + bez r18, .L_copy_by_byte +.L_len_less_16bytes_loop: + ldw r3, (r1, 0) + PRE_BNEZAD (r18) + addi r1, 4 + stw r3, (r0, 0) + addi r0, 4 + BNEZAD (r18, .L_len_less_16bytes_loop) + +/* Test if len less than 4 bytes. */ +.L_copy_by_byte: + zext r18, r2, 1, 0 + bez r18, .L_return +.L_copy_by_byte_loop: + ldb r3, (r1, 0) + PRE_BNEZAD (r18) + addi r1, 1 + stb r3, (r0, 0) + addi r0, 1 + BNEZAD (r18, .L_copy_by_byte_loop) + +.L_return: + mov r0, r12 + rts + +/* + * If dest is not aligned, just copying some bytes makes the + * dest align. + */ +.L_dest_not_aligned: + sub r13, r19, r13 + sub r2, r13 + +/* Makes the dest align. */ +.L_dest_not_aligned_loop: + ldb r3, (r1, 0) + PRE_BNEZAD (r13) + addi r1, 1 + stb r3, (r0, 0) + addi r0, 1 + BNEZAD (r13, .L_dest_not_aligned_loop) + cmplti r2, 4 + bt .L_copy_by_byte + + /* Check whether the src is aligned. */ + jbr .L_dest_aligned +ENDPROC(__memcpy) diff --git a/arch/csky/abiv2/memmove.S b/arch/csky/abiv2/memmove.S new file mode 100644 index 000000000000..b0c42ecf1889 --- /dev/null +++ b/arch/csky/abiv2/memmove.S @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + + .weak memmove +ENTRY(__memmove) +ENTRY(memmove) + subu r3, r0, r1 + cmphs r3, r2 + bt memcpy + + mov r12, r0 + addu r0, r0, r2 + addu r1, r1, r2 + + /* Test if len less than 4 bytes. */ + cmplti r2, 4 + bt .L_copy_by_byte + + andi r13, r0, 3 + /* Test if dest is not 4 bytes aligned. */ + bnez r13, .L_dest_not_aligned + /* Hardware can handle unaligned access directly. */ +.L_dest_aligned: + /* If dest is aligned, then copy. */ + zext r18, r2, 31, 4 + /* Test if len less than 16 bytes. */ + bez r18, .L_len_less_16bytes + movi r19, 0 + + /* len > 16 bytes */ + LABLE_ALIGN +.L_len_larger_16bytes: + subi r1, 16 + subi r0, 16 +#if defined(__CSKY_VDSPV2__) + vldx.8 vr0, (r1), r19 + PRE_BNEZAD (r18) + vstx.8 vr0, (r0), r19 +#elif defined(__CK860__) + ldw r3, (r1, 12) + stw r3, (r0, 12) + ldw r3, (r1, 8) + stw r3, (r0, 8) + ldw r3, (r1, 4) + stw r3, (r0, 4) + ldw r3, (r1, 0) + stw r3, (r0, 0) +#else + ldw r20, (r1, 0) + ldw r21, (r1, 4) + ldw r22, (r1, 8) + ldw r23, (r1, 12) + stw r20, (r0, 0) + stw r21, (r0, 4) + stw r22, (r0, 8) + stw r23, (r0, 12) + PRE_BNEZAD (r18) +#endif + BNEZAD (r18, .L_len_larger_16bytes) + +.L_len_less_16bytes: + zext r18, r2, 3, 2 + bez r18, .L_copy_by_byte +.L_len_less_16bytes_loop: + subi r1, 4 + subi r0, 4 + ldw r3, (r1, 0) + PRE_BNEZAD (r18) + stw r3, (r0, 0) + BNEZAD (r18, .L_len_less_16bytes_loop) + + /* Test if len less than 4 bytes. */ +.L_copy_by_byte: + zext r18, r2, 1, 0 + bez r18, .L_return +.L_copy_by_byte_loop: + subi r1, 1 + subi r0, 1 + ldb r3, (r1, 0) + PRE_BNEZAD (r18) + stb r3, (r0, 0) + BNEZAD (r18, .L_copy_by_byte_loop) + +.L_return: + mov r0, r12 + rts + + /* If dest is not aligned, just copy some bytes makes the dest + align. */ +.L_dest_not_aligned: + sub r2, r13 +.L_dest_not_aligned_loop: + subi r1, 1 + subi r0, 1 + /* Makes the dest align. */ + ldb r3, (r1, 0) + PRE_BNEZAD (r13) + stb r3, (r0, 0) + BNEZAD (r13, .L_dest_not_aligned_loop) + cmplti r2, 4 + bt .L_copy_by_byte + /* Check whether the src is aligned. */ + jbr .L_dest_aligned +ENDPROC(memmove) +ENDPROC(__memmove) diff --git a/arch/csky/abiv2/memset.S b/arch/csky/abiv2/memset.S new file mode 100644 index 000000000000..a7e7d994b667 --- /dev/null +++ b/arch/csky/abiv2/memset.S @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + + .weak memset +ENTRY(__memset) +ENTRY(memset) + /* Test if len less than 4 bytes. */ + mov r12, r0 + cmplti r2, 8 + bt .L_set_by_byte + + andi r13, r0, 3 + movi r19, 4 + /* Test if dest is not 4 bytes aligned. */ + bnez r13, .L_dest_not_aligned + /* Hardware can handle unaligned access directly. */ +.L_dest_aligned: + zextb r3, r1 + lsli r1, 8 + or r1, r3 + lsli r3, r1, 16 + or r3, r1 + + /* If dest is aligned, then copy. */ + zext r18, r2, 31, 4 + /* Test if len less than 16 bytes. */ + bez r18, .L_len_less_16bytes + + LABLE_ALIGN +.L_len_larger_16bytes: + stw r3, (r0, 0) + stw r3, (r0, 4) + stw r3, (r0, 8) + stw r3, (r0, 12) + PRE_BNEZAD (r18) + addi r0, 16 + BNEZAD (r18, .L_len_larger_16bytes) + +.L_len_less_16bytes: + zext r18, r2, 3, 2 + andi r2, 3 + bez r18, .L_set_by_byte +.L_len_less_16bytes_loop: + stw r3, (r0, 0) + PRE_BNEZAD (r18) + addi r0, 4 + BNEZAD (r18, .L_len_less_16bytes_loop) + + /* Test if len less than 4 bytes. */ +.L_set_by_byte: + zext r18, r2, 2, 0 + bez r18, .L_return +.L_set_by_byte_loop: + stb r1, (r0, 0) + PRE_BNEZAD (r18) + addi r0, 1 + BNEZAD (r18, .L_set_by_byte_loop) + +.L_return: + mov r0, r12 + rts + + /* If dest is not aligned, just set some bytes makes the dest + align. */ + +.L_dest_not_aligned: + sub r13, r19, r13 + sub r2, r13 +.L_dest_not_aligned_loop: + /* Makes the dest align. */ + stb r1, (r0, 0) + PRE_BNEZAD (r13) + addi r0, 1 + BNEZAD (r13, .L_dest_not_aligned_loop) + cmplti r2, 8 + bt .L_set_by_byte + /* Check whether the src is aligned. */ + jbr .L_dest_aligned +ENDPROC(memset) +ENDPROC(__memset) diff --git a/arch/csky/abiv2/strcmp.S b/arch/csky/abiv2/strcmp.S new file mode 100644 index 000000000000..f8403f4d8c2b --- /dev/null +++ b/arch/csky/abiv2/strcmp.S @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + +ENTRY(strcmp) + mov a3, a0 + /* Check if the s1 addr is aligned. */ + xor a2, a3, a1 + andi a2, 0x3 + bnez a2, 7f + andi t1, a0, 0x3 + bnez t1, 5f + +1: + /* If aligned, load word each time. */ + ldw t0, (a3, 0) + ldw t1, (a1, 0) + /* If s1[i] != s2[i], goto 2f. */ + cmpne t0, t1 + bt 2f + /* If s1[i] == s2[i], check if s1 or s2 is at the end. */ + tstnbz t0 + /* If at the end, goto 3f (finish comparing). */ + bf 3f + + ldw t0, (a3, 4) + ldw t1, (a1, 4) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 8) + ldw t1, (a1, 8) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 12) + ldw t1, (a1, 12) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 16) + ldw t1, (a1, 16) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 20) + ldw t1, (a1, 20) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 24) + ldw t1, (a1, 24) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + ldw t0, (a3, 28) + ldw t1, (a1, 28) + cmpne t0, t1 + bt 2f + tstnbz t0 + bf 3f + + addi a3, 32 + addi a1, 32 + + br 1b + +# ifdef __CSKYBE__ + /* d[i] != s[i] in word, so we check byte 0. */ +2: + xtrb0 a0, t0 + xtrb0 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 1 */ + xtrb1 a0, t0 + xtrb1 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 2 */ + xtrb2 a0, t0 + xtrb2 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 3 */ + xtrb3 a0, t0 + xtrb3 a2, t1 + subu a0, a2 +# else + /* s1[i] != s2[i] in word, so we check byte 3. */ +2: + xtrb3 a0, t0 + xtrb3 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 2 */ + xtrb2 a0, t0 + xtrb2 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 1 */ + xtrb1 a0, t0 + xtrb1 a2, t1 + subu a0, a2 + bez a2, 4f + bnez a0, 4f + + /* check byte 0 */ + xtrb0 a0, t0 + xtrb0 a2, t1 + subu a0, a2 + +# endif /* !__CSKYBE__ */ + jmp lr +3: + movi a0, 0 +4: + jmp lr + + /* Compare when s1 or s2 is not aligned. */ +5: + subi t1, 4 +6: + ldb a0, (a3, 0) + ldb a2, (a1, 0) + subu a0, a2 + bez a2, 4b + bnez a0, 4b + addi t1, 1 + addi a1, 1 + addi a3, 1 + bnez t1, 6b + br 1b + +7: + ldb a0, (a3, 0) + addi a3, 1 + ldb a2, (a1, 0) + addi a1, 1 + subu a0, a2 + bnez a0, 4b + bnez a2, 7b + jmp r15 +ENDPROC(strcmp) diff --git a/arch/csky/abiv2/strcpy.S b/arch/csky/abiv2/strcpy.S new file mode 100644 index 000000000000..3c6d3f6a573a --- /dev/null +++ b/arch/csky/abiv2/strcpy.S @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + +ENTRY(strcpy) + mov a3, a0 + /* Check if the src addr is aligned. */ + andi t0, a1, 3 + bnez t0, 11f +1: + /* Check if all the bytes in the word are not zero. */ + ldw a2, (a1) + tstnbz a2 + bf 9f + stw a2, (a3) + + ldw a2, (a1, 4) + tstnbz a2 + bf 2f + stw a2, (a3, 4) + + ldw a2, (a1, 8) + tstnbz a2 + bf 3f + stw a2, (a3, 8) + + ldw a2, (a1, 12) + tstnbz a2 + bf 4f + stw a2, (a3, 12) + + ldw a2, (a1, 16) + tstnbz a2 + bf 5f + stw a2, (a3, 16) + + ldw a2, (a1, 20) + tstnbz a2 + bf 6f + stw a2, (a3, 20) + + ldw a2, (a1, 24) + tstnbz a2 + bf 7f + stw a2, (a3, 24) + + ldw a2, (a1, 28) + tstnbz a2 + bf 8f + stw a2, (a3, 28) + + addi a3, 32 + addi a1, 32 + br 1b + + +2: + addi a3, 4 + br 9f + +3: + addi a3, 8 + br 9f + +4: + addi a3, 12 + br 9f + +5: + addi a3, 16 + br 9f + +6: + addi a3, 20 + br 9f + +7: + addi a3, 24 + br 9f + +8: + addi a3, 28 +9: +# ifdef __CSKYBE__ + xtrb0 t0, a2 + st.b t0, (a3) + bez t0, 10f + xtrb1 t0, a2 + st.b t0, (a3, 1) + bez t0, 10f + xtrb2 t0, a2 + st.b t0, (a3, 2) + bez t0, 10f + stw a2, (a3) +# else + xtrb3 t0, a2 + st.b t0, (a3) + bez t0, 10f + xtrb2 t0, a2 + st.b t0, (a3, 1) + bez t0, 10f + xtrb1 t0, a2 + st.b t0, (a3, 2) + bez t0, 10f + stw a2, (a3) +# endif /* !__CSKYBE__ */ +10: + jmp lr + +11: + subi t0, 4 +12: + ld.b a2, (a1) + st.b a2, (a3) + bez a2, 10b + addi t0, 1 + addi a1, a1, 1 + addi a3, a3, 1 + bnez t0, 12b + jbr 1b +ENDPROC(strcpy) diff --git a/arch/csky/abiv2/strksyms.c b/arch/csky/abiv2/strksyms.c new file mode 100644 index 000000000000..06da723d8202 --- /dev/null +++ b/arch/csky/abiv2/strksyms.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/module.h> + +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strlen); diff --git a/arch/csky/abiv2/strlen.S b/arch/csky/abiv2/strlen.S new file mode 100644 index 000000000000..bcdd70764d08 --- /dev/null +++ b/arch/csky/abiv2/strlen.S @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include "sysdep.h" + +ENTRY(strlen) + /* Check if the start addr is aligned. */ + mov r3, r0 + andi r1, r0, 3 + movi r2, 4 + movi r0, 0 + bnez r1, .L_start_not_aligned + + LABLE_ALIGN +.L_start_addr_aligned: + /* Check if all the bytes in the word are not zero. */ + ldw r1, (r3) + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 4) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 8) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 12) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 16) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 20) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 24) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + ldw r1, (r3, 28) + addi r0, 4 + tstnbz r1 + bf .L_string_tail + + addi r0, 4 + addi r3, 32 + br .L_start_addr_aligned + +.L_string_tail: +# ifdef __CSKYBE__ + xtrb0 r3, r1 + bez r3, .L_return + addi r0, 1 + xtrb1 r3, r1 + bez r3, .L_return + addi r0, 1 + xtrb2 r3, r1 + bez r3, .L_return + addi r0, 1 +# else + xtrb3 r3, r1 + bez r3, .L_return + addi r0, 1 + xtrb2 r3, r1 + bez r3, .L_return + addi r0, 1 + xtrb1 r3, r1 + bez r3, .L_return + addi r0, 1 +# endif /* !__CSKYBE__ */ + +.L_return: + rts + +.L_start_not_aligned: + sub r2, r2, r1 +.L_start_not_aligned_loop: + ldb r1, (r3) + PRE_BNEZAD (r2) + addi r3, 1 + bez r1, .L_return + addi r0, 1 + BNEZAD (r2, .L_start_not_aligned_loop) + br .L_start_addr_aligned +ENDPROC(strlen) diff --git a/arch/csky/abiv2/sysdep.h b/arch/csky/abiv2/sysdep.h new file mode 100644 index 000000000000..bbbedfd34777 --- /dev/null +++ b/arch/csky/abiv2/sysdep.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __SYSDEP_H +#define __SYSDEP_H + +#ifdef __ASSEMBLER__ + +#if defined(__CK860__) +#define LABLE_ALIGN \ + .balignw 16, 0x6c03 + +#define PRE_BNEZAD(R) + +#define BNEZAD(R, L) \ + bnezad R, L +#else +#define LABLE_ALIGN \ + .balignw 8, 0x6c03 + +#define PRE_BNEZAD(R) \ + subi R, 1 + +#define BNEZAD(R, L) \ + bnez R, L +#endif + +#endif + +#endif diff --git a/arch/csky/boot/Makefile b/arch/csky/boot/Makefile new file mode 100644 index 000000000000..47d3d723784c --- /dev/null +++ b/arch/csky/boot/Makefile @@ -0,0 +1,24 @@ +targets := Image zImage uImage +targets += $(dtb-y) + +$(obj)/Image: vmlinux FORCE + $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready' + +compress-$(CONFIG_KERNEL_GZIP) = gzip +compress-$(CONFIG_KERNEL_LZO) = lzo +compress-$(CONFIG_KERNEL_LZMA) = lzma +compress-$(CONFIG_KERNEL_XZ) = xzkern +compress-$(CONFIG_KERNEL_LZ4) = lz4 + +$(obj)/zImage: $(obj)/Image FORCE + $(call if_changed,$(compress-y)) + @echo ' Kernel: $@ is ready' + +UIMAGE_ARCH = sandbox +UIMAGE_COMPRESSION = $(compress-y) +UIMAGE_LOADADDR = $(shell $(NM) vmlinux | awk '$$NF == "_start" {print $$1}') + +$(obj)/uImage: $(obj)/zImage + $(call if_changed,uimage) + @echo 'Image: $@ is ready' diff --git a/arch/csky/boot/dts/Makefile b/arch/csky/boot/dts/Makefile new file mode 100644 index 000000000000..305e81a5e91e --- /dev/null +++ b/arch/csky/boot/dts/Makefile @@ -0,0 +1,13 @@ +dtstree := $(srctree)/$(src) + +ifneq '$(CONFIG_CSKY_BUILTIN_DTB)' '""' +builtindtb-y := $(patsubst "%",%,$(CONFIG_CSKY_BUILTIN_DTB)) +dtb-y += $(builtindtb-y).dtb +obj-y += $(builtindtb-y).dtb.o +.SECONDARY: $(obj)/$(builtindtb-y).dtb.S +else +dtb-y := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) +endif + +always += $(dtb-y) +clean-files += *.dtb *.dtb.S diff --git a/arch/csky/boot/dts/include/dt-bindings b/arch/csky/boot/dts/include/dt-bindings new file mode 120000 index 000000000000..08c00e4972fa --- /dev/null +++ b/arch/csky/boot/dts/include/dt-bindings @@ -0,0 +1 @@ +../../../../../include/dt-bindings
\ No newline at end of file diff --git a/arch/csky/configs/defconfig b/arch/csky/configs/defconfig new file mode 100644 index 000000000000..7ef42895dfb0 --- /dev/null +++ b/arch/csky/configs/defconfig @@ -0,0 +1,61 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="csky" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_DEFAULT_DEADLINE=y +CONFIG_CPU_CK807=y +CONFIG_CPU_HAS_FPU=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_TTY_PRINTK=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_CSKY_MPTIMER=y +CONFIG_GX6605S_TIMER=y +CONFIG_PM_DEVFREQ=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_GENERIC_PHY=y +CONFIG_EXT4_FS=y +CONFIG_FANOTIFY=y +CONFIG_QUOTA=y +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +CONFIG_CACHEFILES=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_UTF8=y +CONFIG_NTFS_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_CHILDREN=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_CRAMFS=y +CONFIG_ROMFS_FS=y +CONFIG_NFS_FS=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild new file mode 100644 index 000000000000..2a0abe8f2a35 --- /dev/null +++ b/arch/csky/include/asm/Kbuild @@ -0,0 +1,49 @@ +generic-y += asm-offsets.h +generic-y += bugs.h +generic-y += clkdev.h +generic-y += compat.h +generic-y += current.h +generic-y += delay.h +generic-y += device.h +generic-y += div64.h +generic-y += dma.h +generic-y += dma-contiguous.h +generic-y += dma-mapping.h +generic-y += emergency-restart.h +generic-y += exec.h +generic-y += fb.h +generic-y += ftrace.h +generic-y += futex.h +generic-y += gpio.h +generic-y += hardirq.h +generic-y += hw_irq.h +generic-y += irq.h +generic-y += irq_regs.h +generic-y += irq_work.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += kprobes.h +generic-y += kvm_para.h +generic-y += linkage.h +generic-y += local.h +generic-y += local64.h +generic-y += mm-arch-hooks.h +generic-y += module.h +generic-y += mutex.h +generic-y += pci.h +generic-y += percpu.h +generic-y += preempt.h +generic-y += qrwlock.h +generic-y += scatterlist.h +generic-y += sections.h +generic-y += serial.h +generic-y += shm.h +generic-y += timex.h +generic-y += topology.h +generic-y += trace_clock.h +generic-y += unaligned.h +generic-y += user.h +generic-y += vga.h +generic-y += vmlinux.lds.h +generic-y += word-at-a-time.h +generic-y += xor.h diff --git a/arch/csky/include/asm/addrspace.h b/arch/csky/include/asm/addrspace.h new file mode 100644 index 000000000000..d1c2ede692ed --- /dev/null +++ b/arch/csky/include/asm/addrspace.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_ADDRSPACE_H +#define __ASM_CSKY_ADDRSPACE_H + +#define KSEG0 0x80000000ul +#define KSEG0ADDR(a) (((unsigned long)a & 0x1fffffff) | KSEG0) + +#endif /* __ASM_CSKY_ADDRSPACE_H */ diff --git a/arch/csky/include/asm/atomic.h b/arch/csky/include/asm/atomic.h new file mode 100644 index 000000000000..e369d73b13e3 --- /dev/null +++ b/arch/csky/include/asm/atomic.h @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_ATOMIC_H +#define __ASM_CSKY_ATOMIC_H + +#include <linux/version.h> +#include <asm/cmpxchg.h> +#include <asm/barrier.h> + +#ifdef CONFIG_CPU_HAS_LDSTEX + +#define __atomic_add_unless __atomic_add_unless +static inline int __atomic_add_unless(atomic_t *v, int a, int u) +{ + unsigned long tmp, ret; + + smp_mb(); + + asm volatile ( + "1: ldex.w %0, (%3) \n" + " mov %1, %0 \n" + " cmpne %0, %4 \n" + " bf 2f \n" + " add %0, %2 \n" + " stex.w %0, (%3) \n" + " bez %0, 1b \n" + "2: \n" + : "=&r" (tmp), "=&r" (ret) + : "r" (a), "r"(&v->counter), "r"(u) + : "memory"); + + if (ret != u) + smp_mb(); + + return ret; +} + +#define ATOMIC_OP(op, c_op) \ +static inline void atomic_##op(int i, atomic_t *v) \ +{ \ + unsigned long tmp; \ + \ + asm volatile ( \ + "1: ldex.w %0, (%2) \n" \ + " " #op " %0, %1 \n" \ + " stex.w %0, (%2) \n" \ + " bez %0, 1b \n" \ + : "=&r" (tmp) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ +} + +#define ATOMIC_OP_RETURN(op, c_op) \ +static inline int atomic_##op##_return(int i, atomic_t *v) \ +{ \ + unsigned long tmp, ret; \ + \ + smp_mb(); \ + asm volatile ( \ + "1: ldex.w %0, (%3) \n" \ + " " #op " %0, %2 \n" \ + " mov %1, %0 \n" \ + " stex.w %0, (%3) \n" \ + " bez %0, 1b \n" \ + : "=&r" (tmp), "=&r" (ret) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ + smp_mb(); \ + \ + return ret; \ +} + +#define ATOMIC_FETCH_OP(op, c_op) \ +static inline int atomic_fetch_##op(int i, atomic_t *v) \ +{ \ + unsigned long tmp, ret; \ + \ + smp_mb(); \ + asm volatile ( \ + "1: ldex.w %0, (%3) \n" \ + " mov %1, %0 \n" \ + " " #op " %0, %2 \n" \ + " stex.w %0, (%3) \n" \ + " bez %0, 1b \n" \ + : "=&r" (tmp), "=&r" (ret) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ + smp_mb(); \ + \ + return ret; \ +} + +#else /* CONFIG_CPU_HAS_LDSTEX */ + +#include <linux/irqflags.h> + +#define __atomic_add_unless __atomic_add_unless +static inline int __atomic_add_unless(atomic_t *v, int a, int u) +{ + unsigned long tmp, ret, flags; + + raw_local_irq_save(flags); + + asm volatile ( + " ldw %0, (%3) \n" + " mov %1, %0 \n" + " cmpne %0, %4 \n" + " bf 2f \n" + " add %0, %2 \n" + " stw %0, (%3) \n" + "2: \n" + : "=&r" (tmp), "=&r" (ret) + : "r" (a), "r"(&v->counter), "r"(u) + : "memory"); + + raw_local_irq_restore(flags); + + return ret; +} + +#define ATOMIC_OP(op, c_op) \ +static inline void atomic_##op(int i, atomic_t *v) \ +{ \ + unsigned long tmp, flags; \ + \ + raw_local_irq_save(flags); \ + \ + asm volatile ( \ + " ldw %0, (%2) \n" \ + " " #op " %0, %1 \n" \ + " stw %0, (%2) \n" \ + : "=&r" (tmp) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ + \ + raw_local_irq_restore(flags); \ +} + +#define ATOMIC_OP_RETURN(op, c_op) \ +static inline int atomic_##op##_return(int i, atomic_t *v) \ +{ \ + unsigned long tmp, ret, flags; \ + \ + raw_local_irq_save(flags); \ + \ + asm volatile ( \ + " ldw %0, (%3) \n" \ + " " #op " %0, %2 \n" \ + " stw %0, (%3) \n" \ + " mov %1, %0 \n" \ + : "=&r" (tmp), "=&r" (ret) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ + \ + raw_local_irq_restore(flags); \ + \ + return ret; \ +} + +#define ATOMIC_FETCH_OP(op, c_op) \ +static inline int atomic_fetch_##op(int i, atomic_t *v) \ +{ \ + unsigned long tmp, ret, flags; \ + \ + raw_local_irq_save(flags); \ + \ + asm volatile ( \ + " ldw %0, (%3) \n" \ + " mov %1, %0 \n" \ + " " #op " %0, %2 \n" \ + " stw %0, (%3) \n" \ + : "=&r" (tmp), "=&r" (ret) \ + : "r" (i), "r"(&v->counter) \ + : "memory"); \ + \ + raw_local_irq_restore(flags); \ + \ + return ret; \ +} + +#endif /* CONFIG_CPU_HAS_LDSTEX */ + +#define atomic_add_return atomic_add_return +ATOMIC_OP_RETURN(add, +) +#define atomic_sub_return atomic_sub_return +ATOMIC_OP_RETURN(sub, -) + +#define atomic_fetch_add atomic_fetch_add +ATOMIC_FETCH_OP(add, +) +#define atomic_fetch_sub atomic_fetch_sub +ATOMIC_FETCH_OP(sub, -) +#define atomic_fetch_and atomic_fetch_and +ATOMIC_FETCH_OP(and, &) +#define atomic_fetch_or atomic_fetch_or +ATOMIC_FETCH_OP(or, |) +#define atomic_fetch_xor atomic_fetch_xor +ATOMIC_FETCH_OP(xor, ^) + +#define atomic_and atomic_and +ATOMIC_OP(and, &) +#define atomic_or atomic_or +ATOMIC_OP(or, |) +#define atomic_xor atomic_xor +ATOMIC_OP(xor, ^) + +#undef ATOMIC_FETCH_OP +#undef ATOMIC_OP_RETURN +#undef ATOMIC_OP + +#include <asm-generic/atomic.h> + +#endif /* __ASM_CSKY_ATOMIC_H */ diff --git a/arch/csky/include/asm/barrier.h b/arch/csky/include/asm/barrier.h new file mode 100644 index 000000000000..476eb786f22d --- /dev/null +++ b/arch/csky/include/asm/barrier.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_BARRIER_H +#define __ASM_CSKY_BARRIER_H + +#ifndef __ASSEMBLY__ + +#define nop() asm volatile ("nop\n":::"memory") + +/* + * sync: completion barrier + * sync.s: completion barrier and shareable to other cores + * sync.i: completion barrier with flush cpu pipeline + * sync.is: completion barrier with flush cpu pipeline and shareable to + * other cores + * + * bar.brwarw: ordering barrier for all load/store instructions before it + * bar.brwarws: ordering barrier for all load/store instructions before it + * and shareable to other cores + * bar.brar: ordering barrier for all load instructions before it + * bar.brars: ordering barrier for all load instructions before it + * and shareable to other cores + * bar.bwaw: ordering barrier for all store instructions before it + * bar.bwaws: ordering barrier for all store instructions before it + * and shareable to other cores + */ + +#ifdef CONFIG_CPU_HAS_CACHEV2 +#define mb() asm volatile ("bar.brwarw\n":::"memory") +#define rmb() asm volatile ("bar.brar\n":::"memory") +#define wmb() asm volatile ("bar.bwaw\n":::"memory") + +#ifdef CONFIG_SMP +#define __smp_mb() asm volatile ("bar.brwarws\n":::"memory") +#define __smp_rmb() asm volatile ("bar.brars\n":::"memory") +#define __smp_wmb() asm volatile ("bar.bwaws\n":::"memory") +#endif /* CONFIG_SMP */ + +#define sync_is() asm volatile ("sync.is\n":::"memory") + +#else /* !CONFIG_CPU_HAS_CACHEV2 */ +#define mb() asm volatile ("sync\n":::"memory") +#endif + +#include <asm-generic/barrier.h> + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_CSKY_BARRIER_H */ diff --git a/arch/csky/include/asm/bitops.h b/arch/csky/include/asm/bitops.h new file mode 100644 index 000000000000..335f2883fb1e --- /dev/null +++ b/arch/csky/include/asm/bitops.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_BITOPS_H +#define __ASM_CSKY_BITOPS_H + +#include <linux/compiler.h> +#include <asm/barrier.h> + +/* + * asm-generic/bitops/ffs.h + */ +static inline int ffs(int x) +{ + if (!x) + return 0; + + asm volatile ( + "brev %0\n" + "ff1 %0\n" + "addi %0, 1\n" + : "=&r"(x) + : "0"(x)); + return x; +} + +/* + * asm-generic/bitops/__ffs.h + */ +static __always_inline unsigned long __ffs(unsigned long x) +{ + asm volatile ( + "brev %0\n" + "ff1 %0\n" + : "=&r"(x) + : "0"(x)); + return x; +} + +/* + * asm-generic/bitops/fls.h + */ +static __always_inline int fls(int x) +{ + asm volatile( + "ff1 %0\n" + : "=&r"(x) + : "0"(x)); + + return (32 - x); +} + +/* + * asm-generic/bitops/__fls.h + */ +static __always_inline unsigned long __fls(unsigned long x) +{ + return fls(x) - 1; +} + +#include <asm-generic/bitops/ffz.h> +#include <asm-generic/bitops/fls64.h> +#include <asm-generic/bitops/find.h> + +#ifndef _LINUX_BITOPS_H +#error only <linux/bitops.h> can be included directly +#endif + +#include <asm-generic/bitops/sched.h> +#include <asm-generic/bitops/hweight.h> +#include <asm-generic/bitops/lock.h> +#include <asm-generic/bitops/atomic.h> + +/* + * bug fix, why only could use atomic!!!! + */ +#include <asm-generic/bitops/non-atomic.h> +#define __clear_bit(nr, vaddr) clear_bit(nr, vaddr) + +#include <asm-generic/bitops/le.h> +#include <asm-generic/bitops/ext2-atomic.h> +#endif /* __ASM_CSKY_BITOPS_H */ diff --git a/arch/csky/include/asm/bug.h b/arch/csky/include/asm/bug.h new file mode 100644 index 000000000000..bd7b3235bb84 --- /dev/null +++ b/arch/csky/include/asm/bug.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_BUG_H +#define __ASM_CSKY_BUG_H + +#include <linux/compiler.h> +#include <linux/const.h> +#include <linux/types.h> + +#define BUG() \ +do { \ + asm volatile ("bkpt\n"); \ + unreachable(); \ +} while (0) + +#define HAVE_ARCH_BUG + +#include <asm-generic/bug.h> + +struct pt_regs; + +void die_if_kernel(char *str, struct pt_regs *regs, int nr); +void show_regs(struct pt_regs *regs); + +#endif /* __ASM_CSKY_BUG_H */ diff --git a/arch/csky/include/asm/cache.h b/arch/csky/include/asm/cache.h new file mode 100644 index 000000000000..d68373463676 --- /dev/null +++ b/arch/csky/include/asm/cache.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_CACHE_H +#define __ASM_CSKY_CACHE_H + +/* bytes per L1 cache line */ +#define L1_CACHE_SHIFT CONFIG_L1_CACHE_SHIFT + +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#ifndef __ASSEMBLY__ + +void dcache_wb_line(unsigned long start); + +void icache_inv_range(unsigned long start, unsigned long end); +void icache_inv_all(void); + +void dcache_wb_range(unsigned long start, unsigned long end); +void dcache_wbinv_all(void); + +void cache_wbinv_range(unsigned long start, unsigned long end); +void cache_wbinv_all(void); + +void dma_wbinv_range(unsigned long start, unsigned long end); +void dma_wb_range(unsigned long start, unsigned long end); + +#endif +#endif /* __ASM_CSKY_CACHE_H */ diff --git a/arch/csky/include/asm/cacheflush.h b/arch/csky/include/asm/cacheflush.h new file mode 100644 index 000000000000..a96da67261ae --- /dev/null +++ b/arch/csky/include/asm/cacheflush.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_CACHEFLUSH_H +#define __ASM_CSKY_CACHEFLUSH_H + +#include <abi/cacheflush.h> + +#endif /* __ASM_CSKY_CACHEFLUSH_H */ diff --git a/arch/csky/include/asm/checksum.h b/arch/csky/include/asm/checksum.h new file mode 100644 index 000000000000..7685824291b1 --- /dev/null +++ b/arch/csky/include/asm/checksum.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_CHECKSUM_H +#define __ASM_CSKY_CHECKSUM_H + +#include <linux/in6.h> +#include <asm/byteorder.h> + +static inline __sum16 csum_fold(__wsum csum) +{ + u32 tmp; + + asm volatile( + "mov %1, %0\n" + "rori %0, 16\n" + "addu %0, %1\n" + "lsri %0, 16\n" + : "=r"(csum), "=r"(tmp) + : "0"(csum)); + + return (__force __sum16) ~csum; +} +#define csum_fold csum_fold + +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, unsigned short proto, __wsum sum) +{ + asm volatile( + "clrc\n" + "addc %0, %1\n" + "addc %0, %2\n" + "addc %0, %3\n" + "inct %0\n" + : "=r"(sum) + : "r"((__force u32)saddr), "r"((__force u32)daddr), +#ifdef __BIG_ENDIAN + "r"(proto + len), +#else + "r"((proto + len) << 8), +#endif + "0" ((__force unsigned long)sum) + : "cc"); + return sum; +} +#define csum_tcpudp_nofold csum_tcpudp_nofold + +#include <asm-generic/checksum.h> + +#endif /* __ASM_CSKY_CHECKSUM_H */ diff --git a/arch/csky/include/asm/cmpxchg.h b/arch/csky/include/asm/cmpxchg.h new file mode 100644 index 000000000000..89224530a0ee --- /dev/null +++ b/arch/csky/include/asm/cmpxchg.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_CMPXCHG_H +#define __ASM_CSKY_CMPXCHG_H + +#ifdef CONFIG_CPU_HAS_LDSTEX +#include <asm/barrier.h> + +extern void __bad_xchg(void); + +#define __xchg(new, ptr, size) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(new) __new = (new); \ + __typeof__(*(ptr)) __ret; \ + unsigned long tmp; \ + switch (size) { \ + case 4: \ + smp_mb(); \ + asm volatile ( \ + "1: ldex.w %0, (%3) \n" \ + " mov %1, %2 \n" \ + " stex.w %1, (%3) \n" \ + " bez %1, 1b \n" \ + : "=&r" (__ret), "=&r" (tmp) \ + : "r" (__new), "r"(__ptr) \ + :); \ + smp_mb(); \ + break; \ + default: \ + __bad_xchg(); \ + } \ + __ret; \ +}) + +#define xchg(ptr, x) (__xchg((x), (ptr), sizeof(*(ptr)))) + +#define __cmpxchg(ptr, old, new, size) \ +({ \ + __typeof__(ptr) __ptr = (ptr); \ + __typeof__(new) __new = (new); \ + __typeof__(new) __tmp; \ + __typeof__(old) __old = (old); \ + __typeof__(*(ptr)) __ret; \ + switch (size) { \ + case 4: \ + smp_mb(); \ + asm volatile ( \ + "1: ldex.w %0, (%3) \n" \ + " cmpne %0, %4 \n" \ + " bt 2f \n" \ + " mov %1, %2 \n" \ + " stex.w %1, (%3) \n" \ + " bez %1, 1b \n" \ + "2: \n" \ + : "=&r" (__ret), "=&r" (__tmp) \ + : "r" (__new), "r"(__ptr), "r"(__old) \ + :); \ + smp_mb(); \ + break; \ + default: \ + __bad_xchg(); \ + } \ + __ret; \ +}) + +#define cmpxchg(ptr, o, n) \ + (__cmpxchg((ptr), (o), (n), sizeof(*(ptr)))) +#else +#include <asm-generic/cmpxchg.h> +#endif + +#endif /* __ASM_CSKY_CMPXCHG_H */ diff --git a/arch/csky/include/asm/elf.h b/arch/csky/include/asm/elf.h new file mode 100644 index 000000000000..773b133ca297 --- /dev/null +++ b/arch/csky/include/asm/elf.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_ELF_H +#define __ASM_CSKY_ELF_H + +#include <asm/ptrace.h> +#include <abi/regdef.h> + +#define ELF_ARCH 252 + +/* CSKY Relocations */ +#define R_CSKY_NONE 0 +#define R_CSKY_32 1 +#define R_CSKY_PCIMM8BY4 2 +#define R_CSKY_PCIMM11BY2 3 +#define R_CSKY_PCIMM4BY2 4 +#define R_CSKY_PC32 5 +#define R_CSKY_PCRELJSR_IMM11BY2 6 +#define R_CSKY_GNU_VTINHERIT 7 +#define R_CSKY_GNU_VTENTRY 8 +#define R_CSKY_RELATIVE 9 +#define R_CSKY_COPY 10 +#define R_CSKY_GLOB_DAT 11 +#define R_CSKY_JUMP_SLOT 12 +#define R_CSKY_ADDR_HI16 24 +#define R_CSKY_ADDR_LO16 25 +#define R_CSKY_PCRELJSR_IMM26BY2 40 + +typedef unsigned long elf_greg_t; + +typedef struct user_fp elf_fpregset_t; + +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) + +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) + +/* + * These are used to set parameters in the core dumps. + */ +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 +#define ELF_CLASS ELFCLASS32 +#define ELF_PLAT_INIT(_r, load_addr) { _r->a0 = 0; } + +#ifdef __cskyBE__ +#define ELF_DATA ELFDATA2MSB +#else +#define ELF_DATA ELFDATA2LSB +#endif + +/* + * This is the location that an ET_DYN program is loaded if exec'ed. Typical + * use of this is to invoke "./ld.so someprog" to test out a new version of + * the loader. We need to make sure that it is out of the way of the program + * that it will "exec", and that there is sufficient room for the brk. + */ +#define ELF_ET_DYN_BASE 0x0UL +#include <abi/elf.h> + +/* Similar, but for a thread other than current. */ +struct task_struct; +extern int dump_task_regs(struct task_struct *tsk, elf_gregset_t *elf_regs); +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) + +#define ELF_HWCAP (0) + +/* + * This yields a string that ld.so will use to load implementation specific + * libraries for optimization. This is more specific in intent than poking + * at uname or /proc/cpuinfo. + */ +#define ELF_PLATFORM (NULL) +#define SET_PERSONALITY(ex) set_personality(PER_LINUX) + +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 +struct linux_binprm; +extern int arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp); +#endif /* __ASM_CSKY_ELF_H */ diff --git a/arch/csky/include/asm/fixmap.h b/arch/csky/include/asm/fixmap.h new file mode 100644 index 000000000000..380ff0a307df --- /dev/null +++ b/arch/csky/include/asm/fixmap.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_FIXMAP_H +#define __ASM_CSKY_FIXMAP_H + +#include <asm/page.h> +#ifdef CONFIG_HIGHMEM +#include <linux/threads.h> +#include <asm/kmap_types.h> +#endif + +enum fixed_addresses { +#ifdef CONFIG_HIGHMEM + FIX_KMAP_BEGIN, + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, +#endif + __end_of_fixed_addresses +}; + +#define FIXADDR_TOP 0xffffc000 +#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) + +#include <asm-generic/fixmap.h> + +#endif /* __ASM_CSKY_FIXMAP_H */ diff --git a/arch/csky/include/asm/highmem.h b/arch/csky/include/asm/highmem.h new file mode 100644 index 000000000000..a345a2f2c22e --- /dev/null +++ b/arch/csky/include/asm/highmem.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_HIGHMEM_H +#define __ASM_CSKY_HIGHMEM_H + +#ifdef __KERNEL__ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/uaccess.h> +#include <asm/kmap_types.h> +#include <asm/cache.h> + +/* undef for production */ +#define HIGHMEM_DEBUG 1 + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *pkmap_page_table; + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#define LAST_PKMAP 1024 +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern void *kmap(struct page *page); +extern void kunmap(struct page *page); +extern void *kmap_atomic(struct page *page); +extern void __kunmap_atomic(void *kvaddr); +extern void *kmap_atomic_pfn(unsigned long pfn); +extern struct page *kmap_atomic_to_page(void *ptr); + +#define flush_cache_kmaps() do {} while (0) + +extern void kmap_init(void); + +#define kmap_prot PAGE_KERNEL + +#endif /* __KERNEL__ */ + +#endif /* __ASM_CSKY_HIGHMEM_H */ diff --git a/arch/csky/include/asm/io.h b/arch/csky/include/asm/io.h new file mode 100644 index 000000000000..ecae6b358f95 --- /dev/null +++ b/arch/csky/include/asm/io.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_IO_H +#define __ASM_CSKY_IO_H + +#include <abi/pgtable-bits.h> +#include <linux/types.h> +#include <linux/version.h> + +extern void __iomem *ioremap(phys_addr_t offset, size_t size); + +extern void iounmap(void *addr); + +extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr, + size_t size, unsigned long flags); + +#define ioremap_nocache(phy, sz) ioremap(phy, sz) +#define ioremap_wc ioremap_nocache +#define ioremap_wt ioremap_nocache + +#include <asm-generic/io.h> + +#endif /* __ASM_CSKY_IO_H */ diff --git a/arch/csky/include/asm/irqflags.h b/arch/csky/include/asm/irqflags.h new file mode 100644 index 000000000000..9e3a569a55d6 --- /dev/null +++ b/arch/csky/include/asm/irqflags.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_IRQFLAGS_H +#define __ASM_CSKY_IRQFLAGS_H +#include <abi/reg_ops.h> + +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + + flags = mfcr("psr"); + asm volatile("psrclr ie\n":::"memory"); + return flags; +} +#define arch_local_irq_save arch_local_irq_save + +static inline void arch_local_irq_enable(void) +{ + asm volatile("psrset ee, ie\n":::"memory"); +} +#define arch_local_irq_enable arch_local_irq_enable + +static inline void arch_local_irq_disable(void) +{ + asm volatile("psrclr ie\n":::"memory"); +} +#define arch_local_irq_disable arch_local_irq_disable + +static inline unsigned long arch_local_save_flags(void) +{ + return mfcr("psr"); +} +#define arch_local_save_flags arch_local_save_flags + +static inline void arch_local_irq_restore(unsigned long flags) +{ + mtcr("psr", flags); +} +#define arch_local_irq_restore arch_local_irq_restore + +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & (1<<6)); +} +#define arch_irqs_disabled_flags arch_irqs_disabled_flags + +#include <asm-generic/irqflags.h> + +#endif /* __ASM_CSKY_IRQFLAGS_H */ diff --git a/arch/csky/include/asm/mmu.h b/arch/csky/include/asm/mmu.h new file mode 100644 index 000000000000..cb344675ccc4 --- /dev/null +++ b/arch/csky/include/asm/mmu.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_MMU_H +#define __ASM_CSKY_MMU_H + +typedef struct { + unsigned long asid[NR_CPUS]; + void *vdso; +} mm_context_t; + +#endif /* __ASM_CSKY_MMU_H */ diff --git a/arch/csky/include/asm/mmu_context.h b/arch/csky/include/asm/mmu_context.h new file mode 100644 index 000000000000..c410aa4fff1a --- /dev/null +++ b/arch/csky/include/asm/mmu_context.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_MMU_CONTEXT_H +#define __ASM_CSKY_MMU_CONTEXT_H + +#include <asm-generic/mm_hooks.h> +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> + +#include <linux/errno.h> +#include <linux/sched.h> +#include <abi/ckmmu.h> + +static inline void tlbmiss_handler_setup_pgd(unsigned long pgd, bool kernel) +{ + pgd &= ~(1<<31); + pgd += PHYS_OFFSET; + pgd |= 1; + setup_pgd(pgd, kernel); +} + +#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ + tlbmiss_handler_setup_pgd((unsigned long)pgd, 0) +#define TLBMISS_HANDLER_SETUP_PGD_KERNEL(pgd) \ + tlbmiss_handler_setup_pgd((unsigned long)pgd, 1) + +static inline unsigned long tlb_get_pgd(void) +{ + return ((get_pgd()|(1<<31)) - PHYS_OFFSET) & ~1; +} + +#define cpu_context(cpu, mm) ((mm)->context.asid[cpu]) +#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) +#define asid_cache(cpu) (cpu_data[cpu].asid_cache) + +#define ASID_FIRST_VERSION (1 << CONFIG_CPU_ASID_BITS) +#define ASID_INC 0x1 +#define ASID_MASK (ASID_FIRST_VERSION - 1) +#define ASID_VERSION_MASK ~ASID_MASK + +#define destroy_context(mm) do {} while (0) +#define enter_lazy_tlb(mm, tsk) do {} while (0) +#define deactivate_mm(tsk, mm) do {} while (0) + +/* + * All unused by hardware upper bits will be considered + * as a software asid extension. + */ +static inline void +get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) +{ + unsigned long asid = asid_cache(cpu); + + asid += ASID_INC; + if (!(asid & ASID_MASK)) { + flush_tlb_all(); /* start new asid cycle */ + if (!asid) /* fix version if needed */ + asid = ASID_FIRST_VERSION; + } + cpu_context(cpu, mm) = asid_cache(cpu) = asid; +} + +/* + * Initialize the context related info for a new mm_struct + * instance. + */ +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + int i; + + for_each_online_cpu(i) + cpu_context(i, mm) = 0; + return 0; +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + unsigned int cpu = smp_processor_id(); + unsigned long flags; + + local_irq_save(flags); + /* Check if our ASID is of an older version and thus invalid */ + if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) + get_new_mmu_context(next, cpu); + write_mmu_entryhi(cpu_asid(cpu, next)); + TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* + * Mark current->active_mm as not "active" anymore. + * We don't want to mislead possible IPI tlb flush routines. + */ + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + cpumask_set_cpu(cpu, mm_cpumask(next)); + + local_irq_restore(flags); +} + +/* + * After we have set current->mm to a new value, this activates + * the context for the new mm so we see the new mappings. + */ +static inline void +activate_mm(struct mm_struct *prev, struct mm_struct *next) +{ + unsigned long flags; + int cpu = smp_processor_id(); + + local_irq_save(flags); + + /* Unconditionally get a new ASID. */ + get_new_mmu_context(next, cpu); + + write_mmu_entryhi(cpu_asid(cpu, next)); + TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* mark mmu ownership change */ + cpumask_clear_cpu(cpu, mm_cpumask(prev)); + cpumask_set_cpu(cpu, mm_cpumask(next)); + + local_irq_restore(flags); +} + +/* + * If mm is currently active_mm, we can't really drop it. Instead, + * we will get a new one for it. + */ +static inline void +drop_mmu_context(struct mm_struct *mm, unsigned int cpu) +{ + unsigned long flags; + + local_irq_save(flags); + + if (cpumask_test_cpu(cpu, mm_cpumask(mm))) { + get_new_mmu_context(mm, cpu); + write_mmu_entryhi(cpu_asid(cpu, mm)); + } else { + /* will get a new context next time */ + cpu_context(cpu, mm) = 0; + } + + local_irq_restore(flags); +} + +#endif /* __ASM_CSKY_MMU_CONTEXT_H */ diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h new file mode 100644 index 000000000000..73cf2bd66a13 --- /dev/null +++ b/arch/csky/include/asm/page.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_PAGE_H +#define __ASM_CSKY_PAGE_H + +#include <asm/setup.h> +#include <asm/cache.h> +#include <linux/const.h> + +/* + * PAGE_SHIFT determines the page size + */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) +#define THREAD_SIZE (PAGE_SIZE * 2) +#define THREAD_MASK (~(THREAD_SIZE - 1)) +#define THREAD_SHIFT (PAGE_SHIFT + 1) + +/* + * NOTE: virtual isn't really correct, actually it should be the offset into the + * memory node, but we have no highmem, so that works for now. + * TODO: implement (fast) pfn<->pgdat_idx conversion functions, this makes lots + * of the shifts unnecessary. + */ + +#ifndef __ASSEMBLY__ + +#include <linux/pfn.h> + +#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) +#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) + +#define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && \ + (void *)(kaddr) < high_memory) +#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr) + +extern void *memset(void *dest, int c, size_t l); +extern void *memcpy(void *to, const void *from, size_t l); + +#define clear_page(page) memset((page), 0, PAGE_SIZE) +#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) + +#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) +#define phys_to_page(paddr) (pfn_to_page(PFN_DOWN(paddr))) + +struct page; + +#include <abi/page.h> + +struct vm_area_struct; + +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte_low; } pte_t; +#define pte_val(x) ((x).pte_low) + +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct page *pgtable_t; + +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define ptep_buddy(x) ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t))) + +#define __pte(x) ((pte_t) { (x) }) +#define __pgd(x) ((pgd_t) { (x) }) +#define __pgprot(x) ((pgprot_t) { (x) }) + +#endif /* !__ASSEMBLY__ */ + +#define PHYS_OFFSET (CONFIG_RAM_BASE & ~(LOWMEM_LIMIT - 1)) +#define PHYS_OFFSET_OFFSET (CONFIG_RAM_BASE & (LOWMEM_LIMIT - 1)) +#define ARCH_PFN_OFFSET PFN_DOWN(CONFIG_RAM_BASE) + +#define PAGE_OFFSET 0x80000000 +#define LOWMEM_LIMIT 0x40000000 + +#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) +#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - \ + PHYS_OFFSET)) +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) + +#define MAP_NR(x) PFN_DOWN((unsigned long)(x) - PAGE_OFFSET - \ + PHYS_OFFSET_OFFSET) +#define virt_to_page(x) (mem_map + MAP_NR(x)) + +#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +/* + * main RAM and kernel working space are coincident at 0x80000000, but to make + * life more interesting, there's also an uncached virtual shadow at 0xb0000000 + * - these mappings are fixed in the MMU + */ + +#define pfn_to_kaddr(x) __va(PFN_PHYS(x)) + +#include <asm-generic/memory_model.h> +#include <asm-generic/getorder.h> + +#endif /* __ASM_CSKY_PAGE_H */ diff --git a/arch/csky/include/asm/pgalloc.h b/arch/csky/include/asm/pgalloc.h new file mode 100644 index 000000000000..bf4f4a0e140e --- /dev/null +++ b/arch/csky/include/asm/pgalloc.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_PGALLOC_H +#define __ASM_CSKY_PGALLOC_H + +#include <linux/highmem.h> +#include <linux/mm.h> +#include <linux/sched.h> + +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + set_pmd(pmd, __pmd(__pa(pte))); +} + +static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, + pgtable_t pte) +{ + set_pmd(pmd, __pmd(__pa(page_address(pte)))); +} + +#define pmd_pgtable(pmd) pmd_page(pmd) + +extern void pgd_init(unsigned long *p); + +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) +{ + pte_t *pte; + unsigned long *kaddr, i; + + pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, + PTE_ORDER); + kaddr = (unsigned long *)pte; + if (address & 0x80000000) + for (i = 0; i < (PAGE_SIZE/4); i++) + *(kaddr + i) = 0x1; + else + clear_page(kaddr); + + return pte; +} + +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long address) +{ + struct page *pte; + unsigned long *kaddr, i; + + pte = alloc_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, PTE_ORDER); + if (pte) { + kaddr = kmap_atomic(pte); + if (address & 0x80000000) { + for (i = 0; i < (PAGE_SIZE/4); i++) + *(kaddr + i) = 0x1; + } else + clear_page(kaddr); + kunmap_atomic(kaddr); + pgtable_page_ctor(pte); + } + return pte; +} + +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + free_pages((unsigned long)pte, PTE_ORDER); +} + +static inline void pte_free(struct mm_struct *mm, pgtable_t pte) +{ + pgtable_page_dtor(pte); + __free_pages(pte, PTE_ORDER); +} + +static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ + free_pages((unsigned long)pgd, PGD_ORDER); +} + +static inline pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *ret; + pgd_t *init; + + ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER); + if (ret) { + init = pgd_offset(&init_mm, 0UL); + pgd_init((unsigned long *)ret); + memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + /* prevent out of order excute */ + smp_mb(); +#ifdef CONFIG_CPU_NEED_TLBSYNC + dcache_wb_range((unsigned int)ret, + (unsigned int)(ret + PTRS_PER_PGD)); +#endif + } + + return ret; +} + +#define __pte_free_tlb(tlb, pte, address) \ +do { \ + pgtable_page_dtor(pte); \ + tlb_remove_page(tlb, pte); \ +} while (0) + +#define check_pgt_cache() do {} while (0) + +extern void pagetable_init(void); +extern void pre_mmu_init(void); +extern void pre_trap_init(void); + +#endif /* __ASM_CSKY_PGALLOC_H */ diff --git a/arch/csky/include/asm/pgtable.h b/arch/csky/include/asm/pgtable.h new file mode 100644 index 000000000000..edfcbb25fd9f --- /dev/null +++ b/arch/csky/include/asm/pgtable.h @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_PGTABLE_H +#define __ASM_CSKY_PGTABLE_H + +#include <asm/fixmap.h> +#include <asm/addrspace.h> +#include <abi/pgtable-bits.h> +#include <asm-generic/pgtable-nopmd.h> + +#define PGDIR_SHIFT 22 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +#define USER_PTRS_PER_PGD (0x80000000UL/PGDIR_SIZE) +#define FIRST_USER_ADDRESS 0UL + +#define PKMAP_BASE (0xff800000) + +#define VMALLOC_START (0xc0008000) +#define VMALLOC_END (PKMAP_BASE - 2*PAGE_SIZE) + +/* + * C-SKY is two-level paging structure: + */ +#define PGD_ORDER 0 +#define PTE_ORDER 0 + +#define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#define PTRS_PER_PMD 1 +#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) + +#define pte_ERROR(e) \ + pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low) +#define pgd_ERROR(e) \ + pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) + +/* Find an entry in the third-level page table.. */ +#define __pte_offset_t(address) \ + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset_kernel(dir, address) \ + (pmd_page_vaddr(*(dir)) + __pte_offset_t(address)) +#define pte_offset_map(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset_t(address)) +#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) +#define pte_clear(mm, addr, ptep) set_pte((ptep), \ + (((unsigned int)addr&0x80000000)?__pte(1):__pte(0))) +#define pte_none(pte) (!(pte_val(pte)&0xfffffffe)) +#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) +#define pte_pfn(x) ((unsigned long)((x).pte_low >> PAGE_SHIFT)) +#define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \ + | pgprot_val(prot)) + +#define __READABLE (_PAGE_READ | _PAGE_VALID | _PAGE_ACCESSED) +#define __WRITEABLE (_PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED) + +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | \ + _CACHE_MASK) + +#define pte_unmap(pte) ((void)(pte)) + +#define __swp_type(x) (((x).val >> 4) & 0xff) +#define __swp_offset(x) ((x).val >> 12) +#define __swp_entry(type, offset) ((swp_entry_t) {((type) << 4) | \ + ((offset) << 12) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +#define pte_page(x) pfn_to_page(pte_pfn(x)) +#define __mk_pte(page_nr, pgprot) __pte(((page_nr) << PAGE_SHIFT) | \ + pgprot_val(pgprot)) + +/* + * CSKY can't do page protection for execute, and considers that the same like + * read. Also, write permissions imply read permissions. This is the closest + * we can get by reasonable means.. + */ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _CACHE_CACHED) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ + _PAGE_GLOBAL | _CACHE_CACHED) +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _CACHE_CACHED) + +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + +extern void load_pgd(unsigned long pg_dir); +extern pte_t invalid_pte_table[PTRS_PER_PTE]; + +static inline int pte_special(pte_t pte) { return 0; } +static inline pte_t pte_mkspecial(pte_t pte) { return pte; } + +static inline void set_pte(pte_t *p, pte_t pte) +{ + *p = pte; +#if defined(CONFIG_CPU_NEED_TLBSYNC) + dcache_wb_line((u32)p); +#endif + /* prevent out of order excution */ + smp_mb(); +} +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) + +static inline pte_t *pmd_page_vaddr(pmd_t pmd) +{ + unsigned long ptr; + + ptr = pmd_val(pmd); + + return __va(ptr); +} + +#define pmd_phys(pmd) pmd_val(pmd) + +static inline void set_pmd(pmd_t *p, pmd_t pmd) +{ + *p = pmd; +#if defined(CONFIG_CPU_NEED_TLBSYNC) + dcache_wb_line((u32)p); +#endif + /* prevent specul excute */ + smp_mb(); +} + + +static inline int pmd_none(pmd_t pmd) +{ + return pmd_val(pmd) == __pa(invalid_pte_table); +} + +#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) + +static inline int pmd_present(pmd_t pmd) +{ + return (pmd_val(pmd) != __pa(invalid_pte_table)); +} + +static inline void pmd_clear(pmd_t *p) +{ + pmd_val(*p) = (__pa(invalid_pte_table)); +#if defined(CONFIG_CPU_NEED_TLBSYNC) + dcache_wb_line((u32)p); +#endif +} + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +static inline int pte_read(pte_t pte) +{ + return pte.pte_low & _PAGE_READ; +} + +static inline int pte_write(pte_t pte) +{ + return (pte).pte_low & _PAGE_WRITE; +} + +static inline int pte_dirty(pte_t pte) +{ + return (pte).pte_low & _PAGE_MODIFIED; +} + +static inline int pte_young(pte_t pte) +{ + return (pte).pte_low & _PAGE_ACCESSED; +} + +static inline pte_t pte_wrprotect(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY); + return pte; +} + +static inline pte_t pte_mkclean(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_DIRTY); + return pte; +} + +static inline pte_t pte_mkold(pte_t pte) +{ + pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_VALID); + return pte; +} + +static inline pte_t pte_mkwrite(pte_t pte) +{ + pte_val(pte) |= _PAGE_WRITE; + if (pte_val(pte) & _PAGE_MODIFIED) + pte_val(pte) |= _PAGE_DIRTY; + return pte; +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + pte_val(pte) |= _PAGE_MODIFIED; + if (pte_val(pte) & _PAGE_WRITE) + pte_val(pte) |= _PAGE_DIRTY; + return pte; +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + pte_val(pte) |= _PAGE_ACCESSED; + if (pte_val(pte) & _PAGE_READ) + pte_val(pte) |= _PAGE_VALID; + return pte; +} + +#define __pgd_offset(address) pgd_index(address) +#define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) +#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +#define pgd_index(address) ((address) >> PGDIR_SHIFT) + +/* + * Macro to make mark a page protection value as "uncacheable". Note + * that "protection" is really a misnomer here as the protection value + * contains the memory attribute bits, dirty bits, and various other + * bits as well. + */ +#define pgprot_noncached pgprot_noncached + +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; + + return __pgprot(prot); +} + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | + (pgprot_val(newprot))); +} + +/* to find an entry in a page-table-directory */ +static inline pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address) +{ + return mm->pgd + pgd_index(address); +} + +/* Find an entry in the third-level page table.. */ +static inline pte_t *pte_offset(pmd_t *dir, unsigned long address) +{ + return (pte_t *) (pmd_page_vaddr(*dir)) + + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern void paging_init(void); + +extern void show_jtlb_table(void); + +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t *pte); + +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +#define kern_addr_valid(addr) (1) + +/* + * No page table caches to initialise + */ +#define pgtable_cache_init() do {} while (0) + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + +#include <asm-generic/pgtable.h> + +#endif /* __ASM_CSKY_PGTABLE_H */ diff --git a/arch/csky/include/asm/processor.h b/arch/csky/include/asm/processor.h new file mode 100644 index 000000000000..5ad4f0b83092 --- /dev/null +++ b/arch/csky/include/asm/processor.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_PROCESSOR_H +#define __ASM_CSKY_PROCESSOR_H + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +#include <linux/bitops.h> +#include <asm/segment.h> +#include <asm/ptrace.h> +#include <asm/current.h> +#include <asm/cache.h> +#include <abi/reg_ops.h> +#include <abi/regdef.h> +#ifdef CONFIG_CPU_HAS_FPU +#include <abi/fpu.h> +#endif + +struct cpuinfo_csky { + unsigned long udelay_val; + unsigned long asid_cache; + /* + * Capability and feature descriptor structure for CSKY CPU + */ + unsigned long options; + unsigned int processor_id[4]; + unsigned int fpu_id; +} __aligned(SMP_CACHE_BYTES); + +extern struct cpuinfo_csky cpu_data[]; + +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. TASK_SIZE + * for a 64 bit kernel expandable to 8192EB, of which the current CSKY + * implementations will "only" be able to use 1TB ... + */ +#define TASK_SIZE 0x7fff8000UL + +#ifdef __KERNEL__ +#define STACK_TOP TASK_SIZE +#define STACK_TOP_MAX STACK_TOP +#endif + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +struct thread_struct { + unsigned long ksp; /* kernel stack pointer */ + unsigned long sr; /* saved status register */ + unsigned long esp0; /* points to SR of stack frame */ + unsigned long hi; + unsigned long lo; + + /* Other stuff associated with the thread. */ + unsigned long address; /* Last user fault */ + unsigned long error_code; + + /* FPU regs */ + struct user_fp __aligned(16) user_fp; +}; + +#define INIT_THREAD { \ + .ksp = (unsigned long) init_thread_union.stack + THREAD_SIZE, \ + .sr = DEFAULT_PSR_VALUE, \ +} + +/* + * Do necessary setup to start up a newly executed thread. + * + * pass the data segment into user programs if it exists, + * it can't hurt anything as far as I can tell + */ +#define start_thread(_regs, _pc, _usp) \ +do { \ + set_fs(USER_DS); /* reads from user space */ \ + (_regs)->pc = (_pc); \ + (_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */ \ + (_regs)->regs[2] = 0; \ + (_regs)->regs[3] = 0; /* ABIV2 is R7, use it? */ \ + (_regs)->sr &= ~PS_S; \ + (_regs)->usp = (_usp); \ +} while (0) + +/* Forward declaration, a strange C thing */ +struct task_struct; + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ +} + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + +extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + +#define copy_segments(tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) +#define forget_segments() do { } while (0) + +extern unsigned long thread_saved_pc(struct task_struct *tsk); + +unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->usp) + +#define task_pt_regs(p) \ + ((struct pt_regs *)(THREAD_SIZE + p->stack) - 1) + +#define cpu_relax() barrier() + +#endif /* __ASM_CSKY_PROCESSOR_H */ diff --git a/arch/csky/include/asm/reg_ops.h b/arch/csky/include/asm/reg_ops.h new file mode 100644 index 000000000000..cccf7d525fe2 --- /dev/null +++ b/arch/csky/include/asm/reg_ops.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_REGS_OPS_H +#define __ASM_REGS_OPS_H + +#define mfcr(reg) \ +({ \ + unsigned int tmp; \ + asm volatile( \ + "mfcr %0, "reg"\n" \ + : "=r"(tmp) \ + : \ + : "memory"); \ + tmp; \ +}) + +#define mtcr(reg, val) \ +({ \ + asm volatile( \ + "mtcr %0, "reg"\n" \ + : \ + : "r"(val) \ + : "memory"); \ +}) + +#endif /* __ASM_REGS_OPS_H */ diff --git a/arch/csky/include/asm/segment.h b/arch/csky/include/asm/segment.h new file mode 100644 index 000000000000..ffdc4c47ff43 --- /dev/null +++ b/arch/csky/include/asm/segment.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_SEGMENT_H +#define __ASM_CSKY_SEGMENT_H + +typedef struct { + unsigned long seg; +} mm_segment_t; + +#define KERNEL_DS ((mm_segment_t) { 0xFFFFFFFF }) +#define get_ds() KERNEL_DS + +#define USER_DS ((mm_segment_t) { 0x80000000UL }) +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(x) (current_thread_info()->addr_limit = (x)) +#define segment_eq(a, b) ((a).seg == (b).seg) + +#endif /* __ASM_CSKY_SEGMENT_H */ diff --git a/arch/csky/include/asm/shmparam.h b/arch/csky/include/asm/shmparam.h new file mode 100644 index 000000000000..efafe4c79fed --- /dev/null +++ b/arch/csky/include/asm/shmparam.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_SHMPARAM_H +#define __ASM_CSKY_SHMPARAM_H + +#define SHMLBA (4 * PAGE_SIZE) + +#define __ARCH_FORCE_SHMLBA + +#endif /* __ASM_CSKY_SHMPARAM_H */ diff --git a/arch/csky/include/asm/smp.h b/arch/csky/include/asm/smp.h new file mode 100644 index 000000000000..4a929c4d6437 --- /dev/null +++ b/arch/csky/include/asm/smp.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_SMP_H +#define __ASM_CSKY_SMP_H + +#include <linux/cpumask.h> +#include <linux/irqreturn.h> +#include <linux/threads.h> + +#ifdef CONFIG_SMP + +void __init setup_smp(void); + +void __init setup_smp_ipi(void); + +void arch_send_call_function_ipi_mask(struct cpumask *mask); + +void arch_send_call_function_single_ipi(int cpu); + +void __init set_send_ipi(void (*func)(const struct cpumask *mask), int irq); + +#define raw_smp_processor_id() (current_thread_info()->cpu) + +#endif /* CONFIG_SMP */ + +#endif /* __ASM_CSKY_SMP_H */ diff --git a/arch/csky/include/asm/spinlock.h b/arch/csky/include/asm/spinlock.h new file mode 100644 index 000000000000..7cf3f2b34cea --- /dev/null +++ b/arch/csky/include/asm/spinlock.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_SPINLOCK_H +#define __ASM_CSKY_SPINLOCK_H + +#include <linux/spinlock_types.h> +#include <asm/barrier.h> + +#ifdef CONFIG_QUEUED_RWLOCKS + +/* + * Ticket-based spin-locking. + */ +static inline void arch_spin_lock(arch_spinlock_t *lock) +{ + arch_spinlock_t lockval; + u32 ticket_next = 1 << TICKET_NEXT; + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%2) \n" + " mov %1, %0 \n" + " add %0, %3 \n" + " stex.w %0, (%2) \n" + " bez %0, 1b \n" + : "=&r" (tmp), "=&r" (lockval) + : "r"(p), "r"(ticket_next) + : "cc"); + + while (lockval.tickets.next != lockval.tickets.owner) + lockval.tickets.owner = READ_ONCE(lock->tickets.owner); + + smp_mb(); +} + +static inline int arch_spin_trylock(arch_spinlock_t *lock) +{ + u32 tmp, contended, res; + u32 ticket_next = 1 << TICKET_NEXT; + u32 *p = &lock->lock; + + do { + asm volatile ( + " ldex.w %0, (%3) \n" + " movi %2, 1 \n" + " rotli %1, %0, 16 \n" + " cmpne %1, %0 \n" + " bt 1f \n" + " movi %2, 0 \n" + " add %0, %0, %4 \n" + " stex.w %0, (%3) \n" + "1: \n" + : "=&r" (res), "=&r" (tmp), "=&r" (contended) + : "r"(p), "r"(ticket_next) + : "cc"); + } while (!res); + + if (!contended) + smp_mb(); + + return !contended; +} + +static inline void arch_spin_unlock(arch_spinlock_t *lock) +{ + smp_mb(); + WRITE_ONCE(lock->tickets.owner, lock->tickets.owner + 1); +} + +static inline int arch_spin_value_unlocked(arch_spinlock_t lock) +{ + return lock.tickets.owner == lock.tickets.next; +} + +static inline int arch_spin_is_locked(arch_spinlock_t *lock) +{ + return !arch_spin_value_unlocked(READ_ONCE(*lock)); +} + +static inline int arch_spin_is_contended(arch_spinlock_t *lock) +{ + struct __raw_tickets tickets = READ_ONCE(lock->tickets); + + return (tickets.next - tickets.owner) > 1; +} +#define arch_spin_is_contended arch_spin_is_contended + +#include <asm/qrwlock.h> + +/* See include/linux/spinlock.h */ +#define smp_mb__after_spinlock() smp_mb() + +#else /* CONFIG_QUEUED_RWLOCKS */ + +/* + * Test-and-set spin-locking. + */ +static inline void arch_spin_lock(arch_spinlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " bnez %0, 1b \n" + " movi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + smp_mb(); +} + +static inline void arch_spin_unlock(arch_spinlock_t *lock) +{ + smp_mb(); + WRITE_ONCE(lock->lock, 0); +} + +static inline int arch_spin_trylock(arch_spinlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " bnez %0, 2f \n" + " movi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + " movi %0, 0 \n" + "2: \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + + if (!tmp) + smp_mb(); + + return !tmp; +} + +#define arch_spin_is_locked(x) (READ_ONCE((x)->lock) != 0) + +/* + * read lock/unlock/trylock + */ +static inline void arch_read_lock(arch_rwlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " blz %0, 1b \n" + " addi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + smp_mb(); +} + +static inline void arch_read_unlock(arch_rwlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + smp_mb(); + asm volatile ( + "1: ldex.w %0, (%1) \n" + " subi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); +} + +static inline int arch_read_trylock(arch_rwlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " blz %0, 2f \n" + " addi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + " movi %0, 0 \n" + "2: \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + + if (!tmp) + smp_mb(); + + return !tmp; +} + +/* + * write lock/unlock/trylock + */ +static inline void arch_write_lock(arch_rwlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " bnez %0, 1b \n" + " subi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + smp_mb(); +} + +static inline void arch_write_unlock(arch_rwlock_t *lock) +{ + smp_mb(); + WRITE_ONCE(lock->lock, 0); +} + +static inline int arch_write_trylock(arch_rwlock_t *lock) +{ + u32 *p = &lock->lock; + u32 tmp; + + asm volatile ( + "1: ldex.w %0, (%1) \n" + " bnez %0, 2f \n" + " subi %0, 1 \n" + " stex.w %0, (%1) \n" + " bez %0, 1b \n" + " movi %0, 0 \n" + "2: \n" + : "=&r" (tmp) + : "r"(p) + : "cc"); + + if (!tmp) + smp_mb(); + + return !tmp; +} + +#endif /* CONFIG_QUEUED_RWLOCKS */ +#endif /* __ASM_CSKY_SPINLOCK_H */ diff --git a/arch/csky/include/asm/spinlock_types.h b/arch/csky/include/asm/spinlock_types.h new file mode 100644 index 000000000000..88b82438b182 --- /dev/null +++ b/arch/csky/include/asm/spinlock_types.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_SPINLOCK_TYPES_H +#define __ASM_CSKY_SPINLOCK_TYPES_H + +#ifndef __LINUX_SPINLOCK_TYPES_H +# error "please don't include this file directly" +#endif + +#define TICKET_NEXT 16 + +typedef struct { + union { + u32 lock; + struct __raw_tickets { + /* little endian */ + u16 owner; + u16 next; + } tickets; + }; +} arch_spinlock_t; + +#define __ARCH_SPIN_LOCK_UNLOCKED { { 0 } } + +#ifdef CONFIG_QUEUED_RWLOCKS +#include <asm-generic/qrwlock_types.h> + +#else /* CONFIG_NR_CPUS > 2 */ + +typedef struct { + u32 lock; +} arch_rwlock_t; + +#define __ARCH_RW_LOCK_UNLOCKED { 0 } + +#endif /* CONFIG_QUEUED_RWLOCKS */ +#endif /* __ASM_CSKY_SPINLOCK_TYPES_H */ diff --git a/arch/csky/include/asm/string.h b/arch/csky/include/asm/string.h new file mode 100644 index 000000000000..73142de18355 --- /dev/null +++ b/arch/csky/include/asm/string.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef _CSKY_STRING_MM_H_ +#define _CSKY_STRING_MM_H_ + +#ifndef __ASSEMBLY__ +#include <linux/types.h> +#include <linux/compiler.h> +#include <abi/string.h> +#endif + +#endif /* _CSKY_STRING_MM_H_ */ diff --git a/arch/csky/include/asm/switch_to.h b/arch/csky/include/asm/switch_to.h new file mode 100644 index 000000000000..35a39e88933d --- /dev/null +++ b/arch/csky/include/asm/switch_to.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_SWITCH_TO_H +#define __ASM_CSKY_SWITCH_TO_H + +#include <linux/thread_info.h> +#ifdef CONFIG_CPU_HAS_FPU +#include <abi/fpu.h> +static inline void __switch_to_fpu(struct task_struct *prev, + struct task_struct *next) +{ + save_to_user_fp(&prev->thread.user_fp); + restore_from_user_fp(&next->thread.user_fp); +} +#else +static inline void __switch_to_fpu(struct task_struct *prev, + struct task_struct *next) +{} +#endif + +/* + * Context switching is now performed out-of-line in switch_to.S + */ +extern struct task_struct *__switch_to(struct task_struct *, + struct task_struct *); + +#define switch_to(prev, next, last) \ + do { \ + struct task_struct *__prev = (prev); \ + struct task_struct *__next = (next); \ + __switch_to_fpu(__prev, __next); \ + ((last) = __switch_to((prev), (next))); \ + } while (0) + +#endif /* __ASM_CSKY_SWITCH_TO_H */ diff --git a/arch/csky/include/asm/syscall.h b/arch/csky/include/asm/syscall.h new file mode 100644 index 000000000000..926a64a8b4ee --- /dev/null +++ b/arch/csky/include/asm/syscall.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_SYSCALL_H +#define __ASM_SYSCALL_H + +#include <linux/sched.h> +#include <linux/err.h> +#include <abi/regdef.h> + +static inline int +syscall_get_nr(struct task_struct *task, struct pt_regs *regs) +{ + return regs_syscallid(regs); +} + +static inline void +syscall_rollback(struct task_struct *task, struct pt_regs *regs) +{ + regs->a0 = regs->orig_a0; +} + +static inline long +syscall_get_error(struct task_struct *task, struct pt_regs *regs) +{ + unsigned long error = regs->a0; + + return IS_ERR_VALUE(error) ? error : 0; +} + +static inline long +syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) +{ + return regs->a0; +} + +static inline void +syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, + int error, long val) +{ + regs->a0 = (long) error ?: val; +} + +static inline void +syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, unsigned long *args) +{ + BUG_ON(i + n > 6); + if (i == 0) { + args[0] = regs->orig_a0; + args++; + i++; + n--; + } + memcpy(args, ®s->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); +} + +static inline void +syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, const unsigned long *args) +{ + BUG_ON(i + n > 6); + if (i == 0) { + regs->orig_a0 = args[0]; + args++; + i++; + n--; + } + memcpy(®s->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); +} + +#endif /* __ASM_SYSCALL_H */ diff --git a/arch/csky/include/asm/syscalls.h b/arch/csky/include/asm/syscalls.h new file mode 100644 index 000000000000..5d48e5e0082e --- /dev/null +++ b/arch/csky/include/asm/syscalls.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_SYSCALLS_H +#define __ASM_CSKY_SYSCALLS_H + +#include <asm-generic/syscalls.h> + +long sys_cacheflush(void __user *, unsigned long, int); + +long sys_set_thread_area(unsigned long addr); + +long sys_csky_fadvise64_64(int fd, int advice, loff_t offset, loff_t len); + +#endif /* __ASM_CSKY_SYSCALLS_H */ diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h new file mode 100644 index 000000000000..a2c69a7836f7 --- /dev/null +++ b/arch/csky/include/asm/thread_info.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef _ASM_CSKY_THREAD_INFO_H +#define _ASM_CSKY_THREAD_INFO_H + +#ifndef __ASSEMBLY__ + +#include <linux/version.h> +#include <asm/types.h> +#include <asm/page.h> +#include <asm/processor.h> + +struct thread_info { + struct task_struct *task; + void *dump_exec_domain; + unsigned long flags; + int preempt_count; + unsigned long tp_value; + mm_segment_t addr_limit; + struct restart_block restart_block; + struct pt_regs *regs; + unsigned int cpu; +}; + +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ + .cpu = 0, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ +} + +#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) + +static inline struct thread_info *current_thread_info(void) +{ + unsigned long sp; + + asm volatile("mov %0, sp\n":"=r"(sp)); + + return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); +} + +#endif /* !__ASSEMBLY__ */ + +/* entry.S relies on these definitions! + * bits 0-5 are tested at every exception exit + */ +#define TIF_SIGPENDING 0 /* signal pending */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ +#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ +#define TIF_SYSCALL_TRACE 5 /* syscall trace active */ +#define TIF_DELAYED_TRACE 14 /* single step a syscall */ +#define TIF_POLLING_NRFLAG 16 /* poll_idle() is TIF_NEED_RESCHED */ +#define TIF_MEMDIE 18 /* is terminating due to OOM killer */ +#define TIF_FREEZE 19 /* thread is freezing for suspend */ +#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ +#define TIF_SECCOMP 21 /* secure computing */ + +#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_DELAYED_TRACE (1 << TIF_DELAYED_TRACE) +#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) +#define _TIF_MEMDIE (1 << TIF_MEMDIE) +#define _TIF_FREEZE (1 << TIF_FREEZE) +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) +#define _TIF_SECCOMP (1 << TIF_SECCOMP) + +#endif /* _ASM_CSKY_THREAD_INFO_H */ diff --git a/arch/csky/include/asm/tlb.h b/arch/csky/include/asm/tlb.h new file mode 100644 index 000000000000..8c7cc097666f --- /dev/null +++ b/arch/csky/include/asm/tlb.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_TLB_H +#define __ASM_CSKY_TLB_H + +#include <asm/cacheflush.h> + +#define tlb_start_vma(tlb, vma) \ + do { \ + if (!tlb->fullmm) \ + flush_cache_range(vma, vma->vm_start, vma->vm_end); \ + } while (0) + +#define tlb_end_vma(tlb, vma) \ + do { \ + if (!tlb->fullmm) \ + flush_tlb_range(vma, vma->vm_start, vma->vm_end); \ + } while (0) + +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#include <asm-generic/tlb.h> + +#endif /* __ASM_CSKY_TLB_H */ diff --git a/arch/csky/include/asm/tlbflush.h b/arch/csky/include/asm/tlbflush.h new file mode 100644 index 000000000000..6845b0667703 --- /dev/null +++ b/arch/csky/include/asm/tlbflush.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_TLBFLUSH_H +#define __ASM_TLBFLUSH_H + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLB entries + * - flush_tlb_mm(mm) flushes the specified mm context TLB entries + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + */ +extern void flush_tlb_all(void); +extern void flush_tlb_mm(struct mm_struct *mm); +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); + +extern void flush_tlb_one(unsigned long vaddr); + +#endif diff --git a/arch/csky/include/asm/traps.h b/arch/csky/include/asm/traps.h new file mode 100644 index 000000000000..1c081805b962 --- /dev/null +++ b/arch/csky/include/asm/traps.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_TRAPS_H +#define __ASM_CSKY_TRAPS_H + +#define VEC_RESET 0 +#define VEC_ALIGN 1 +#define VEC_ACCESS 2 +#define VEC_ZERODIV 3 +#define VEC_ILLEGAL 4 +#define VEC_PRIV 5 +#define VEC_TRACE 6 +#define VEC_BREAKPOINT 7 +#define VEC_UNRECOVER 8 +#define VEC_SOFTRESET 9 +#define VEC_AUTOVEC 10 +#define VEC_FAUTOVEC 11 +#define VEC_HWACCEL 12 + +#define VEC_TLBMISS 14 +#define VEC_TLBMODIFIED 15 + +#define VEC_TRAP0 16 +#define VEC_TRAP1 17 +#define VEC_TRAP2 18 +#define VEC_TRAP3 19 + +#define VEC_TLBINVALIDL 20 +#define VEC_TLBINVALIDS 21 + +#define VEC_PRFL 29 +#define VEC_FPE 30 + +extern void *vec_base[]; + +#define VEC_INIT(i, func) \ +do { \ + vec_base[i] = (void *)func; \ +} while (0) + +void csky_alignment(struct pt_regs *regs); + +#endif /* __ASM_CSKY_TRAPS_H */ diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h new file mode 100644 index 000000000000..acaf0e210d81 --- /dev/null +++ b/arch/csky/include/asm/uaccess.h @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_UACCESS_H +#define __ASM_CSKY_UACCESS_H + +/* + * User space memory access functions + */ +#include <linux/compiler.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/version.h> +#include <asm/segment.h> + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +static inline int access_ok(int type, const void *addr, unsigned long size) +{ + unsigned long limit = current_thread_info()->addr_limit.seg; + + return (((unsigned long)addr < limit) && + ((unsigned long)(addr + size) < limit)); +} + +static inline int verify_area(int type, const void *addr, unsigned long size) +{ + return access_ok(type, addr, size) ? 0 : -EFAULT; +} + +#define __addr_ok(addr) (access_ok(VERIFY_READ, addr, 0)) + +extern int __put_user_bad(void); + +/* + * Tell gcc we read from memory instead of writing: this is because + * we do not write to any memory gcc knows about, so there are no + * aliasing issues. + */ + +/* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + * + * This gets kind of ugly. We want to return _two_ values in "get_user()" + * and yet we don't want to do any pointers, because that is too much + * of a performance impact. Thus we have a few rather ugly macros here, + * and hide all the ugliness from the user. + * + * The "__xxx" versions of the user access functions are versions that + * do not verify the address space, that must have been done previously + * with a separate "access_ok()" call (this is used when we do multiple + * accesses to the same area of user memory). + * + * As we use the same address space for kernel and user data on + * Ckcore, we can just do these as direct assignments. (Of course, the + * exception handling means that it's no longer "just"...) + */ + +#define put_user(x, ptr) \ + __put_user_check((x), (ptr), sizeof(*(ptr))) + +#define __put_user(x, ptr) \ + __put_user_nocheck((x), (ptr), sizeof(*(ptr))) + +#define __ptr(x) ((unsigned long *)(x)) + +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) + +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) + +#define __put_user_nocheck(x, ptr, size) \ +({ \ + long __pu_err = 0; \ + typeof(*(ptr)) *__pu_addr = (ptr); \ + typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x); \ + if (__pu_addr) \ + __put_user_size(__pu_val, (__pu_addr), (size), \ + __pu_err); \ + __pu_err; \ +}) + +#define __put_user_check(x, ptr, size) \ +({ \ + long __pu_err = -EFAULT; \ + typeof(*(ptr)) *__pu_addr = (ptr); \ + typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size) && __pu_addr) \ + __put_user_size(__pu_val, __pu_addr, (size), __pu_err); \ + __pu_err; \ +}) + +#define __put_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: \ + __put_user_asm_b(x, ptr, retval); \ + break; \ + case 2: \ + __put_user_asm_h(x, ptr, retval); \ + break; \ + case 4: \ + __put_user_asm_w(x, ptr, retval); \ + break; \ + case 8: \ + __put_user_asm_64(x, ptr, retval); \ + break; \ + default: \ + __put_user_bad(); \ + } \ +} while (0) + +/* + * We don't tell gcc that we are accessing memory, but this is OK + * because we do not write to any memory gcc knows about, so there + * are no aliasing issues. + * + * Note that PC at a fault is the address *after* the faulting + * instruction. + */ +#define __put_user_asm_b(x, ptr, err) \ +do { \ + int errcode; \ + asm volatile( \ + "1: stb %1, (%2,0) \n" \ + " br 3f \n" \ + "2: mov %0, %3 \n" \ + " br 3f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 1b,2b \n" \ + ".previous \n" \ + "3: \n" \ + : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ + : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ + : "memory"); \ +} while (0) + +#define __put_user_asm_h(x, ptr, err) \ +do { \ + int errcode; \ + asm volatile( \ + "1: sth %1, (%2,0) \n" \ + " br 3f \n" \ + "2: mov %0, %3 \n" \ + " br 3f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 1b,2b \n" \ + ".previous \n" \ + "3: \n" \ + : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ + : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ + : "memory"); \ +} while (0) + +#define __put_user_asm_w(x, ptr, err) \ +do { \ + int errcode; \ + asm volatile( \ + "1: stw %1, (%2,0) \n" \ + " br 3f \n" \ + "2: mov %0, %3 \n" \ + " br 3f \n" \ + ".section __ex_table,\"a\" \n" \ + ".align 2 \n" \ + ".long 1b, 2b \n" \ + ".previous \n" \ + "3: \n" \ + : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ + : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ + : "memory"); \ +} while (0) + +#define __put_user_asm_64(x, ptr, err) \ +do { \ + int tmp; \ + int errcode; \ + typeof(*(ptr))src = (typeof(*(ptr)))x; \ + typeof(*(ptr))*psrc = &src; \ + \ + asm volatile( \ + " ldw %3, (%1, 0) \n" \ + "1: stw %3, (%2, 0) \n" \ + " ldw %3, (%1, 4) \n" \ + "2: stw %3, (%2, 4) \n" \ + " br 4f \n" \ + "3: mov %0, %4 \n" \ + " br 4f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 1b, 3b \n" \ + ".long 2b, 3b \n" \ + ".previous \n" \ + "4: \n" \ + : "=r"(err), "=r"(psrc), "=r"(ptr), \ + "=r"(tmp), "=r"(errcode) \ + : "0"(err), "1"(psrc), "2"(ptr), "3"(0), "4"(-EFAULT) \ + : "memory"); \ +} while (0) + +#define __get_user_nocheck(x, ptr, size) \ +({ \ + long __gu_err; \ + __get_user_size(x, (ptr), (size), __gu_err); \ + __gu_err; \ +}) + +#define __get_user_check(x, ptr, size) \ +({ \ + int __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + if (access_ok(VERIFY_READ, __gu_ptr, size) && __gu_ptr) \ + __get_user_size(x, __gu_ptr, size, __gu_err); \ + __gu_err; \ +}) + +#define __get_user_size(x, ptr, size, retval) \ +do { \ + switch (size) { \ + case 1: \ + __get_user_asm_common((x), ptr, "ldb", retval); \ + break; \ + case 2: \ + __get_user_asm_common((x), ptr, "ldh", retval); \ + break; \ + case 4: \ + __get_user_asm_common((x), ptr, "ldw", retval); \ + break; \ + default: \ + x = 0; \ + (retval) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_asm_common(x, ptr, ins, err) \ +do { \ + int errcode; \ + asm volatile( \ + "1: " ins " %1, (%4,0) \n" \ + " br 3f \n" \ + /* Fix up codes */ \ + "2: mov %0, %2 \n" \ + " movi %1, 0 \n" \ + " br 3f \n" \ + ".section __ex_table,\"a\" \n" \ + ".align 2 \n" \ + ".long 1b, 2b \n" \ + ".previous \n" \ + "3: \n" \ + : "=r"(err), "=r"(x), "=r"(errcode) \ + : "0"(0), "r"(ptr), "2"(-EFAULT) \ + : "memory"); \ +} while (0) + +extern int __get_user_bad(void); + +#define __copy_user(to, from, n) \ +do { \ + int w0, w1, w2, w3; \ + asm volatile( \ + "0: cmpnei %1, 0 \n" \ + " bf 8f \n" \ + " mov %3, %1 \n" \ + " or %3, %2 \n" \ + " andi %3, 3 \n" \ + " cmpnei %3, 0 \n" \ + " bf 1f \n" \ + " br 5f \n" \ + "1: cmplti %0, 16 \n" /* 4W */ \ + " bt 3f \n" \ + " ldw %3, (%2, 0) \n" \ + " ldw %4, (%2, 4) \n" \ + " ldw %5, (%2, 8) \n" \ + " ldw %6, (%2, 12) \n" \ + "2: stw %3, (%1, 0) \n" \ + "9: stw %4, (%1, 4) \n" \ + "10: stw %5, (%1, 8) \n" \ + "11: stw %6, (%1, 12) \n" \ + " addi %2, 16 \n" \ + " addi %1, 16 \n" \ + " subi %0, 16 \n" \ + " br 1b \n" \ + "3: cmplti %0, 4 \n" /* 1W */ \ + " bt 5f \n" \ + " ldw %3, (%2, 0) \n" \ + "4: stw %3, (%1, 0) \n" \ + " addi %2, 4 \n" \ + " addi %1, 4 \n" \ + " subi %0, 4 \n" \ + " br 3b \n" \ + "5: cmpnei %0, 0 \n" /* 1B */ \ + " bf 8f \n" \ + " ldb %3, (%2, 0) \n" \ + "6: stb %3, (%1, 0) \n" \ + " addi %2, 1 \n" \ + " addi %1, 1 \n" \ + " subi %0, 1 \n" \ + " br 5b \n" \ + "7: br 8f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 2b, 7b \n" \ + ".long 9b, 7b \n" \ + ".long 10b, 7b \n" \ + ".long 11b, 7b \n" \ + ".long 4b, 7b \n" \ + ".long 6b, 7b \n" \ + ".previous \n" \ + "8: \n" \ + : "=r"(n), "=r"(to), "=r"(from), "=r"(w0), \ + "=r"(w1), "=r"(w2), "=r"(w3) \ + : "0"(n), "1"(to), "2"(from) \ + : "memory"); \ +} while (0) + +#define __copy_user_zeroing(to, from, n) \ +do { \ + int tmp; \ + int nsave; \ + asm volatile( \ + "0: cmpnei %1, 0 \n" \ + " bf 7f \n" \ + " mov %3, %1 \n" \ + " or %3, %2 \n" \ + " andi %3, 3 \n" \ + " cmpnei %3, 0 \n" \ + " bf 1f \n" \ + " br 5f \n" \ + "1: cmplti %0, 16 \n" \ + " bt 3f \n" \ + "2: ldw %3, (%2, 0) \n" \ + "10: ldw %4, (%2, 4) \n" \ + " stw %3, (%1, 0) \n" \ + " stw %4, (%1, 4) \n" \ + "11: ldw %3, (%2, 8) \n" \ + "12: ldw %4, (%2, 12) \n" \ + " stw %3, (%1, 8) \n" \ + " stw %4, (%1, 12) \n" \ + " addi %2, 16 \n" \ + " addi %1, 16 \n" \ + " subi %0, 16 \n" \ + " br 1b \n" \ + "3: cmplti %0, 4 \n" \ + " bt 5f \n" \ + "4: ldw %3, (%2, 0) \n" \ + " stw %3, (%1, 0) \n" \ + " addi %2, 4 \n" \ + " addi %1, 4 \n" \ + " subi %0, 4 \n" \ + " br 3b \n" \ + "5: cmpnei %0, 0 \n" \ + " bf 7f \n" \ + "6: ldb %3, (%2, 0) \n" \ + " stb %3, (%1, 0) \n" \ + " addi %2, 1 \n" \ + " addi %1, 1 \n" \ + " subi %0, 1 \n" \ + " br 5b \n" \ + "8: mov %3, %0 \n" \ + " movi %4, 0 \n" \ + "9: stb %4, (%1, 0) \n" \ + " addi %1, 1 \n" \ + " subi %3, 1 \n" \ + " cmpnei %3, 0 \n" \ + " bt 9b \n" \ + " br 7f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 2b, 8b \n" \ + ".long 10b, 8b \n" \ + ".long 11b, 8b \n" \ + ".long 12b, 8b \n" \ + ".long 4b, 8b \n" \ + ".long 6b, 8b \n" \ + ".previous \n" \ + "7: \n" \ + : "=r"(n), "=r"(to), "=r"(from), "=r"(nsave), \ + "=r"(tmp) \ + : "0"(n), "1"(to), "2"(from) \ + : "memory"); \ +} while (0) + +unsigned long raw_copy_from_user(void *to, const void *from, unsigned long n); +unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n); + +unsigned long clear_user(void *to, unsigned long n); +unsigned long __clear_user(void __user *to, unsigned long n); + +long strncpy_from_user(char *dst, const char *src, long count); +long __strncpy_from_user(char *dst, const char *src, long count); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char *src, long n); + +#define strlen_user(str) strnlen_user(str, 32767) + +struct exception_table_entry { + unsigned long insn; + unsigned long nextinsn; +}; + +extern int fixup_exception(struct pt_regs *regs); + +#endif /* __ASM_CSKY_UACCESS_H */ diff --git a/arch/csky/include/asm/unistd.h b/arch/csky/include/asm/unistd.h new file mode 100644 index 000000000000..284487477a61 --- /dev/null +++ b/arch/csky/include/asm/unistd.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <uapi/asm/unistd.h> diff --git a/arch/csky/include/asm/vdso.h b/arch/csky/include/asm/vdso.h new file mode 100644 index 000000000000..d963d691f3a1 --- /dev/null +++ b/arch/csky/include/asm/vdso.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_VDSO_H +#define __ASM_CSKY_VDSO_H + +#include <abi/vdso.h> + +struct csky_vdso { + unsigned short rt_signal_retcode[4]; +}; + +#endif /* __ASM_CSKY_VDSO_H */ diff --git a/arch/csky/include/uapi/asm/Kbuild b/arch/csky/include/uapi/asm/Kbuild new file mode 100644 index 000000000000..e02fd44e6447 --- /dev/null +++ b/arch/csky/include/uapi/asm/Kbuild @@ -0,0 +1,32 @@ +include include/uapi/asm-generic/Kbuild.asm + +header-y += cachectl.h + +generic-y += auxvec.h +generic-y += param.h +generic-y += bpf_perf_event.h +generic-y += errno.h +generic-y += fcntl.h +generic-y += ioctl.h +generic-y += ioctls.h +generic-y += ipcbuf.h +generic-y += shmbuf.h +generic-y += bitsperlong.h +generic-y += mman.h +generic-y += msgbuf.h +generic-y += poll.h +generic-y += posix_types.h +generic-y += resource.h +generic-y += sembuf.h +generic-y += siginfo.h +generic-y += signal.h +generic-y += socket.h +generic-y += sockios.h +generic-y += statfs.h +generic-y += stat.h +generic-y += setup.h +generic-y += swab.h +generic-y += termbits.h +generic-y += termios.h +generic-y += types.h +generic-y += ucontext.h diff --git a/arch/csky/include/uapi/asm/byteorder.h b/arch/csky/include/uapi/asm/byteorder.h new file mode 100644 index 000000000000..b079ec715cdf --- /dev/null +++ b/arch/csky/include/uapi/asm/byteorder.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_BYTEORDER_H +#define __ASM_CSKY_BYTEORDER_H + +#include <linux/byteorder/little_endian.h> + +#endif /* __ASM_CSKY_BYTEORDER_H */ diff --git a/arch/csky/include/uapi/asm/cachectl.h b/arch/csky/include/uapi/asm/cachectl.h new file mode 100644 index 000000000000..ddf2f39aa925 --- /dev/null +++ b/arch/csky/include/uapi/asm/cachectl.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_CSKY_CACHECTL_H +#define __ASM_CSKY_CACHECTL_H + +/* + * See "man cacheflush" + */ +#define ICACHE (1<<0) +#define DCACHE (1<<1) +#define BCACHE (ICACHE|DCACHE) + +#endif /* __ASM_CSKY_CACHECTL_H */ diff --git a/arch/csky/include/uapi/asm/ptrace.h b/arch/csky/include/uapi/asm/ptrace.h new file mode 100644 index 000000000000..f10d02c8b09e --- /dev/null +++ b/arch/csky/include/uapi/asm/ptrace.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef _CSKY_PTRACE_H +#define _CSKY_PTRACE_H + +#ifndef __ASSEMBLY__ + +struct pt_regs { + unsigned long tls; + unsigned long lr; + unsigned long pc; + unsigned long sr; + unsigned long usp; + + /* + * a0, a1, a2, a3: + * abiv1: r2, r3, r4, r5 + * abiv2: r0, r1, r2, r3 + */ + unsigned long orig_a0; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + + /* + * ABIV2: r4 ~ r13 + * ABIV1: r6 ~ r14, r1 + */ + unsigned long regs[10]; + +#if defined(__CSKYABIV2__) + /* r16 ~ r30 */ + unsigned long exregs[15]; + + unsigned long rhi; + unsigned long rlo; + unsigned long pad; /* reserved */ +#endif +}; + +struct user_fp { + unsigned long vr[96]; + unsigned long fcr; + unsigned long fesr; + unsigned long fid; + unsigned long reserved; +}; + +/* + * Switch stack for switch_to after push pt_regs. + * + * ABI_CSKYV2: r4 ~ r11, r15 ~ r17, r26 ~ r30; + * ABI_CSKYV1: r8 ~ r14, r15; + */ +struct switch_stack { +#if defined(__CSKYABIV2__) + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; +#else + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; +#endif + unsigned long r15; +#if defined(__CSKYABIV2__) + unsigned long r16; + unsigned long r17; + unsigned long r26; + unsigned long r27; + unsigned long r28; + unsigned long r29; + unsigned long r30; +#endif +}; + +#ifdef __KERNEL__ + +#define PS_S 0x80000000 /* Supervisor Mode */ + +#define arch_has_single_step() (1) +#define current_pt_regs() \ +({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; }) + +#define user_stack_pointer(regs) ((regs)->usp) + +#define user_mode(regs) (!((regs)->sr & PS_S)) +#define instruction_pointer(regs) ((regs)->pc) +#define profile_pc(regs) instruction_pointer(regs) + +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ +#endif /* _CSKY_PTRACE_H */ diff --git a/arch/csky/include/uapi/asm/sigcontext.h b/arch/csky/include/uapi/asm/sigcontext.h new file mode 100644 index 000000000000..e81e7ff11e36 --- /dev/null +++ b/arch/csky/include/uapi/asm/sigcontext.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#ifndef __ASM_CSKY_SIGCONTEXT_H +#define __ASM_CSKY_SIGCONTEXT_H + +#include <asm/ptrace.h> + +struct sigcontext { + struct pt_regs sc_pt_regs; + struct user_fp sc_user_fp; +}; + +#endif /* __ASM_CSKY_SIGCONTEXT_H */ diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h new file mode 100644 index 000000000000..224c9a9ab45b --- /dev/null +++ b/arch/csky/include/uapi/asm/unistd.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#define __ARCH_WANT_SYS_CLONE +#include <asm-generic/unistd.h> + +#define __NR_set_thread_area (__NR_arch_specific_syscall + 0) +__SYSCALL(__NR_set_thread_area, sys_set_thread_area) +#define __NR_cacheflush (__NR_arch_specific_syscall + 1) +__SYSCALL(__NR_cacheflush, sys_cacheflush) diff --git a/arch/csky/kernel/Makefile b/arch/csky/kernel/Makefile new file mode 100644 index 000000000000..4422de756cde --- /dev/null +++ b/arch/csky/kernel/Makefile @@ -0,0 +1,8 @@ +extra-y := head.o vmlinux.lds + +obj-y += entry.o atomic.o signal.o traps.o irq.o time.o vdso.o +obj-y += power.o syscall.o syscall_table.o setup.o +obj-y += process.o cpu-probe.o ptrace.o dumpstack.o + +obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_SMP) += smp.o diff --git a/arch/csky/kernel/asm-offsets.c b/arch/csky/kernel/asm-offsets.c new file mode 100644 index 000000000000..8d3ed811321f --- /dev/null +++ b/arch/csky/kernel/asm-offsets.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/kbuild.h> +#include <abi/regdef.h> + +int main(void) +{ + /* offsets into the task struct */ + DEFINE(TASK_STATE, offsetof(struct task_struct, state)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); + DEFINE(TASK_MM, offsetof(struct task_struct, mm)); + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); + + /* offsets into the thread struct */ + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FESR, offsetof(struct thread_struct, user_fp.fesr)); + DEFINE(THREAD_FCR, offsetof(struct thread_struct, user_fp.fcr)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, user_fp.vr)); + DEFINE(THREAD_DSPHI, offsetof(struct thread_struct, hi)); + DEFINE(THREAD_DSPLO, offsetof(struct thread_struct, lo)); + + /* offsets into the thread_info struct */ + DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(TINFO_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); + DEFINE(TINFO_TP_VALUE, offsetof(struct thread_info, tp_value)); + DEFINE(TINFO_TASK, offsetof(struct thread_info, task)); + + /* offsets into the pt_regs */ + DEFINE(PT_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_ORIG_AO, offsetof(struct pt_regs, orig_a0)); + DEFINE(PT_SR, offsetof(struct pt_regs, sr)); + + DEFINE(PT_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_A3, offsetof(struct pt_regs, a3)); + DEFINE(PT_REGS0, offsetof(struct pt_regs, regs[0])); + DEFINE(PT_REGS1, offsetof(struct pt_regs, regs[1])); + DEFINE(PT_REGS2, offsetof(struct pt_regs, regs[2])); + DEFINE(PT_REGS3, offsetof(struct pt_regs, regs[3])); + DEFINE(PT_REGS4, offsetof(struct pt_regs, regs[4])); + DEFINE(PT_REGS5, offsetof(struct pt_regs, regs[5])); + DEFINE(PT_REGS6, offsetof(struct pt_regs, regs[6])); + DEFINE(PT_REGS7, offsetof(struct pt_regs, regs[7])); + DEFINE(PT_REGS8, offsetof(struct pt_regs, regs[8])); + DEFINE(PT_REGS9, offsetof(struct pt_regs, regs[9])); + DEFINE(PT_R15, offsetof(struct pt_regs, lr)); +#if defined(__CSKYABIV2__) + DEFINE(PT_R16, offsetof(struct pt_regs, exregs[0])); + DEFINE(PT_R17, offsetof(struct pt_regs, exregs[1])); + DEFINE(PT_R18, offsetof(struct pt_regs, exregs[2])); + DEFINE(PT_R19, offsetof(struct pt_regs, exregs[3])); + DEFINE(PT_R20, offsetof(struct pt_regs, exregs[4])); + DEFINE(PT_R21, offsetof(struct pt_regs, exregs[5])); + DEFINE(PT_R22, offsetof(struct pt_regs, exregs[6])); + DEFINE(PT_R23, offsetof(struct pt_regs, exregs[7])); + DEFINE(PT_R24, offsetof(struct pt_regs, exregs[8])); + DEFINE(PT_R25, offsetof(struct pt_regs, exregs[9])); + DEFINE(PT_R26, offsetof(struct pt_regs, exregs[10])); + DEFINE(PT_R27, offsetof(struct pt_regs, exregs[11])); + DEFINE(PT_R28, offsetof(struct pt_regs, exregs[12])); + DEFINE(PT_R29, offsetof(struct pt_regs, exregs[13])); + DEFINE(PT_R30, offsetof(struct pt_regs, exregs[14])); + DEFINE(PT_R31, offsetof(struct pt_regs, exregs[15])); + DEFINE(PT_RHI, offsetof(struct pt_regs, rhi)); + DEFINE(PT_RLO, offsetof(struct pt_regs, rlo)); +#endif + DEFINE(PT_USP, offsetof(struct pt_regs, usp)); + + /* offsets into the irq_cpustat_t struct */ + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, + __softirq_pending)); + + /* signal defines */ + DEFINE(SIGSEGV, SIGSEGV); + DEFINE(SIGTRAP, SIGTRAP); + + return 0; +} diff --git a/arch/csky/kernel/atomic.S b/arch/csky/kernel/atomic.S new file mode 100644 index 000000000000..d2357c8f85bd --- /dev/null +++ b/arch/csky/kernel/atomic.S @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include <abi/entry.h> + +.text + +/* + * int csky_cmpxchg(int oldval, int newval, int *ptr) + * + * If *ptr != oldval && return 1, + * else *ptr = newval return 0. + */ +#ifdef CONFIG_CPU_HAS_LDSTEX +ENTRY(csky_cmpxchg) + USPTOKSP + mfcr a3, epc + INCTRAP a3 + + subi sp, 8 + stw a3, (sp, 0) + mfcr a3, epsr + stw a3, (sp, 4) + + psrset ee +1: + ldex a3, (a2) + cmpne a0, a3 + bt16 2f + mov a3, a1 + stex a3, (a2) + bez a3, 1b +2: + sync.is + mvc a0 + ldw a3, (sp, 0) + mtcr a3, epc + ldw a3, (sp, 4) + mtcr a3, epsr + addi sp, 8 + KSPTOUSP + rte +END(csky_cmpxchg) +#else +ENTRY(csky_cmpxchg) + USPTOKSP + mfcr a3, epc + INCTRAP a3 + + subi sp, 8 + stw a3, (sp, 0) + mfcr a3, epsr + stw a3, (sp, 4) + + psrset ee +1: + ldw a3, (a2) + cmpne a0, a3 + bt16 3f +2: + stw a1, (a2) +3: + mvc a0 + ldw a3, (sp, 0) + mtcr a3, epc + ldw a3, (sp, 4) + mtcr a3, epsr + addi sp, 8 + KSPTOUSP + rte +END(csky_cmpxchg) + +/* + * Called from tlbmodified exception + */ +ENTRY(csky_cmpxchg_fixup) + mfcr a0, epc + lrw a1, 2b + cmpne a1, a0 + bt 1f + subi a1, (2b - 1b) + stw a1, (sp, LSAVE_PC) +1: + rts +END(csky_cmpxchg_fixup) +#endif diff --git a/arch/csky/kernel/cpu-probe.c b/arch/csky/kernel/cpu-probe.c new file mode 100644 index 000000000000..5f15ca31d3e8 --- /dev/null +++ b/arch/csky/kernel/cpu-probe.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/of.h> +#include <linux/init.h> +#include <linux/seq_file.h> +#include <linux/memblock.h> + +#include <abi/reg_ops.h> + +static void percpu_print(void *arg) +{ + struct seq_file *m = (struct seq_file *)arg; + unsigned int cur, next, i; + + seq_printf(m, "processor : %d\n", smp_processor_id()); + seq_printf(m, "C-SKY CPU model : %s\n", CSKYCPU_DEF_NAME); + + /* read processor id, max is 100 */ + cur = mfcr("cr13"); + for (i = 0; i < 100; i++) { + seq_printf(m, "product info[%d] : 0x%08x\n", i, cur); + + next = mfcr("cr13"); + + /* some CPU only has one id reg */ + if (cur == next) + break; + + cur = next; + + /* cpid index is 31-28, reset */ + if (!(next >> 28)) { + while ((mfcr("cr13") >> 28) != i); + break; + } + } + + /* CPU feature regs, setup by bootloader or gdbinit */ + seq_printf(m, "hint (CPU funcs): 0x%08x\n", mfcr_hint()); + seq_printf(m, "ccr (L1C & MMU): 0x%08x\n", mfcr("cr18")); + seq_printf(m, "ccr2 (L2C) : 0x%08x\n", mfcr_ccr2()); + seq_printf(m, "\n"); +} + +static int c_show(struct seq_file *m, void *v) +{ + int cpu; + + for_each_online_cpu(cpu) + smp_call_function_single(cpu, percpu_print, m, true); + +#ifdef CSKY_ARCH_VERSION + seq_printf(m, "arch-version : %s\n", CSKY_ARCH_VERSION); + seq_printf(m, "\n"); +#endif + + return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < 1 ? (void *)1 : NULL; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +static void c_stop(struct seq_file *m, void *v) {} + +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show, +}; diff --git a/arch/csky/kernel/dumpstack.c b/arch/csky/kernel/dumpstack.c new file mode 100644 index 000000000000..a9a03ac57ec5 --- /dev/null +++ b/arch/csky/kernel/dumpstack.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/ptrace.h> + +int kstack_depth_to_print = 48; + +void show_trace(unsigned long *stack) +{ + unsigned long *endstack; + unsigned long addr; + int i; + + pr_info("Call Trace:\n"); + addr = (unsigned long)stack + THREAD_SIZE - 1; + endstack = (unsigned long *)(addr & -THREAD_SIZE); + i = 0; + while (stack + 1 <= endstack) { + addr = *stack++; + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (__kernel_text_address(addr)) { +#ifndef CONFIG_KALLSYMS + if (i % 5 == 0) + pr_cont("\n "); +#endif + pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr); + i++; + } + } + pr_cont("\n"); +} + +void show_stack(struct task_struct *task, unsigned long *stack) +{ + unsigned long *p; + unsigned long *endstack; + int i; + + if (!stack) { + if (task) + stack = (unsigned long *)task->thread.esp0; + else + stack = (unsigned long *)&stack; + } + endstack = (unsigned long *) + (((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); + + pr_info("Stack from %08lx:", (unsigned long)stack); + p = stack; + for (i = 0; i < kstack_depth_to_print; i++) { + if (p + 1 > endstack) + break; + if (i % 8 == 0) + pr_cont("\n "); + pr_cont(" %08lx", *p++); + } + pr_cont("\n"); + show_trace(stack); +} diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S new file mode 100644 index 000000000000..79f92b8606c8 --- /dev/null +++ b/arch/csky/kernel/entry.S @@ -0,0 +1,396 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/linkage.h> +#include <abi/entry.h> +#include <abi/pgtable-bits.h> +#include <asm/errno.h> +#include <asm/setup.h> +#include <asm/unistd.h> +#include <asm/asm-offsets.h> +#include <linux/threads.h> +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/thread_info.h> + +#define PTE_INDX_MSK 0xffc +#define PTE_INDX_SHIFT 10 +#define _PGDIR_SHIFT 22 + +.macro tlbop_begin name, val0, val1, val2 +ENTRY(csky_\name) + mtcr a3, ss2 + mtcr r6, ss3 + mtcr a2, ss4 + + RD_PGDR r6 + RD_MEH a3 +#ifdef CONFIG_CPU_HAS_TLBI + tlbi.vaas a3 + sync.is + + btsti a3, 31 + bf 1f + RD_PGDR_K r6 +1: +#else + bgeni a2, 31 + WR_MCIR a2 + bgeni a2, 25 + WR_MCIR a2 +#endif + bclri r6, 0 + lrw a2, PHYS_OFFSET + subu r6, a2 + bseti r6, 31 + + mov a2, a3 + lsri a2, _PGDIR_SHIFT + lsli a2, 2 + addu r6, a2 + ldw r6, (r6) + + lrw a2, PHYS_OFFSET + subu r6, a2 + bseti r6, 31 + + lsri a3, PTE_INDX_SHIFT + lrw a2, PTE_INDX_MSK + and a3, a2 + addu r6, a3 + ldw a3, (r6) + + movi a2, (_PAGE_PRESENT | \val0) + and a3, a2 + cmpne a3, a2 + bt \name + + /* First read/write the page, just update the flags */ + ldw a3, (r6) + bgeni a2, PAGE_VALID_BIT + bseti a2, PAGE_ACCESSED_BIT + bseti a2, \val1 + bseti a2, \val2 + or a3, a2 + stw a3, (r6) + + /* Some cpu tlb-hardrefill bypass the cache */ +#ifdef CONFIG_CPU_NEED_TLBSYNC + movi a2, 0x22 + bseti a2, 6 + mtcr r6, cr22 + mtcr a2, cr17 + sync +#endif + + mfcr a3, ss2 + mfcr r6, ss3 + mfcr a2, ss4 + rte +\name: + mfcr a3, ss2 + mfcr r6, ss3 + mfcr a2, ss4 + SAVE_ALL EPC_KEEP +.endm +.macro tlbop_end is_write + RD_MEH a2 + psrset ee, ie + mov a0, sp + movi a1, \is_write + jbsr do_page_fault + movi r11_sig, 0 /* r11 = 0, Not a syscall. */ + jmpi ret_from_exception +.endm + +.text + +tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT +tlbop_end 0 + +tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT +tlbop_end 1 + +tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT +#ifndef CONFIG_CPU_HAS_LDSTEX +jbsr csky_cmpxchg_fixup +#endif +tlbop_end 1 + +ENTRY(csky_systemcall) + SAVE_ALL EPC_INCREASE + + psrset ee, ie + + /* Stack frame for syscall, origin call set_esp0 */ + mov r12, sp + + bmaski r11, 13 + andn r12, r11 + bgeni r11, 9 + addi r11, 32 + addu r12, r11 + st sp, (r12, 0) + + lrw r11, __NR_syscalls + cmphs syscallid, r11 /* Check nr of syscall */ + bt ret_from_exception + + lrw r13, sys_call_table + ixw r13, syscallid + ldw r11, (r13) + cmpnei r11, 0 + bf ret_from_exception + + mov r9, sp + bmaski r10, THREAD_SHIFT + andn r9, r10 + ldw r8, (r9, TINFO_FLAGS) + btsti r8, TIF_SYSCALL_TRACE + bt 1f +#if defined(__CSKYABIV2__) + subi sp, 8 + stw r5, (sp, 0x4) + stw r4, (sp, 0x0) + jsr r11 /* Do system call */ + addi sp, 8 +#else + jsr r11 +#endif + stw a0, (sp, LSAVE_A0) /* Save return value */ + jmpi ret_from_exception + +1: + movi a0, 0 /* enter system call */ + mov a1, sp /* sp = pt_regs pointer */ + jbsr syscall_trace + /* Prepare args before do system call */ + ldw a0, (sp, LSAVE_A0) + ldw a1, (sp, LSAVE_A1) + ldw a2, (sp, LSAVE_A2) + ldw a3, (sp, LSAVE_A3) +#if defined(__CSKYABIV2__) + subi sp, 8 + stw r5, (sp, 0x4) + stw r4, (sp, 0x0) +#else + ldw r6, (sp, LSAVE_A4) + ldw r7, (sp, LSAVE_A5) +#endif + jsr r11 /* Do system call */ +#if defined(__CSKYABIV2__) + addi sp, 8 +#endif + stw a0, (sp, LSAVE_A0) /* Save return value */ + + movi a0, 1 /* leave system call */ + mov a1, sp /* sp = pt_regs pointer */ + jbsr syscall_trace + +syscall_exit_work: + ld syscallid, (sp, LSAVE_PSR) + btsti syscallid, 31 + bt 2f + + jmpi resume_userspace + +2: RESTORE_ALL + +ENTRY(ret_from_kernel_thread) + jbsr schedule_tail + mov a0, r8 + jsr r9 + jbsr ret_from_exception + +ENTRY(ret_from_fork) + jbsr schedule_tail + mov r9, sp + bmaski r10, THREAD_SHIFT + andn r9, r10 + ldw r8, (r9, TINFO_FLAGS) + movi r11_sig, 1 + btsti r8, TIF_SYSCALL_TRACE + bf 3f + movi a0, 1 + mov a1, sp /* sp = pt_regs pointer */ + jbsr syscall_trace +3: + jbsr ret_from_exception + +ret_from_exception: + ld syscallid, (sp, LSAVE_PSR) + btsti syscallid, 31 + bt 1f + + /* + * Load address of current->thread_info, Then get address of task_struct + * Get task_needreshed in task_struct + */ + mov r9, sp + bmaski r10, THREAD_SHIFT + andn r9, r10 + +resume_userspace: + ldw r8, (r9, TINFO_FLAGS) + andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) + cmpnei r8, 0 + bt exit_work +1: RESTORE_ALL + +exit_work: + mov a0, sp /* Stack address is arg[0] */ + jbsr set_esp0 /* Call C level */ + btsti r8, TIF_NEED_RESCHED + bt work_resched + /* If thread_info->flag is empty, RESTORE_ALL */ + cmpnei r8, 0 + bf 1b + mov a1, sp + mov a0, r8 + mov a2, r11_sig /* syscall? */ + btsti r8, TIF_SIGPENDING /* delivering a signal? */ + /* prevent further restarts(set r11 = 0) */ + clrt r11_sig + jbsr do_notify_resume /* do signals */ + br resume_userspace + +work_resched: + lrw syscallid, ret_from_exception + mov r15, syscallid /* Return address in link */ + jmpi schedule + +ENTRY(sys_rt_sigreturn) + movi r11_sig, 0 + jmpi do_rt_sigreturn + +ENTRY(csky_trap) + SAVE_ALL EPC_KEEP + psrset ee + movi r11_sig, 0 /* r11 = 0, Not a syscall. */ + mov a0, sp /* Push Stack pointer arg */ + jbsr trap_c /* Call C-level trap handler */ + jmpi ret_from_exception + +/* + * Prototype from libc for abiv1: + * register unsigned int __result asm("a0"); + * asm( "trap 3" :"=r"(__result)::); + */ +ENTRY(csky_get_tls) + USPTOKSP + + /* increase epc for continue */ + mfcr a0, epc + INCTRAP a0 + mtcr a0, epc + + /* get current task thread_info with kernel 8K stack */ + bmaski a0, THREAD_SHIFT + not a0 + subi sp, 1 + and a0, sp + addi sp, 1 + + /* get tls */ + ldw a0, (a0, TINFO_TP_VALUE) + + KSPTOUSP + rte + +ENTRY(csky_irq) + SAVE_ALL EPC_KEEP + psrset ee + movi r11_sig, 0 /* r11 = 0, Not a syscall. */ + +#ifdef CONFIG_PREEMPT + mov r9, sp /* Get current stack pointer */ + bmaski r10, THREAD_SHIFT + andn r9, r10 /* Get thread_info */ + + /* + * Get task_struct->stack.preempt_count for current, + * and increase 1. + */ + ldw r8, (r9, TINFO_PREEMPT) + addi r8, 1 + stw r8, (r9, TINFO_PREEMPT) +#endif + + mov a0, sp + jbsr csky_do_IRQ + +#ifdef CONFIG_PREEMPT + subi r8, 1 + stw r8, (r9, TINFO_PREEMPT) + cmpnei r8, 0 + bt 2f + ldw r8, (r9, TINFO_FLAGS) + btsti r8, TIF_NEED_RESCHED + bf 2f +1: + jbsr preempt_schedule_irq /* irq en/disable is done inside */ + ldw r7, (r9, TINFO_FLAGS) /* get new tasks TI_FLAGS */ + btsti r7, TIF_NEED_RESCHED + bt 1b /* go again */ +#endif +2: + jmpi ret_from_exception + +/* + * a0 = prev task_struct * + * a1 = next task_struct * + * a0 = return next + */ +ENTRY(__switch_to) + lrw a3, TASK_THREAD + addu a3, a0 + + mfcr a2, psr /* Save PSR value */ + stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ + bclri a2, 6 /* Disable interrupts */ + mtcr a2, psr + + SAVE_SWITCH_STACK + + stw sp, (a3, THREAD_KSP) + +#ifdef CONFIG_CPU_HAS_HILO + lrw r10, THREAD_DSPHI + add r10, a3 + mfhi r6 + mflo r7 + stw r6, (r10, 0) /* THREAD_DSPHI */ + stw r7, (r10, 4) /* THREAD_DSPLO */ + mfcr r6, cr14 + stw r6, (r10, 8) /* THREAD_DSPCSR */ +#endif + + /* Set up next process to run */ + lrw a3, TASK_THREAD + addu a3, a1 + + ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ + +#ifdef CONFIG_CPU_HAS_HILO + lrw r10, THREAD_DSPHI + add r10, a3 + ldw r6, (r10, 8) /* THREAD_DSPCSR */ + mtcr r6, cr14 + ldw r6, (r10, 0) /* THREAD_DSPHI */ + ldw r7, (r10, 4) /* THREAD_DSPLO */ + mthi r6 + mtlo r7 +#endif + + ldw a2, (a3, THREAD_SR) /* Set next PSR */ + mtcr a2, psr + +#if defined(__CSKYABIV2__) + addi r7, a1, TASK_THREAD_INFO + ldw tls, (r7, TINFO_TP_VALUE) +#endif + + RESTORE_SWITCH_STACK + + rts +ENDPROC(__switch_to) diff --git a/arch/csky/kernel/head.S b/arch/csky/kernel/head.S new file mode 100644 index 000000000000..9c4ec473b76b --- /dev/null +++ b/arch/csky/kernel/head.S @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/page.h> +#include <abi/entry.h> + +__HEAD +ENTRY(_start) + /* set super user mode */ + lrw a3, DEFAULT_PSR_VALUE + mtcr a3, psr + psrset ee + + SETUP_MMU a3 + + /* set stack point */ + lrw a3, init_thread_union + THREAD_SIZE + mov sp, a3 + + jmpi csky_start +END(_start) + +#ifdef CONFIG_SMP +.align 10 +ENTRY(_start_smp_secondary) + /* Invalid I/Dcache BTB BHT */ + movi a3, 7 + lsli a3, 16 + addi a3, (1<<4) | 3 + mtcr a3, cr17 + + tlbi.alls + + /* setup PAGEMASK */ + movi a3, 0 + mtcr a3, cr<6, 15> + + /* setup MEL0/MEL1 */ + grs a0, _start_smp_pc +_start_smp_pc: + bmaski a1, 13 + andn a0, a1 + movi a1, 0x00000006 + movi a2, 0x00001006 + or a1, a0 + or a2, a0 + mtcr a1, cr<2, 15> + mtcr a2, cr<3, 15> + + /* setup MEH */ + mtcr a0, cr<4, 15> + + /* write TLB */ + bgeni a3, 28 + mtcr a3, cr<8, 15> + + SETUP_MMU a3 + + /* enable MMU */ + movi a3, 1 + mtcr a3, cr18 + + jmpi _goto_mmu_on +_goto_mmu_on: + lrw a3, DEFAULT_PSR_VALUE + mtcr a3, psr + psrset ee + + /* set stack point */ + lrw a3, secondary_stack + ld.w a3, (a3, 0) + mov sp, a3 + + jmpi csky_start_secondary +END(_start_smp_secondary) +#endif diff --git a/arch/csky/kernel/irq.c b/arch/csky/kernel/irq.c new file mode 100644 index 000000000000..03a1930f1cbb --- /dev/null +++ b/arch/csky/kernel/irq.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <asm/traps.h> +#include <asm/smp.h> + +void __init init_IRQ(void) +{ + irqchip_init(); +#ifdef CONFIG_SMP + setup_smp_ipi(); +#endif +} + +asmlinkage void __irq_entry csky_do_IRQ(struct pt_regs *regs) +{ + handle_arch_irq(regs); +} diff --git a/arch/csky/kernel/module.c b/arch/csky/kernel/module.c new file mode 100644 index 000000000000..65abab0c7a47 --- /dev/null +++ b/arch/csky/kernel/module.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/moduleloader.h> +#include <linux/elf.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <asm/pgtable.h> + +#if defined(__CSKYABIV2__) +#define IS_BSR32(hi16, lo16) (((hi16) & 0xFC00) == 0xE000) +#define IS_JSRI32(hi16, lo16) ((hi16) == 0xEAE0) + +#define CHANGE_JSRI_TO_LRW(addr) do { \ + *(uint16_t *)(addr) = (*(uint16_t *)(addr) & 0xFF9F) | 0x001a; \ + *((uint16_t *)(addr) + 1) = *((uint16_t *)(addr) + 1) & 0xFFFF; \ +} while (0) + +#define SET_JSR32_R26(addr) do { \ + *(uint16_t *)(addr) = 0xE8Fa; \ + *((uint16_t *)(addr) + 1) = 0x0000; \ +} while (0) +#endif + +int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *me) +{ + unsigned int i; + Elf32_Rela *rel = (void *) sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + short *temp; +#if defined(__CSKYABIV2__) + uint16_t *location_tmp; +#endif + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_CSKY_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_CSKY_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value + - (uint32_t)location; + break; + case R_CSKY_PCRELJSR_IMM11BY2: + break; + case R_CSKY_PCRELJSR_IMM26BY2: +#if defined(__CSKYABIV2__) + location_tmp = (uint16_t *)location; + if (IS_BSR32(*location_tmp, *(location_tmp + 1))) + break; + + if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) { + /* jsri 0x... --> lrw r26, 0x... */ + CHANGE_JSRI_TO_LRW(location); + /* lsli r0, r0 --> jsr r26 */ + SET_JSR32_R26(location + 1); + } +#endif + break; + case R_CSKY_ADDR_HI16: + temp = ((short *)location) + 1; + *temp = (short) + ((rel[i].r_addend + sym->st_value) >> 16); + break; + case R_CSKY_ADDR_LO16: + temp = ((short *)location) + 1; + *temp = (short) + ((rel[i].r_addend + sym->st_value) & 0xffff); + break; + default: + pr_err("module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} diff --git a/arch/csky/kernel/power.c b/arch/csky/kernel/power.c new file mode 100644 index 000000000000..923ee4e381b8 --- /dev/null +++ b/arch/csky/kernel/power.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/reboot.h> + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + +void machine_power_off(void) +{ + local_irq_disable(); + if (pm_power_off) + pm_power_off(); + asm volatile ("bkpt"); +} + +void machine_halt(void) +{ + local_irq_disable(); + if (pm_power_off) + pm_power_off(); + asm volatile ("bkpt"); +} + +void machine_restart(char *cmd) +{ + local_irq_disable(); + do_kernel_restart(cmd); + asm volatile ("bkpt"); +} diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c new file mode 100644 index 000000000000..8ed20028b160 --- /dev/null +++ b/arch/csky/kernel/process.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/module.h> +#include <linux/version.h> +#include <linux/sched.h> +#include <linux/sched/task_stack.h> +#include <linux/sched/debug.h> +#include <linux/delay.h> +#include <linux/kallsyms.h> +#include <linux/uaccess.h> +#include <linux/ptrace.h> + +#include <asm/elf.h> +#include <abi/reg_ops.h> + +struct cpuinfo_csky cpu_data[NR_CPUS]; + +asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); + +/* + * Some archs flush debug and FPU info here + */ +void flush_thread(void){} + +/* + * Return saved PC from a blocked thread + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; + + return sw->r15; +} + +int copy_thread(unsigned long clone_flags, + unsigned long usp, + unsigned long kthread_arg, + struct task_struct *p) +{ + struct switch_stack *childstack; + struct pt_regs *childregs = task_pt_regs(p); + +#ifdef CONFIG_CPU_HAS_FPU + save_to_user_fp(&p->thread.user_fp); +#endif + + childstack = ((struct switch_stack *) childregs) - 1; + memset(childstack, 0, sizeof(struct switch_stack)); + + /* setup ksp for switch_to !!! */ + p->thread.ksp = (unsigned long)childstack; + + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + childstack->r15 = (unsigned long) ret_from_kernel_thread; + childstack->r8 = kthread_arg; + childstack->r9 = usp; + childregs->sr = mfcr("psr"); + } else { + *childregs = *(current_pt_regs()); + if (usp) + childregs->usp = usp; + if (clone_flags & CLONE_SETTLS) + task_thread_info(p)->tp_value = childregs->tls + = childregs->regs[0]; + + childregs->a0 = 0; + childstack->r15 = (unsigned long) ret_from_fork; + } + + return 0; +} + +/* Fill in the fpu structure for a core dump. */ +int dump_fpu(struct pt_regs *regs, struct user_fp *fpu) +{ + memcpy(fpu, ¤t->thread.user_fp, sizeof(*fpu)); + return 1; +} +EXPORT_SYMBOL(dump_fpu); + +int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs) +{ + struct pt_regs *regs = task_pt_regs(tsk); + + /* NOTE: usp is error value. */ + ELF_CORE_COPY_REGS((*pr_regs), regs) + + return 1; +} + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long esp, pc; + unsigned long stack_page; + int count = 0; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = (unsigned long)p; + esp = p->thread.esp0; + do { + if (esp < stack_page+sizeof(struct task_struct) || + esp >= 8184+stack_page) + return 0; + /*FIXME: There's may be error here!*/ + pc = ((unsigned long *)esp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (!in_sched_functions(pc)) + return pc; + esp = *(unsigned long *) esp; + } while (count++ < 16); + return 0; +} +EXPORT_SYMBOL(get_wchan); + +#ifndef CONFIG_CPU_PM_NONE +void arch_cpu_idle(void) +{ +#ifdef CONFIG_CPU_PM_WAIT + asm volatile("wait\n"); +#endif + +#ifdef CONFIG_CPU_PM_DOZE + asm volatile("doze\n"); +#endif + +#ifdef CONFIG_CPU_PM_STOP + asm volatile("stop\n"); +#endif + local_irq_enable(); +} +#endif diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c new file mode 100644 index 000000000000..34b30257298f --- /dev/null +++ b/arch/csky/kernel/ptrace.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/elf.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/ptrace.h> +#include <linux/regset.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/smp.h> +#include <linux/uaccess.h> +#include <linux/user.h> + +#include <asm/thread_info.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/asm-offsets.h> + +#include <abi/regdef.h> + +/* sets the trace bits. */ +#define TRACE_MODE_SI (1 << 14) +#define TRACE_MODE_RUN 0 +#define TRACE_MODE_MASK ~(0x3 << 14) + +/* + * Make sure the single step bit is not set. + */ +static void singlestep_disable(struct task_struct *tsk) +{ + struct pt_regs *regs; + + regs = task_pt_regs(tsk); + regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_RUN; +} + +static void singlestep_enable(struct task_struct *tsk) +{ + struct pt_regs *regs; + + regs = task_pt_regs(tsk); + regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_SI; +} + +/* + * Make sure the single step bit is set. + */ +void user_enable_single_step(struct task_struct *child) +{ + if (child->thread.esp0 == 0) + return; + singlestep_enable(child); +} + +void user_disable_single_step(struct task_struct *child) +{ + if (child->thread.esp0 == 0) + return; + singlestep_disable(child); +} + +enum csky_regset { + REGSET_GPR, + REGSET_FPR, +}; + +static int gpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + struct pt_regs *regs; + + regs = task_pt_regs(target); + + /* Abiv1 regs->tls is fake and we need sync here. */ + regs->tls = task_thread_info(target)->tp_value; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1); +} + +static int gpr_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 pt_regs regs; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s, 0, -1); + if (ret) + return ret; + + regs.sr = task_pt_regs(target)->sr; + + task_thread_info(target)->tp_value = regs.tls; + + *task_pt_regs(target) = regs; + + return 0; +} + +static int fpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + struct user_fp *regs = (struct user_fp *)&target->thread.user_fp; + +#if defined(CONFIG_CPU_HAS_FPUV2) && !defined(CONFIG_CPU_HAS_VDSP) + int i; + struct user_fp tmp = *regs; + + for (i = 0; i < 16; i++) { + tmp.vr[i*4] = regs->vr[i*2]; + tmp.vr[i*4 + 1] = regs->vr[i*2 + 1]; + } + + for (i = 0; i < 32; i++) + tmp.vr[64 + i] = regs->vr[32 + i]; + + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tmp, 0, -1); +#else + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1); +#endif +} + +static int fpr_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_fp *regs = (struct user_fp *)&target->thread.user_fp; + +#if defined(CONFIG_CPU_HAS_FPUV2) && !defined(CONFIG_CPU_HAS_VDSP) + int i; + struct user_fp tmp; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tmp, 0, -1); + + *regs = tmp; + + for (i = 0; i < 16; i++) { + regs->vr[i*2] = tmp.vr[i*4]; + regs->vr[i*2 + 1] = tmp.vr[i*4 + 1]; + } + + for (i = 0; i < 32; i++) + regs->vr[32 + i] = tmp.vr[64 + i]; +#else + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1); +#endif + + return ret; +} + +static const struct user_regset csky_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(u32), + .align = sizeof(u32), + .get = &gpr_get, + .set = &gpr_set, + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_fp) / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + .get = &fpr_get, + .set = &fpr_set, + }, +}; + +static const struct user_regset_view user_csky_view = { + .name = "csky", + .e_machine = ELF_ARCH, + .regsets = csky_regsets, + .n = ARRAY_SIZE(csky_regsets), +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_csky_view; +} + +void ptrace_disable(struct task_struct *child) +{ + singlestep_disable(child); +} + +long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) +{ + long ret = -EIO; + + switch (request) { + default: + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; +} + +/* + * If process's system calls is traces, do some corresponding handles in this + * function before entering system call function and after exiting system call + * function. + */ +asmlinkage void syscall_trace(int why, struct pt_regs *regs) +{ + long saved_why; + /* + * Save saved_why, why is used to denote syscall entry/exit; + * why = 0:entry, why = 1: exit + */ + saved_why = regs->regs[SYSTRACE_SAVENUM]; + regs->regs[SYSTRACE_SAVENUM] = why; + + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); + + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } + + regs->regs[SYSTRACE_SAVENUM] = saved_why; +} + +void show_regs(struct pt_regs *fp) +{ + unsigned long *sp; + unsigned char *tp; + int i; + + pr_info("\nCURRENT PROCESS:\n\n"); + pr_info("COMM=%s PID=%d\n", current->comm, current->pid); + + if (current->mm) { + pr_info("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", + (int) current->mm->start_code, + (int) current->mm->end_code, + (int) current->mm->start_data, + (int) current->mm->end_data, + (int) current->mm->end_data, + (int) current->mm->brk); + pr_info("USER-STACK=%08x KERNEL-STACK=%08x\n\n", + (int) current->mm->start_stack, + (int) (((unsigned long) current) + 2 * PAGE_SIZE)); + } + + pr_info("PC: 0x%08lx\n", (long)fp->pc); + pr_info("orig_a0: 0x%08lx\n", fp->orig_a0); + pr_info("PSR: 0x%08lx\n", (long)fp->sr); + + pr_info("a0: 0x%08lx a1: 0x%08lx a2: 0x%08lx a3: 0x%08lx\n", + fp->a0, fp->a1, fp->a2, fp->a3); +#if defined(__CSKYABIV2__) + pr_info("r4: 0x%08lx r5: 0x%08lx r6: 0x%08lx r7: 0x%08lx\n", + fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]); + pr_info("r8: 0x%08lx r9: 0x%08lx r10: 0x%08lx r11: 0x%08lx\n", + fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]); + pr_info("r12 0x%08lx r13: 0x%08lx r15: 0x%08lx\n", + fp->regs[8], fp->regs[9], fp->lr); + pr_info("r16:0x%08lx r17: 0x%08lx r18: 0x%08lx r19: 0x%08lx\n", + fp->exregs[0], fp->exregs[1], fp->exregs[2], fp->exregs[3]); + pr_info("r20 0x%08lx r21: 0x%08lx r22: 0x%08lx r23: 0x%08lx\n", + fp->exregs[4], fp->exregs[5], fp->exregs[6], fp->exregs[7]); + pr_info("r24 0x%08lx r25: 0x%08lx r26: 0x%08lx r27: 0x%08lx\n", + fp->exregs[8], fp->exregs[9], fp->exregs[10], fp->exregs[11]); + pr_info("r28 0x%08lx r29: 0x%08lx r30: 0x%08lx tls: 0x%08lx\n", + fp->exregs[12], fp->exregs[13], fp->exregs[14], fp->tls); + pr_info("hi 0x%08lx lo: 0x%08lx\n", + fp->rhi, fp->rlo); +#else + pr_info("r6: 0x%08lx r7: 0x%08lx r8: 0x%08lx r9: 0x%08lx\n", + fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]); + pr_info("r10: 0x%08lx r11: 0x%08lx r12: 0x%08lx r13: 0x%08lx\n", + fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]); + pr_info("r14 0x%08lx r1: 0x%08lx r15: 0x%08lx\n", + fp->regs[8], fp->regs[9], fp->lr); +#endif + + pr_info("\nCODE:"); + tp = ((unsigned char *) fp->pc) - 0x20; + tp += ((int)tp % 4) ? 2 : 0; + for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { + if ((i % 0x10) == 0) + pr_cont("\n%08x: ", (int) (tp + i)); + pr_cont("%08x ", (int) *sp++); + } + pr_cont("\n"); + + pr_info("\nKERNEL STACK:"); + tp = ((unsigned char *) fp) - 0x40; + for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { + if ((i % 0x10) == 0) + pr_cont("\n%08x: ", (int) (tp + i)); + pr_cont("%08x ", (int) *sp++); + } + pr_cont("\n"); +} diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c new file mode 100644 index 000000000000..a5e3ab1d5360 --- /dev/null +++ b/arch/csky/kernel/setup.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/console.h> +#include <linux/memblock.h> +#include <linux/bootmem.h> +#include <linux/initrd.h> +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/start_kernel.h> +#include <linux/dma-contiguous.h> +#include <linux/screen_info.h> +#include <asm/sections.h> +#include <asm/mmu_context.h> +#include <asm/pgalloc.h> + +#ifdef CONFIG_DUMMY_CONSOLE +struct screen_info screen_info = { + .orig_video_lines = 30, + .orig_video_cols = 80, + .orig_video_mode = 0, + .orig_video_ega_bx = 0, + .orig_video_isVGA = 1, + .orig_video_points = 8 +}; +#endif + +phys_addr_t __init_memblock memblock_end_of_REG0(void) +{ + return (memblock.memory.regions[0].base + + memblock.memory.regions[0].size); +} + +phys_addr_t __init_memblock memblock_start_of_REG1(void) +{ + return memblock.memory.regions[1].base; +} + +size_t __init_memblock memblock_size_of_REG1(void) +{ + return memblock.memory.regions[1].size; +} + +static void __init csky_memblock_init(void) +{ + unsigned long zone_size[MAX_NR_ZONES]; + unsigned long zhole_size[MAX_NR_ZONES]; + signed long size; + + memblock_reserve(__pa(_stext), _end - _stext); +#ifdef CONFIG_BLK_DEV_INITRD + memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); +#endif + + early_init_fdt_reserve_self(); + early_init_fdt_scan_reserved_mem(); + + memblock_dump_all(); + + memset(zone_size, 0, sizeof(zone_size)); + memset(zhole_size, 0, sizeof(zhole_size)); + + min_low_pfn = PFN_UP(memblock_start_of_DRAM()); + max_pfn = PFN_DOWN(memblock_end_of_DRAM()); + + max_low_pfn = PFN_UP(memblock_end_of_REG0()); + if (max_low_pfn == 0) + max_low_pfn = max_pfn; + + size = max_pfn - min_low_pfn; + + if (memblock.memory.cnt > 1) { + zone_size[ZONE_NORMAL] = + PFN_DOWN(memblock_start_of_REG1()) - min_low_pfn; + zhole_size[ZONE_NORMAL] = + PFN_DOWN(memblock_start_of_REG1()) - max_low_pfn; + } else { + if (size <= PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET)) + zone_size[ZONE_NORMAL] = max_pfn - min_low_pfn; + else { + zone_size[ZONE_NORMAL] = + PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); + max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL]; + } + } + +#ifdef CONFIG_HIGHMEM + size = 0; + if (memblock.memory.cnt > 1) { + size = PFN_DOWN(memblock_size_of_REG1()); + highstart_pfn = PFN_DOWN(memblock_start_of_REG1()); + } else { + size = max_pfn - min_low_pfn - + PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); + highstart_pfn = min_low_pfn + + PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); + } + + if (size > 0) + zone_size[ZONE_HIGHMEM] = size; + + highend_pfn = max_pfn; +#endif + memblock_set_current_limit(PFN_PHYS(max_low_pfn)); + + dma_contiguous_reserve(0); + + free_area_init_node(0, zone_size, min_low_pfn, zhole_size); +} + +void __init setup_arch(char **cmdline_p) +{ + *cmdline_p = boot_command_line; + + console_verbose(); + + pr_info("Phys. mem: %ldMB\n", + (unsigned long) memblock_phys_mem_size()/1024/1024); + + init_mm.start_code = (unsigned long) _stext; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; + + parse_early_param(); + + csky_memblock_init(); + + unflatten_and_copy_device_tree(); + +#ifdef CONFIG_SMP + setup_smp(); +#endif + + sparse_init(); + +#ifdef CONFIG_HIGHMEM + kmap_init(); +#endif + +#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +} + +asmlinkage __visible void __init csky_start(unsigned int unused, void *param) +{ + /* Clean up bss section */ + memset(__bss_start, 0, __bss_stop - __bss_start); + + pre_trap_init(); + pre_mmu_init(); + + if (param == NULL) + early_init_dt_scan(__dtb_start); + else + early_init_dt_scan(param); + + start_kernel(); + + asm volatile("br .\n"); +} diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c new file mode 100644 index 000000000000..66e1b729b10b --- /dev/null +++ b/arch/csky/kernel/signal.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/syscalls.h> +#include <linux/errno.h> +#include <linux/wait.h> +#include <linux/ptrace.h> +#include <linux/unistd.h> +#include <linux/stddef.h> +#include <linux/highuid.h> +#include <linux/personality.h> +#include <linux/tty.h> +#include <linux/binfmts.h> +#include <linux/tracehook.h> +#include <linux/freezer.h> +#include <linux/uaccess.h> + +#include <asm/setup.h> +#include <asm/pgtable.h> +#include <asm/traps.h> +#include <asm/ucontext.h> +#include <asm/vdso.h> + +#include <abi/regdef.h> + +#ifdef CONFIG_CPU_HAS_FPU +#include <abi/fpu.h> + +static int restore_fpu_state(struct sigcontext *sc) +{ + int err = 0; + struct user_fp user_fp; + + err = copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp)); + + restore_from_user_fp(&user_fp); + + return err; +} + +static int save_fpu_state(struct sigcontext *sc) +{ + struct user_fp user_fp; + + save_to_user_fp(&user_fp); + + return copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp)); +} +#else +static inline int restore_fpu_state(struct sigcontext *sc) { return 0; } +static inline int save_fpu_state(struct sigcontext *sc) { return 0; } +#endif + +struct rt_sigframe { + int sig; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; +}; + +static int +restore_sigframe(struct pt_regs *regs, + struct sigcontext *sc, int *pr2) +{ + int err = 0; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->task->restart_block.fn = do_no_restart_syscall; + + err |= copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs)); + + err |= restore_fpu_state(sc); + + *pr2 = regs->a0; + return err; +} + +asmlinkage int +do_rt_sigreturn(void) +{ + sigset_t set; + int a0; + struct pt_regs *regs = current_pt_regs(); + struct rt_sigframe *frame = (struct rt_sigframe *)(regs->usp); + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, (sigmask(SIGKILL) | sigmask(SIGSTOP))); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if (restore_sigframe(regs, &frame->uc.uc_mcontext, &a0)) + goto badframe; + + return a0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +static int setup_sigframe(struct sigcontext *sc, struct pt_regs *regs) +{ + int err = 0; + + err |= copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs)); + err |= save_fpu_state(sc); + + return err; +} + +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + unsigned long usp; + + /* Default to using normal stack. */ + usp = regs->usp; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(usp)) { + if (!on_sig_stack(usp)) + usp = current->sas_ss_sp + current->sas_ss_size; + } + return (void *)((usp - frame_size) & -8UL); +} + +static int +setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe *frame; + int err = 0; + + struct csky_vdso *vdso = current->mm->context.vdso; + + frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); + if (!frame) + return 1; + + err |= __put_user(ksig->sig, &frame->sig); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, &ksig->info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->usp), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigframe(&frame->uc.uc_mcontext, regs); + err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->usp = (unsigned long)frame; + regs->pc = (unsigned long)ksig->ka.sa.sa_handler; + regs->lr = (unsigned long)vdso->rt_signal_retcode; + +adjust_stack: + regs->a0 = ksig->sig; /* first arg is signo */ + regs->a1 = (unsigned long)(&(frame->info)); + regs->a2 = (unsigned long)(&(frame->uc)); + return err; + +give_sigsegv: + if (ksig->sig == SIGSEGV) + ksig->ka.sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); + goto adjust_stack; +} + +/* + * OK, we're invoking a handler + */ +static int +handle_signal(struct ksignal *ksig, struct pt_regs *regs) +{ + int ret; + sigset_t *oldset = sigmask_to_save(); + + /* + * set up the stack frame, regardless of SA_SIGINFO, + * and pass info anyway. + */ + ret = setup_rt_frame(ksig, oldset, regs); + + if (ret != 0) { + force_sigsegv(ksig->sig, current); + return ret; + } + + /* Block the signal if we were successful. */ + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, &ksig->ka.sa.sa_mask); + if (!(ksig->ka.sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, ksig->sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + return 0; +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals + * that the kernel can handle, and then we build all the user-level signal + * handling stack-frames in one go after that. + */ +static void do_signal(struct pt_regs *regs, int syscall) +{ + unsigned int retval = 0, continue_addr = 0, restart_addr = 0; + struct ksignal ksig; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return; + + current->thread.esp0 = (unsigned long)regs; + + /* + * If we were from a system call, check for system call restarting... + */ + if (syscall) { + continue_addr = regs->pc; +#if defined(__CSKYABIV2__) + restart_addr = continue_addr - 4; +#else + restart_addr = continue_addr - 2; +#endif + retval = regs->a0; + + /* + * Prepare for system call restart. We do this here so that a + * debugger will see the already changed. + */ + switch (retval) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + regs->a0 = regs->orig_a0; + regs->pc = restart_addr; + break; + case -ERESTART_RESTARTBLOCK: + regs->a0 = -EINTR; + break; + } + } + + if (try_to_freeze()) + goto no_signal; + + /* + * Get the signal to deliver. When running under ptrace, at this + * point the debugger may change all our registers ... + */ + if (get_signal(&ksig)) { + /* + * Depending on the signal settings we may need to revert the + * decision to restart the system call. But skip this if a + * debugger has chosen to restart at a different PC. + */ + if (regs->pc == restart_addr) { + if (retval == -ERESTARTNOHAND || + (retval == -ERESTARTSYS && + !(ksig.ka.sa.sa_flags & SA_RESTART))) { + regs->a0 = -EINTR; + regs->pc = continue_addr; + } + } + + /* Whee! Actually deliver the signal. */ + if (handle_signal(&ksig, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; + } + +no_signal: + if (syscall) { + /* + * Handle restarting a different system call. As above, + * if a debugger has chosen to restart at a different PC, + * ignore the restart. + */ + if (retval == -ERESTART_RESTARTBLOCK + && regs->pc == continue_addr) { +#if defined(__CSKYABIV2__) + regs->regs[3] = __NR_restart_syscall; + regs->pc -= 4; +#else + regs->regs[9] = __NR_restart_syscall; + regs->pc -= 2; +#endif + } + + /* + * If there's no signal to deliver, we just put the saved + * sigmask back. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + } +} + +asmlinkage void +do_notify_resume(unsigned int thread_flags, struct pt_regs *regs, int syscall) +{ + if (thread_flags & _TIF_SIGPENDING) + do_signal(regs, syscall); + + if (thread_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } +} diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c new file mode 100644 index 000000000000..36ebaf9834e1 --- /dev/null +++ b/arch/csky/kernel/smp.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/notifier.h> +#include <linux/cpu.h> +#include <linux/percpu.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/sched/task_stack.h> +#include <linux/sched/mm.h> +#include <asm/irq.h> +#include <asm/traps.h> +#include <asm/sections.h> +#include <asm/mmu_context.h> +#include <asm/pgalloc.h> + +struct ipi_data_struct { + unsigned long bits ____cacheline_aligned; +}; +static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data); + +enum ipi_message_type { + IPI_EMPTY, + IPI_RESCHEDULE, + IPI_CALL_FUNC, + IPI_MAX +}; + +static irqreturn_t handle_ipi(int irq, void *dev) +{ + while (true) { + unsigned long ops; + + ops = xchg(&this_cpu_ptr(&ipi_data)->bits, 0); + if (ops == 0) + return IRQ_HANDLED; + + if (ops & (1 << IPI_RESCHEDULE)) + scheduler_ipi(); + + if (ops & (1 << IPI_CALL_FUNC)) + generic_smp_call_function_interrupt(); + + BUG_ON((ops >> IPI_MAX) != 0); + } + + return IRQ_HANDLED; +} + +static void (*send_arch_ipi)(const struct cpumask *mask); + +static int ipi_irq; +void __init set_send_ipi(void (*func)(const struct cpumask *mask), int irq) +{ + if (send_arch_ipi) + return; + + send_arch_ipi = func; + ipi_irq = irq; +} + +static void +send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) +{ + int i; + + for_each_cpu(i, to_whom) + set_bit(operation, &per_cpu_ptr(&ipi_data, i)->bits); + + smp_mb(); + send_arch_ipi(to_whom); +} + +void arch_send_call_function_ipi_mask(struct cpumask *mask) +{ + send_ipi_message(mask, IPI_CALL_FUNC); +} + +void arch_send_call_function_single_ipi(int cpu) +{ + send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC); +} + +static void ipi_stop(void *unused) +{ + while (1); +} + +void smp_send_stop(void) +{ + on_each_cpu(ipi_stop, NULL, 1); +} + +void smp_send_reschedule(int cpu) +{ + send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); +} + +void __init smp_prepare_boot_cpu(void) +{ +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ +} + +static void __init enable_smp_ipi(void) +{ + enable_percpu_irq(ipi_irq, 0); +} + +static int ipi_dummy_dev; +void __init setup_smp_ipi(void) +{ + int rc; + + if (ipi_irq == 0) + panic("%s IRQ mapping failed\n", __func__); + + rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", + &ipi_dummy_dev); + if (rc) + panic("%s IRQ request failed\n", __func__); + + enable_smp_ipi(); +} + +void __init setup_smp(void) +{ + struct device_node *node = NULL; + int cpu; + + while ((node = of_find_node_by_type(node, "cpu"))) { + if (!of_device_is_available(node)) + continue; + + if (of_property_read_u32(node, "reg", &cpu)) + continue; + + if (cpu >= NR_CPUS) + continue; + + set_cpu_possible(cpu, true); + set_cpu_present(cpu, true); + } +} + +extern void _start_smp_secondary(void); + +volatile unsigned int secondary_hint; +volatile unsigned int secondary_ccr; +volatile unsigned int secondary_stack; + +int __cpu_up(unsigned int cpu, struct task_struct *tidle) +{ + unsigned int tmp; + + secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE; + + secondary_hint = mfcr("cr31"); + + secondary_ccr = mfcr("cr18"); + + /* + * Because other CPUs are in reset status, we must flush data + * from cache to out and secondary CPUs use them in + * csky_start_secondary(void) + */ + mtcr("cr17", 0x22); + + /* Enable cpu in SMP reset ctrl reg */ + tmp = mfcr("cr<29, 0>"); + tmp |= 1 << cpu; + mtcr("cr<29, 0>", tmp); + + /* Wait for the cpu online */ + while (!cpu_online(cpu)); + + secondary_stack = 0; + + return 0; +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ +} + +int setup_profiling_timer(unsigned int multiplier) +{ + return -EINVAL; +} + +void csky_start_secondary(void) +{ + struct mm_struct *mm = &init_mm; + unsigned int cpu = smp_processor_id(); + + mtcr("cr31", secondary_hint); + mtcr("cr18", secondary_ccr); + + mtcr("vbr", vec_base); + + flush_tlb_all(); + write_mmu_pagemask(0); + TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); + TLBMISS_HANDLER_SETUP_PGD_KERNEL(swapper_pg_dir); + + asid_cache(smp_processor_id()) = ASID_FIRST_VERSION; + +#ifdef CONFIG_CPU_HAS_FPU + init_fpu(); +#endif + + enable_smp_ipi(); + + mmget(mm); + mmgrab(mm); + current->active_mm = mm; + cpumask_set_cpu(cpu, mm_cpumask(mm)); + + notify_cpu_starting(cpu); + set_cpu_online(cpu, true); + + pr_info("CPU%u Online: %s...\n", cpu, __func__); + + local_irq_enable(); + preempt_disable(); + cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); +} diff --git a/arch/csky/kernel/syscall.c b/arch/csky/kernel/syscall.c new file mode 100644 index 000000000000..3d30e58a45d2 --- /dev/null +++ b/arch/csky/kernel/syscall.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/syscalls.h> + +SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) +{ + struct thread_info *ti = task_thread_info(current); + struct pt_regs *reg = current_pt_regs(); + + reg->tls = addr; + ti->tp_value = addr; + + return 0; +} + +SYSCALL_DEFINE6(mmap2, + unsigned long, addr, + unsigned long, len, + unsigned long, prot, + unsigned long, flags, + unsigned long, fd, + off_t, offset) +{ + if (unlikely(offset & (~PAGE_MASK >> 12))) + return -EINVAL; + + return ksys_mmap_pgoff(addr, len, prot, flags, fd, + offset >> (PAGE_SHIFT - 12)); +} + +/* + * for abiv1 the 64bits args should be even th, So we need mov the advice + * forward. + */ +SYSCALL_DEFINE4(csky_fadvise64_64, + int, fd, + int, advice, + loff_t, offset, + loff_t, len) +{ + return ksys_fadvise64_64(fd, offset, len, advice); +} diff --git a/arch/csky/kernel/syscall_table.c b/arch/csky/kernel/syscall_table.c new file mode 100644 index 000000000000..a0c238c5377a --- /dev/null +++ b/arch/csky/kernel/syscall_table.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/syscalls.h> +#include <asm/syscalls.h> + +#undef __SYSCALL +#define __SYSCALL(nr, call)[nr] = (call), + +#define sys_fadvise64_64 sys_csky_fadvise64_64 +void * const sys_call_table[__NR_syscalls] __page_aligned_data = { + [0 ... __NR_syscalls - 1] = sys_ni_syscall, +#include <asm/unistd.h> +}; diff --git a/arch/csky/kernel/time.c b/arch/csky/kernel/time.c new file mode 100644 index 000000000000..b5fc9447d93f --- /dev/null +++ b/arch/csky/kernel/time.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/clk-provider.h> +#include <linux/clocksource.h> + +void __init time_init(void) +{ + of_clk_init(NULL); + timer_probe(); +} diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c new file mode 100644 index 000000000000..a8368ed43517 --- /dev/null +++ b/arch/csky/kernel/traps.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/user.h> +#include <linux/string.h> +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/ptrace.h> +#include <linux/kallsyms.h> +#include <linux/rtc.h> +#include <linux/uaccess.h> + +#include <asm/setup.h> +#include <asm/traps.h> +#include <asm/pgalloc.h> +#include <asm/siginfo.h> + +#include <asm/mmu_context.h> + +#ifdef CONFIG_CPU_HAS_FPU +#include <abi/fpu.h> +#endif + +/* Defined in entry.S */ +asmlinkage void csky_trap(void); + +asmlinkage void csky_systemcall(void); +asmlinkage void csky_cmpxchg(void); +asmlinkage void csky_get_tls(void); +asmlinkage void csky_irq(void); + +asmlinkage void csky_tlbinvalidl(void); +asmlinkage void csky_tlbinvalids(void); +asmlinkage void csky_tlbmodified(void); + +/* Defined in head.S */ +asmlinkage void _start_smp_secondary(void); + +void __init pre_trap_init(void) +{ + int i; + + mtcr("vbr", vec_base); + + for (i = 1; i < 128; i++) + VEC_INIT(i, csky_trap); +} + +void __init trap_init(void) +{ + VEC_INIT(VEC_AUTOVEC, csky_irq); + + /* setup trap0 trap2 trap3 */ + VEC_INIT(VEC_TRAP0, csky_systemcall); + VEC_INIT(VEC_TRAP2, csky_cmpxchg); + VEC_INIT(VEC_TRAP3, csky_get_tls); + + /* setup MMU TLB exception */ + VEC_INIT(VEC_TLBINVALIDL, csky_tlbinvalidl); + VEC_INIT(VEC_TLBINVALIDS, csky_tlbinvalids); + VEC_INIT(VEC_TLBMODIFIED, csky_tlbmodified); + +#ifdef CONFIG_CPU_HAS_FPU + init_fpu(); +#endif + +#ifdef CONFIG_SMP + mtcr("cr<28, 0>", virt_to_phys(vec_base)); + + VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary)); +#endif +} + +void die_if_kernel(char *str, struct pt_regs *regs, int nr) +{ + if (user_mode(regs)) + return; + + console_verbose(); + pr_err("%s: %08x\n", str, nr); + show_regs(regs); + add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); + do_exit(SIGSEGV); +} + +void buserr(struct pt_regs *regs) +{ +#ifdef CONFIG_CPU_CK810 + static unsigned long prev_pc; + + if ((regs->pc == prev_pc) && prev_pc != 0) { + prev_pc = 0; + } else { + prev_pc = regs->pc; + return; + } +#endif + + die_if_kernel("Kernel mode BUS error", regs, 0); + + pr_err("User mode Bus Error\n"); + show_regs(regs); + + current->thread.esp0 = (unsigned long) regs; + force_sig_fault(SIGSEGV, 0, (void __user *)regs->pc, current); +} + +#define USR_BKPT 0x1464 +asmlinkage void trap_c(struct pt_regs *regs) +{ + int sig; + unsigned long vector; + siginfo_t info; + + vector = (mfcr("psr") >> 16) & 0xff; + + switch (vector) { + case VEC_ZERODIV: + sig = SIGFPE; + break; + /* ptrace */ + case VEC_TRACE: + info.si_code = TRAP_TRACE; + sig = SIGTRAP; + break; + case VEC_ILLEGAL: +#ifndef CONFIG_CPU_NO_USER_BKPT + if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) +#endif + { + sig = SIGILL; + break; + } + /* gdbserver breakpoint */ + case VEC_TRAP1: + /* jtagserver breakpoint */ + case VEC_BREAKPOINT: + info.si_code = TRAP_BRKPT; + sig = SIGTRAP; + break; + case VEC_ACCESS: + return buserr(regs); +#ifdef CONFIG_CPU_NEED_SOFTALIGN + case VEC_ALIGN: + return csky_alignment(regs); +#endif +#ifdef CONFIG_CPU_HAS_FPU + case VEC_FPE: + return fpu_fpe(regs); + case VEC_PRIV: + if (fpu_libc_helper(regs)) + return; +#endif + default: + sig = SIGSEGV; + break; + } + send_sig(sig, current, 0); +} + +asmlinkage void set_esp0(unsigned long ssp) +{ + current->thread.esp0 = ssp; +} diff --git a/arch/csky/kernel/vdso.c b/arch/csky/kernel/vdso.c new file mode 100644 index 000000000000..60ff7adfad1d --- /dev/null +++ b/arch/csky/kernel/vdso.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/binfmts.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/unistd.h> +#include <linux/uaccess.h> + +#include <asm/vdso.h> +#include <asm/cacheflush.h> + +static struct page *vdso_page; + +static int __init init_vdso(void) +{ + struct csky_vdso *vdso; + int err = 0; + + vdso_page = alloc_page(GFP_KERNEL); + if (!vdso_page) + panic("Cannot allocate vdso"); + + vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL); + if (!vdso) + panic("Cannot map vdso"); + + clear_page(vdso); + + err = setup_vdso_page(vdso->rt_signal_retcode); + if (err) + panic("Cannot set signal return code, err: %x.", err); + + dcache_wb_range((unsigned long)vdso, (unsigned long)vdso + 16); + + vunmap(vdso); + + return 0; +} +subsys_initcall(init_vdso); + +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) +{ + int ret; + unsigned long addr; + struct mm_struct *mm = current->mm; + + down_write(&mm->mmap_sem); + + addr = get_unmapped_area(NULL, STACK_TOP, PAGE_SIZE, 0, 0); + if (IS_ERR_VALUE(addr)) { + ret = addr; + goto up_fail; + } + + ret = install_special_mapping( + mm, + addr, + PAGE_SIZE, + VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, + &vdso_page); + if (ret) + goto up_fail; + + mm->context.vdso = (void *)addr; + +up_fail: + up_write(&mm->mmap_sem); + return ret; +} + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_mm == NULL) + return NULL; + + if (vma->vm_start == (long)vma->vm_mm->context.vdso) + return "[vdso]"; + else + return NULL; +} diff --git a/arch/csky/kernel/vmlinux.lds.S b/arch/csky/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..ae7961b973f2 --- /dev/null +++ b/arch/csky/kernel/vmlinux.lds.S @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <asm/vmlinux.lds.h> +#include <asm/page.h> + +OUTPUT_ARCH(csky) +ENTRY(_start) + +#ifndef __cskyBE__ +jiffies = jiffies_64; +#else +jiffies = jiffies_64 + 4; +#endif + +#define VBR_BASE \ + . = ALIGN(1024); \ + vec_base = .; \ + . += 512; + +SECTIONS +{ + . = PAGE_OFFSET + PHYS_OFFSET_OFFSET; + + _stext = .; + __init_begin = .; + HEAD_TEXT_SECTION + INIT_TEXT_SECTION(PAGE_SIZE) + INIT_DATA_SECTION(PAGE_SIZE) + PERCPU_SECTION(L1_CACHE_BYTES) + . = ALIGN(PAGE_SIZE); + __init_end = .; + + .text : AT(ADDR(.text) - LOAD_OFFSET) { + _text = .; + IRQENTRY_TEXT + SOFTIRQENTRY_TEXT + TEXT_TEXT + SCHED_TEXT + CPUIDLE_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) + *(.gnu.warning) + } = 0 + _etext = .; + + /* __init_begin __init_end must be page aligned for free_initmem */ + . = ALIGN(PAGE_SIZE); + + + _sdata = .; + RO_DATA_SECTION(PAGE_SIZE) + RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) + _edata = .; + + NOTES + EXCEPTION_TABLE(L1_CACHE_BYTES) + BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES) + VBR_BASE + _end = . ; + + STABS_DEBUG + DWARF_DEBUG + + DISCARDS +} diff --git a/arch/csky/lib/Makefile b/arch/csky/lib/Makefile new file mode 100644 index 000000000000..d1f368c59ef6 --- /dev/null +++ b/arch/csky/lib/Makefile @@ -0,0 +1 @@ +lib-y := usercopy.o delay.o diff --git a/arch/csky/lib/delay.c b/arch/csky/lib/delay.c new file mode 100644 index 000000000000..22570b0790d6 --- /dev/null +++ b/arch/csky/lib/delay.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/delay.h> + +void __delay(unsigned long loops) +{ + asm volatile ( + "mov r0, r0\n" + "1:declt %0\n" + "bf 1b" + : "=r"(loops) + : "0"(loops)); +} +EXPORT_SYMBOL(__delay); + +void __const_udelay(unsigned long xloops) +{ + unsigned long long loops; + + loops = (unsigned long long)xloops * loops_per_jiffy * HZ; + + __delay(loops >> 32); +} +EXPORT_SYMBOL(__const_udelay); + +void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */ +} +EXPORT_SYMBOL(__udelay); + +void __ndelay(unsigned long nsecs) +{ + __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */ +} +EXPORT_SYMBOL(__ndelay); diff --git a/arch/csky/lib/usercopy.c b/arch/csky/lib/usercopy.c new file mode 100644 index 000000000000..ac9170e2cbb8 --- /dev/null +++ b/arch/csky/lib/usercopy.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/uaccess.h> +#include <linux/types.h> + +unsigned long raw_copy_from_user(void *to, const void *from, + unsigned long n) +{ + if (access_ok(VERIFY_READ, from, n)) + __copy_user_zeroing(to, from, n); + else + memset(to, 0, n); + return n; +} +EXPORT_SYMBOL(raw_copy_from_user); + +unsigned long raw_copy_to_user(void *to, const void *from, + unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + __copy_user(to, from, n); + return n; +} +EXPORT_SYMBOL(raw_copy_to_user); + + +/* + * copy a null terminated string from userspace. + */ +#define __do_strncpy_from_user(dst, src, count, res) \ +do { \ + int tmp; \ + long faultres; \ + asm volatile( \ + " cmpnei %3, 0 \n" \ + " bf 4f \n" \ + "1: cmpnei %1, 0 \n" \ + " bf 5f \n" \ + "2: ldb %4, (%3, 0) \n" \ + " stb %4, (%2, 0) \n" \ + " cmpnei %4, 0 \n" \ + " bf 3f \n" \ + " addi %3, 1 \n" \ + " addi %2, 1 \n" \ + " subi %1, 1 \n" \ + " br 1b \n" \ + "3: subu %0, %1 \n" \ + " br 5f \n" \ + "4: mov %0, %5 \n" \ + " br 5f \n" \ + ".section __ex_table, \"a\" \n" \ + ".align 2 \n" \ + ".long 2b, 4b \n" \ + ".previous \n" \ + "5: \n" \ + : "=r"(res), "=r"(count), "=r"(dst), \ + "=r"(src), "=r"(tmp), "=r"(faultres) \ + : "5"(-EFAULT), "0"(count), "1"(count), \ + "2"(dst), "3"(src) \ + : "memory", "cc"); \ +} while (0) + +/* + * __strncpy_from_user: - Copy a NUL terminated string from userspace, + * with less checking. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * Caller must check the specified block with access_ok() before calling + * this function. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +long __strncpy_from_user(char *dst, const char *src, long count) +{ + long res; + + __do_strncpy_from_user(dst, src, count, res); + return res; +} +EXPORT_SYMBOL(__strncpy_from_user); + +/* + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +long strncpy_from_user(char *dst, const char *src, long count) +{ + long res = -EFAULT; + + if (access_ok(VERIFY_READ, src, 1)) + __do_strncpy_from_user(dst, src, count, res); + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * @n: The maximum valid length + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ +long strnlen_user(const char *s, long n) +{ + unsigned long res, tmp; + + if (s == NULL) + return 0; + + asm volatile( + " cmpnei %1, 0 \n" + " bf 3f \n" + "1: cmpnei %0, 0 \n" + " bf 3f \n" + "2: ldb %3, (%1, 0) \n" + " cmpnei %3, 0 \n" + " bf 3f \n" + " subi %0, 1 \n" + " addi %1, 1 \n" + " br 1b \n" + "3: subu %2, %0 \n" + " addi %2, 1 \n" + " br 5f \n" + "4: movi %0, 0 \n" + " br 5f \n" + ".section __ex_table, \"a\" \n" + ".align 2 \n" + ".long 2b, 4b \n" + ".previous \n" + "5: \n" + : "=r"(n), "=r"(s), "=r"(res), "=r"(tmp) + : "0"(n), "1"(s), "2"(n) + : "memory", "cc"); + + return res; +} +EXPORT_SYMBOL(strnlen_user); + +#define __do_clear_user(addr, size) \ +do { \ + int __d0, zvalue, tmp; \ + \ + asm volatile( \ + "0: cmpnei %1, 0 \n" \ + " bf 7f \n" \ + " mov %3, %1 \n" \ + " andi %3, 3 \n" \ + " cmpnei %3, 0 \n" \ + " bf 1f \n" \ + " br 5f \n" \ + "1: cmplti %0, 32 \n" /* 4W */ \ + " bt 3f \n" \ + "8: stw %2, (%1, 0) \n" \ + "10: stw %2, (%1, 4) \n" \ + "11: stw %2, (%1, 8) \n" \ + "12: stw %2, (%1, 12) \n" \ + "13: stw %2, (%1, 16) \n" \ + "14: stw %2, (%1, 20) \n" \ + "15: stw %2, (%1, 24) \n" \ + "16: stw %2, (%1, 28) \n" \ + " addi %1, 32 \n" \ + " subi %0, 32 \n" \ + " br 1b \n" \ + "3: cmplti %0, 4 \n" /* 1W */ \ + " bt 5f \n" \ + "4: stw %2, (%1, 0) \n" \ + " addi %1, 4 \n" \ + " subi %0, 4 \n" \ + " br 3b \n" \ + "5: cmpnei %0, 0 \n" /* 1B */ \ + "9: bf 7f \n" \ + "6: stb %2, (%1, 0) \n" \ + " addi %1, 1 \n" \ + " subi %0, 1 \n" \ + " br 5b \n" \ + ".section __ex_table,\"a\" \n" \ + ".align 2 \n" \ + ".long 8b, 9b \n" \ + ".long 10b, 9b \n" \ + ".long 11b, 9b \n" \ + ".long 12b, 9b \n" \ + ".long 13b, 9b \n" \ + ".long 14b, 9b \n" \ + ".long 15b, 9b \n" \ + ".long 16b, 9b \n" \ + ".long 4b, 9b \n" \ + ".long 6b, 9b \n" \ + ".previous \n" \ + "7: \n" \ + : "=r"(size), "=r" (__d0), \ + "=r"(zvalue), "=r"(tmp) \ + : "0"(size), "1"(addr), "2"(0) \ + : "memory", "cc"); \ +} while (0) + +/* + * clear_user: - Zero a block of memory in user space. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +unsigned long +clear_user(void __user *to, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + __do_clear_user(to, n); + return n; +} +EXPORT_SYMBOL(clear_user); + +/* + * __clear_user: - Zero a block of memory in user space, with less checking. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +unsigned long +__clear_user(void __user *to, unsigned long n) +{ + __do_clear_user(to, n); + return n; +} +EXPORT_SYMBOL(__clear_user); diff --git a/arch/csky/mm/Makefile b/arch/csky/mm/Makefile new file mode 100644 index 000000000000..c870eb36efbc --- /dev/null +++ b/arch/csky/mm/Makefile @@ -0,0 +1,13 @@ +ifeq ($(CONFIG_CPU_HAS_CACHEV2),y) +obj-y += cachev2.o +else +obj-y += cachev1.o +endif + +obj-y += dma-mapping.o +obj-y += fault.o +obj-$(CONFIG_HIGHMEM) += highmem.o +obj-y += init.o +obj-y += ioremap.o +obj-y += syscache.o +obj-y += tlb.o diff --git a/arch/csky/mm/cachev1.c b/arch/csky/mm/cachev1.c new file mode 100644 index 000000000000..b8a75cce0b8c --- /dev/null +++ b/arch/csky/mm/cachev1.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/spinlock.h> +#include <asm/cache.h> +#include <abi/reg_ops.h> + +/* for L1-cache */ +#define INS_CACHE (1 << 0) +#define DATA_CACHE (1 << 1) +#define CACHE_INV (1 << 4) +#define CACHE_CLR (1 << 5) +#define CACHE_OMS (1 << 6) +#define CACHE_ITS (1 << 7) +#define CACHE_LICF (1 << 31) + +/* for L2-cache */ +#define CR22_LEVEL_SHIFT (1) +#define CR22_SET_SHIFT (7) +#define CR22_WAY_SHIFT (30) +#define CR22_WAY_SHIFT_L2 (29) + +static DEFINE_SPINLOCK(cache_lock); + +static inline void cache_op_line(unsigned long i, unsigned int val) +{ + mtcr("cr22", i); + mtcr("cr17", val); +} + +#define CCR2_L2E (1 << 3) +static void cache_op_all(unsigned int value, unsigned int l2) +{ + mtcr("cr17", value | CACHE_CLR); + mb(); + + if (l2 && (mfcr_ccr2() & CCR2_L2E)) { + mtcr("cr24", value | CACHE_CLR); + mb(); + } +} + +static void cache_op_range( + unsigned int start, + unsigned int end, + unsigned int value, + unsigned int l2) +{ + unsigned long i, flags; + unsigned int val = value | CACHE_CLR | CACHE_OMS; + bool l2_sync; + + if (unlikely((end - start) >= PAGE_SIZE) || + unlikely(start < PAGE_OFFSET) || + unlikely(start >= PAGE_OFFSET + LOWMEM_LIMIT)) { + cache_op_all(value, l2); + return; + } + + if ((mfcr_ccr2() & CCR2_L2E) && l2) + l2_sync = 1; + else + l2_sync = 0; + + spin_lock_irqsave(&cache_lock, flags); + + i = start & ~(L1_CACHE_BYTES - 1); + for (; i < end; i += L1_CACHE_BYTES) { + cache_op_line(i, val); + if (l2_sync) { + mb(); + mtcr("cr24", val); + } + } + spin_unlock_irqrestore(&cache_lock, flags); + + mb(); +} + +void dcache_wb_line(unsigned long start) +{ + asm volatile("idly4\n":::"memory"); + cache_op_line(start, DATA_CACHE|CACHE_CLR); + mb(); +} + +void icache_inv_range(unsigned long start, unsigned long end) +{ + cache_op_range(start, end, INS_CACHE|CACHE_INV, 0); +} + +void icache_inv_all(void) +{ + cache_op_all(INS_CACHE|CACHE_INV, 0); +} + +void dcache_wb_range(unsigned long start, unsigned long end) +{ + cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0); +} + +void dcache_wbinv_all(void) +{ + cache_op_all(DATA_CACHE|CACHE_CLR|CACHE_INV, 0); +} + +void cache_wbinv_range(unsigned long start, unsigned long end) +{ + cache_op_range(start, end, INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0); +} +EXPORT_SYMBOL(cache_wbinv_range); + +void cache_wbinv_all(void) +{ + cache_op_all(INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0); +} + +void dma_wbinv_range(unsigned long start, unsigned long end) +{ + cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1); +} + +void dma_wb_range(unsigned long start, unsigned long end) +{ + cache_op_range(start, end, DATA_CACHE|CACHE_INV, 1); +} diff --git a/arch/csky/mm/cachev2.c b/arch/csky/mm/cachev2.c new file mode 100644 index 000000000000..baaf05d69f44 --- /dev/null +++ b/arch/csky/mm/cachev2.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <asm/cache.h> +#include <asm/barrier.h> + +inline void dcache_wb_line(unsigned long start) +{ + asm volatile("dcache.cval1 %0\n"::"r"(start):"memory"); + sync_is(); +} + +void icache_inv_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("icache.iva %0\n"::"r"(i):"memory"); + sync_is(); +} + +void icache_inv_all(void) +{ + asm volatile("icache.ialls\n":::"memory"); + sync_is(); +} + +void dcache_wb_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("dcache.cval1 %0\n"::"r"(i):"memory"); + sync_is(); +} + +void dcache_inv_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("dcache.civa %0\n"::"r"(i):"memory"); + sync_is(); +} + +void cache_wbinv_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("dcache.cval1 %0\n"::"r"(i):"memory"); + sync_is(); + + i = start & ~(L1_CACHE_BYTES - 1); + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("icache.iva %0\n"::"r"(i):"memory"); + sync_is(); +} +EXPORT_SYMBOL(cache_wbinv_range); + +void dma_wbinv_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("dcache.civa %0\n"::"r"(i):"memory"); + sync_is(); +} + +void dma_wb_range(unsigned long start, unsigned long end) +{ + unsigned long i = start & ~(L1_CACHE_BYTES - 1); + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile("dcache.civa %0\n"::"r"(i):"memory"); + sync_is(); +} diff --git a/arch/csky/mm/dma-mapping.c b/arch/csky/mm/dma-mapping.c new file mode 100644 index 000000000000..85437b21e045 --- /dev/null +++ b/arch/csky/mm/dma-mapping.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/cache.h> +#include <linux/dma-mapping.h> +#include <linux/dma-contiguous.h> +#include <linux/dma-noncoherent.h> +#include <linux/genalloc.h> +#include <linux/highmem.h> +#include <linux/io.h> +#include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/types.h> +#include <linux/version.h> +#include <asm/cache.h> + +static struct gen_pool *atomic_pool; +static size_t atomic_pool_size __initdata = SZ_256K; + +static int __init early_coherent_pool(char *p) +{ + atomic_pool_size = memparse(p, &p); + return 0; +} +early_param("coherent_pool", early_coherent_pool); + +static int __init atomic_pool_init(void) +{ + struct page *page; + size_t size = atomic_pool_size; + void *ptr; + int ret; + + atomic_pool = gen_pool_create(PAGE_SHIFT, -1); + if (!atomic_pool) + BUG(); + + page = alloc_pages(GFP_KERNEL | GFP_DMA, get_order(size)); + if (!page) + BUG(); + + ptr = dma_common_contiguous_remap(page, size, VM_ALLOC, + pgprot_noncached(PAGE_KERNEL), + __builtin_return_address(0)); + if (!ptr) + BUG(); + + ret = gen_pool_add_virt(atomic_pool, (unsigned long)ptr, + page_to_phys(page), atomic_pool_size, -1); + if (ret) + BUG(); + + gen_pool_set_algo(atomic_pool, gen_pool_first_fit_order_align, NULL); + + pr_info("DMA: preallocated %zu KiB pool for atomic coherent pool\n", + atomic_pool_size / 1024); + + pr_info("DMA: vaddr: 0x%x phy: 0x%lx,\n", (unsigned int)ptr, + page_to_phys(page)); + + return 0; +} +postcore_initcall(atomic_pool_init); + +static void *csky_dma_alloc_atomic(struct device *dev, size_t size, + dma_addr_t *dma_handle) +{ + unsigned long addr; + + addr = gen_pool_alloc(atomic_pool, size); + if (addr) + *dma_handle = gen_pool_virt_to_phys(atomic_pool, addr); + + return (void *)addr; +} + +static void csky_dma_free_atomic(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, unsigned long attrs) +{ + gen_pool_free(atomic_pool, (unsigned long)vaddr, size); +} + +static void __dma_clear_buffer(struct page *page, size_t size) +{ + if (PageHighMem(page)) { + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + + do { + void *ptr = kmap_atomic(page); + size_t _size = (size < PAGE_SIZE) ? size : PAGE_SIZE; + + memset(ptr, 0, _size); + dma_wbinv_range((unsigned long)ptr, + (unsigned long)ptr + _size); + + kunmap_atomic(ptr); + + page++; + size -= PAGE_SIZE; + count--; + } while (count); + } else { + void *ptr = page_address(page); + + memset(ptr, 0, size); + dma_wbinv_range((unsigned long)ptr, (unsigned long)ptr + size); + } +} + +static void *csky_dma_alloc_nonatomic(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + unsigned long attrs) +{ + void *vaddr; + struct page *page; + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + + if (DMA_ATTR_NON_CONSISTENT & attrs) { + pr_err("csky %s can't support DMA_ATTR_NON_CONSISTENT.\n", __func__); + return NULL; + } + + if (IS_ENABLED(CONFIG_DMA_CMA)) + page = dma_alloc_from_contiguous(dev, count, get_order(size), + gfp); + else + page = alloc_pages(gfp, get_order(size)); + + if (!page) { + pr_err("csky %s no more free pages.\n", __func__); + return NULL; + } + + *dma_handle = page_to_phys(page); + + __dma_clear_buffer(page, size); + + if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) + return page; + + vaddr = dma_common_contiguous_remap(page, PAGE_ALIGN(size), VM_USERMAP, + pgprot_noncached(PAGE_KERNEL), __builtin_return_address(0)); + if (!vaddr) + BUG(); + + return vaddr; +} + +static void csky_dma_free_nonatomic( + struct device *dev, + size_t size, + void *vaddr, + dma_addr_t dma_handle, + unsigned long attrs + ) +{ + struct page *page = phys_to_page(dma_handle); + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + + if ((unsigned int)vaddr >= VMALLOC_START) + dma_common_free_remap(vaddr, size, VM_USERMAP); + + if (IS_ENABLED(CONFIG_DMA_CMA)) + dma_release_from_contiguous(dev, page, count); + else + __free_pages(page, get_order(size)); +} + +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp, unsigned long attrs) +{ + if (gfpflags_allow_blocking(gfp)) + return csky_dma_alloc_nonatomic(dev, size, dma_handle, gfp, + attrs); + else + return csky_dma_alloc_atomic(dev, size, dma_handle); +} + +void arch_dma_free(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, unsigned long attrs) +{ + if (!addr_in_gen_pool(atomic_pool, (unsigned int) vaddr, size)) + csky_dma_free_nonatomic(dev, size, vaddr, dma_handle, attrs); + else + csky_dma_free_atomic(dev, size, vaddr, dma_handle, attrs); +} + +static inline void cache_op(phys_addr_t paddr, size_t size, + void (*fn)(unsigned long start, unsigned long end)) +{ + struct page *page = pfn_to_page(paddr >> PAGE_SHIFT); + unsigned int offset = paddr & ~PAGE_MASK; + size_t left = size; + unsigned long start; + + do { + size_t len = left; + + if (PageHighMem(page)) { + void *addr; + + if (offset + len > PAGE_SIZE) { + if (offset >= PAGE_SIZE) { + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + } + len = PAGE_SIZE - offset; + } + + addr = kmap_atomic(page); + start = (unsigned long)(addr + offset); + fn(start, start + len); + kunmap_atomic(addr); + } else { + start = (unsigned long)phys_to_virt(paddr); + fn(start, start + size); + } + offset = 0; + page++; + left -= len; + } while (left); +} + +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_op(paddr, size, dma_wb_range); + break; + case DMA_FROM_DEVICE: + case DMA_BIDIRECTIONAL: + cache_op(paddr, size, dma_wbinv_range); + break; + default: + BUG(); + } +} + +void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_op(paddr, size, dma_wb_range); + break; + case DMA_FROM_DEVICE: + case DMA_BIDIRECTIONAL: + cache_op(paddr, size, dma_wbinv_range); + break; + default: + BUG(); + } +} diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c new file mode 100644 index 000000000000..7df57f90b52c --- /dev/null +++ b/arch/csky/mm/fault.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/signal.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/version.h> +#include <linux/vt_kern.h> +#include <linux/kernel.h> +#include <linux/extable.h> +#include <linux/uaccess.h> + +#include <asm/hardirq.h> +#include <asm/mmu_context.h> +#include <asm/traps.h> +#include <asm/page.h> + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(instruction_pointer(regs)); + if (fixup) { + regs->pc = fixup->nextinsn; + + return 1; + } + + return 0; +} + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long mmu_meh) +{ + struct vm_area_struct *vma = NULL; + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + int si_code; + int fault; + unsigned long address = mmu_meh & PAGE_MASK; + + si_code = SEGV_MAPERR; + +#ifndef CONFIG_CPU_HAS_TLBI + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + */ + if (unlikely(address >= VMALLOC_START) && + unlikely(address <= VMALLOC_END)) { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = __pgd_offset(address); + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + pte_t *pte_k; + + unsigned long pgd_base; + + pgd_base = tlb_get_pgd(); + pgd = (pgd_t *)pgd_base + offset; + pgd_k = init_mm.pgd + offset; + + if (!pgd_present(*pgd_k)) + goto no_context; + set_pgd(pgd, *pgd_k); + + pud = (pud_t *)pgd; + pud_k = (pud_t *)pgd_k; + if (!pud_present(*pud_k)) + goto no_context; + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + goto no_context; + set_pmd(pmd, *pmd_k); + + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + goto no_context; + return; + } +#endif + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_atomic() || !mm) + goto bad_area_nosemaphore; + + down_read(&mm->mmap_sem); + vma = find_vma(mm, address); + if (!vma) + goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, address)) + goto bad_area; + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + si_code = SEGV_ACCERR; + + if (write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) + goto bad_area; + } + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + fault = handle_mm_fault(vma, address, write ? FAULT_FLAG_WRITE : 0); + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + else if (fault & VM_FAULT_SIGSEGV) + goto bad_area; + BUG(); + } + if (fault & VM_FAULT_MAJOR) + tsk->maj_flt++; + else + tsk->min_flt++; + + up_read(&mm->mmap_sem); + return; + + /* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up_read(&mm->mmap_sem); + +bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (user_mode(regs)) { + tsk->thread.address = address; + tsk->thread.error_code = write; + force_sig_fault(SIGSEGV, si_code, (void __user *)address, current); + return; + } + +no_context: + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) + return; + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + bust_spinlocks(1); + pr_alert("Unable to %s at vaddr: %08lx, epc: %08lx\n", + __func__, address, regs->pc); + die_if_kernel("Oops", regs, write); + +out_of_memory: + /* + * We ran out of memory, call the OOM killer, and return the userspace + * (which will retry the fault, or kill us if we got oom-killed). + */ + pagefault_out_of_memory(); + return; + +do_sigbus: + up_read(&mm->mmap_sem); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + + tsk->thread.address = address; + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, current); +} diff --git a/arch/csky/mm/highmem.c b/arch/csky/mm/highmem.c new file mode 100644 index 000000000000..e168ac087ccb --- /dev/null +++ b/arch/csky/mm/highmem.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/module.h> +#include <linux/highmem.h> +#include <linux/smp.h> +#include <linux/bootmem.h> +#include <asm/fixmap.h> +#include <asm/tlbflush.h> +#include <asm/cacheflush.h> + +static pte_t *kmap_pte; + +unsigned long highstart_pfn, highend_pfn; + +void *kmap(struct page *page) +{ + void *addr; + + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + addr = kmap_high(page); + flush_tlb_one((unsigned long)addr); + + return addr; +} +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + BUG_ON(in_interrupt()); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} +EXPORT_SYMBOL(kunmap); + +void *kmap_atomic(struct page *page) +{ + unsigned long vaddr; + int idx, type; + + preempt_disable(); + pagefault_disable(); + if (!PageHighMem(page)) + return page_address(page); + + type = kmap_atomic_idx_push(); + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + BUG_ON(!pte_none(*(kmap_pte - idx))); +#endif + set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL)); + flush_tlb_one((unsigned long)vaddr); + + return (void *)vaddr; +} +EXPORT_SYMBOL(kmap_atomic); + +void __kunmap_atomic(void *kvaddr) +{ + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + int idx; + + if (vaddr < FIXADDR_START) + goto out; + +#ifdef CONFIG_DEBUG_HIGHMEM + idx = KM_TYPE_NR*smp_processor_id() + kmap_atomic_idx(); + + BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); + + pte_clear(&init_mm, vaddr, kmap_pte - idx); + flush_tlb_one(vaddr); +#else + (void) idx; /* to kill a warning */ +#endif + kmap_atomic_idx_pop(); +out: + pagefault_enable(); + preempt_enable(); +} +EXPORT_SYMBOL(__kunmap_atomic); + +/* + * This is the same as kmap_atomic() but can map memory that doesn't + * have a struct page associated with it. + */ +void *kmap_atomic_pfn(unsigned long pfn) +{ + unsigned long vaddr; + int idx, type; + + pagefault_disable(); + + type = kmap_atomic_idx_push(); + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL)); + flush_tlb_one(vaddr); + + return (void *) vaddr; +} + +struct page *kmap_atomic_to_page(void *ptr) +{ + unsigned long idx, vaddr = (unsigned long)ptr; + pte_t *pte; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + idx = virt_to_fix(vaddr); + pte = kmap_pte - (idx - FIX_KMAP_BEGIN); + return pte_page(*pte); +} + +static void __init fixrange_init(unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ +#ifdef CONFIG_HIGHMEM + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + int i, j, k; + unsigned long vaddr; + + vaddr = start; + i = __pgd_offset(vaddr); + j = __pud_offset(vaddr); + k = __pmd_offset(vaddr); + pgd = pgd_base + i; + + for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + pud = (pud_t *)pgd; + for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) { + pmd = (pmd_t *)pud; + for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { + if (pmd_none(*pmd)) { + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + set_pmd(pmd, __pmd(__pa(pte))); + BUG_ON(pte != pte_offset_kernel(pmd, 0)); + } + vaddr += PMD_SIZE; + } + k = 0; + } + j = 0; + } +#endif +} + +void __init fixaddr_kmap_pages_init(void) +{ + unsigned long vaddr; + pgd_t *pgd_base; +#ifdef CONFIG_HIGHMEM + pgd_t *pgd; + pmd_t *pmd; + pud_t *pud; + pte_t *pte; +#endif + pgd_base = swapper_pg_dir; + + /* + * Fixed mappings: + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + fixrange_init(vaddr, 0, pgd_base); + +#ifdef CONFIG_HIGHMEM + /* + * Permanent kmaps: + */ + vaddr = PKMAP_BASE; + fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); + + pgd = swapper_pg_dir + __pgd_offset(vaddr); + pud = (pud_t *)pgd; + pmd = pmd_offset(pud, vaddr); + pte = pte_offset_kernel(pmd, vaddr); + pkmap_page_table = pte; +#endif +} + +void __init kmap_init(void) +{ + unsigned long vaddr; + + fixaddr_kmap_pages_init(); + + vaddr = __fix_to_virt(FIX_KMAP_BEGIN); + + kmap_pte = pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr); +} diff --git a/arch/csky/mm/init.c b/arch/csky/mm/init.c new file mode 100644 index 000000000000..ce2711e050ad --- /dev/null +++ b/arch/csky/mm/init.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/bug.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/pagemap.h> +#include <linux/ptrace.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <linux/highmem.h> +#include <linux/memblock.h> +#include <linux/swap.h> +#include <linux/proc_fs.h> +#include <linux/pfn.h> + +#include <asm/setup.h> +#include <asm/cachectl.h> +#include <asm/dma.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> +#include <asm/mmu_context.h> +#include <asm/sections.h> +#include <asm/tlb.h> + +pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; +pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; +unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] + __page_aligned_bss; +EXPORT_SYMBOL(empty_zero_page); + +void __init mem_init(void) +{ +#ifdef CONFIG_HIGHMEM + unsigned long tmp; + + max_mapnr = highend_pfn; +#else + max_mapnr = max_low_pfn; +#endif + high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); + + free_all_bootmem(); + +#ifdef CONFIG_HIGHMEM + for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { + struct page *page = pfn_to_page(tmp); + + /* FIXME not sure about */ + if (!memblock_is_reserved(tmp << PAGE_SHIFT)) + free_highmem_page(page); + } +#endif + mem_init_print_info(NULL); +} + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + if (start < end) + pr_info("Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); + + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + init_page_count(virt_to_page(start)); + free_page(start); + totalram_pages++; + } +} +#endif + +extern char __init_begin[], __init_end[]; + +void free_initmem(void) +{ + unsigned long addr; + + addr = (unsigned long) &__init_begin; + + while (addr < (unsigned long) &__init_end) { + ClearPageReserved(virt_to_page(addr)); + init_page_count(virt_to_page(addr)); + free_page(addr); + totalram_pages++; + addr += PAGE_SIZE; + } + + pr_info("Freeing unused kernel memory: %dk freed\n", + ((unsigned int)&__init_end - (unsigned int)&__init_begin) >> 10); +} + +void pgd_init(unsigned long *p) +{ + int i; + + for (i = 0; i < PTRS_PER_PGD; i++) + p[i] = __pa(invalid_pte_table); +} + +void __init pre_mmu_init(void) +{ + /* + * Setup page-table and enable TLB-hardrefill + */ + flush_tlb_all(); + pgd_init((unsigned long *)swapper_pg_dir); + TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); + TLBMISS_HANDLER_SETUP_PGD_KERNEL(swapper_pg_dir); + + asid_cache(smp_processor_id()) = ASID_FIRST_VERSION; + + /* Setup page mask to 4k */ + write_mmu_pagemask(0); +} diff --git a/arch/csky/mm/ioremap.c b/arch/csky/mm/ioremap.c new file mode 100644 index 000000000000..7ad3ff103f4a --- /dev/null +++ b/arch/csky/mm/ioremap.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/export.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/io.h> + +#include <asm/pgtable.h> + +void __iomem *ioremap(phys_addr_t addr, size_t size) +{ + phys_addr_t last_addr; + unsigned long offset, vaddr; + struct vm_struct *area; + pgprot_t prot; + + last_addr = addr + size - 1; + if (!size || last_addr < addr) + return NULL; + + offset = addr & (~PAGE_MASK); + addr &= PAGE_MASK; + size = PAGE_ALIGN(size + offset); + + area = get_vm_area_caller(size, VM_ALLOC, __builtin_return_address(0)); + if (!area) + return NULL; + + vaddr = (unsigned long)area->addr; + + prot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | + _PAGE_GLOBAL | _CACHE_UNCACHED); + + if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) { + free_vm_area(area); + return NULL; + } + + return (void __iomem *)(vaddr + offset); +} +EXPORT_SYMBOL(ioremap); + +void iounmap(void __iomem *addr) +{ + vunmap((void *)((unsigned long)addr & PAGE_MASK)); +} +EXPORT_SYMBOL(iounmap); diff --git a/arch/csky/mm/syscache.c b/arch/csky/mm/syscache.c new file mode 100644 index 000000000000..c4645e4e97f4 --- /dev/null +++ b/arch/csky/mm/syscache.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/syscalls.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/cachectl.h> + +SYSCALL_DEFINE3(cacheflush, + void __user *, addr, + unsigned long, bytes, + int, cache) +{ + switch (cache) { + case ICACHE: + icache_inv_range((unsigned long)addr, + (unsigned long)addr + bytes); + break; + case DCACHE: + dcache_wb_range((unsigned long)addr, + (unsigned long)addr + bytes); + break; + case BCACHE: + cache_wbinv_range((unsigned long)addr, + (unsigned long)addr + bytes); + break; + default: + return -EINVAL; + } + + return 0; +} diff --git a/arch/csky/mm/tlb.c b/arch/csky/mm/tlb.c new file mode 100644 index 000000000000..08b8394e5b8f --- /dev/null +++ b/arch/csky/mm/tlb.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. + +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/sched.h> + +#include <asm/mmu_context.h> +#include <asm/pgtable.h> +#include <asm/setup.h> + +#define CSKY_TLB_SIZE CONFIG_CPU_TLB_SIZE + +void flush_tlb_all(void) +{ + tlb_invalid_all(); +} + +void flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) + drop_mmu_context(mm, cpu); + + tlb_invalid_all(); +} + +#define restore_asid_inv_utlb(oldpid, newpid) \ +do { \ + if ((oldpid & ASID_MASK) == newpid) \ + write_mmu_entryhi(oldpid + 1); \ + write_mmu_entryhi(oldpid); \ +} while (0) + +void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { + unsigned long size, flags; + int newpid = cpu_asid(cpu, mm); + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= CSKY_TLB_SIZE/2) { + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); +#ifdef CONFIG_CPU_HAS_TLBI + while (start < end) { + asm volatile("tlbi.vaas %0" + ::"r"(start | newpid)); + start += (PAGE_SIZE << 1); + } + sync_is(); +#else + { + int oldpid = read_mmu_entryhi(); + + while (start < end) { + int idx; + + write_mmu_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_mmu_index(); + if (idx >= 0) + tlb_invalid_indexed(); + } + restore_asid_inv_utlb(oldpid, newpid); + } +#endif + } else { + drop_mmu_context(mm, cpu); + } + local_irq_restore(flags); + } +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long size, flags; + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size <= CSKY_TLB_SIZE) { + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); +#ifdef CONFIG_CPU_HAS_TLBI + while (start < end) { + asm volatile("tlbi.vaas %0"::"r"(start)); + start += (PAGE_SIZE << 1); + } + sync_is(); +#else + { + int oldpid = read_mmu_entryhi(); + + while (start < end) { + int idx; + + write_mmu_entryhi(start); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_mmu_index(); + if (idx >= 0) + tlb_invalid_indexed(); + } + restore_asid_inv_utlb(oldpid, 0); + } +#endif + } else { + flush_tlb_all(); + } + + local_irq_restore(flags); +} + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + int cpu = smp_processor_id(); + int newpid = cpu_asid(cpu, vma->vm_mm); + + if (!vma || cpu_context(cpu, vma->vm_mm) != 0) { + page &= (PAGE_MASK << 1); + +#ifdef CONFIG_CPU_HAS_TLBI + asm volatile("tlbi.vaas %0"::"r"(page | newpid)); + sync_is(); +#else + { + int oldpid, idx; + unsigned long flags; + + local_irq_save(flags); + oldpid = read_mmu_entryhi(); + write_mmu_entryhi(page | newpid); + tlb_probe(); + idx = read_mmu_index(); + if (idx >= 0) + tlb_invalid_indexed(); + + restore_asid_inv_utlb(oldpid, newpid); + local_irq_restore(flags); + } +#endif + } +} + +/* + * Remove one kernel space TLB entry. This entry is assumed to be marked + * global so we don't do the ASID thing. + */ +void flush_tlb_one(unsigned long page) +{ + int oldpid; + + oldpid = read_mmu_entryhi(); + page &= (PAGE_MASK << 1); + +#ifdef CONFIG_CPU_HAS_TLBI + page = page | (oldpid & 0xfff); + asm volatile("tlbi.vaas %0"::"r"(page)); + sync_is(); +#else + { + int idx; + unsigned long flags; + + page = page | (oldpid & 0xff); + + local_irq_save(flags); + write_mmu_entryhi(page); + tlb_probe(); + idx = read_mmu_index(); + if (idx >= 0) + tlb_invalid_indexed(); + restore_asid_inv_utlb(oldpid, oldpid); + local_irq_restore(flags); + } +#endif +} +EXPORT_SYMBOL(flush_tlb_one); + +/* show current 32 jtlbs */ +void show_jtlb_table(void) +{ + unsigned long flags; + int entryhi, entrylo0, entrylo1; + int entry; + int oldpid; + + local_irq_save(flags); + entry = 0; + pr_info("\n\n\n"); + + oldpid = read_mmu_entryhi(); + while (entry < CSKY_TLB_SIZE) { + write_mmu_index(entry); + tlb_read(); + entryhi = read_mmu_entryhi(); + entrylo0 = read_mmu_entrylo0(); + entrylo0 = entrylo0; + entrylo1 = read_mmu_entrylo1(); + entrylo1 = entrylo1; + pr_info("jtlb[%d]: entryhi - 0x%x; entrylo0 - 0x%x;" + " entrylo1 - 0x%x\n", + entry, entryhi, entrylo0, entrylo1); + entry++; + } + write_mmu_entryhi(oldpid); + local_irq_restore(flags); +} diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile index 58634e6bae92..4003ddc616e1 100644 --- a/arch/h8300/Makefile +++ b/arch/h8300/Makefile @@ -31,21 +31,12 @@ CROSS_COMPILE := h8300-unknown-linux- endif core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ -ifneq '$(CONFIG_H8300_BUILTIN_DTB)' '""' -core-y += arch/h8300/boot/dts/ -endif +core-y += arch/$(ARCH)/boot/dts/ libs-y += arch/$(ARCH)/lib/ boot := arch/h8300/boot -%.dtb %.dtb.S %.dtb.o: | scripts - $(Q)$(MAKE) $(build)=arch/h8300/boot/dts arch/h8300/boot/dts/$@ - -PHONY += dtbs -dtbs: scripts - $(Q)$(MAKE) $(build)=arch/h8300/boot/dts - archmrproper: archclean: diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h index 7dd20ef7625a..628195823816 100644 --- a/arch/h8300/include/uapi/asm/unistd.h +++ b/arch/h8300/include/uapi/asm/unistd.h @@ -1,5 +1,6 @@ #define __ARCH_NOMMU #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #include <asm-generic/unistd.h> diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index 35716a3048de..49f716c0a1df 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S @@ -56,7 +56,6 @@ SECTIONS __init_begin = .; INIT_TEXT_SECTION(4) INIT_DATA_SECTION(4) - SECURITY_INIT __init_end = .; _edata = . ; _begin_data = LOADADDR(.data); diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 3ef46522e89f..7b25d7c8fa49 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig @@ -21,6 +21,9 @@ config HEXAGON select GENERIC_IRQ_SHOW select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK + select HAVE_MEMBLOCK + select ARCH_DISCARD_MEMBLOCK + select NO_BOOTMEM select NEED_SG_DMA_LENGTH select NO_IOPORT_MAP select GENERIC_IOMAP diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h index ea181e79162e..c91ca7d02461 100644 --- a/arch/hexagon/include/uapi/asm/unistd.h +++ b/arch/hexagon/include/uapi/asm/unistd.h @@ -29,6 +29,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_VFORK diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c index 1495d45e472d..d789b9cc0189 100644 --- a/arch/hexagon/mm/init.c +++ b/arch/hexagon/mm/init.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/mm.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <asm/atomic.h> #include <linux/highmem.h> #include <asm/tlb.h> @@ -176,7 +177,6 @@ size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22); void __init setup_arch_memory(void) { - int bootmap_size; /* XXX Todo: this probably should be cleaned up */ u32 *segtable = (u32 *) &swapper_pg_dir[0]; u32 *segtable_end; @@ -195,18 +195,22 @@ void __init setup_arch_memory(void) bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) & ~((BIG_KERNEL_PAGE_SIZE) - 1)); + memblock_add(PHYS_OFFSET, + (bootmem_lastpg - ARCH_PFN_OFFSET) << PAGE_SHIFT); + + /* Reserve kernel text/data/bss */ + memblock_reserve(PHYS_OFFSET, + (bootmem_startpg - ARCH_PFN_OFFSET) << PAGE_SHIFT); /* * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached) * memory allocation */ - max_low_pfn = bootmem_lastpg - PFN_DOWN(DMA_RESERVED_BYTES); min_low_pfn = ARCH_PFN_OFFSET; - bootmap_size = init_bootmem_node(NODE_DATA(0), bootmem_startpg, min_low_pfn, max_low_pfn); + memblock_reserve(PFN_PHYS(max_low_pfn), DMA_RESERVED_BYTES); printk(KERN_INFO "bootmem_startpg: 0x%08lx\n", bootmem_startpg); printk(KERN_INFO "bootmem_lastpg: 0x%08lx\n", bootmem_lastpg); - printk(KERN_INFO "bootmap_size: %d\n", bootmap_size); printk(KERN_INFO "min_low_pfn: 0x%08lx\n", min_low_pfn); printk(KERN_INFO "max_low_pfn: 0x%08lx\n", max_low_pfn); @@ -257,14 +261,6 @@ void __init setup_arch_memory(void) #endif /* - * Free all the memory that wasn't taken up by the bootmap, the DMA - * reserve, or kernel itself. - */ - free_bootmem(PFN_PHYS(bootmem_startpg) + bootmap_size, - PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size - - DMA_RESERVED_BYTES); - - /* * The bootmem allocator seemingly just lives to feed memory * to the paging system */ diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 663388a73d4e..7aeb48a18576 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -297,29 +297,29 @@ static void rs_unthrottle(struct tty_struct * tty) printk(KERN_INFO "simrs_unthrottle called\n"); } +static int rs_setserial(struct tty_struct *tty, struct serial_struct *ss) +{ + return 0; +} + +static int rs_getserial(struct tty_struct *tty, struct serial_struct *ss) +{ + return 0; +} + static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT)) { + if ((cmd != TIOCSERCONFIG) && (cmd != TIOCMIWAIT)) { if (tty_io_error(tty)) return -EIO; } switch (cmd) { - case TIOCGSERIAL: - case TIOCSSERIAL: - case TIOCSERGSTRUCT: case TIOCMIWAIT: return 0; case TIOCSERCONFIG: case TIOCSERGETLSR: /* Get line status register */ return -EINVAL; - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk (KERN_INFO "TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; } return -ENOIOCTLCMD; } @@ -448,6 +448,8 @@ static const struct tty_operations hp_ops = { .throttle = rs_throttle, .unthrottle = rs_unthrottle, .send_xchar = rs_send_xchar, + .set_serial = rs_setserial, + .get_serial = rs_getserial, .hangup = rs_hangup, .proc_show = rs_proc_show, }; diff --git a/arch/ia64/include/asm/hugetlb.h b/arch/ia64/include/asm/hugetlb.h index 74d2a5540aaf..36cc0396b214 100644 --- a/arch/ia64/include/asm/hugetlb.h +++ b/arch/ia64/include/asm/hugetlb.h @@ -3,13 +3,13 @@ #define _ASM_IA64_HUGETLB_H #include <asm/page.h> -#include <asm-generic/hugetlb.h> - +#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); +#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE int prepare_hugepage_range(struct file *file, unsigned long addr, unsigned long len); @@ -21,53 +21,16 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE); } -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - return ptep_get_and_clear(mm, addr, ptep); -} - +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { } -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - -static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep, - pte_t pte, int dirty) -{ - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); -} - -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } +#include <asm-generic/hugetlb.h> + #endif /* _ASM_IA64_HUGETLB_H */ diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h index 165827774bea..b1e7468eb65a 100644 --- a/arch/ia64/include/asm/pgtable.h +++ b/arch/ia64/include/asm/pgtable.h @@ -544,7 +544,6 @@ extern struct page *zero_page_memmap_ptr; # ifdef CONFIG_VIRTUAL_MEM_MAP /* arch mem_map init routine is needed due to holes in a virtual mem_map */ -# define __HAVE_ARCH_MEMMAP_INIT extern void memmap_init (unsigned long size, int nid, unsigned long zone, unsigned long start_pfn); # endif /* CONFIG_VIRTUAL_MEM_MAP */ diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index ffb705dc9c13..49e34db2529c 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -28,6 +28,9 @@ #define __IGNORE_vfork /* clone() */ #define __IGNORE_umount2 /* umount() */ +#define __ARCH_WANT_NEW_STAT +#define __ARCH_WANT_SYS_UTIME + #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) #include <linux/types.h> diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h index 52b5af424511..796af1ccaa7e 100644 --- a/arch/ia64/include/uapi/asm/siginfo.h +++ b/arch/ia64/include/uapi/asm/siginfo.h @@ -9,8 +9,6 @@ #define _UAPI_ASM_IA64_SIGINFO_H -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) - #include <asm-generic/siginfo.h> #define si_imm _sifields._sigfault._imm /* as per UNIX SysV ABI spec */ diff --git a/arch/ia64/kernel/brl_emu.c b/arch/ia64/kernel/brl_emu.c index a61f6c6a36f8..c0239bf77a09 100644 --- a/arch/ia64/kernel/brl_emu.c +++ b/arch/ia64/kernel/brl_emu.c @@ -58,11 +58,9 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec) unsigned long bundle[2]; unsigned long opcode, btype, qp, offset, cpl; unsigned long next_ip; - struct siginfo siginfo; struct illegal_op_return rv; long tmp_taken, unimplemented_address; - clear_siginfo(&siginfo); rv.fkt = (unsigned long) -1; /* @@ -198,39 +196,22 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec) * The target address contains unimplemented bits. */ printk(KERN_DEBUG "Woah! Unimplemented Instruction Address Trap!\n"); - siginfo.si_signo = SIGILL; - siginfo.si_errno = 0; - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_imm = 0; - siginfo.si_code = ILL_BADIADDR; - force_sig_info(SIGILL, &siginfo, current); + force_sig_fault(SIGILL, ILL_BADIADDR, (void __user *)NULL, + 0, 0, 0, current); } else if (ia64_psr(regs)->tb) { /* * Branch Tracing is enabled. * Force a taken branch signal. */ - siginfo.si_signo = SIGTRAP; - siginfo.si_errno = 0; - siginfo.si_code = TRAP_BRANCH; - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_addr = 0; - siginfo.si_imm = 0; - force_sig_info(SIGTRAP, &siginfo, current); + force_sig_fault(SIGTRAP, TRAP_BRANCH, (void __user *)NULL, + 0, 0, 0, current); } else if (ia64_psr(regs)->ss) { /* * Single Step is enabled. * Force a trace signal. */ - siginfo.si_signo = SIGTRAP; - siginfo.si_errno = 0; - siginfo.si_code = TRAP_TRACE; - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_addr = 0; - siginfo.si_imm = 0; - force_sig_info(SIGTRAP, &siginfo, current); + force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)NULL, + 0, 0, 0, current); } return rv; } diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index d1234a5ba4c5..9a960829a01d 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -110,7 +110,6 @@ ia64_rt_sigreturn (struct sigscratch *scr) { extern char ia64_strace_leave_kernel, ia64_leave_kernel; struct sigcontext __user *sc; - struct siginfo si; sigset_t set; long retval; @@ -153,14 +152,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) return retval; give_sigsegv: - clear_siginfo(&si); - si.si_signo = SIGSEGV; - si.si_errno = 0; - si.si_code = SI_KERNEL; - si.si_pid = task_pid_vnr(current); - si.si_uid = from_kuid_munged(current_user_ns(), current_uid()); - si.si_addr = sc; - force_sig_info(SIGSEGV, &si, current); + force_sig(SIGSEGV, current); return retval; } @@ -232,37 +224,6 @@ rbs_on_sig_stack (unsigned long bsp) } static long -force_sigsegv_info (int sig, void __user *addr) -{ - unsigned long flags; - struct siginfo si; - - clear_siginfo(&si); - if (sig == SIGSEGV) { - /* - * Acquiring siglock around the sa_handler-update is almost - * certainly overkill, but this isn't a - * performance-critical path and I'd rather play it safe - * here than having to debug a nasty race if and when - * something changes in kernel/signal.c that would make it - * no longer safe to modify sa_handler without holding the - * lock. - */ - spin_lock_irqsave(¤t->sighand->siglock, flags); - current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - si.si_signo = SIGSEGV; - si.si_errno = 0; - si.si_code = SI_KERNEL; - si.si_pid = task_pid_vnr(current); - si.si_uid = from_kuid_munged(current_user_ns(), current_uid()); - si.si_addr = addr; - force_sig_info(SIGSEGV, &si, current); - return 1; -} - -static long setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) { extern char __kernel_sigtramp[]; @@ -295,15 +256,18 @@ setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) * instead so we will die with SIGSEGV. */ check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN; - if (!likely(on_sig_stack(check_sp))) - return force_sigsegv_info(ksig->sig, (void __user *) - check_sp); + if (!likely(on_sig_stack(check_sp))) { + force_sigsegv(ksig->sig, current); + return 1; + } } } frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return force_sigsegv_info(ksig->sig, frame); + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) { + force_sigsegv(ksig->sig, current); + return 1; + } err = __put_user(ksig->sig, &frame->arg0); err |= __put_user(&frame->info, &frame->arg1); @@ -317,8 +281,10 @@ setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12); err |= setup_sigcontext(&frame->sc, set, scr); - if (unlikely(err)) - return force_sigsegv_info(ksig->sig, frame); + if (unlikely(err)) { + force_sigsegv(ksig->sig, current); + return 1; + } scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index c6f4932073a1..85d8616ac4f6 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -100,16 +100,8 @@ die_if_kernel (char *str, struct pt_regs *regs, long err) void __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) { - siginfo_t siginfo; int sig, code; - /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ - clear_siginfo(&siginfo); - siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); - siginfo.si_imm = break_num; - siginfo.si_flags = 0; /* clear __ISR_VALID */ - siginfo.si_isr = 0; - switch (break_num) { case 0: /* unknown error (used by GCC for __builtin_abort()) */ if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) @@ -182,10 +174,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) sig = SIGTRAP; code = TRAP_BRKPT; } } - siginfo.si_signo = sig; - siginfo.si_errno = 0; - siginfo.si_code = code; - force_sig_info(sig, &siginfo, current); + force_sig_fault(sig, code, + (void __user *) (regs->cr_iip + ia64_psr(regs)->ri), + break_num, 0 /* clear __ISR_VALID */, 0, current); } /* @@ -344,30 +335,25 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n"); return -1; } else { - struct siginfo siginfo; - /* is next instruction a trap? */ + int si_code; + if (exception & 2) { ia64_increment_ip(regs); } - clear_siginfo(&siginfo); - siginfo.si_signo = SIGFPE; - siginfo.si_errno = 0; - siginfo.si_code = FPE_FLTUNK; /* default code */ - siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); + si_code = FPE_FLTUNK; /* default code */ if (isr & 0x11) { - siginfo.si_code = FPE_FLTINV; + si_code = FPE_FLTINV; } else if (isr & 0x22) { /* denormal operand gets the same si_code as underflow * see arch/i386/kernel/traps.c:math_error() */ - siginfo.si_code = FPE_FLTUND; + si_code = FPE_FLTUND; } else if (isr & 0x44) { - siginfo.si_code = FPE_FLTDIV; + si_code = FPE_FLTDIV; } - siginfo.si_isr = isr; - siginfo.si_flags = __ISR_VALID; - siginfo.si_imm = 0; - force_sig_info(SIGFPE, &siginfo, current); + force_sig_fault(SIGFPE, si_code, + (void __user *) (regs->cr_iip + ia64_psr(regs)->ri), + 0, __ISR_VALID, isr, current); } } else { if (exception == -1) { @@ -375,24 +361,19 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) return -1; } else if (exception != 0) { /* raise exception */ - struct siginfo siginfo; + int si_code; - clear_siginfo(&siginfo); - siginfo.si_signo = SIGFPE; - siginfo.si_errno = 0; - siginfo.si_code = FPE_FLTUNK; /* default code */ - siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); + si_code = FPE_FLTUNK; /* default code */ if (isr & 0x880) { - siginfo.si_code = FPE_FLTOVF; + si_code = FPE_FLTOVF; } else if (isr & 0x1100) { - siginfo.si_code = FPE_FLTUND; + si_code = FPE_FLTUND; } else if (isr & 0x2200) { - siginfo.si_code = FPE_FLTRES; + si_code = FPE_FLTRES; } - siginfo.si_isr = isr; - siginfo.si_flags = __ISR_VALID; - siginfo.si_imm = 0; - force_sig_info(SIGFPE, &siginfo, current); + force_sig_fault(SIGFPE, si_code, + (void __user *) (regs->cr_iip + ia64_psr(regs)->ri), + 0, __ISR_VALID, isr, current); } } return 0; @@ -408,7 +389,6 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, struct pt_regs regs) { struct illegal_op_return rv; - struct siginfo si; char buf[128]; #ifdef CONFIG_IA64_BRL_EMU @@ -426,11 +406,9 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, if (die_if_kernel(buf, ®s, 0)) return rv; - clear_siginfo(&si); - si.si_signo = SIGILL; - si.si_code = ILL_ILLOPC; - si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); - force_sig_info(SIGILL, &si, current); + force_sig_fault(SIGILL, ILL_ILLOPC, + (void __user *) (regs.cr_iip + ia64_psr(®s)->ri), + 0, 0, 0, current); return rv; } @@ -441,7 +419,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, { unsigned long code, error = isr, iip; char buf[128]; - int result, sig; + int result, sig, si_code; static const char *reason[] = { "IA-64 Illegal Operation fault", "IA-64 Privileged Operation fault", @@ -490,7 +468,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 26: /* NaT Consumption */ if (user_mode(®s)) { - struct siginfo siginfo; void __user *addr; if (((isr >> 4) & 0xf) == 2) { @@ -505,15 +482,8 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); } - clear_siginfo(&siginfo); - siginfo.si_signo = sig; - siginfo.si_code = code; - siginfo.si_errno = 0; - siginfo.si_addr = addr; - siginfo.si_imm = vector; - siginfo.si_flags = __ISR_VALID; - siginfo.si_isr = isr; - force_sig_info(sig, &siginfo, current); + force_sig_fault(sig, code, addr, + vector, __ISR_VALID, isr, current); return; } else if (ia64_done_with_exception(®s)) return; @@ -522,17 +492,8 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 31: /* Unsupported Data Reference */ if (user_mode(®s)) { - struct siginfo siginfo; - - clear_siginfo(&siginfo); - siginfo.si_signo = SIGILL; - siginfo.si_code = ILL_ILLOPN; - siginfo.si_errno = 0; - siginfo.si_addr = (void __user *) iip; - siginfo.si_imm = vector; - siginfo.si_flags = __ISR_VALID; - siginfo.si_isr = isr; - force_sig_info(SIGILL, &siginfo, current); + force_sig_fault(SIGILL, ILL_ILLOPN, (void __user *) iip, + vector, __ISR_VALID, isr, current); return; } sprintf(buf, "Unsupported data reference"); @@ -541,10 +502,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 29: /* Debug */ case 35: /* Taken Branch Trap */ case 36: /* Single Step Trap */ - { - struct siginfo siginfo; - - clear_siginfo(&siginfo); if (fsys_mode(current, ®s)) { extern char __kernel_syscall_via_break[]; /* @@ -568,7 +525,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, switch (vector) { default: case 29: - siginfo.si_code = TRAP_HWBKPT; + si_code = TRAP_HWBKPT; #ifdef CONFIG_ITANIUM /* * Erratum 10 (IFA may contain incorrect address) now has @@ -578,37 +535,22 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ifa = regs.cr_iip; #endif break; - case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; - case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; + case 35: si_code = TRAP_BRANCH; ifa = 0; break; + case 36: si_code = TRAP_TRACE; ifa = 0; break; } - if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP) + if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, si_code, SIGTRAP) == NOTIFY_STOP) return; - siginfo.si_signo = SIGTRAP; - siginfo.si_errno = 0; - siginfo.si_addr = (void __user *) ifa; - siginfo.si_imm = 0; - siginfo.si_flags = __ISR_VALID; - siginfo.si_isr = isr; - force_sig_info(SIGTRAP, &siginfo, current); + force_sig_fault(SIGTRAP, si_code, (void __user *) ifa, + 0, __ISR_VALID, isr, current); return; - } case 32: /* fp fault */ case 33: /* fp trap */ result = handle_fpu_swa((vector == 32) ? 1 : 0, ®s, isr); if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) { - struct siginfo siginfo; - - clear_siginfo(&siginfo); - siginfo.si_signo = SIGFPE; - siginfo.si_errno = 0; - siginfo.si_code = FPE_FLTINV; - siginfo.si_addr = (void __user *) iip; - siginfo.si_flags = __ISR_VALID; - siginfo.si_isr = isr; - siginfo.si_imm = 0; - force_sig_info(SIGFPE, &siginfo, current); + force_sig_fault(SIGFPE, FPE_FLTINV, (void __user *) iip, + 0, __ISR_VALID, isr, current); } return; @@ -634,17 +576,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, } else { /* Unimplemented Instr. Address Trap */ if (user_mode(®s)) { - struct siginfo siginfo; - - clear_siginfo(&siginfo); - siginfo.si_signo = SIGILL; - siginfo.si_code = ILL_BADIADDR; - siginfo.si_errno = 0; - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_imm = 0; - siginfo.si_addr = (void __user *) iip; - force_sig_info(SIGILL, &siginfo, current); + force_sig_fault(SIGILL, ILL_BADIADDR, + (void __user *) iip, + 0, 0, 0, current); return; } sprintf(buf, "Unimplemented Instruction Address fault"); diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index e309f9859acc..a167a3824b35 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1298,7 +1298,6 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) mm_segment_t old_fs = get_fs(); unsigned long bundle[2]; unsigned long opcode; - struct siginfo si; const struct exception_table_entry *eh = NULL; union { unsigned long l; @@ -1537,14 +1536,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) /* NOT_REACHED */ } force_sigbus: - clear_siginfo(&si); - si.si_signo = SIGBUS; - si.si_errno = 0; - si.si_code = BUS_ADRALN; - si.si_addr = (void __user *) ifa; - si.si_flags = 0; - si.si_isr = 0; - si.si_imm = 0; - force_sig_info(SIGBUS, &si, current); + force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) ifa, + 0, 0, 0, current); goto done; } diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index a9d55ad8d67b..5baeb022f474 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -248,16 +248,8 @@ retry: return; } if (user_mode(regs)) { - struct siginfo si; - - clear_siginfo(&si); - si.si_signo = signal; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void __user *) address; - si.si_isr = isr; - si.si_flags = __ISR_VALID; - force_sig_info(signal, &si, current); + force_sig_fault(signal, code, (void __user *) address, + 0, __ISR_VALID, isr, current); return; } diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 1d5483f6e457..85904b73e261 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -621,7 +621,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -657,7 +656,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 52a0af127951..9b3818bbb68b 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -578,7 +578,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -614,7 +613,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index b3103e51268a..769677809945 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -599,7 +599,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -635,7 +634,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index fb7d651a4cab..7dd264ddf2ea 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -570,7 +570,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -606,7 +605,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 6b37f5537c39..515f7439c755 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -580,7 +580,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -616,7 +615,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index c717bf879449..8e1038ceb407 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -602,7 +602,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -638,7 +637,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 226c994ce794..62c8aaa15cc7 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -684,7 +684,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -720,7 +719,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index b383327fd77a..733973f91297 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -570,7 +570,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -606,7 +605,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 9783d3deb9e9..fee30cc9ac16 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -570,7 +570,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -606,7 +605,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index a35d10ee10cb..eebf9c9088e7 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -593,7 +593,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -629,7 +628,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 573bf922d448..dabc54318c09 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -571,7 +571,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -607,7 +606,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index efb27a7fcc55..0d9a5c2a311a 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -572,7 +572,6 @@ CONFIG_CRYPTO_ECDH=m CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_USER=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_AEGIS128=m @@ -608,7 +607,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_LZO=m diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c index e45ce4243aaa..a4ebd2445eda 100644 --- a/arch/m68k/emu/nfeth.c +++ b/arch/m68k/emu/nfeth.c @@ -47,10 +47,6 @@ static const char version[] = MODULE_AUTHOR("Milan Jurik"); MODULE_DESCRIPTION("Atari NFeth driver"); MODULE_LICENSE("GPL"); -/* -MODULE_PARM(nfeth_debug, "i"); -MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)"); -*/ static long nfEtherID; diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 30d0d3fbd4ef..e680031bda7b 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -7,6 +7,7 @@ #define NR_syscalls 380 +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 @@ -21,7 +22,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_MMAP diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S index faf18f4fab1f..d19a94754d56 100644 --- a/arch/m68k/kernel/sun3-head.S +++ b/arch/m68k/kernel/sun3-head.S @@ -88,9 +88,3 @@ kpt: .long 0 availmem: .long 0 -| todo: remove next two. --m -is_medusa: - .long 0 -m68k_pgtable_cachemode: - .long 0 - diff --git a/arch/m68k/kernel/uboot.c b/arch/m68k/kernel/uboot.c index b29c3b241e1b..107082877064 100644 --- a/arch/m68k/kernel/uboot.c +++ b/arch/m68k/kernel/uboot.c @@ -102,5 +102,5 @@ __init void process_uboot_commandline(char *commandp, int size) } parse_uboot_commandline(commandp, len); - commandp[size - 1] = 0; + commandp[len - 1] = 0; } diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 1b083c500b9a..ebb3b6d169ea 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -37,35 +37,6 @@ static void (*rom_reset)(void); #ifdef CONFIG_ADB_CUDA -static time64_t cuda_read_time(void) -{ - struct adb_request req; - time64_t time; - - if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) - return 0; - while (!req.complete) - cuda_poll(); - - time = (u32)((req.reply[3] << 24) | (req.reply[4] << 16) | - (req.reply[5] << 8) | req.reply[6]); - - return time - RTC_OFFSET; -} - -static void cuda_write_time(time64_t time) -{ - struct adb_request req; - u32 data = lower_32_bits(time + RTC_OFFSET); - - if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, - (data >> 24) & 0xFF, (data >> 16) & 0xFF, - (data >> 8) & 0xFF, data & 0xFF) < 0) - return; - while (!req.complete) - cuda_poll(); -} - static __u8 cuda_read_pram(int offset) { struct adb_request req; @@ -91,33 +62,6 @@ static void cuda_write_pram(int offset, __u8 data) #endif /* CONFIG_ADB_CUDA */ #ifdef CONFIG_ADB_PMU -static time64_t pmu_read_time(void) -{ - struct adb_request req; - time64_t time; - - if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) - return 0; - pmu_wait_complete(&req); - - time = (u32)((req.reply[0] << 24) | (req.reply[1] << 16) | - (req.reply[2] << 8) | req.reply[3]); - - return time - RTC_OFFSET; -} - -static void pmu_write_time(time64_t time) -{ - struct adb_request req; - u32 data = lower_32_bits(time + RTC_OFFSET); - - if (pmu_request(&req, NULL, 5, PMU_SET_RTC, - (data >> 24) & 0xFF, (data >> 16) & 0xFF, - (data >> 8) & 0xFF, data & 0xFF) < 0) - return; - pmu_wait_complete(&req); -} - static __u8 pmu_read_pram(int offset) { struct adb_request req; @@ -295,13 +239,17 @@ static time64_t via_read_time(void) * is basically any machine with Mac II-style ADB. */ -static void via_write_time(time64_t time) +static void via_set_rtc_time(struct rtc_time *tm) { union { __u8 cdata[4]; __u32 idata; } data; __u8 temp; + time64_t time; + + time = mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); /* Clear the write protect bit */ @@ -641,12 +589,12 @@ int mac_hwclk(int op, struct rtc_time *t) #ifdef CONFIG_ADB_CUDA case MAC_ADB_EGRET: case MAC_ADB_CUDA: - now = cuda_read_time(); + now = cuda_get_time(); break; #endif #ifdef CONFIG_ADB_PMU case MAC_ADB_PB2: - now = pmu_read_time(); + now = pmu_get_time(); break; #endif default: @@ -665,24 +613,21 @@ int mac_hwclk(int op, struct rtc_time *t) __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - now = mktime64(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, - t->tm_hour, t->tm_min, t->tm_sec); - switch (macintosh_config->adb_type) { case MAC_ADB_IOP: case MAC_ADB_II: case MAC_ADB_PB1: - via_write_time(now); + via_set_rtc_time(t); break; #ifdef CONFIG_ADB_CUDA case MAC_ADB_EGRET: case MAC_ADB_CUDA: - cuda_write_time(now); + cuda_set_rtc_time(t); break; #endif #ifdef CONFIG_ADB_PMU case MAC_ADB_PB2: - pmu_write_time(now); + pmu_set_rtc_time(t); break; #endif default: diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 4f3ab5707265..0823d291fbeb 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -65,9 +65,7 @@ boot := arch/microblaze/boot # Are we making a simpleImage.<boardname> target? If so, crack out the boardname DTB:=$(subst simpleImage.,,$(filter simpleImage.%, $(MAKECMDGOALS))) -ifneq ($(DTB),) - core-y += $(boot)/dts/ -endif +core-y += $(boot)/dts/ # defines filename extension depending memory management type ifeq ($(CONFIG_MMU),) diff --git a/arch/microblaze/boot/dts/Makefile b/arch/microblaze/boot/dts/Makefile index 1f77913d404d..c7324e74f9ef 100644 --- a/arch/microblaze/boot/dts/Makefile +++ b/arch/microblaze/boot/dts/Makefile @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 # +dtb-y := system.dtb + +ifneq ($(DTB),) obj-y += linked_dtb.o # Ensure system.dtb exists @@ -11,6 +14,7 @@ ifneq ($(DTB),system) $(obj)/system.dtb: $(obj)/$(DTB).dtb $(call if_changed,cp) endif +endif quiet_cmd_cp = CP $< $@$2 cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false) diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index a62d09420a47..f42c40f5001b 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -15,6 +15,7 @@ /* #define __ARCH_WANT_OLD_READDIR */ /* #define __ARCH_WANT_OLD_STAT */ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME @@ -26,7 +27,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE /* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */ #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 96b3f26d16be..ef2f49471a2a 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -89,9 +89,9 @@ static struct device_node *cpu; void __init setup_cpuinfo(void) { - cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu"); + cpu = of_get_cpu_node(0, NULL); if (!cpu) - pr_err("You don't have cpu!!!\n"); + pr_err("You don't have cpu or are missing cpu reg property!!!\n"); pr_info("%s: initialising\n", __func__); @@ -117,6 +117,8 @@ void __init setup_cpuinfo(void) if (cpuinfo.mmu_privins) pr_warn("%s: Stream instructions enabled" " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__); + + of_node_put(cpu); } void __init setup_cpuinfo_clk(void) diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 289d0e7f3e3a..e1f3e8741292 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -117,8 +117,6 @@ SECTIONS { CON_INITCALL } - SECURITY_INIT - __init_end_before_initramfs = .; .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 77c022e56e6e..80778b40f8fa 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -21,6 +21,7 @@ config MIPS select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE select GENERIC_CPU_AUTOPROBE + select GENERIC_IOMAP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW select GENERIC_LIB_ASHLDI3 @@ -28,7 +29,6 @@ config MIPS select GENERIC_LIB_CMPDI2 select GENERIC_LIB_LSHRDI3 select GENERIC_LIB_UCMPDI2 - select GENERIC_PCI_IOMAP select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL @@ -75,9 +75,10 @@ config MIPS select MODULES_USE_ELF_RELA if MODULES && 64BIT select MODULES_USE_ELF_REL if MODULES select PERF_USE_VMALLOC - select RTC_LIB if !MACH_LOONGSON64 + select RTC_LIB select SYSCTL_EXCEPTION_TRACE select VIRT_TO_BUS + select NO_BOOTMEM menu "Machine selection" @@ -132,6 +133,7 @@ config MIPS_GENERIC select USB_UHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN select USE_OF + select UHI_BOOT help Select this to build a kernel which aims to support multiple boards, generally using a flattened device tree passed from the bootloader @@ -1149,6 +1151,7 @@ config NO_IOPORT_MAP config GENERIC_CSUM bool + default y if !CPU_HAS_LOAD_STORE_LR config GENERIC_ISA_DMA bool @@ -1367,6 +1370,7 @@ config CPU_LOONGSON3 select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC select MIPS_PGD_C0_CONTEXT @@ -1443,6 +1447,7 @@ config CPU_MIPS32_R1 bool "MIPS32 Release 1" depends on SYS_HAS_CPU_MIPS32_R1 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM help @@ -1460,6 +1465,7 @@ config CPU_MIPS32_R2 bool "MIPS32 Release 2" depends on SYS_HAS_CPU_MIPS32_R2 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_MSA @@ -1478,7 +1484,6 @@ config CPU_MIPS32_R6 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_MSA - select GENERIC_CSUM select HAVE_KVM select MIPS_O32_FP64_SUPPORT help @@ -1491,6 +1496,7 @@ config CPU_MIPS64_R1 bool "MIPS64 Release 1" depends on SYS_HAS_CPU_MIPS64_R1 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1510,6 +1516,7 @@ config CPU_MIPS64_R2 bool "MIPS64 Release 2" depends on SYS_HAS_CPU_MIPS64_R2 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1531,7 +1538,6 @@ config CPU_MIPS64_R6 select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_MSA - select GENERIC_CSUM select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32 select HAVE_KVM help @@ -1544,6 +1550,7 @@ config CPU_R3000 bool "R3000" depends on SYS_HAS_CPU_R3000 select CPU_HAS_WB + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM help @@ -1558,12 +1565,14 @@ config CPU_TX39XX bool "R39XX" depends on SYS_HAS_CPU_TX39XX select CPU_SUPPORTS_32BIT_KERNEL + select CPU_HAS_LOAD_STORE_LR config CPU_VR41XX bool "R41xx" depends on SYS_HAS_CPU_VR41XX select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL + select CPU_HAS_LOAD_STORE_LR help The options selects support for the NEC VR4100 series of processors. Only choose this option if you have one of these processors as a @@ -1575,6 +1584,7 @@ config CPU_R4300 depends on SYS_HAS_CPU_R4300 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL + select CPU_HAS_LOAD_STORE_LR help MIPS Technologies R4300-series processors. @@ -1584,6 +1594,7 @@ config CPU_R4X00 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR help MIPS Technologies R4000-series processors other than 4300, including the R4000, R4400, R4600, and 4700. @@ -1592,6 +1603,7 @@ config CPU_TX49XX bool "R49XX" depends on SYS_HAS_CPU_TX49XX select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES @@ -1602,6 +1614,7 @@ config CPU_R5000 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR help MIPS Technologies R5000-series processors other than the Nevada. @@ -1611,6 +1624,7 @@ config CPU_R5432 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR config CPU_R5500 bool "R5500" @@ -1618,6 +1632,7 @@ config CPU_R5500 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR help NEC VR5500 and VR5500A series processors implement 64-bit MIPS IV instruction set. @@ -1628,6 +1643,7 @@ config CPU_NEVADA select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HUGEPAGES + select CPU_HAS_LOAD_STORE_LR help QED / PMC-Sierra RM52xx-series ("Nevada") processors. @@ -1635,6 +1651,7 @@ config CPU_R8000 bool "R8000" depends on SYS_HAS_CPU_R8000 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_64BIT_KERNEL help MIPS Technologies R8000 processors. Note these processors are @@ -1644,6 +1661,7 @@ config CPU_R10000 bool "R10000" depends on SYS_HAS_CPU_R10000 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1655,6 +1673,7 @@ config CPU_RM7000 bool "RM7000" depends on SYS_HAS_CPU_RM7000 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1663,6 +1682,7 @@ config CPU_RM7000 config CPU_SB1 bool "SB1" depends on SYS_HAS_CPU_SB1 + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1673,6 +1693,7 @@ config CPU_CAVIUM_OCTEON bool "Cavium Octeon processor" depends on SYS_HAS_CPU_CAVIUM_OCTEON select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_64BIT_KERNEL select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM @@ -1702,6 +1723,7 @@ config CPU_BMIPS select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_CPUFREQ select MIPS_EXTERNAL_TIMER help @@ -1710,6 +1732,7 @@ config CPU_BMIPS config CPU_XLR bool "Netlogic XLR SoC" depends on SYS_HAS_CPU_XLR + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM @@ -1728,6 +1751,7 @@ config CPU_XLP select WEAK_ORDERING select WEAK_REORDERING_BEYOND_LLSC select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_MIPSR2 select CPU_SUPPORTS_HUGEPAGES select MIPS_ASID_BITS_VARIABLE @@ -1833,12 +1857,14 @@ config CPU_LOONGSON2 select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES select ARCH_HAS_PHYS_TO_DMA + select CPU_HAS_LOAD_STORE_LR config CPU_LOONGSON1 bool select CPU_MIPS32 select CPU_MIPSR1 select CPU_HAS_PREFETCH + select CPU_HAS_LOAD_STORE_LR select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_CPUFREQ @@ -2452,6 +2478,13 @@ config XKS01 config CPU_HAS_RIXI bool +config CPU_HAS_LOAD_STORE_LR + bool + help + CPU has support for unaligned load and store instructions: + LWL, LWR, SWL, SWR (Load/store word left/right). + LDL, LDR, SDL, SDR (Load/store doubleword left/right, for 64bit systems). + # # Vectored interrupt mode is an R2 feature # @@ -2899,6 +2932,9 @@ config USE_OF select OF_EARLY_FLATTREE select IRQ_DOMAIN +config UHI_BOOT + bool + config BUILTIN_DTB bool diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d74b3742fa5d..15a84cfd0719 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -13,6 +13,7 @@ # archscripts: scripts_basic + $(Q)$(MAKE) $(build)=arch/mips/tools elf-entry $(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs KBUILD_DEFCONFIG := 32r2el_defconfig @@ -230,6 +231,8 @@ toolchain-xpa := $(call cc-option-yn,$(xpa-cflags-y) -mxpa) cflags-$(toolchain-xpa) += -DTOOLCHAIN_SUPPORTS_XPA toolchain-crc := $(call cc-option-yn,$(mips-cflags) -Wa$(comma)-mcrc) cflags-$(toolchain-crc) += -DTOOLCHAIN_SUPPORTS_CRC +toolchain-dsp := $(call cc-option-yn,$(mips-cflags) -Wa$(comma)-mdsp) +cflags-$(toolchain-dsp) += -DTOOLCHAIN_SUPPORTS_DSP # # Firmware support @@ -257,13 +260,7 @@ ifdef CONFIG_PHYSICAL_START load-y = $(CONFIG_PHYSICAL_START) endif -# Sign-extend the entry point to 64 bits if retrieved as a 32-bit number. -entry-y = $(shell $(OBJDUMP) -f vmlinux 2>/dev/null \ - | sed -n '/^start address / { \ - s/^.* //; \ - s/0x\([0-7].......\)$$/0x00000000\1/; \ - s/0x\(........\)$$/0xffffffff\1/; p }') - +entry-y = $(shell $(objtree)/arch/mips/tools/elf-entry vmlinux) cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ @@ -407,18 +404,7 @@ endif CLEAN_FILES += vmlinux.32 vmlinux.64 # device-trees -core-$(CONFIG_BUILTIN_DTB) += arch/mips/boot/dts/ - -%.dtb %.dtb.S %.dtb.o: | scripts - $(Q)$(MAKE) $(build)=arch/mips/boot/dts arch/mips/boot/dts/$@ - -PHONY += dtbs -dtbs: scripts - $(Q)$(MAKE) $(build)=arch/mips/boot/dts - -PHONY += dtbs_install -dtbs_install: - $(Q)$(MAKE) $(dtbinst)=arch/mips/boot/dts +core-y += arch/mips/boot/dts/ archprepare: ifdef CONFIG_MIPS32_N32 @@ -461,8 +447,6 @@ define archhelp echo ' uImage.lzma - U-Boot image (lzma)' echo ' uImage.lzo - U-Boot image (lzo)' echo ' uzImage.bin - U-Boot image (self-extracting)' - echo ' dtbs - Device-tree blobs for enabled boards' - echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' echo echo ' These will be default as appropriate for a configured platform.' echo diff --git a/arch/mips/bcm47xx/workarounds.c b/arch/mips/bcm47xx/workarounds.c index 1a8a07e7a563..46eddbec8d9f 100644 --- a/arch/mips/bcm47xx/workarounds.c +++ b/arch/mips/bcm47xx/workarounds.c @@ -5,9 +5,8 @@ #include <bcm47xx_board.h> #include <bcm47xx.h> -static void __init bcm47xx_workarounds_netgear_wnr3500l(void) +static void __init bcm47xx_workarounds_enable_usb_power(int usb_power) { - const int usb_power = 12; int err; err = gpio_request_one(usb_power, GPIOF_OUT_INIT_HIGH, "usb_power"); @@ -23,7 +22,10 @@ void __init bcm47xx_workarounds(void) switch (board) { case BCM47XX_BOARD_NETGEAR_WNR3500L: - bcm47xx_workarounds_netgear_wnr3500l(); + bcm47xx_workarounds_enable_usb_power(12); + break; + case BCM47XX_BOARD_NETGEAR_WNDR3400_V3: + bcm47xx_workarounds_enable_usb_power(21); break; default: /* No workaround(s) needed */ diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c index 231fc5ce375e..6329c5f780d6 100644 --- a/arch/mips/bmips/setup.c +++ b/arch/mips/bmips/setup.c @@ -153,8 +153,6 @@ void __init plat_time_init(void) mips_hpt_frequency = freq; } -extern const char __appended_dtb; - void __init plat_mem_setup(void) { void *dtb; @@ -164,15 +162,10 @@ void __init plat_mem_setup(void) ioport_resource.start = 0; ioport_resource.end = ~0; -#ifdef CONFIG_MIPS_ELF_APPENDED_DTB - if (!fdt_check_header(&__appended_dtb)) - dtb = (void *)&__appended_dtb; - else -#endif /* intended to somewhat resemble ARM; see Documentation/arm/Booting */ if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) dtb = phys_to_virt(fw_arg2); - else if (fw_passed_dtb) /* UHI interface */ + else if (fw_passed_dtb) /* UHI interface or appended dtb */ dtb = (void *)fw_passed_dtb; else if (__dtb_start != __dtb_end) dtb = (void *)__dtb_start; diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 26c6b561d6f7..6fb16fd24035 100644 --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi @@ -154,6 +154,21 @@ clock-names = "baud", "module"; }; + dmac: dma-controller@13020000 { + compatible = "ingenic,jz4740-dma"; + reg = <0x13020000 0xbc + 0x13020300 0x14>; + #dma-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <29>; + + clocks = <&cgu JZ4740_CLK_DMA>; + + /* Disable dmac until we have something that uses it */ + status = "disabled"; + }; + uhc: uhc@13030000 { compatible = "ingenic,jz4740-ohci", "generic-ohci"; reg = <0x13030000 0x1000>; diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi index 7c2804f3f5f1..49ede6c14ff3 100644 --- a/arch/mips/boot/dts/ingenic/jz4770.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4770.dtsi @@ -196,6 +196,36 @@ status = "disabled"; }; + dmac0: dma-controller@13420000 { + compatible = "ingenic,jz4770-dma"; + reg = <0x13420000 0xC0 + 0x13420300 0x20>; + + #dma-cells = <1>; + + clocks = <&cgu JZ4770_CLK_DMA>; + interrupt-parent = <&intc>; + interrupts = <24>; + + /* Disable dmac0 until we have something that uses it */ + status = "disabled"; + }; + + dmac1: dma-controller@13420100 { + compatible = "ingenic,jz4770-dma"; + reg = <0x13420100 0xC0 + 0x13420400 0x20>; + + #dma-cells = <1>; + + clocks = <&cgu JZ4770_CLK_DMA>; + interrupt-parent = <&intc>; + interrupts = <23>; + + /* Disable dmac1 until we have something that uses it */ + status = "disabled"; + }; + uhc: uhc@13430000 { compatible = "generic-ohci"; reg = <0x13430000 0x1000>; diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi index ce93d57f1b4d..b03cdec56de9 100644 --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi @@ -266,7 +266,8 @@ dma: dma@13420000 { compatible = "ingenic,jz4780-dma"; - reg = <0x13420000 0x10000>; + reg = <0x13420000 0x400 + 0x13421000 0x40>; #dma-cells = <2>; interrupt-parent = <&intc>; diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi index 2dd950181f8a..510be63c8bdf 100644 --- a/arch/mips/boot/dts/lantiq/danube.dtsi +++ b/arch/mips/boot/dts/lantiq/danube.dtsi @@ -10,12 +10,12 @@ }; }; - biu@1F800000 { + biu@1f800000 { #address-cells = <1>; #size-cells = <1>; compatible = "lantiq,biu", "simple-bus"; - reg = <0x1F800000 0x800000>; - ranges = <0x0 0x1F800000 0x7FFFFF>; + reg = <0x1f800000 0x800000>; + ranges = <0x0 0x1f800000 0x7fffff>; icu0: icu@80200 { #interrupt-cells = <1>; @@ -24,18 +24,18 @@ reg = <0x80200 0x120>; }; - watchdog@803F0 { + watchdog@803f0 { compatible = "lantiq,wdt"; - reg = <0x803F0 0x10>; + reg = <0x803f0 0x10>; }; }; - sram@1F000000 { + sram@1f000000 { #address-cells = <1>; #size-cells = <1>; compatible = "lantiq,sram"; - reg = <0x1F000000 0x800000>; - ranges = <0x0 0x1F000000 0x7FFFFF>; + reg = <0x1f000000 0x800000>; + ranges = <0x0 0x1f000000 0x7fffff>; eiu0: eiu@101000 { #interrupt-cells = <1>; @@ -66,41 +66,41 @@ #address-cells = <1>; #size-cells = <1>; compatible = "lantiq,fpi", "simple-bus"; - ranges = <0x0 0x10000000 0xEEFFFFF>; - reg = <0x10000000 0xEF00000>; + ranges = <0x0 0x10000000 0xeefffff>; + reg = <0x10000000 0xef00000>; - gptu@E100A00 { + gptu@e100a00 { compatible = "lantiq,gptu-xway"; - reg = <0xE100A00 0x100>; + reg = <0xe100a00 0x100>; }; - serial@E100C00 { + serial@e100c00 { compatible = "lantiq,asc"; - reg = <0xE100C00 0x400>; + reg = <0xe100c00 0x400>; interrupt-parent = <&icu0>; interrupts = <112 113 114>; }; - dma0: dma@E104100 { + dma0: dma@e104100 { compatible = "lantiq,dma-xway"; - reg = <0xE104100 0x800>; + reg = <0xe104100 0x800>; }; - ebu0: ebu@E105300 { + ebu0: ebu@e105300 { compatible = "lantiq,ebu-xway"; - reg = <0xE105300 0x100>; + reg = <0xe105300 0x100>; }; - pci0: pci@E105400 { + pci0: pci@e105400 { #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; compatible = "lantiq,pci-xway"; bus-range = <0x0 0x0>; ranges = <0x2000000 0 0x8000000 0x8000000 0 0x2000000 /* pci memory */ - 0x1000000 0 0x00000000 0xAE00000 0 0x200000>; /* io space */ + 0x1000000 0 0x00000000 0xae00000 0 0x200000>; /* io space */ reg = <0x7000000 0x8000 /* config space */ - 0xE105400 0x400>; /* pci bridge */ + 0xe105400 0x400>; /* pci bridge */ }; }; }; diff --git a/arch/mips/boot/dts/lantiq/easy50712.dts b/arch/mips/boot/dts/lantiq/easy50712.dts index c37a33962f28..1ce20b7d05cb 100644 --- a/arch/mips/boot/dts/lantiq/easy50712.dts +++ b/arch/mips/boot/dts/lantiq/easy50712.dts @@ -52,14 +52,14 @@ }; }; - gpio: pinmux@E100B10 { + gpio: pinmux@e100b10 { compatible = "lantiq,danube-pinctrl"; pinctrl-names = "default"; pinctrl-0 = <&state_default>; #gpio-cells = <2>; gpio-controller; - reg = <0xE100B10 0xA0>; + reg = <0xe100b10 0xa0>; state_default: pinmux { stp { @@ -82,26 +82,26 @@ }; }; - etop@E180000 { + etop@e180000 { compatible = "lantiq,etop-xway"; - reg = <0xE180000 0x40000>; + reg = <0xe180000 0x40000>; interrupt-parent = <&icu0>; interrupts = <73 78>; phy-mode = "rmii"; mac-address = [ 00 11 22 33 44 55 ]; }; - stp0: stp@E100BB0 { + stp0: stp@e100bb0 { #gpio-cells = <2>; compatible = "lantiq,gpio-stp-xway"; gpio-controller; - reg = <0xE100BB0 0x40>; + reg = <0xe100bb0 0x40>; lantiq,shadow = <0xfff>; lantiq,groups = <0x3>; }; - pci@E105400 { + pci@e105400 { lantiq,bus-clock = <33333333>; interrupt-map-mask = <0xf800 0x0 0x0 0x7>; interrupt-map = < diff --git a/arch/mips/boot/dts/mscc/Makefile b/arch/mips/boot/dts/mscc/Makefile index 9a9bb7ea0503..ec6f5b2bf093 100644 --- a/arch/mips/boot/dts/mscc/Makefile +++ b/arch/mips/boot/dts/mscc/Makefile @@ -1,3 +1,3 @@ -dtb-$(CONFIG_MSCC_OCELOT) += ocelot_pcb123.dtb +dtb-$(CONFIG_MSCC_OCELOT) += ocelot_pcb123.dtb ocelot_pcb120.dtb obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y)) diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi index 8ce317c5b9ed..90c60d42f571 100644 --- a/arch/mips/boot/dts/mscc/ocelot.dtsi +++ b/arch/mips/boot/dts/mscc/ocelot.dtsi @@ -78,6 +78,19 @@ status = "disabled"; }; + i2c: i2c@100400 { + compatible = "mscc,ocelot-i2c", "snps,designware-i2c"; + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; + reg = <0x100400 0x100>, <0x198 0x8>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8>; + clocks = <&ahb_clk>; + + status = "disabled"; + }; + uart2: serial@100800 { pinctrl-0 = <&uart2_pins>; pinctrl-names = "default"; @@ -182,6 +195,11 @@ interrupts = <13>; #interrupt-cells = <2>; + i2c_pins: i2c-pins { + pins = "GPIO_16", "GPIO_17"; + function = "twi"; + }; + uart_pins: uart-pins { pins = "GPIO_6", "GPIO_7"; function = "uart"; @@ -196,6 +214,7 @@ pins = "GPIO_14", "GPIO_15"; function = "miim1"; }; + }; mdio0: mdio@107009c { diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts new file mode 100644 index 000000000000..33991fd209f5 --- /dev/null +++ b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Copyright (c) 2017 Microsemi Corporation */ + +/dts-v1/; + +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/phy/phy-ocelot-serdes.h> +#include "ocelot.dtsi" + +/ { + compatible = "mscc,ocelot-pcb120", "mscc,ocelot"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0e000000>; + }; +}; + +&gpio { + phy_int_pins: phy_int_pins { + pins = "GPIO_4"; + function = "gpio"; + }; +}; + +&mdio0 { + status = "okay"; +}; + +&mdio1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&miim1>, <&phy_int_pins>; + + phy7: ethernet-phy@0 { + reg = <0>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpio>; + }; + phy6: ethernet-phy@1 { + reg = <1>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpio>; + }; + phy5: ethernet-phy@2 { + reg = <2>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpio>; + }; + phy4: ethernet-phy@3 { + reg = <3>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&gpio>; + }; +}; + +&port0 { + phy-handle = <&phy0>; +}; + +&port1 { + phy-handle = <&phy1>; +}; + +&port2 { + phy-handle = <&phy2>; +}; + +&port3 { + phy-handle = <&phy3>; +}; + +&port4 { + phy-handle = <&phy7>; + phy-mode = "sgmii"; + phys = <&serdes 4 SERDES1G(2)>; +}; + +&port5 { + phy-handle = <&phy4>; + phy-mode = "sgmii"; + phys = <&serdes 5 SERDES1G(5)>; +}; + +&port6 { + phy-handle = <&phy6>; + phy-mode = "sgmii"; + phys = <&serdes 6 SERDES1G(3)>; +}; + +&port9 { + phy-handle = <&phy5>; + phy-mode = "sgmii"; + phys = <&serdes 9 SERDES1G(4)>; +}; + +&uart0 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts index 2266027759f9..ef852f382da8 100644 --- a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts +++ b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts @@ -36,6 +36,12 @@ }; }; +&i2c { + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <300>; + status = "okay"; +}; + &mdio0 { status = "okay"; }; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 8272d8c648ca..cc1d8525e651 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1180,8 +1180,8 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d, type = IRQ_TYPE_LEVEL_LOW; break; default: - pr_err("Error: (%s) Invalid irq trigger specification: %x\n", - node->name, + pr_err("Error: (%pOFn) Invalid irq trigger specification: %x\n", + node, trigger); type = IRQ_TYPE_LEVEL_LOW; break; @@ -2271,8 +2271,8 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, parent_irq = irq_of_parse_and_map(ciu_node, 0); if (!parent_irq) { - pr_err("ERROR: Couldn't acquire parent_irq for %s\n", - ciu_node->name); + pr_err("ERROR: Couldn't acquire parent_irq for %pOFn\n", + ciu_node); return -EINVAL; } @@ -2283,7 +2283,7 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, addr = of_get_address(ciu_node, 0, NULL, NULL); if (!addr) { - pr_err("ERROR: Couldn't acquire reg(0) %s\n", ciu_node->name); + pr_err("ERROR: Couldn't acquire reg(0) %pOFn\n", ciu_node); return -EINVAL; } host_data->raw_reg = (u64)phys_to_virt( @@ -2291,7 +2291,7 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, addr = of_get_address(ciu_node, 1, NULL, NULL); if (!addr) { - pr_err("ERROR: Couldn't acquire reg(1) %s\n", ciu_node->name); + pr_err("ERROR: Couldn't acquire reg(1) %pOFn\n", ciu_node); return -EINVAL; } host_data->en_reg = (u64)phys_to_virt( @@ -2299,8 +2299,8 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, r = of_property_read_u32(ciu_node, "cavium,max-bits", &val); if (r) { - pr_err("ERROR: Couldn't read cavium,max-bits from %s\n", - ciu_node->name); + pr_err("ERROR: Couldn't read cavium,max-bits from %pOFn\n", + ciu_node); return r; } host_data->max_bits = val; diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index c2426232db06..dfb95cffef3e 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1161,15 +1161,12 @@ void __init device_tree_init(void) bool do_prune; bool fill_mac; -#ifdef CONFIG_MIPS_ELF_APPENDED_DTB - if (!fdt_check_header(&__appended_dtb)) { - fdt = &__appended_dtb; + if (fw_passed_dtb) { + fdt = (void *)fw_passed_dtb; do_prune = false; fill_mac = true; pr_info("Using appended Device Tree.\n"); - } else -#endif - if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { + } else if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { fdt = phys_to_virt(octeon_bootinfo->fdt_addr); if (fdt_check_header(fdt)) panic("Corrupt Device Tree passed to kernel."); diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 75e7c8625659..39f2a2ec1286 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -15,6 +15,7 @@ #include <linux/sched/task_stack.h> #include <linux/init.h> #include <linux/export.h> +#include <linux/kexec.h> #include <asm/mmu_context.h> #include <asm/time.h> @@ -424,6 +425,9 @@ const struct plat_smp_ops octeon_smp_ops = { .cpu_disable = octeon_cpu_disable, .cpu_die = octeon_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = kexec_nonboot_cpu_jump, +#endif }; static irqreturn_t octeon_78xx_reched_interrupt(int irq, void *dev_id) @@ -501,6 +505,9 @@ static const struct plat_smp_ops octeon_78xx_smp_ops = { .cpu_disable = octeon_cpu_disable, .cpu_die = octeon_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = kexec_nonboot_cpu_jump, +#endif }; void __init octeon_setup_smp(void) diff --git a/arch/mips/configs/generic/board-ocelot.config b/arch/mips/configs/generic/board-ocelot.config index aa815761d85e..f607888d2483 100644 --- a/arch/mips/configs/generic/board-ocelot.config +++ b/arch/mips/configs/generic/board-ocelot.config @@ -18,17 +18,25 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_GPIO_SYSFS=y +CONFIG_NETDEVICES=y +CONFIG_MSCC_OCELOT_SWITCH=y +CONFIG_MSCC_OCELOT_SWITCH_OCELOT=y +CONFIG_MDIO_MSCC_MIIM=y +CONFIG_MICROSEMI_PHY=y CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_BITBANG=y CONFIG_SPI_DESIGNWARE=y +CONFIG_SPI_DW_MMIO=y CONFIG_SPI_SPIDEV=y +CONFIG_GPIO_SYSFS=y + CONFIG_POWER_RESET=y CONFIG_POWER_RESET_OCELOT_RESET=y diff --git a/arch/mips/generic/Kconfig b/arch/mips/generic/Kconfig index 08e33c6b2539..fd6019802657 100644 --- a/arch/mips/generic/Kconfig +++ b/arch/mips/generic/Kconfig @@ -65,11 +65,11 @@ config FIT_IMAGE_FDT_XILFPGA Enable this to include the FDT for the MIPSfpga platform from Imagination Technologies in the FIT kernel image. -config FIT_IMAGE_FDT_OCELOT_PCB123 - bool "Include FDT for Microsemi Ocelot PCB123" +config FIT_IMAGE_FDT_OCELOT + bool "Include FDT for Microsemi Ocelot development platforms" select MSCC_OCELOT help - Enable this to include the FDT for the Ocelot PCB123 platform + Enable this to include the FDT for the Ocelot development platforms from Microsemi in the FIT kernel image. This requires u-boot on the platform. diff --git a/arch/mips/generic/Makefile b/arch/mips/generic/Makefile index d03a36f869a4..181aa1335419 100644 --- a/arch/mips/generic/Makefile +++ b/arch/mips/generic/Makefile @@ -15,5 +15,4 @@ obj-y += proc.o obj-$(CONFIG_YAMON_DT_SHIM) += yamon-dt.o obj-$(CONFIG_LEGACY_BOARD_SEAD3) += board-sead3.o obj-$(CONFIG_LEGACY_BOARD_OCELOT) += board-ocelot.o -obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_VIRT_BOARD_RANCHU) += board-ranchu.o diff --git a/arch/mips/generic/Platform b/arch/mips/generic/Platform index 879cb80396c8..eaa19d189324 100644 --- a/arch/mips/generic/Platform +++ b/arch/mips/generic/Platform @@ -16,5 +16,5 @@ all-$(CONFIG_MIPS_GENERIC) := vmlinux.gz.itb its-y := vmlinux.its.S its-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += board-boston.its.S its-$(CONFIG_FIT_IMAGE_FDT_NI169445) += board-ni169445.its.S -its-$(CONFIG_FIT_IMAGE_FDT_OCELOT_PCB123) += board-ocelot_pcb123.its.S +its-$(CONFIG_FIT_IMAGE_FDT_OCELOT) += board-ocelot.its.S its-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += board-xilfpga.its.S diff --git a/arch/mips/generic/board-ocelot_pcb123.its.S b/arch/mips/generic/board-ocelot.its.S index 5a7d5e1c878a..3da23988149a 100644 --- a/arch/mips/generic/board-ocelot_pcb123.its.S +++ b/arch/mips/generic/board-ocelot.its.S @@ -11,6 +11,17 @@ algo = "sha1"; }; }; + + fdt@ocelot_pcb120 { + description = "MSCC Ocelot PCB120 Device Tree"; + data = /incbin/("boot/dts/mscc/ocelot_pcb120.dtb"); + type = "flat_dt"; + arch = "mips"; + compression = "none"; + hash@0 { + algo = "sha1"; + }; + }; }; configurations { @@ -19,5 +30,11 @@ kernel = "kernel@0"; fdt = "fdt@ocelot_pcb123"; }; + + conf@ocelot_pcb120 { + description = "Ocelot Linux kernel"; + kernel = "kernel@0"; + fdt = "fdt@ocelot_pcb120"; + }; }; }; diff --git a/arch/mips/generic/kexec.c b/arch/mips/generic/kexec.c deleted file mode 100644 index 1ca409f58929..000000000000 --- a/arch/mips/generic/kexec.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016 Imagination Technologies - * Author: Marcin Nowakowski <marcin.nowakowski@mips.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include <linux/kexec.h> -#include <linux/libfdt.h> -#include <linux/uaccess.h> - -static int generic_kexec_prepare(struct kimage *image) -{ - int i; - - for (i = 0; i < image->nr_segments; i++) { - struct fdt_header fdt; - - if (image->segment[i].memsz <= sizeof(fdt)) - continue; - - if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt))) - continue; - - if (fdt_check_header(&fdt)) - continue; - - kexec_args[0] = -2; - kexec_args[1] = (unsigned long) - phys_to_virt((unsigned long)image->segment[i].mem); - break; - } - return 0; -} - -static int __init register_generic_kexec(void) -{ - _machine_kexec_prepare = generic_kexec_prepare; - return 0; -} -arch_initcall(register_generic_kexec); diff --git a/arch/mips/include/asm/asm-eva.h b/arch/mips/include/asm/asm-eva.h index 1e38f0e1ea3e..d80be38c4144 100644 --- a/arch/mips/include/asm/asm-eva.h +++ b/arch/mips/include/asm/asm-eva.h @@ -15,6 +15,7 @@ /* Kernel variants */ #define kernel_cache(op, base) "cache " op ", " base "\n" +#define kernel_pref(hint, base) "pref " hint ", " base "\n" #define kernel_ll(reg, addr) "ll " reg ", " addr "\n" #define kernel_sc(reg, addr) "sc " reg ", " addr "\n" #define kernel_lw(reg, addr) "lw " reg ", " addr "\n" @@ -51,6 +52,7 @@ " .set pop\n" #define user_cache(op, base) __BUILD_EVA_INSN("cachee", op, base) +#define user_pref(hint, base) __BUILD_EVA_INSN("prefe", hint, base) #define user_ll(reg, addr) __BUILD_EVA_INSN("lle", reg, addr) #define user_sc(reg, addr) __BUILD_EVA_INSN("sce", reg, addr) #define user_lw(reg, addr) __BUILD_EVA_INSN("lwe", reg, addr) @@ -72,6 +74,7 @@ #else #define user_cache(op, base) kernel_cache(op, base) +#define user_pref(hint, base) kernel_pref(hint, base) #define user_ll(reg, addr) kernel_ll(reg, addr) #define user_sc(reg, addr) kernel_sc(reg, addr) #define user_lw(reg, addr) kernel_lw(reg, addr) @@ -99,6 +102,7 @@ #else /* __ASSEMBLY__ */ #define kernel_cache(op, base) cache op, base +#define kernel_pref(hint, base) pref hint, base #define kernel_ll(reg, addr) ll reg, addr #define kernel_sc(reg, addr) sc reg, addr #define kernel_lw(reg, addr) lw reg, addr @@ -135,6 +139,7 @@ .set pop; #define user_cache(op, base) __BUILD_EVA_INSN(cachee, op, base) +#define user_pref(hint, base) __BUILD_EVA_INSN(prefe, hint, base) #define user_ll(reg, addr) __BUILD_EVA_INSN(lle, reg, addr) #define user_sc(reg, addr) __BUILD_EVA_INSN(sce, reg, addr) #define user_lw(reg, addr) __BUILD_EVA_INSN(lwe, reg, addr) @@ -155,6 +160,7 @@ #else #define user_cache(op, base) kernel_cache(op, base) +#define user_pref(hint, base) kernel_pref(hint, base) #define user_ll(reg, addr) kernel_ll(reg, addr) #define user_sc(reg, addr) kernel_sc(reg, addr) #define user_lw(reg, addr) kernel_lw(reg, addr) diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h index 81fae23ce7cd..c23527ba65d0 100644 --- a/arch/mips/include/asm/asm.h +++ b/arch/mips/include/asm/asm.h @@ -20,32 +20,6 @@ #include <asm/sgidefs.h> #include <asm/asm-eva.h> -#ifndef CAT -#ifdef __STDC__ -#define __CAT(str1, str2) str1##str2 -#else -#define __CAT(str1, str2) str1/**/str2 -#endif -#define CAT(str1, str2) __CAT(str1, str2) -#endif - -/* - * PIC specific declarations - * Not used for the kernel but here seems to be the right place. - */ -#ifdef __PIC__ -#define CPRESTORE(register) \ - .cprestore register -#define CPADD(register) \ - .cpadd register -#define CPLOAD(register) \ - .cpload register -#else -#define CPRESTORE(register) -#define CPADD(register) -#define CPLOAD(register) -#endif - /* * LEAF - declare leaf routine */ @@ -130,96 +104,6 @@ symbol = value .popsection; /* - * Build text tables - */ -#define TTABLE(string) \ - .pushsection .text; \ - .word 1f; \ - .popsection \ - .pushsection .data; \ -1: .asciiz string; \ - .popsection - -/* - * MIPS IV pref instruction. - * Use with .set noreorder only! - * - * MIPS IV implementations are free to treat this as a nop. The R5000 - * is one of them. So we should have an option not to use this instruction. - */ -#ifdef CONFIG_CPU_HAS_PREFETCH - -#define PREF(hint,addr) \ - .set push; \ - .set arch=r5000; \ - pref hint, addr; \ - .set pop - -#define PREFE(hint, addr) \ - .set push; \ - .set mips0; \ - .set eva; \ - prefe hint, addr; \ - .set pop - -#define PREFX(hint,addr) \ - .set push; \ - .set arch=r5000; \ - prefx hint, addr; \ - .set pop - -#else /* !CONFIG_CPU_HAS_PREFETCH */ - -#define PREF(hint, addr) -#define PREFE(hint, addr) -#define PREFX(hint, addr) - -#endif /* !CONFIG_CPU_HAS_PREFETCH */ - -/* - * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. - */ -#if (_MIPS_ISA == _MIPS_ISA_MIPS1) -#define MOVN(rd, rs, rt) \ - .set push; \ - .set reorder; \ - beqz rt, 9f; \ - move rd, rs; \ - .set pop; \ -9: -#define MOVZ(rd, rs, rt) \ - .set push; \ - .set reorder; \ - bnez rt, 9f; \ - move rd, rs; \ - .set pop; \ -9: -#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ -#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) -#define MOVN(rd, rs, rt) \ - .set push; \ - .set noreorder; \ - bnezl rt, 9f; \ - move rd, rs; \ - .set pop; \ -9: -#define MOVZ(rd, rs, rt) \ - .set push; \ - .set noreorder; \ - beqzl rt, 9f; \ - move rd, rs; \ - .set pop; \ -9: -#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ -#if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ - (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) -#define MOVN(rd, rs, rt) \ - movn rd, rs, rt -#define MOVZ(rd, rs, rt) \ - movz rd, rs, rt -#endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */ - -/* * Stack alignment */ #if (_MIPS_SIM == _MIPS_SIM_ABI32) diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 78675f19440f..c99166eadbde 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -9,43 +9,25 @@ #include <asm/page.h> #include <asm/ptrace.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "mips\0\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_suseconds_t; - -typedef s32 compat_pid_t; typedef s32 __compat_uid_t; typedef s32 __compat_gid_t; typedef __compat_uid_t __compat_uid32_t; typedef __compat_gid_t __compat_gid32_t; typedef u32 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u32 compat_nlink_t; typedef s32 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef s32 compat_caddr_t; typedef struct { s32 val[2]; } compat_fsid_t; -typedef s32 compat_timer_t; -typedef s32 compat_key_t; - -typedef s16 compat_short_t; -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u16 compat_ushort_t; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; @@ -59,11 +41,11 @@ struct compat_stat { s32 st_pad2[2]; compat_off_t st_size; s32 st_pad3; - compat_time_t st_atime; + old_time32_t st_atime; s32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; s32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; s32 st_ctime_nsec; s32 st_blksize; s32 st_blocks; diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h index 982bc0685330..425bb6fc3bda 100644 --- a/arch/mips/include/asm/hugetlb.h +++ b/arch/mips/include/asm/hugetlb.h @@ -10,8 +10,6 @@ #define __ASM_HUGETLB_H #include <asm/page.h> -#include <asm-generic/hugetlb.h> - static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, @@ -20,6 +18,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, return 0; } +#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE static inline int prepare_hugepage_range(struct file *file, unsigned long addr, unsigned long len) @@ -38,21 +37,7 @@ static inline int prepare_hugepage_range(struct file *file, return 0; } -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, - unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - +#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -64,29 +49,21 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, return pte; } +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { flush_tlb_page(vma, addr & huge_page_mask(hstate_vma(vma))); } +#define __HAVE_ARCH_HUGE_PTE_NONE static inline int huge_pte_none(pte_t pte) { unsigned long val = pte_val(pte) & ~_PAGE_GLOBAL; return !val || (val == (unsigned long)invalid_pte_table); } -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - +#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, @@ -105,13 +82,10 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, return changed; } -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } +#include <asm-generic/hugetlb.h> + #endif /* __ASM_HUGETLB_H */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 54c730aed327..266257d56fb6 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -20,6 +20,7 @@ #include <linux/irqflags.h> #include <asm/addrspace.h> +#include <asm/barrier.h> #include <asm/bug.h> #include <asm/byteorder.h> #include <asm/cpu.h> @@ -34,11 +35,6 @@ #include <mangle-port.h> /* - * Slowdown I/O port space accesses for antique hardware. - */ -#undef CONF_SLOWDOWN_IO - -/* * Raw operations are never swapped in software. OTOH values that raw * operations are working on may or may not have been swapped by the bus * hardware. An example use would be for flash memory that's used for @@ -50,6 +46,11 @@ # define __raw_ioswabq(a, x) (x) # define ____raw_ioswabq(a, x) (x) +# define __relaxed_ioswabb ioswabb +# define __relaxed_ioswabw ioswabw +# define __relaxed_ioswabl ioswabl +# define __relaxed_ioswabq ioswabq + /* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */ #define IO_SPACE_LIMIT 0xffff @@ -80,31 +81,29 @@ static inline void set_io_port_base(unsigned long base) } /* - * Thanks to James van Artsdalen for a better timing-fix than - * the two short jumps: using outb's to a nonexistent port seems - * to guarantee better timings even on fast machines. - * - * On the other hand, I'd like to be sure of a non-existent port: - * I feel a bit unsafe about using 0x80 (should be safe, though) - * - * Linus - * + * Provide the necessary definitions for generic iomap. We make use of + * mips_io_port_base for iomap(), but we don't reserve any low addresses for + * use with I/O ports. */ -#define __SLOW_DOWN_IO \ - __asm__ __volatile__( \ - "sb\t$0,0x80(%0)" \ - : : "r" (mips_io_port_base)); +#define HAVE_ARCH_PIO_SIZE +#define PIO_OFFSET mips_io_port_base +#define PIO_MASK IO_SPACE_LIMIT +#define PIO_RESERVED 0x0UL -#ifdef CONF_SLOWDOWN_IO -#ifdef REALLY_SLOW_IO -#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } -#else -#define SLOW_DOWN_IO __SLOW_DOWN_IO -#endif -#else -#define SLOW_DOWN_IO -#endif +/* + * Enforce in-order execution of data I/O. In the MIPS architecture + * these are equivalent to corresponding platform-specific memory + * barriers defined in <asm/barrier.h>. API pinched from PowerPC, + * with sync additionally defined. + */ +#define iobarrier_rw() mb() +#define iobarrier_r() rmb() +#define iobarrier_w() wmb() +#define iobarrier_sync() iob() + +/* Some callers use this older API instead. */ +#define mmiowb() iobarrier_w() /* * virt_to_phys - map virtual addresses to physical @@ -172,11 +171,6 @@ static inline void *isa_bus_to_virt(unsigned long address) extern void __iomem * __ioremap(phys_addr_t offset, phys_addr_t size, unsigned long flags); extern void __iounmap(const volatile void __iomem *addr); -#ifndef CONFIG_PCI -struct pci_dev; -static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} -#endif - static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long size, unsigned long flags) { @@ -316,13 +310,13 @@ static inline void iounmap(const volatile void __iomem *addr) #undef __IS_KSEG1 } -#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT) +#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_CPU_LOONGSON3) #define war_io_reorder_wmb() wmb() #else #define war_io_reorder_wmb() barrier() #endif -#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \ +#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, barrier, relax, irq) \ \ static inline void pfx##write##bwlq(type val, \ volatile void __iomem *mem) \ @@ -330,7 +324,10 @@ static inline void pfx##write##bwlq(type val, \ volatile type *__mem; \ type __val; \ \ - war_io_reorder_wmb(); \ + if (barrier) \ + iobarrier_rw(); \ + else \ + war_io_reorder_wmb(); \ \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ \ @@ -367,6 +364,9 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ \ __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \ \ + if (barrier) \ + iobarrier_rw(); \ + \ if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \ __val = *__mem; \ else if (cpu_has_64bits) { \ @@ -390,18 +390,22 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ } \ \ /* prevent prefetching of coherent DMA data prematurely */ \ - rmb(); \ + if (!relax) \ + rmb(); \ return pfx##ioswab##bwlq(__mem, __val); \ } -#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ +#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, barrier, relax, p) \ \ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ { \ volatile type *__addr; \ type __val; \ \ - war_io_reorder_wmb(); \ + if (barrier) \ + iobarrier_rw(); \ + else \ + war_io_reorder_wmb(); \ \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ @@ -411,7 +415,6 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ *__addr = __val; \ - slow; \ } \ \ static inline type pfx##in##bwlq##p(unsigned long port) \ @@ -423,23 +426,27 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ + if (barrier) \ + iobarrier_rw(); \ + \ __val = *__addr; \ - slow; \ \ /* prevent prefetching of coherent DMA data prematurely */ \ - rmb(); \ + if (!relax) \ + rmb(); \ return pfx##ioswab##bwlq(__addr, __val); \ } -#define __BUILD_MEMORY_PFX(bus, bwlq, type) \ +#define __BUILD_MEMORY_PFX(bus, bwlq, type, relax) \ \ -__BUILD_MEMORY_SINGLE(bus, bwlq, type, 1) +__BUILD_MEMORY_SINGLE(bus, bwlq, type, 1, relax, 1) #define BUILDIO_MEM(bwlq, type) \ \ -__BUILD_MEMORY_PFX(__raw_, bwlq, type) \ -__BUILD_MEMORY_PFX(, bwlq, type) \ -__BUILD_MEMORY_PFX(__mem_, bwlq, type) \ +__BUILD_MEMORY_PFX(__raw_, bwlq, type, 0) \ +__BUILD_MEMORY_PFX(__relaxed_, bwlq, type, 1) \ +__BUILD_MEMORY_PFX(__mem_, bwlq, type, 0) \ +__BUILD_MEMORY_PFX(, bwlq, type, 0) BUILDIO_MEM(b, u8) BUILDIO_MEM(w, u16) @@ -447,8 +454,8 @@ BUILDIO_MEM(l, u32) BUILDIO_MEM(q, u64) #define __BUILD_IOPORT_PFX(bus, bwlq, type) \ - __BUILD_IOPORT_SINGLE(bus, bwlq, type, ,) \ - __BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO) + __BUILD_IOPORT_SINGLE(bus, bwlq, type, 1, 0,) \ + __BUILD_IOPORT_SINGLE(bus, bwlq, type, 1, 0, _p) #define BUILDIO_IOPORT(bwlq, type) \ __BUILD_IOPORT_PFX(, bwlq, type) \ @@ -463,19 +470,19 @@ BUILDIO_IOPORT(q, u64) #define __BUILDIO(bwlq, type) \ \ -__BUILD_MEMORY_SINGLE(____raw_, bwlq, type, 0) +__BUILD_MEMORY_SINGLE(____raw_, bwlq, type, 1, 0, 0) __BUILDIO(q, u64) -#define readb_relaxed readb -#define readw_relaxed readw -#define readl_relaxed readl -#define readq_relaxed readq +#define readb_relaxed __relaxed_readb +#define readw_relaxed __relaxed_readw +#define readl_relaxed __relaxed_readl +#define readq_relaxed __relaxed_readq -#define writeb_relaxed writeb -#define writew_relaxed writew -#define writel_relaxed writel -#define writeq_relaxed writeq +#define writeb_relaxed __relaxed_writeb +#define writew_relaxed __relaxed_writew +#define writel_relaxed __relaxed_writel +#define writeq_relaxed __relaxed_writeq #define readb_be(addr) \ __raw_readb((__force unsigned *)(addr)) @@ -561,14 +568,6 @@ BUILDSTRING(l, u32) BUILDSTRING(q, u64) #endif - -#ifdef CONFIG_CPU_CAVIUM_OCTEON -#define mmiowb() wmb() -#else -/* Depends on MIPS II instruction set */ -#define mmiowb() asm volatile ("sync" ::: "memory") -#endif - static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count) { memset((void __force *) addr, val, count); diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h index 493a3cc7c39a..40795ca89961 100644 --- a/arch/mips/include/asm/kexec.h +++ b/arch/mips/include/asm/kexec.h @@ -12,11 +12,11 @@ #include <asm/stacktrace.h> /* Maximum physical address we can use pages from */ -#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000) +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) /* Maximum address we can reach in physical address mode */ -#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000) +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) /* Maximum address we can use for the control code buffer */ -#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000) +#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) /* Reserve 3*4096 bytes for board-specific info */ #define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096) @@ -39,11 +39,12 @@ extern unsigned long kexec_args[4]; extern int (*_machine_kexec_prepare)(struct kimage *); extern void (*_machine_kexec_shutdown)(void); extern void (*_machine_crash_shutdown)(struct pt_regs *regs); -extern void default_machine_crash_shutdown(struct pt_regs *regs); +void default_machine_crash_shutdown(struct pt_regs *regs); +void kexec_nonboot_cpu_jump(void); +void kexec_reboot(void); #ifdef CONFIG_SMP extern const unsigned char kexec_smp_wait[]; extern unsigned long secondary_kexec_args[4]; -extern void (*relocated_kexec_smp_wait) (void *); extern atomic_t kexec_ready_to_reboot; extern void (*_crash_smp_send_stop)(void); #endif diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h index 3644b68c0ccc..be9f727a9328 100644 --- a/arch/mips/include/asm/mach-loongson64/irq.h +++ b/arch/mips/include/asm/mach-loongson64/irq.h @@ -10,7 +10,7 @@ #define MIPS_CPU_IRQ_BASE 56 #define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 2) /* UART */ -#define LOONGSON_HT1_IRQ (MIPS_CPU_IRQ_BASE + 3) /* HT1 */ +#define LOONGSON_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 3) /* CASCADE */ #define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */ #define LOONGSON_HT1_CFG_BASE loongson_sysconf.ht_control_base diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h index 312739117bb0..cbac603ced19 100644 --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h @@ -11,6 +11,8 @@ #ifndef __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H #define __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H +#include <asm/cpu.h> + /* * Override macros used in arch/mips/kernel/head.S. */ @@ -26,12 +28,15 @@ mfc0 t0, CP0_PAGEGRAIN or t0, (0x1 << 29) mtc0 t0, CP0_PAGEGRAIN -#ifdef CONFIG_LOONGSON3_ENHANCEMENT /* Enable STFill Buffer */ + mfc0 t0, CP0_PRID + andi t0, (PRID_IMP_MASK | PRID_REV_MASK) + slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2) + bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100 mtc0 t0, CP0_CONFIG6 -#endif +1: _ehb .set pop #endif @@ -52,12 +57,15 @@ mfc0 t0, CP0_PAGEGRAIN or t0, (0x1 << 29) mtc0 t0, CP0_PAGEGRAIN -#ifdef CONFIG_LOONGSON3_ENHANCEMENT /* Enable STFill Buffer */ + mfc0 t0, CP0_PRID + andi t0, (PRID_IMP_MASK | PRID_REV_MASK) + slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2) + bnez t0, 1f mfc0 t0, CP0_CONFIG6 or t0, 0x100 mtc0 t0, CP0_CONFIG6 -#endif +1: _ehb .set pop #endif diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 01df9ad62fb8..341a02c92985 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -2287,13 +2287,14 @@ do { \ _write_32bit_cp1_register(dest, val, ) #endif -#ifdef HAVE_AS_DSP +#ifdef TOOLCHAIN_SUPPORTS_DSP #define rddsp(mask) \ ({ \ unsigned int __dspctl; \ \ __asm__ __volatile__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " rddsp %0, %x1 \n" \ " .set pop \n" \ @@ -2306,6 +2307,7 @@ do { \ do { \ __asm__ __volatile__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " wrdsp %0, %x1 \n" \ " .set pop \n" \ @@ -2318,6 +2320,7 @@ do { \ long mflo0; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mflo %0, $ac0 \n" \ " .set pop \n" \ @@ -2330,6 +2333,7 @@ do { \ long mflo1; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mflo %0, $ac1 \n" \ " .set pop \n" \ @@ -2342,6 +2346,7 @@ do { \ long mflo2; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mflo %0, $ac2 \n" \ " .set pop \n" \ @@ -2354,6 +2359,7 @@ do { \ long mflo3; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mflo %0, $ac3 \n" \ " .set pop \n" \ @@ -2366,6 +2372,7 @@ do { \ long mfhi0; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mfhi %0, $ac0 \n" \ " .set pop \n" \ @@ -2378,6 +2385,7 @@ do { \ long mfhi1; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mfhi %0, $ac1 \n" \ " .set pop \n" \ @@ -2390,6 +2398,7 @@ do { \ long mfhi2; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mfhi %0, $ac2 \n" \ " .set pop \n" \ @@ -2402,6 +2411,7 @@ do { \ long mfhi3; \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mfhi %0, $ac3 \n" \ " .set pop \n" \ @@ -2414,6 +2424,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mtlo %0, $ac0 \n" \ " .set pop \n" \ @@ -2425,6 +2436,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mtlo %0, $ac1 \n" \ " .set pop \n" \ @@ -2436,6 +2448,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mtlo %0, $ac2 \n" \ " .set pop \n" \ @@ -2447,6 +2460,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mtlo %0, $ac3 \n" \ " .set pop \n" \ @@ -2458,6 +2472,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mthi %0, $ac0 \n" \ " .set pop \n" \ @@ -2469,6 +2484,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mthi %0, $ac1 \n" \ " .set pop \n" \ @@ -2480,6 +2496,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mthi %0, $ac2 \n" \ " .set pop \n" \ @@ -2491,6 +2508,7 @@ do { \ ({ \ __asm__( \ " .set push \n" \ + " .set " MIPS_ISA_LEVEL " \n" \ " .set dsp \n" \ " mthi %0, $ac3 \n" \ " .set pop \n" \ diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 49d6046ca1d0..c373eb605040 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -81,7 +81,7 @@ extern unsigned int vced_count, vcei_count; #endif -#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_256M) +#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_64M) extern unsigned long mips_stack_top(void); #define STACK_TOP mips_stack_top() diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index 7f12d7e27c94..d19b2d65336b 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -48,58 +48,14 @@ extern void (*r4k_blast_icache)(void); : \ : "i" (op), "R" (*(unsigned char *)(addr))) -#ifdef CONFIG_MIPS_MT - -#define __iflush_prologue \ - unsigned long redundance; \ - extern int mt_n_iflushes; \ - for (redundance = 0; redundance < mt_n_iflushes; redundance++) { - -#define __iflush_epilogue \ - } - -#define __dflush_prologue \ - unsigned long redundance; \ - extern int mt_n_dflushes; \ - for (redundance = 0; redundance < mt_n_dflushes; redundance++) { - -#define __dflush_epilogue \ - } - -#define __inv_dflush_prologue __dflush_prologue -#define __inv_dflush_epilogue __dflush_epilogue -#define __sflush_prologue { -#define __sflush_epilogue } -#define __inv_sflush_prologue __sflush_prologue -#define __inv_sflush_epilogue __sflush_epilogue - -#else /* CONFIG_MIPS_MT */ - -#define __iflush_prologue { -#define __iflush_epilogue } -#define __dflush_prologue { -#define __dflush_epilogue } -#define __inv_dflush_prologue { -#define __inv_dflush_epilogue } -#define __sflush_prologue { -#define __sflush_epilogue } -#define __inv_sflush_prologue { -#define __inv_sflush_epilogue } - -#endif /* CONFIG_MIPS_MT */ - static inline void flush_icache_line_indexed(unsigned long addr) { - __iflush_prologue cache_op(Index_Invalidate_I, addr); - __iflush_epilogue } static inline void flush_dcache_line_indexed(unsigned long addr) { - __dflush_prologue cache_op(Index_Writeback_Inv_D, addr); - __dflush_epilogue } static inline void flush_scache_line_indexed(unsigned long addr) @@ -109,7 +65,6 @@ static inline void flush_scache_line_indexed(unsigned long addr) static inline void flush_icache_line(unsigned long addr) { - __iflush_prologue switch (boot_cpu_type()) { case CPU_LOONGSON2: cache_op(Hit_Invalidate_I_Loongson2, addr); @@ -119,21 +74,16 @@ static inline void flush_icache_line(unsigned long addr) cache_op(Hit_Invalidate_I, addr); break; } - __iflush_epilogue } static inline void flush_dcache_line(unsigned long addr) { - __dflush_prologue cache_op(Hit_Writeback_Inv_D, addr); - __dflush_epilogue } static inline void invalidate_dcache_line(unsigned long addr) { - __dflush_prologue cache_op(Hit_Invalidate_D, addr); - __dflush_epilogue } static inline void invalidate_scache_line(unsigned long addr) @@ -586,13 +536,9 @@ static inline void extra##blast_##pfx##cache##lsize(void) \ current_cpu_data.desc.waybit; \ unsigned long ws, addr; \ \ - __##pfx##flush_prologue \ - \ for (ws = 0; ws < ws_end; ws += ws_inc) \ for (addr = start; addr < end; addr += lsize * 32) \ cache##lsize##_unroll32(addr|ws, indexop); \ - \ - __##pfx##flush_epilogue \ } \ \ static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \ @@ -600,14 +546,10 @@ static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \ unsigned long start = page; \ unsigned long end = page + PAGE_SIZE; \ \ - __##pfx##flush_prologue \ - \ do { \ cache##lsize##_unroll32(start, hitop); \ start += lsize * 32; \ } while (start < end); \ - \ - __##pfx##flush_epilogue \ } \ \ static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ @@ -620,13 +562,9 @@ static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long current_cpu_data.desc.waybit; \ unsigned long ws, addr; \ \ - __##pfx##flush_prologue \ - \ for (ws = 0; ws < ws_end; ws += ws_inc) \ for (addr = start; addr < end; addr += lsize * 32) \ cache##lsize##_unroll32(addr|ws, indexop); \ - \ - __##pfx##flush_epilogue \ } __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) @@ -656,14 +594,10 @@ static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \ unsigned long start = page; \ unsigned long end = page + PAGE_SIZE; \ \ - __##pfx##flush_prologue \ - \ do { \ cache##lsize##_unroll32_user(start, hitop); \ start += lsize * 32; \ } while (start < end); \ - \ - __##pfx##flush_epilogue \ } __BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, @@ -685,16 +619,12 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, unsigned long addr = start & ~(lsize - 1); \ unsigned long aend = (end - 1) & ~(lsize - 1); \ \ - __##pfx##flush_prologue \ - \ while (1) { \ prot##cache_op(hitop, addr); \ if (addr == aend) \ break; \ addr += lsize; \ } \ - \ - __##pfx##flush_epilogue \ } #ifndef CONFIG_EVA @@ -712,8 +642,6 @@ static inline void protected_blast_##pfx##cache##_range(unsigned long start,\ unsigned long addr = start & ~(lsize - 1); \ unsigned long aend = (end - 1) & ~(lsize - 1); \ \ - __##pfx##flush_prologue \ - \ if (!uaccess_kernel()) { \ while (1) { \ protected_cachee_op(hitop, addr); \ @@ -730,7 +658,6 @@ static inline void protected_blast_##pfx##cache##_range(unsigned long start,\ } \ \ } \ - __##pfx##flush_epilogue \ } __BUILD_PROT_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D) diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h index 53b2cb8e5966..b7123f9c0785 100644 --- a/arch/mips/include/asm/smp-ops.h +++ b/arch/mips/include/asm/smp-ops.h @@ -33,6 +33,9 @@ struct plat_smp_ops { int (*cpu_disable)(void); void (*cpu_die)(unsigned int cpu); #endif +#ifdef CONFIG_KEXEC + void (*kexec_nonboot_cpu)(void); +#endif }; extern void register_smp_ops(const struct plat_smp_ops *ops); diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 056a6bf13491..7990c1c70471 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -91,6 +91,22 @@ static inline void __cpu_die(unsigned int cpu) extern void play_dead(void); #endif +#ifdef CONFIG_KEXEC +static inline void kexec_nonboot_cpu(void) +{ + extern const struct plat_smp_ops *mp_ops; /* private */ + + return mp_ops->kexec_nonboot_cpu(); +} + +static inline void *kexec_nonboot_cpu_func(void) +{ + extern const struct plat_smp_ops *mp_ops; /* private */ + + return mp_ops->kexec_nonboot_cpu; +} +#endif + /* * This function will set up the necessary IPIs for Linux to communicate * with the CPUs in mask. diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 3c09450908aa..c68b8ae3efcb 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -24,16 +24,17 @@ #ifndef __ASSEMBLY__ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_UNAME #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h index 890245a9f0c4..16aa8a766aec 100644 --- a/arch/mips/include/uapi/asm/ioctls.h +++ b/arch/mips/include/uapi/asm/ioctls.h @@ -93,6 +93,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) /* I hope the range from 0x5480 on is free ... */ #define TIOCSCTTY 0x5480 /* become controlling tty */ diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index 262504bd59a5..c34c7eef0a1c 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -14,17 +14,6 @@ #define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int)) #undef __ARCH_SI_TRAPNO /* exception code needs to fill this ... */ -/* - * Careful to keep union _sifields from shifting ... - */ -#if _MIPS_SZLONG == 32 -#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int)) -#elif _MIPS_SZLONG == 64 -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#else -#error _MIPS_SZLONG neither 32 nor 64 -#endif - #define __ARCH_HAS_SWAPPED_SIGINFO #include <asm-generic/siginfo.h> diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index f10e1e15e1c6..210c2802cf4d 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -113,22 +113,4 @@ obj-$(CONFIG_MIPS_CPC) += mips-cpc.o obj-$(CONFIG_CPU_PM) += pm.o obj-$(CONFIG_MIPS_CPS_PM) += pm-cps.o -# -# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not -# safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches -# here because the compiler may use DSP ASE instructions (such as lwx) in -# code paths where we cannot check that the CPU we are running on supports it. -# Proper abstraction using HAVE_AS_DSP and macros is done in -# arch/mips/include/asm/mipsregs.h. -# -ifeq ($(CONFIG_CPU_MIPSR2), y) -CFLAGS_DSP = -DHAVE_AS_DSP - -CFLAGS_signal.o = $(CFLAGS_DSP) -CFLAGS_signal32.o = $(CFLAGS_DSP) -CFLAGS_process.o = $(CFLAGS_DSP) -CFLAGS_branch.o = $(CFLAGS_DSP) -CFLAGS_ptrace.o = $(CFLAGS_DSP) -endif - CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index 89b234844534..7a12763d553a 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -54,10 +54,10 @@ struct elf_prstatus32 pid_t pr_ppid; pid_t pr_pgrp; pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime;/* Cumulative user time */ - struct compat_timeval pr_cstime;/* Cumulative system time */ + struct old_timeval32 pr_utime; /* User time */ + struct old_timeval32 pr_stime; /* System time */ + struct old_timeval32 pr_cutime;/* Cumulative user time */ + struct old_timeval32 pr_cstime;/* Cumulative system time */ elf_gregset_t pr_reg; /* GP registers */ int pr_fpvalid; /* True if math co-processor being used. */ }; @@ -81,9 +81,9 @@ struct elf_prpsinfo32 #define elf_caddr_t u32 #define init_elf_binfmt init_elfn32_binfmt -#define jiffies_to_timeval jiffies_to_compat_timeval +#define jiffies_to_timeval jiffies_to_old_timeval32 static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) { /* * Convert jiffies to nanoseconds and separate with @@ -101,6 +101,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) #define TASK_SIZE TASK_SIZE32 #undef ns_to_timeval -#define ns_to_timeval ns_to_compat_timeval +#define ns_to_timeval ns_to_old_timeval32 #include "../../../fs/binfmt_elf.c" diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index a88c59db3d48..e6db06a1d31a 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -59,10 +59,10 @@ struct elf_prstatus32 pid_t pr_ppid; pid_t pr_pgrp; pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime;/* Cumulative user time */ - struct compat_timeval pr_cstime;/* Cumulative system time */ + struct old_timeval32 pr_utime; /* User time */ + struct old_timeval32 pr_stime; /* System time */ + struct old_timeval32 pr_cutime;/* Cumulative user time */ + struct old_timeval32 pr_cstime;/* Cumulative system time */ elf_gregset_t pr_reg; /* GP registers */ int pr_fpvalid; /* True if math co-processor being used. */ }; @@ -86,9 +86,9 @@ struct elf_prpsinfo32 #define elf_caddr_t u32 #define init_elf_binfmt init_elf32_binfmt -#define jiffies_to_timeval jiffies_to_compat_timeval +#define jiffies_to_timeval jiffies_to_old_timeval32 static inline void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value) { /* * Convert jiffies to nanoseconds and separate with @@ -104,6 +104,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) #define TASK_SIZE TASK_SIZE32 #undef ns_to_timeval -#define ns_to_timeval ns_to_compat_timeval +#define ns_to_timeval ns_to_old_timeval32 #include "../../../fs/binfmt_elf.c" diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c index d455363d51c3..2c7288041a99 100644 --- a/arch/mips/kernel/crash.c +++ b/arch/mips/kernel/crash.c @@ -36,6 +36,9 @@ static void crash_shutdown_secondary(void *passed_regs) if (!cpu_online(cpu)) return; + /* We won't be sent IPIs any more. */ + set_cpu_online(cpu, false); + local_irq_disable(); if (!cpumask_test_cpu(cpu, &cpus_in_crash)) crash_save_cpu(regs, cpu); @@ -43,7 +46,9 @@ static void crash_shutdown_secondary(void *passed_regs) while (!atomic_read(&kexec_ready_to_reboot)) cpu_relax(); - relocated_kexec_smp_wait(NULL); + + kexec_reboot(); + /* NOTREACHED */ } diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index d1bb506adc10..351d40fe0859 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -77,7 +77,7 @@ EXPORT(_stext) */ FEXPORT(__kernel_entry) j kernel_entry -#endif +#endif /* CONFIG_BOOT_RAW */ __REF @@ -94,24 +94,26 @@ NESTED(kernel_entry, 16, sp) # kernel entry point 0: #ifdef CONFIG_USE_OF -#ifdef CONFIG_MIPS_RAW_APPENDED_DTB +#if defined(CONFIG_MIPS_RAW_APPENDED_DTB) || \ + defined(CONFIG_MIPS_ELF_APPENDED_DTB) + PTR_LA t2, __appended_dtb #ifdef CONFIG_CPU_BIG_ENDIAN li t1, 0xd00dfeed -#else +#else /* !CONFIG_CPU_BIG_ENDIAN */ li t1, 0xedfe0dd0 -#endif +#endif /* !CONFIG_CPU_BIG_ENDIAN */ lw t0, (t2) beq t0, t1, dtb_found -#endif +#endif /* CONFIG_MIPS_RAW_APPENDED_DTB || CONFIG_MIPS_ELF_APPENDED_DTB */ li t1, -2 move t2, a1 beq a0, t1, dtb_found li t2, 0 dtb_found: -#endif +#endif /* CONFIG_USE_OF */ PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE @@ -156,9 +158,9 @@ dtb_found: * newly sync'd icache. */ jr.hb v0 -#else +#else /* !CONFIG_RELOCATABLE */ j start_kernel -#endif +#endif /* !CONFIG_RELOCATABLE */ END(kernel_entry) #ifdef CONFIG_SMP diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c index 8b574bcd39ba..93936dce04d6 100644 --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c @@ -9,6 +9,7 @@ #include <linux/kexec.h> #include <linux/mm.h> #include <linux/delay.h> +#include <linux/libfdt.h> #include <asm/cacheflush.h> #include <asm/page.h> @@ -19,15 +20,18 @@ extern const size_t relocate_new_kernel_size; extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; -int (*_machine_kexec_prepare)(struct kimage *) = NULL; -void (*_machine_kexec_shutdown)(void) = NULL; -void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; +static unsigned long reboot_code_buffer; + #ifdef CONFIG_SMP -void (*relocated_kexec_smp_wait) (void *); +static void (*relocated_kexec_smp_wait)(void *); + atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); void (*_crash_smp_send_stop)(void) = NULL; #endif +void (*_machine_kexec_shutdown)(void) = NULL; +void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; + static void kexec_image_info(const struct kimage *kimage) { unsigned long i; @@ -48,13 +52,59 @@ static void kexec_image_info(const struct kimage *kimage) } } +#ifdef CONFIG_UHI_BOOT + +static int uhi_machine_kexec_prepare(struct kimage *kimage) +{ + int i; + + /* + * In case DTB file is not passed to the new kernel, a flat device + * tree will be created by kexec tool. It holds modified command + * line for the new kernel. + */ + for (i = 0; i < kimage->nr_segments; i++) { + struct fdt_header fdt; + + if (kimage->segment[i].memsz <= sizeof(fdt)) + continue; + + if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt))) + continue; + + if (fdt_check_header(&fdt)) + continue; + + kexec_args[0] = -2; + kexec_args[1] = (unsigned long) + phys_to_virt((unsigned long)kimage->segment[i].mem); + break; + } + + return 0; +} + +int (*_machine_kexec_prepare)(struct kimage *) = uhi_machine_kexec_prepare; + +#else + +int (*_machine_kexec_prepare)(struct kimage *) = NULL; + +#endif /* CONFIG_UHI_BOOT */ + int machine_kexec_prepare(struct kimage *kimage) { +#ifdef CONFIG_SMP + if (!kexec_nonboot_cpu_func()) + return -EINVAL; +#endif + kexec_image_info(kimage); if (_machine_kexec_prepare) return _machine_kexec_prepare(kimage); + return 0; } @@ -63,11 +113,41 @@ machine_kexec_cleanup(struct kimage *kimage) { } +#ifdef CONFIG_SMP +static void kexec_shutdown_secondary(void *param) +{ + int cpu = smp_processor_id(); + + if (!cpu_online(cpu)) + return; + + /* We won't be sent IPIs any more. */ + set_cpu_online(cpu, false); + + local_irq_disable(); + while (!atomic_read(&kexec_ready_to_reboot)) + cpu_relax(); + + kexec_reboot(); + + /* NOTREACHED */ +} +#endif + void machine_shutdown(void) { if (_machine_kexec_shutdown) _machine_kexec_shutdown(); + +#ifdef CONFIG_SMP + smp_call_function(kexec_shutdown_secondary, NULL, 0); + + while (num_online_cpus() > 1) { + cpu_relax(); + mdelay(1); + } +#endif } void @@ -79,12 +159,57 @@ machine_crash_shutdown(struct pt_regs *regs) default_machine_crash_shutdown(regs); } -typedef void (*noretfun_t)(void) __noreturn; +#ifdef CONFIG_SMP +void kexec_nonboot_cpu_jump(void) +{ + local_flush_icache_range((unsigned long)relocated_kexec_smp_wait, + reboot_code_buffer + relocate_new_kernel_size); + + relocated_kexec_smp_wait(NULL); +} +#endif + +void kexec_reboot(void) +{ + void (*do_kexec)(void) __noreturn; + + /* + * We know we were online, and there will be no incoming IPIs at + * this point. Mark online again before rebooting so that the crash + * analysis tool will see us correctly. + */ + set_cpu_online(smp_processor_id(), true); + + /* Ensure remote CPUs observe that we're online before rebooting. */ + smp_mb__after_atomic(); + +#ifdef CONFIG_SMP + if (smp_processor_id() > 0) { + /* + * Instead of cpu_relax() or wait, this is needed for kexec + * smp reboot. Kdump usually doesn't require an smp new + * kernel, but kexec may do. + */ + kexec_nonboot_cpu(); + + /* NOTREACHED */ + } +#endif + + /* + * Make sure we get correct instructions written by the + * machine_kexec() CPU. + */ + local_flush_icache_range(reboot_code_buffer, + reboot_code_buffer + relocate_new_kernel_size); + + do_kexec = (void *)reboot_code_buffer; + do_kexec(); +} void machine_kexec(struct kimage *image) { - unsigned long reboot_code_buffer; unsigned long entry; unsigned long *ptr; @@ -118,6 +243,9 @@ machine_kexec(struct kimage *image) *ptr = (unsigned long) phys_to_virt(*ptr); } + /* Mark offline BEFORE disabling local irq. */ + set_cpu_online(smp_processor_id(), false); + /* * we do not want to be bothered. */ @@ -125,6 +253,7 @@ machine_kexec(struct kimage *image) printk("Will call new kernel at %08lx\n", image->start); printk("Bye ...\n"); + /* Make reboot code buffer available to the boot CPU. */ __flush_cache_all(); #ifdef CONFIG_SMP /* All secondary cpus now may jump to kexec_wait cycle */ @@ -133,5 +262,5 @@ machine_kexec(struct kimage *image) smp_wmb(); atomic_set(&kexec_ready_to_reboot, 1); #endif - ((noretfun_t) reboot_code_buffer)(); + kexec_reboot(); } diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index efaa2527657d..9f85b98d24ac 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -154,40 +154,6 @@ static int __init config7_set(char *str) } __setup("config7=", config7_set); -/* Experimental cache flush control parameters that should go away some day */ -int mt_protiflush; -int mt_protdflush; -int mt_n_iflushes = 1; -int mt_n_dflushes = 1; - -static int __init set_protiflush(char *s) -{ - mt_protiflush = 1; - return 1; -} -__setup("protiflush", set_protiflush); - -static int __init set_protdflush(char *s) -{ - mt_protdflush = 1; - return 1; -} -__setup("protdflush", set_protdflush); - -static int __init niflush(char *s) -{ - get_option(&s, &mt_n_iflushes); - return 1; -} -__setup("niflush=", niflush); - -static int __init ndflush(char *s) -{ - get_option(&s, &mt_n_dflushes); - return 1; -} -__setup("ndflush=", ndflush); - static unsigned int itc_base; static int __init set_itc_base(char *str) @@ -232,16 +198,6 @@ void mips_mt_set_cpuoptions(void) printk("Config7: 0x%08x\n", read_c0_config7()); } - /* Report Cache management debug options */ - if (mt_protiflush) - printk("I-cache flushes single-threaded\n"); - if (mt_protdflush) - printk("D-cache flushes single-threaded\n"); - if (mt_n_iflushes != 1) - printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes); - if (mt_n_dflushes != 1) - printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes); - if (itc_base != 0) { /* * Configure ITC mapping. This code is very @@ -283,21 +239,6 @@ void mips_mt_set_cpuoptions(void) } } -/* - * Function to protect cache flushes from concurrent execution - * depends on MP software model chosen. - */ - -void mt_cflush_lockdown(void) -{ - /* FILL IN VSMP and AP/SP VERSIONS HERE */ -} - -void mt_cflush_release(void) -{ - /* FILL IN VSMP and AP/SP VERSIONS HERE */ -} - struct class *mt_class; static int __init mt_init(void) diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index cbf4cc0b0b6c..3d80a51256de 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -146,7 +146,7 @@ int __init do_relocations(void *kbase_old, void *kbase_new, long offset) break; type = (*r >> 24) & 0xff; - loc_orig = (void *)(kbase_old + ((*r & 0x00ffffff) << 2)); + loc_orig = kbase_old + ((*r & 0x00ffffff) << 2); loc_new = RELOCATED(loc_orig); if (reloc_handlers_rel[type] == NULL) { diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index e64b9e8bb002..01a5ff4c41ff 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -333,7 +333,7 @@ static void __init finalize_initrd(void) maybe_bswap_initrd(); - reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); + memblock_reserve(__pa(initrd_start), size); initrd_below_start_ok = 1; pr_info("Initial ramdisk at: 0x%lx (%lu bytes)\n", @@ -370,20 +370,10 @@ static void __init bootmem_init(void) #else /* !CONFIG_SGI_IP27 */ -static unsigned long __init bootmap_bytes(unsigned long pages) -{ - unsigned long bytes = DIV_ROUND_UP(pages, 8); - - return ALIGN(bytes, sizeof(long)); -} - static void __init bootmem_init(void) { unsigned long reserved_end; - unsigned long mapstart = ~0UL; - unsigned long bootmap_size; phys_addr_t ramstart = PHYS_ADDR_MAX; - bool bootmap_valid = false; int i; /* @@ -395,6 +385,8 @@ static void __init bootmem_init(void) init_initrd(); reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end)); + memblock_reserve(PHYS_OFFSET, reserved_end << PAGE_SHIFT); + /* * max_low_pfn is not a number of pages. The number of pages * of the system is given by 'max_low_pfn - min_low_pfn'. @@ -442,9 +434,6 @@ static void __init bootmem_init(void) if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) continue; #endif - if (start >= mapstart) - continue; - mapstart = max(reserved_end, start); } if (min_low_pfn >= max_low_pfn) @@ -456,9 +445,11 @@ static void __init bootmem_init(void) /* * Reserve any memory between the start of RAM and PHYS_OFFSET */ - if (ramstart > PHYS_OFFSET) + if (ramstart > PHYS_OFFSET) { add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET, BOOT_MEM_RESERVED); + memblock_reserve(PHYS_OFFSET, ramstart - PHYS_OFFSET); + } if (min_low_pfn > ARCH_PFN_OFFSET) { pr_info("Wasting %lu bytes for tracking %lu unused pages\n", @@ -483,52 +474,6 @@ static void __init bootmem_init(void) max_low_pfn = PFN_DOWN(HIGHMEM_START); } -#ifdef CONFIG_BLK_DEV_INITRD - /* - * mapstart should be after initrd_end - */ - if (initrd_end) - mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); -#endif - - /* - * check that mapstart doesn't overlap with any of - * memory regions that have been reserved through eg. DTB - */ - bootmap_size = bootmap_bytes(max_low_pfn - min_low_pfn); - - bootmap_valid = memory_region_available(PFN_PHYS(mapstart), - bootmap_size); - for (i = 0; i < boot_mem_map.nr_map && !bootmap_valid; i++) { - unsigned long mapstart_addr; - - switch (boot_mem_map.map[i].type) { - case BOOT_MEM_RESERVED: - mapstart_addr = PFN_ALIGN(boot_mem_map.map[i].addr + - boot_mem_map.map[i].size); - if (PHYS_PFN(mapstart_addr) < mapstart) - break; - - bootmap_valid = memory_region_available(mapstart_addr, - bootmap_size); - if (bootmap_valid) - mapstart = PHYS_PFN(mapstart_addr); - break; - default: - break; - } - } - - if (!bootmap_valid) - panic("No memory area to place a bootmap bitmap"); - - /* - * Initialize the boot-time allocator with low memory only. - */ - if (bootmap_size != init_bootmem_node(NODE_DATA(0), mapstart, - min_low_pfn, max_low_pfn)) - panic("Unexpected memory size required for bootmap"); - for (i = 0; i < boot_mem_map.nr_map; i++) { unsigned long start, end; @@ -577,9 +522,9 @@ static void __init bootmem_init(void) default: /* Not usable memory */ if (start > min_low_pfn && end < max_low_pfn) - reserve_bootmem(boot_mem_map.map[i].addr, - boot_mem_map.map[i].size, - BOOTMEM_DEFAULT); + memblock_reserve(boot_mem_map.map[i].addr, + boot_mem_map.map[i].size); + continue; } @@ -602,15 +547,9 @@ static void __init bootmem_init(void) size = end - start; /* Register lowmem ranges */ - free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); memory_present(0, start, end); } - /* - * Reserve the bootmap memory. - */ - reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT); - #ifdef CONFIG_RELOCATABLE /* * The kernel reserves all memory below its _end symbol as bootmem, @@ -642,29 +581,6 @@ static void __init bootmem_init(void) #endif /* CONFIG_SGI_IP27 */ -/* - * arch_mem_init - initialize memory management subsystem - * - * o plat_mem_setup() detects the memory configuration and will record detected - * memory areas using add_memory_region. - * - * At this stage the memory configuration of the system is known to the - * kernel but generic memory management system is still entirely uninitialized. - * - * o bootmem_init() - * o sparse_init() - * o paging_init() - * o dma_contiguous_reserve() - * - * At this stage the bootmem allocator is ready to use. - * - * NOTE: historically plat_mem_setup did the entire platform initialization. - * This was rather impractical because it meant plat_mem_setup had to - * get away without any kind of memory allocator. To keep old code from - * breaking plat_setup was just renamed to plat_mem_setup and a second platform - * initialization hook for anything else was introduced. - */ - static int usermem __initdata; static int __init early_parse_mem(char *p) @@ -841,6 +757,28 @@ static void __init request_crashkernel(struct resource *res) #define BUILTIN_EXTEND_WITH_PROM \ IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND) +/* + * arch_mem_init - initialize memory management subsystem + * + * o plat_mem_setup() detects the memory configuration and will record detected + * memory areas using add_memory_region. + * + * At this stage the memory configuration of the system is known to the + * kernel but generic memory management system is still entirely uninitialized. + * + * o bootmem_init() + * o sparse_init() + * o paging_init() + * o dma_contiguous_reserve() + * + * At this stage the bootmem allocator is ready to use. + * + * NOTE: historically plat_mem_setup did the entire platform initialization. + * This was rather impractical because it meant plat_mem_setup had to + * get away without any kind of memory allocator. To keep old code from + * breaking plat_setup was just renamed to plat_mem_setup and a second platform + * initialization hook for anything else was introduced. + */ static void __init arch_mem_init(char **cmdline_p) { struct memblock_region *reg; @@ -916,21 +854,29 @@ static void __init arch_mem_init(char **cmdline_p) early_init_fdt_scan_reserved_mem(); bootmem_init(); + + /* + * Prevent memblock from allocating high memory. + * This cannot be done before max_low_pfn is detected, so up + * to this point is possible to only reserve physical memory + * with memblock_reserve; memblock_virt_alloc* can be used + * only after this point + */ + memblock_set_current_limit(PFN_PHYS(max_low_pfn)); + #ifdef CONFIG_PROC_VMCORE if (setup_elfcorehdr && setup_elfcorehdr_size) { printk(KERN_INFO "kdump reserved memory at %lx-%lx\n", setup_elfcorehdr, setup_elfcorehdr_size); - reserve_bootmem(setup_elfcorehdr, setup_elfcorehdr_size, - BOOTMEM_DEFAULT); + memblock_reserve(setup_elfcorehdr, setup_elfcorehdr_size); } #endif mips_parse_crashkernel(); #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) - reserve_bootmem(crashk_res.start, - crashk_res.end - crashk_res.start + 1, - BOOTMEM_DEFAULT); + memblock_reserve(crashk_res.start, + crashk_res.end - crashk_res.start + 1); #endif device_tree_init(); sparse_init(); @@ -940,7 +886,7 @@ static void __init arch_mem_init(char **cmdline_p) /* Tell bootmem about cma reserved memblock section */ for_each_memblock(reserved, reg) if (reg->size != 0) - reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); + memblock_reserve(reg->base, reg->size); reserve_bootmem_region(__pa_symbol(&__nosave_begin), __pa_symbol(&__nosave_end)); /* Reserve for hibernation */ diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 159e83add4bb..76fae9b79f13 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -25,6 +25,7 @@ #include <linux/linkage.h> #include <linux/bug.h> #include <linux/kernel.h> +#include <linux/kexec.h> #include <asm/time.h> #include <asm/pgtable.h> @@ -423,6 +424,9 @@ const struct plat_smp_ops bmips43xx_smp_ops = { .cpu_disable = bmips_cpu_disable, .cpu_die = bmips_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = kexec_nonboot_cpu_jump, +#endif }; const struct plat_smp_ops bmips5000_smp_ops = { @@ -437,6 +441,9 @@ const struct plat_smp_ops bmips5000_smp_ops = { .cpu_disable = bmips_cpu_disable, .cpu_die = bmips_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = kexec_nonboot_cpu_jump, +#endif }; #endif /* CONFIG_SMP */ diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 03f1026ad148..faccfa4b280b 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -398,6 +398,55 @@ static void cps_smp_finish(void) local_irq_enable(); } +#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC) + +enum cpu_death { + CPU_DEATH_HALT, + CPU_DEATH_POWER, +}; + +static void cps_shutdown_this_cpu(enum cpu_death death) +{ + unsigned int cpu, core, vpe_id; + + cpu = smp_processor_id(); + core = cpu_core(&cpu_data[cpu]); + + if (death == CPU_DEATH_HALT) { + vpe_id = cpu_vpe_id(&cpu_data[cpu]); + + pr_debug("Halting core %d VP%d\n", core, vpe_id); + if (cpu_has_mipsmt) { + /* Halt this TC */ + write_c0_tchalt(TCHALT_H); + instruction_hazard(); + } else if (cpu_has_vp) { + write_cpc_cl_vp_stop(1 << vpe_id); + + /* Ensure that the VP_STOP register is written */ + wmb(); + } + } else { + pr_debug("Gating power to core %d\n", core); + /* Power down the core */ + cps_pm_enter_state(CPS_PM_POWER_GATED); + } +} + +#ifdef CONFIG_KEXEC + +static void cps_kexec_nonboot_cpu(void) +{ + if (cpu_has_mipsmt || cpu_has_vp) + cps_shutdown_this_cpu(CPU_DEATH_HALT); + else + cps_shutdown_this_cpu(CPU_DEATH_POWER); +} + +#endif /* CONFIG_KEXEC */ + +#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */ + #ifdef CONFIG_HOTPLUG_CPU static int cps_cpu_disable(void) @@ -421,19 +470,15 @@ static int cps_cpu_disable(void) } static unsigned cpu_death_sibling; -static enum { - CPU_DEATH_HALT, - CPU_DEATH_POWER, -} cpu_death; +static enum cpu_death cpu_death; void play_dead(void) { - unsigned int cpu, core, vpe_id; + unsigned int cpu; local_irq_disable(); idle_task_exit(); cpu = smp_processor_id(); - core = cpu_core(&cpu_data[cpu]); cpu_death = CPU_DEATH_POWER; pr_debug("CPU%d going offline\n", cpu); @@ -456,25 +501,7 @@ void play_dead(void) /* This CPU has chosen its way out */ (void)cpu_report_death(); - if (cpu_death == CPU_DEATH_HALT) { - vpe_id = cpu_vpe_id(&cpu_data[cpu]); - - pr_debug("Halting core %d VP%d\n", core, vpe_id); - if (cpu_has_mipsmt) { - /* Halt this TC */ - write_c0_tchalt(TCHALT_H); - instruction_hazard(); - } else if (cpu_has_vp) { - write_cpc_cl_vp_stop(1 << vpe_id); - - /* Ensure that the VP_STOP register is written */ - wmb(); - } - } else { - pr_debug("Gating power to core %d\n", core); - /* Power down the core */ - cps_pm_enter_state(CPS_PM_POWER_GATED); - } + cps_shutdown_this_cpu(cpu_death); /* This should never be reached */ panic("Failed to offline CPU %u", cpu); @@ -593,6 +620,9 @@ static const struct plat_smp_ops cps_smp_ops = { .cpu_disable = cps_cpu_disable, .cpu_die = cps_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = cps_kexec_nonboot_cpu, +#endif }; bool mips_cps_smp_in_use(void) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 9dab0ed1b227..5feef28deac8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -29,6 +29,7 @@ #include <linux/spinlock.h> #include <linux/kallsyms.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/interrupt.h> #include <linux/ptrace.h> #include <linux/kgdb.h> @@ -348,7 +349,7 @@ static void __show_regs(const struct pt_regs *regs) */ void show_regs(struct pt_regs *regs) { - __show_regs((struct pt_regs *)regs); + __show_regs(regs); dump_stack(); } @@ -2260,8 +2261,10 @@ void __init trap_init(void) unsigned long size = 0x200 + VECTORSPACING*64; phys_addr_t ebase_pa; + memblock_set_bottom_up(true); ebase = (unsigned long) __alloc_bootmem(size, 1 << fls(size), 0); + memblock_set_bottom_up(false); /* * Try to ensure ebase resides in KSeg0 if possible. diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 2d0b912f9e3e..ce446eed62d2 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -130,7 +130,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _LoadW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -151,8 +151,8 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has no lwl instruction */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ +/* For CPUs without lwl instruction */ #define _LoadW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -186,7 +186,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define _LoadHWU(addr, value, res, type) \ do { \ @@ -212,7 +212,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _LoadWU(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -255,8 +255,8 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has not lwl and ldl instructions */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ +/* For CPUs without lwl and ldl instructions */ #define _LoadWU(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -339,7 +339,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define _StoreHW(addr, value, res, type) \ @@ -365,7 +365,7 @@ do { \ : "r" (value), "r" (addr), "i" (-EFAULT));\ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _StoreW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -406,8 +406,7 @@ do { \ : "r" (value), "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has no swl and sdl instructions */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define _StoreW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -483,7 +482,7 @@ do { \ : "memory"); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #else /* __BIG_ENDIAN */ @@ -509,7 +508,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _LoadW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -530,8 +529,8 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has no lwl instruction */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ +/* For CPUs without lwl instruction */ #define _LoadW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -565,7 +564,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define _LoadHWU(addr, value, res, type) \ @@ -592,7 +591,7 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _LoadWU(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -635,8 +634,8 @@ do { \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has not lwl and ldl instructions */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ +/* For CPUs without lwl and ldl instructions */ #define _LoadWU(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -718,7 +717,7 @@ do { \ : "=&r" (value), "=r" (res) \ : "r" (addr), "i" (-EFAULT)); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define _StoreHW(addr, value, res, type) \ do { \ @@ -743,7 +742,7 @@ do { \ : "r" (value), "r" (addr), "i" (-EFAULT));\ } while(0) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR #define _StoreW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -784,8 +783,8 @@ do { \ : "r" (value), "r" (addr), "i" (-EFAULT)); \ } while(0) -#else -/* MIPSR6 has no swl and sdl instructions */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ +/* For CPUs without swl and sdl instructions */ #define _StoreW(addr, value, res, type) \ do { \ __asm__ __volatile__ ( \ @@ -861,7 +860,7 @@ do { \ : "memory"); \ } while(0) -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #endif #define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel) diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 6537e022ef62..479f50559c83 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,7 +7,7 @@ lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \ mips-atomic.o strncpy_user.o \ strnlen_user.o uncached.o -obj-y += iomap.o iomap_copy.o +obj-y += iomap_copy.o obj-$(CONFIG_PCI) += iomap-pci.o lib-$(CONFIG_GENERIC_CSUM) := $(filter-out csum_partial.o, $(lib-y)) diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c index 4850509c5534..210f5a95ecb1 100644 --- a/arch/mips/lib/iomap-pci.c +++ b/arch/mips/lib/iomap-pci.c @@ -44,10 +44,3 @@ void __iomem *__pci_ioport_map(struct pci_dev *dev, } #endif /* CONFIG_PCI_DRIVERS_LEGACY */ - -void pci_iounmap(struct pci_dev *dev, void __iomem * addr) -{ - iounmap(addr); -} - -EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c deleted file mode 100644 index 9b31653f318c..000000000000 --- a/arch/mips/lib/iomap.c +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Implement the default iomap interfaces - * - * (C) Copyright 2004 Linus Torvalds - * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org> - * (C) Copyright 2007 MIPS Technologies, Inc. - * written by Ralf Baechle <ralf@linux-mips.org> - */ -#include <linux/export.h> -#include <asm/io.h> - -/* - * Read/write from/to an (offsettable) iomem cookie. It might be a PIO - * access or a MMIO access, these functions don't care. The info is - * encoded in the hardware mapping set up by the mapping functions - * (or the cookie itself, depending on implementation and hw). - * - * The generic routines don't assume any hardware mappings, and just - * encode the PIO/MMIO as part of the cookie. They coldly assume that - * the MMIO IO mappings are not in the low address range. - * - * Architectures for which this is not true can't use this generic - * implementation and should do their own copy. - */ - -#define PIO_MASK 0x0ffffUL - -unsigned int ioread8(void __iomem *addr) -{ - return readb(addr); -} - -EXPORT_SYMBOL(ioread8); - -unsigned int ioread16(void __iomem *addr) -{ - return readw(addr); -} - -EXPORT_SYMBOL(ioread16); - -unsigned int ioread16be(void __iomem *addr) -{ - return be16_to_cpu(__raw_readw(addr)); -} - -EXPORT_SYMBOL(ioread16be); - -unsigned int ioread32(void __iomem *addr) -{ - return readl(addr); -} - -EXPORT_SYMBOL(ioread32); - -unsigned int ioread32be(void __iomem *addr) -{ - return be32_to_cpu(__raw_readl(addr)); -} - -EXPORT_SYMBOL(ioread32be); - -void iowrite8(u8 val, void __iomem *addr) -{ - writeb(val, addr); -} - -EXPORT_SYMBOL(iowrite8); - -void iowrite16(u16 val, void __iomem *addr) -{ - writew(val, addr); -} - -EXPORT_SYMBOL(iowrite16); - -void iowrite16be(u16 val, void __iomem *addr) -{ - __raw_writew(cpu_to_be16(val), addr); -} - -EXPORT_SYMBOL(iowrite16be); - -void iowrite32(u32 val, void __iomem *addr) -{ - writel(val, addr); -} - -EXPORT_SYMBOL(iowrite32); - -void iowrite32be(u32 val, void __iomem *addr) -{ - __raw_writel(cpu_to_be32(val), addr); -} - -EXPORT_SYMBOL(iowrite32be); - -/* - * These are the "repeat MMIO read/write" functions. - * Note the "__mem" accesses, since we want to convert - * to CPU byte order if the host bus happens to not match the - * endianness of PCI/ISA (see mach-generic/mangle-port.h). - */ -static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) -{ - while (--count >= 0) { - u8 data = __mem_readb(addr); - *dst = data; - dst++; - } -} - -static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) -{ - while (--count >= 0) { - u16 data = __mem_readw(addr); - *dst = data; - dst++; - } -} - -static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) -{ - while (--count >= 0) { - u32 data = __mem_readl(addr); - *dst = data; - dst++; - } -} - -static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) -{ - while (--count >= 0) { - __mem_writeb(*src, addr); - src++; - } -} - -static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) -{ - while (--count >= 0) { - __mem_writew(*src, addr); - src++; - } -} - -static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) -{ - while (--count >= 0) { - __mem_writel(*src, addr); - src++; - } -} - -void ioread8_rep(void __iomem *addr, void *dst, unsigned long count) -{ - mmio_insb(addr, dst, count); -} - -EXPORT_SYMBOL(ioread8_rep); - -void ioread16_rep(void __iomem *addr, void *dst, unsigned long count) -{ - mmio_insw(addr, dst, count); -} - -EXPORT_SYMBOL(ioread16_rep); - -void ioread32_rep(void __iomem *addr, void *dst, unsigned long count) -{ - mmio_insl(addr, dst, count); -} - -EXPORT_SYMBOL(ioread32_rep); - -void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) -{ - mmio_outsb(addr, src, count); -} - -EXPORT_SYMBOL(iowrite8_rep); - -void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) -{ - mmio_outsw(addr, src, count); -} - -EXPORT_SYMBOL(iowrite16_rep); - -void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) -{ - mmio_outsl(addr, src, count); -} - -EXPORT_SYMBOL(iowrite32_rep); - -/* - * Create a virtual mapping cookie for an IO port range - * - * This uses the same mapping are as the in/out family which has to be setup - * by the platform initialization code. - * - * Just to make matters somewhat more interesting on MIPS systems with - * multiple host bridge each will have it's own ioport address space. - */ -static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr) -{ - return (void __iomem *) (mips_io_port_base + port); -} - -void __iomem *ioport_map(unsigned long port, unsigned int nr) -{ - if (port > PIO_MASK) - return NULL; - - return ioport_map_legacy(port, nr); -} - -EXPORT_SYMBOL(ioport_map); - -void ioport_unmap(void __iomem *addr) -{ - /* Nothing to do */ -} - -EXPORT_SYMBOL(ioport_unmap); diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index 03e3304d6ae5..cdd19d8561e8 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -204,9 +204,10 @@ #define LOADB(reg, addr, handler) EXC(lb, LD_INSN, reg, addr, handler) #define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler) -#define _PREF(hint, addr, type) \ +#ifdef CONFIG_CPU_HAS_PREFETCH +# define _PREF(hint, addr, type) \ .if \mode == LEGACY_MODE; \ - PREF(hint, addr); \ + kernel_pref(hint, addr); \ .else; \ .if ((\from == USEROP) && (type == SRC_PREFETCH)) || \ ((\to == USEROP) && (type == DST_PREFETCH)); \ @@ -218,12 +219,15 @@ * used later on. Therefore use $v1. \ */ \ .set at=v1; \ - PREFE(hint, addr); \ + user_pref(hint, addr); \ .set noat; \ .else; \ - PREF(hint, addr); \ + kernel_pref(hint, addr); \ .endif; \ .endif +#else +# define _PREF(hint, addr, type) +#endif #define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH) #define PREFD(hint, addr) _PREF(hint, addr, DST_PREFETCH) @@ -297,7 +301,7 @@ and t0, src, ADDRMASK PREFS( 0, 2*32(src) ) PREFD( 1, 2*32(dst) ) -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR bnez t1, .Ldst_unaligned\@ nop bnez t0, .Lsrc_unaligned_dst_aligned\@ @@ -385,7 +389,7 @@ bne rem, len, 1b .set noreorder -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR /* * src and dst are aligned, need to copy rem bytes (rem < NBYTES) * A loop would do only a byte at a time with possible branch @@ -487,7 +491,7 @@ bne len, rem, 1b .set noreorder -#endif /* !CONFIG_CPU_MIPSR6 */ +#endif /* CONFIG_CPU_HAS_LOAD_STORE_LR */ .Lcopy_bytes_checklen\@: beqz len, .Ldone\@ nop @@ -516,7 +520,7 @@ jr ra nop -#ifdef CONFIG_CPU_MIPSR6 +#ifndef CONFIG_CPU_HAS_LOAD_STORE_LR .Lcopy_unaligned_bytes\@: 1: COPY_BYTE(0) @@ -530,7 +534,7 @@ ADD src, src, 8 b 1b ADD dst, dst, 8 -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ .if __memcpy == 1 END(memcpy) .set __memcpy, 0 diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 069acec3df9f..418611ef13cf 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -78,7 +78,6 @@ #endif .endm - .set noreorder .align 5 /* @@ -94,13 +93,16 @@ .endif sltiu t0, a2, STORSIZE /* very small region? */ + .set noreorder bnez t0, .Lsmall_memset\@ andi t0, a0, STORMASK /* aligned? */ + .set reorder #ifdef CONFIG_CPU_MICROMIPS move t8, a1 /* used by 'swp' instruction */ move t9, a1 #endif + .set noreorder #ifndef CONFIG_CPU_DADDI_WORKAROUNDS beqz t0, 1f PTR_SUBU t0, STORSIZE /* alignment in bytes */ @@ -111,8 +113,9 @@ PTR_SUBU t0, AT /* alignment in bytes */ .set at #endif + .set reorder -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR R10KCBARRIER(0(ra)) #ifdef __MIPSEB__ EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ @@ -122,11 +125,13 @@ PTR_SUBU a0, t0 /* long align ptr */ PTR_ADDU a2, t0 /* correct size */ -#else /* CONFIG_CPU_MIPSR6 */ +#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ #define STORE_BYTE(N) \ EX(sb, a1, N(a0), .Lbyte_fixup\@); \ + .set noreorder; \ beqz t0, 0f; \ - PTR_ADDU t0, 1; + PTR_ADDU t0, 1; \ + .set reorder; PTR_ADDU a2, t0 /* correct size */ PTR_ADDU t0, 1 @@ -145,19 +150,17 @@ ori a0, STORMASK xori a0, STORMASK PTR_ADDIU a0, STORSIZE -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ 1: ori t1, a2, 0x3f /* # of full blocks */ xori t1, 0x3f + andi t0, a2, 0x40-STORSIZE beqz t1, .Lmemset_partial\@ /* no block to fill */ - andi t0, a2, 0x40-STORSIZE PTR_ADDU t1, a0 /* end address */ - .set reorder 1: PTR_ADDIU a0, 64 R10KCBARRIER(0(ra)) f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode bne t1, a0, 1b - .set noreorder .Lmemset_partial\@: R10KCBARRIER(0(ra)) @@ -173,20 +176,18 @@ PTR_SUBU t1, AT .set at #endif + PTR_ADDU a0, t0 /* dest ptr */ jr t1 - PTR_ADDU a0, t0 /* dest ptr */ - .set push - .set noreorder - .set nomacro /* ... but first do longs ... */ f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode -2: .set pop - andi a2, STORMASK /* At most one long to go */ +2: andi a2, STORMASK /* At most one long to go */ + .set noreorder beqz a2, 1f -#ifndef CONFIG_CPU_MIPSR6 +#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR PTR_ADDU a0, a2 /* What's left */ + .set reorder R10KCBARRIER(0(ra)) #ifdef __MIPSEB__ EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) @@ -195,6 +196,7 @@ #endif #else PTR_SUBU t0, $0, a2 + .set reorder move a2, zero /* No remaining longs */ PTR_ADDIU t0, 1 STORE_BYTE(0) @@ -210,41 +212,42 @@ #endif 0: #endif -1: jr ra - move a2, zero +1: move a2, zero + jr ra .Lsmall_memset\@: + PTR_ADDU t1, a0, a2 beqz a2, 2f - PTR_ADDU t1, a0, a2 1: PTR_ADDIU a0, 1 /* fill bytewise */ R10KCBARRIER(0(ra)) + .set noreorder bne t1, a0, 1b EX(sb, a1, -1(a0), .Lsmall_fixup\@) + .set reorder -2: jr ra /* done */ - move a2, zero +2: move a2, zero + jr ra /* done */ .if __memset == 1 END(memset) .set __memset, 0 .hidden __memset .endif -#ifdef CONFIG_CPU_MIPSR6 +#ifndef CONFIG_CPU_HAS_LOAD_STORE_LR .Lbyte_fixup\@: /* * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1 * a2 = a2 - t0 + 1 */ PTR_SUBU a2, t0 + PTR_ADDIU a2, 1 jr ra - PTR_ADDIU a2, 1 -#endif /* CONFIG_CPU_MIPSR6 */ +#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */ .Lfirst_fixup\@: /* unset_bytes already in a2 */ jr ra - nop .Lfwd_fixup\@: /* @@ -255,8 +258,8 @@ andi a2, 0x3f LONG_L t0, THREAD_BUADDR(t0) LONG_ADDU a2, t1 + LONG_SUBU a2, t0 jr ra - LONG_SUBU a2, t0 .Lpartial_fixup\@: /* @@ -267,24 +270,21 @@ andi a2, STORMASK LONG_L t0, THREAD_BUADDR(t0) LONG_ADDU a2, a0 + LONG_SUBU a2, t0 jr ra - LONG_SUBU a2, t0 .Llast_fixup\@: /* unset_bytes already in a2 */ jr ra - nop .Lsmall_fixup\@: /* * unset_bytes = end_addr - current_addr + 1 * a2 = t1 - a0 + 1 */ - .set reorder PTR_SUBU a2, t1, a0 PTR_ADDIU a2, 1 jr ra - .set noreorder .endm @@ -298,8 +298,8 @@ LEAF(memset) EXPORT_SYMBOL(memset) + move v0, a0 /* result */ beqz a1, 1f - move v0, a0 /* result */ andi a1, 0xff /* spread fillword */ LONG_SLL t1, a1, 8 diff --git a/arch/mips/loongson64/common/Makefile b/arch/mips/loongson64/common/Makefile index 57ee03022941..684624f61f5a 100644 --- a/arch/mips/loongson64/common/Makefile +++ b/arch/mips/loongson64/common/Makefile @@ -6,7 +6,6 @@ obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ bonito-irq.o mem.o machtype.o platform.o serial.o obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_CPU_LOONGSON2) += dma.o # # Serial port support diff --git a/arch/mips/loongson64/fuloong-2e/Makefile b/arch/mips/loongson64/fuloong-2e/Makefile index b7622720c1ad..0a9a472bec0a 100644 --- a/arch/mips/loongson64/fuloong-2e/Makefile +++ b/arch/mips/loongson64/fuloong-2e/Makefile @@ -2,4 +2,4 @@ # Makefile for Lemote Fuloong2e mini-PC board. # -obj-y += irq.o reset.o +obj-y += irq.o reset.o dma.o diff --git a/arch/mips/loongson64/fuloong-2e/dma.c b/arch/mips/loongson64/fuloong-2e/dma.c new file mode 100644 index 000000000000..e122292bf666 --- /dev/null +++ b/arch/mips/loongson64/fuloong-2e/dma.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/dma-direct.h> + +dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) +{ + return paddr | 0x80000000; +} + +phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dma_addr) +{ + return dma_addr & 0x7fffffff; +} diff --git a/arch/mips/loongson64/lemote-2f/Makefile b/arch/mips/loongson64/lemote-2f/Makefile index 08b8abcbfef5..b5792c334cd5 100644 --- a/arch/mips/loongson64/lemote-2f/Makefile +++ b/arch/mips/loongson64/lemote-2f/Makefile @@ -2,7 +2,7 @@ # Makefile for lemote loongson2f family machines # -obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o +obj-y += clock.o machtype.o irq.o reset.o dma.o ec_kb3310b.o # # Suspend Support diff --git a/arch/mips/loongson64/common/dma.c b/arch/mips/loongson64/lemote-2f/dma.c index 48f04126bde2..abf0e39d7e46 100644 --- a/arch/mips/loongson64/common/dma.c +++ b/arch/mips/loongson64/lemote-2f/dma.c @@ -8,11 +8,7 @@ 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 dma_addr) { -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) if (dma_addr > 0x8fffffff) return dma_addr; return dma_addr & 0x0fffffff; -#else - return dma_addr & 0x7fffffff; -#endif } diff --git a/arch/mips/loongson64/loongson-3/irq.c b/arch/mips/loongson64/loongson-3/irq.c index cbeb20f9fc95..5605061f5f98 100644 --- a/arch/mips/loongson64/loongson-3/irq.c +++ b/arch/mips/loongson64/loongson-3/irq.c @@ -96,51 +96,8 @@ void mach_irq_dispatch(unsigned int pending) } } -static struct irqaction cascade_irqaction = { - .handler = no_action, - .flags = IRQF_NO_SUSPEND, - .name = "cascade", -}; - -static inline void mask_loongson_irq(struct irq_data *d) -{ - clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); - irq_disable_hazard(); - - /* Workaround: UART IRQ may deliver to any core */ - if (d->irq == LOONGSON_UART_IRQ) { - int cpu = smp_processor_id(); - int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node; - int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node; - u64 intenclr_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_INTENCLR); - u64 introuter_lpc_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_LPC); - - *(volatile u32 *)intenclr_addr = 1 << 10; - *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id); - } -} - -static inline void unmask_loongson_irq(struct irq_data *d) -{ - /* Workaround: UART IRQ may deliver to any core */ - if (d->irq == LOONGSON_UART_IRQ) { - int cpu = smp_processor_id(); - int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node; - int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node; - u64 intenset_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_INTENSET); - u64 introuter_lpc_addr = smp_group[node_id] | - (u64)(&LOONGSON_INT_ROUTER_LPC); - - *(volatile u32 *)intenset_addr = 1 << 10; - *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id); - } - - set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE)); - irq_enable_hazard(); -} +static inline void mask_loongson_irq(struct irq_data *d) { } +static inline void unmask_loongson_irq(struct irq_data *d) { } /* For MIPS IRQs which shared by all cores */ static struct irq_chip loongson_irq_chip = { @@ -183,12 +140,11 @@ void __init mach_init_irq(void) chip->irq_set_affinity = plat_set_irq_affinity; irq_set_chip_and_handler(LOONGSON_UART_IRQ, - &loongson_irq_chip, handle_level_irq); - - /* setup HT1 irq */ - setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction); + &loongson_irq_chip, handle_percpu_irq); + irq_set_chip_and_handler(LOONGSON_BRIDGE_IRQ, + &loongson_irq_chip, handle_percpu_irq); - set_c0_status(STATUSF_IP2 | STATUSF_IP6); + set_c0_status(STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP6); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 9717106de4a5..c1e6ec52c614 100644 --- a/arch/mips/loongson64/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c @@ -180,43 +180,39 @@ static void __init szmem(unsigned int node) static void __init node_mem_init(unsigned int node) { - unsigned long bootmap_size; unsigned long node_addrspace_offset; - unsigned long start_pfn, end_pfn, freepfn; + unsigned long start_pfn, end_pfn; node_addrspace_offset = nid_to_addroffset(node); pr_info("Node%d's addrspace_offset is 0x%lx\n", node, node_addrspace_offset); get_pfn_range_for_nid(node, &start_pfn, &end_pfn); - freepfn = start_pfn; - if (node == 0) - freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */ - pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n", - node, start_pfn, end_pfn, freepfn); + pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n", + node, start_pfn, end_pfn); __node_data[node] = prealloc__node_data + node; - NODE_DATA(node)->bdata = &bootmem_node_data[node]; NODE_DATA(node)->node_start_pfn = start_pfn; NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; - bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn, - start_pfn, end_pfn); free_bootmem_with_active_regions(node, end_pfn); - if (node == 0) /* used by finalize_initrd() */ + + if (node == 0) { + /* kernel end address */ + unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end)); + + /* used by finalize_initrd() */ max_low_pfn = end_pfn; - /* This is reserved for the kernel and bdata->node_bootmem_map */ - reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT, - ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size, - BOOTMEM_DEFAULT); + /* Reserve the kernel text/data/bss */ + memblock_reserve(start_pfn << PAGE_SHIFT, + ((kernel_end_pfn - start_pfn) << PAGE_SHIFT)); - if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) { /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ - reserve_bootmem_node(NODE_DATA(node), - (node_addrspace_offset | 0xfe000000), - 32 << 20, BOOTMEM_DEFAULT); + if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) + memblock_reserve((node_addrspace_offset | 0xfe000000), + 32 << 20); } sparse_memory_present_with_active_regions(node); diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c index fea95d003269..b5c1e0aa955e 100644 --- a/arch/mips/loongson64/loongson-3/smp.c +++ b/arch/mips/loongson64/loongson-3/smp.c @@ -21,6 +21,7 @@ #include <linux/sched/task_stack.h> #include <linux/smp.h> #include <linux/cpufreq.h> +#include <linux/kexec.h> #include <asm/processor.h> #include <asm/time.h> #include <asm/clock.h> @@ -349,7 +350,7 @@ static void loongson3_smp_finish(void) write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); local_irq_enable(); loongson3_ipi_write64(0, - (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0)); + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); pr_info("CPU#%d finished, CP0_ST=%x\n", smp_processor_id(), read_c0_status()); } @@ -416,13 +417,13 @@ static int loongson3_boot_secondary(int cpu, struct task_struct *idle) cpu, startargs[0], startargs[1], startargs[2]); loongson3_ipi_write64(startargs[3], - (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x18)); + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x18); loongson3_ipi_write64(startargs[2], - (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x10)); + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x10); loongson3_ipi_write64(startargs[1], - (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8)); + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x8); loongson3_ipi_write64(startargs[0], - (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0)); + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); return 0; } @@ -749,4 +750,7 @@ const struct plat_smp_ops loongson3_smp_ops = { .cpu_disable = loongson3_cpu_disable, .cpu_die = loongson3_cpu_die, #endif +#ifdef CONFIG_KEXEC + .kexec_nonboot_cpu = kexec_nonboot_cpu_jump, +#endif }; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 400676ce03f4..15cae0f11880 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -32,7 +32,6 @@ #include <linux/kcore.h> #include <linux/initrd.h> -#include <asm/asm-offsets.h> #include <asm/bootinfo.h> #include <asm/cachectl.h> #include <asm/cpu.h> @@ -521,17 +520,13 @@ unsigned long pgd_current[NR_CPUS]; #endif /* - * gcc 3.3 and older have trouble determining that PTRS_PER_PGD and PGD_ORDER - * are constants. So we use the variants from asm-offset.h until that gcc - * will officially be retired. - * * Align swapper_pg_dir in to 64K, allows its address to be loaded * with a single LUI instruction in the TLB handlers. If we used * __aligned(64K), its size would get rounded up to the alignment * size, and waste space. So we place it in its own section and align * it in the linker script. */ -pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir); +pgd_t swapper_pg_dir[PTRS_PER_PGD] __section(.bss..swapper_pg_dir); #ifndef __PAGETABLE_PUD_FOLDED pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss; #endif diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index f4961bc9a61d..cf33dd8a487e 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -291,7 +291,7 @@ static int __init xlp_of_pic_init(struct device_node *node, /* we need a hack to get the PIC's SoC chip id */ ret = of_address_to_resource(node, 0, &res); if (ret < 0) { - pr_err("PIC %s: reg property not found!\n", node->name); + pr_err("PIC %pOFn: reg property not found!\n", node); return -EINVAL; } @@ -304,21 +304,21 @@ static int __init xlp_of_pic_init(struct device_node *node, break; } if (socid == NLM_NR_NODES) { - pr_err("PIC %s: Node mapping for bus %d not found!\n", - node->name, bus); + pr_err("PIC %pOFn: Node mapping for bus %d not found!\n", + node, bus); return -EINVAL; } } else { socid = (res.start >> 18) & 0x3; if (!nlm_node_present(socid)) { - pr_err("PIC %s: node %d does not exist!\n", - node->name, socid); + pr_err("PIC %pOFn: node %d does not exist!\n", + node, socid); return -EINVAL; } } if (!nlm_node_present(socid)) { - pr_err("PIC %s: node %d does not exist!\n", node->name, socid); + pr_err("PIC %pOFn: node %d does not exist!\n", node, socid); return -EINVAL; } @@ -326,7 +326,7 @@ static int __init xlp_of_pic_init(struct device_node *node, nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE, &xlp_pic_irq_domain_ops, NULL); if (xlp_pic_domain == NULL) { - pr_err("PIC %s: Creating legacy domain failed!\n", node->name); + pr_err("PIC %pOFn: Creating legacy domain failed!\n", node); return -EINVAL; } pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res); diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c index 9e118431e226..2f6ad36bdea6 100644 --- a/arch/mips/pci/ops-loongson3.c +++ b/arch/mips/pci/ops-loongson3.c @@ -18,22 +18,36 @@ static int loongson3_pci_config_access(unsigned char access_type, int where, u32 *data) { unsigned char busnum = bus->number; - u_int64_t addr, type; - void *addrp; - int device = PCI_SLOT(devfn); int function = PCI_FUNC(devfn); + int device = PCI_SLOT(devfn); int reg = where & ~3; + void *addrp; + u64 addr; + + if (where < PCI_CFG_SPACE_SIZE) { /* standard config */ + addr = (busnum << 16) | (device << 11) | (function << 8) | reg; + if (busnum == 0) { + if (device > 31) + return PCIBIOS_DEVICE_NOT_FOUND; + addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE | addr); + } else { + addrp = (void *)TO_UNCAC(HT1LO_PCICFG_BASE_TP1 | addr); + } + } else if (where < PCI_CFG_SPACE_EXP_SIZE) { /* extended config */ + struct pci_dev *rootdev; + + rootdev = pci_get_domain_bus_and_slot(0, 0, 0); + if (!rootdev) + return PCIBIOS_DEVICE_NOT_FOUND; - addr = (busnum << 16) | (device << 11) | (function << 8) | reg; - if (busnum == 0) { - if (device > 31) + addr = pci_resource_start(rootdev, 3); + if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; - addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff)); - type = 0; + addr |= busnum << 20 | device << 15 | function << 12 | reg; + addrp = (void *)TO_UNCAC(addr); } else { - addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr)); - type = 0x10000; + return PCIBIOS_DEVICE_NOT_FOUND; } if (access_type == PCI_ACCESS_WRITE) diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c index f1e92bf743c2..3c3b1e6abb53 100644 --- a/arch/mips/pci/pci-legacy.c +++ b/arch/mips/pci/pci-legacy.c @@ -127,8 +127,12 @@ static void pcibios_scanbus(struct pci_controller *hose) if (pci_has_flag(PCI_PROBE_ONLY)) { pci_bus_claim_resources(bus); } else { + struct pci_bus *child; + pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); } pci_bus_add_devices(bus); } diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c index 711cdccdf65b..f376a1df326a 100644 --- a/arch/mips/pci/pci-rt2880.c +++ b/arch/mips/pci/pci-rt2880.c @@ -246,6 +246,8 @@ static int rt288x_pci_probe(struct platform_device *pdev) rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); + rt2880_pci_controller.of_node = pdev->dev.of_node; + register_pci_controller(&rt2880_pci_controller); return 0; } diff --git a/arch/mips/pmcs-msp71xx/msp_usb.c b/arch/mips/pmcs-msp71xx/msp_usb.c index c87c5f810cd1..d38ac70b5a2e 100644 --- a/arch/mips/pmcs-msp71xx/msp_usb.c +++ b/arch/mips/pmcs-msp71xx/msp_usb.c @@ -133,13 +133,13 @@ static int __init msp_usb_setup(void) * "D" for device-mode. If it works for Ethernet, why not USB... * -- hammtrev, 2007/03/22 */ - snprintf((char *)&envstr[0], sizeof(envstr), "usbmode"); + snprintf(&envstr[0], sizeof(envstr), "usbmode"); /* set default host mode */ val = 1; /* get environment string */ - strp = prom_getenv((char *)&envstr[0]); + strp = prom_getenv(&envstr[0]); if (strp) { /* compare string */ if (!strcmp(strp, "device")) diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index 92f284d2b802..61a08943eb2f 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -134,7 +134,7 @@ static int __init ralink_systick_init(struct device_node *np) systick.dev.min_delta_ticks = 0x3; systick.dev.irq = irq_of_parse_and_map(np, 0); if (!systick.dev.irq) { - pr_err("%s: request_irq failed", np->name); + pr_err("%pOFn: request_irq failed", np); return -EINVAL; } @@ -146,8 +146,8 @@ static int __init ralink_systick_init(struct device_node *np) clockevents_register_device(&systick.dev); - pr_info("%s: running - mult: %d, shift: %d\n", - np->name, systick.dev.mult, systick.dev.shift); + pr_info("%pOFn: running - mult: %d, shift: %d\n", + np, systick.dev.mult, systick.dev.shift); return 0; } diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c index 765d5ba98fa2..fc056f2acfeb 100644 --- a/arch/mips/ralink/ill_acc.c +++ b/arch/mips/ralink/ill_acc.c @@ -62,7 +62,7 @@ static int __init ill_acc_of_setup(void) pdev = of_find_device_by_node(np); if (!pdev) { - pr_err("%s: failed to lookup pdev\n", np->name); + pr_err("%pOFn: failed to lookup pdev\n", np); return -EINVAL; } diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index 93d472c60ce4..0f2264e0cf76 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -49,6 +49,10 @@ static struct rt2880_pmx_func rgmii_func[] = { FUNC("rgmii", 0, 40, 12) }; static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; +static struct rt2880_pmx_func rt3352_cs1_func[] = { + FUNC("spi_cs1", 0, 45, 1), + FUNC("wdg_cs1", 1, 45, 1), +}; static struct rt2880_pmx_group rt3050_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), @@ -75,6 +79,7 @@ static struct rt2880_pmx_group rt3352_pinmux_data[] = { GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA), GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA), GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED), + GRP("spi_cs1", rt3352_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1), { 0 } }; diff --git a/arch/mips/sgi-ip22/ip28-berr.c b/arch/mips/sgi-ip22/ip28-berr.c index 2ed8e4990b7a..082541d33161 100644 --- a/arch/mips/sgi-ip22/ip28-berr.c +++ b/arch/mips/sgi-ip22/ip28-berr.c @@ -464,7 +464,7 @@ void ip22_be_interrupt(int irq) die_if_kernel("Oops", regs); force_sig(SIGBUS, current); } else if (debug_be_interrupt) - show_regs((struct pt_regs *)regs); + show_regs(regs); } static int ip28_be_handler(struct pt_regs *regs, int is_fixup) diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 59133d0abc83..6f7bef052b7f 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -389,7 +389,6 @@ static void __init node_mem_init(cnodeid_t node) { unsigned long slot_firstpfn = slot_getbasepfn(node, 0); unsigned long slot_freepfn = node_getfirstfree(node); - unsigned long bootmap_size; unsigned long start_pfn, end_pfn; get_pfn_range_for_nid(node, &start_pfn, &end_pfn); @@ -400,7 +399,6 @@ static void __init node_mem_init(cnodeid_t node) __node_data[node] = __va(slot_freepfn << PAGE_SHIFT); memset(__node_data[node], 0, PAGE_SIZE); - NODE_DATA(node)->bdata = &bootmem_node_data[node]; NODE_DATA(node)->node_start_pfn = start_pfn; NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; @@ -409,12 +407,11 @@ static void __init node_mem_init(cnodeid_t node) slot_freepfn += PFN_UP(sizeof(struct pglist_data) + sizeof(struct hub_data)); - bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, - start_pfn, end_pfn); free_bootmem_with_active_regions(node, end_pfn); - reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size, - BOOTMEM_DEFAULT); + + memblock_reserve(slot_firstpfn << PAGE_SHIFT, + ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT)); + sparse_memory_present_with_active_regions(node); } diff --git a/arch/mips/tools/.gitignore b/arch/mips/tools/.gitignore new file mode 100644 index 000000000000..56d34ccccce4 --- /dev/null +++ b/arch/mips/tools/.gitignore @@ -0,0 +1 @@ +elf-entry diff --git a/arch/mips/tools/Makefile b/arch/mips/tools/Makefile new file mode 100644 index 000000000000..3baee4bc6775 --- /dev/null +++ b/arch/mips/tools/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +hostprogs-y := elf-entry +PHONY += elf-entry +elf-entry: $(obj)/elf-entry + @: diff --git a/arch/mips/tools/elf-entry.c b/arch/mips/tools/elf-entry.c new file mode 100644 index 000000000000..adde79ce7fc0 --- /dev/null +++ b/arch/mips/tools/elf-entry.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <byteswap.h> +#include <elf.h> +#include <endian.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef be32toh +/* If libc provides [bl]e{32,64}toh() then we'll use them */ +#elif BYTE_ORDER == LITTLE_ENDIAN +# define be32toh(x) bswap_32(x) +# define le32toh(x) (x) +# define be64toh(x) bswap_64(x) +# define le64toh(x) (x) +#elif BYTE_ORDER == BIG_ENDIAN +# define be32toh(x) (x) +# define le32toh(x) bswap_32(x) +# define be64toh(x) (x) +# define le64toh(x) bswap_64(x) +#endif + +__attribute__((noreturn)) +static void die(const char *msg) +{ + fputs(msg, stderr); + exit(EXIT_FAILURE); +} + +int main(int argc, const char *argv[]) +{ + uint64_t entry; + size_t nread; + FILE *file; + union { + Elf32_Ehdr ehdr32; + Elf64_Ehdr ehdr64; + } hdr; + + if (argc != 2) + die("Usage: elf-entry <elf-file>\n"); + + file = fopen(argv[1], "r"); + if (!file) { + perror("Unable to open input file"); + return EXIT_FAILURE; + } + + nread = fread(&hdr, 1, sizeof(hdr), file); + if (nread != sizeof(hdr)) { + perror("Unable to read input file"); + return EXIT_FAILURE; + } + + if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG)) + die("Input is not an ELF\n"); + + switch (hdr.ehdr32.e_ident[EI_CLASS]) { + case ELFCLASS32: + switch (hdr.ehdr32.e_ident[EI_DATA]) { + case ELFDATA2LSB: + entry = le32toh(hdr.ehdr32.e_entry); + break; + case ELFDATA2MSB: + entry = be32toh(hdr.ehdr32.e_entry); + break; + default: + die("Invalid ELF encoding\n"); + } + + /* Sign extend to form a canonical address */ + entry = (int64_t)(int32_t)entry; + break; + + case ELFCLASS64: + switch (hdr.ehdr32.e_ident[EI_DATA]) { + case ELFDATA2LSB: + entry = le64toh(hdr.ehdr64.e_entry); + break; + case ELFDATA2MSB: + entry = be64toh(hdr.ehdr64.e_entry); + break; + default: + die("Invalid ELF encoding\n"); + } + break; + + default: + die("Invalid ELF class\n"); + } + + printf("0x%016" PRIx64 "\n", entry); + return EXIT_SUCCESS; +} diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index f6d9182ef82a..70a1ab66d252 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -960,12 +960,11 @@ void __init txx9_sramc_init(struct resource *r) goto exit_put; err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr); if (err) { - device_unregister(&dev->dev); iounmap(dev->base); - kfree(dev); + device_unregister(&dev->dev); } return; exit_put: + iounmap(dev->base); put_device(&dev->dev); - return; } diff --git a/arch/nds32/Makefile b/arch/nds32/Makefile index 3509fac10491..9f525ed70049 100644 --- a/arch/nds32/Makefile +++ b/arch/nds32/Makefile @@ -47,7 +47,7 @@ CHECKFLAGS += -D__NDS32_EB__ endif boot := arch/nds32/boot -core-$(BUILTIN_DTB) += $(boot)/dts/ +core-y += $(boot)/dts/ .PHONY: FORCE diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h index 6e95901cabe3..603e826e0449 100644 --- a/arch/nds32/include/uapi/asm/unistd.h +++ b/arch/nds32/include/uapi/asm/unistd.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2005-2017 Andes Technology Corporation +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYNC_FILE_RANGE2 /* Use the standard ABI for syscalls */ diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 03965692fbfe..2df0c57f2833 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig @@ -23,6 +23,9 @@ config NIOS2 select SPARSE_IRQ select USB_ARCH_HAS_HCD if USB_SUPPORT select CPU_NO_EFFICIENT_FFS + select HAVE_MEMBLOCK + select ARCH_DISCARD_MEMBLOCK + select NO_BOOTMEM config GENERIC_CSUM def_bool y diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile index 8673a79dca9c..52c03e60b114 100644 --- a/arch/nios2/Makefile +++ b/arch/nios2/Makefile @@ -49,21 +49,13 @@ BOOT_TARGETS = vmImage zImage PHONY += $(BOOT_TARGETS) install KBUILD_IMAGE := $(nios2-boot)/vmImage -ifneq ($(CONFIG_NIOS2_DTB_SOURCE),"") - core-y += $(nios2-boot)/ -endif +core-y += $(nios2-boot)/dts/ all: vmImage archclean: $(Q)$(MAKE) $(clean)=$(nios2-boot) -%.dtb: | scripts - $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@ - -dtbs: - $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@ - $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@ @@ -76,5 +68,4 @@ define archhelp echo ' (your) ~/bin/$(INSTALLKERNEL) or' echo ' (distribution) /sbin/$(INSTALLKERNEL) or' echo ' install to $$(INSTALL_PATH)' - echo ' dtbs - Build device tree blobs for enabled boards' endef diff --git a/arch/nios2/boot/Makefile b/arch/nios2/boot/Makefile index 2ba23a679732..37dfc7e584bc 100644 --- a/arch/nios2/boot/Makefile +++ b/arch/nios2/boot/Makefile @@ -31,27 +31,5 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ -# Rule to build device tree blobs -DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) - -# Make sure the generated dtb gets removed during clean -extra-$(CONFIG_NIOS2_DTB_SOURCE_BOOL) += system.dtb - -$(obj)/system.dtb: $(DTB_SRC) FORCE - $(call cmd,dtc) - -# Ensure system.dtb exists -$(obj)/linked_dtb.o: $(obj)/system.dtb - -obj-$(CONFIG_NIOS2_DTB_SOURCE_BOOL) += linked_dtb.o - -targets += $(dtb-y) - -# Rule to build device tree blobs with make command -$(obj)/%.dtb: $(src)/dts/%.dts FORCE - $(call if_changed_dep,dtc) - -$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y)) - install: sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/arch/nios2/boot/dts/Makefile b/arch/nios2/boot/dts/Makefile new file mode 100644 index 000000000000..a91a0b09be63 --- /dev/null +++ b/arch/nios2/boot/dts/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y := $(patsubst "%.dts",%.dtb.o,$(CONFIG_NIOS2_DTB_SOURCE)) + +dtstree := $(srctree)/$(src) +dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) diff --git a/arch/nios2/boot/linked_dtb.S b/arch/nios2/boot/linked_dtb.S deleted file mode 100644 index 071f922db338..000000000000 --- a/arch/nios2/boot/linked_dtb.S +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -.section .dtb.init.rodata,"a" -.incbin "arch/nios2/boot/system.dtb" diff --git a/arch/nios2/include/uapi/asm/unistd.h b/arch/nios2/include/uapi/asm/unistd.h index b6bdae04bc84..d9948d88790b 100644 --- a/arch/nios2/include/uapi/asm/unistd.h +++ b/arch/nios2/include/uapi/asm/unistd.h @@ -19,6 +19,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 /* Use the standard ABI for syscalls */ #include <asm-generic/unistd.h> diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 93207718bb22..ccc1d2a15a0a 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c @@ -47,7 +47,7 @@ void __init setup_cpuinfo(void) const char *str; int len; - cpu = of_find_node_by_type(NULL, "cpu"); + cpu = of_get_cpu_node(0, NULL); if (!cpu) panic("%s: No CPU found in devicetree!\n", __func__); @@ -120,6 +120,8 @@ void __init setup_cpuinfo(void) cpuinfo.reset_addr = fcpu(cpu, "altr,reset-addr"); cpuinfo.exception_addr = fcpu(cpu, "altr,exception-addr"); cpuinfo.fast_tlb_miss_exc_addr = fcpu(cpu, "altr,fast-tlb-miss-addr"); + + of_node_put(cpu); } #ifdef CONFIG_PROC_FS diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 8d7446a4b475..a6d4f7530247 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c @@ -32,23 +32,6 @@ #include <asm/sections.h> -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ - u64 kernel_start = (u64)virt_to_phys(_text); - - if (!memory_size && - (kernel_start >= base) && (kernel_start < (base + size))) - memory_size = size; - -} - -int __init early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, - bool nomap) -{ - reserve_bootmem(base, size, BOOTMEM_DEFAULT); - return 0; -} - void __init early_init_devtree(void *params) { __be32 *dtb = (u32 *)__dtb_start; diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index 926a02b17b31..2d0011ddd4d5 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c @@ -17,6 +17,7 @@ #include <linux/sched/task.h> #include <linux/console.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/initrd.h> #include <linux/of_fdt.h> #include <linux/screen_info.h> @@ -143,10 +144,12 @@ asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6, void __init setup_arch(char **cmdline_p) { - int bootmap_size; + int dram_start; console_verbose(); + dram_start = memblock_start_of_DRAM(); + memory_size = memblock_phys_mem_size(); memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; @@ -163,39 +166,11 @@ void __init setup_arch(char **cmdline_p) max_low_pfn = PFN_DOWN(memory_end); max_mapnr = max_low_pfn; - /* - * give all the memory to the bootmap allocator, tell it to put the - * boot mem_map at the start of memory - */ - pr_debug("init_bootmem_node(?,%#lx, %#x, %#lx)\n", - min_low_pfn, PFN_DOWN(PHYS_OFFSET), max_low_pfn); - bootmap_size = init_bootmem_node(NODE_DATA(0), - min_low_pfn, PFN_DOWN(PHYS_OFFSET), - max_low_pfn); - - /* - * free the usable memory, we have to make sure we do not free - * the bootmem bitmap so we then reserve it after freeing it :-) - */ - pr_debug("free_bootmem(%#lx, %#lx)\n", - memory_start, memory_end - memory_start); - free_bootmem(memory_start, memory_end - memory_start); - - /* - * Reserve the bootmem bitmap itself as well. We do this in two - * steps (first step was init_bootmem()) because this catches - * the (very unlikely) case of us accidentally initializing the - * bootmem allocator with an invalid RAM area. - * - * Arguments are start, size - */ - pr_debug("reserve_bootmem(%#lx, %#x)\n", memory_start, bootmap_size); - reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT); - + memblock_reserve(dram_start, memory_start - dram_start); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { - reserve_bootmem(virt_to_phys((void *)initrd_start), - initrd_end - initrd_start, BOOTMEM_DEFAULT); + memblock_reserve(virt_to_phys((void *)initrd_start), + initrd_end - initrd_start); } #endif /* CONFIG_BLK_DEV_INITRD */ diff --git a/arch/nios2/kernel/time.c b/arch/nios2/kernel/time.c index ab88b6dd4679..54467d0085a1 100644 --- a/arch/nios2/kernel/time.c +++ b/arch/nios2/kernel/time.c @@ -214,12 +214,12 @@ static int __init nios2_timer_get_base_and_freq(struct device_node *np, { *base = of_iomap(np, 0); if (!*base) { - pr_crit("Unable to map reg for %s\n", np->name); + pr_crit("Unable to map reg for %pOFn\n", np); return -ENXIO; } if (of_property_read_u32(np, "clock-frequency", freq)) { - pr_crit("Unable to get %s clock frequency\n", np->name); + pr_crit("Unable to get %pOFn clock frequency\n", np); return -EINVAL; } diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 11c5a58ab333..ec37df18d8ed 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -20,6 +20,7 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_CLONE diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c index 9d28ab14d139..e17fcd83120f 100644 --- a/arch/openrisc/kernel/setup.c +++ b/arch/openrisc/kernel/setup.c @@ -158,9 +158,8 @@ static struct device_node *setup_find_cpu_node(int cpu) { u32 hwid; struct device_node *cpun; - struct device_node *cpus = of_find_node_by_path("/cpus"); - for_each_available_child_of_node(cpus, cpun) { + for_each_of_cpu_node(cpun) { if (of_property_read_u32(cpun, "reg", &hwid)) continue; if (hwid == cpu) diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index ab8a54771507..e03e3c849f40 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -8,36 +8,22 @@ #include <linux/sched.h> #include <linux/thread_info.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "parisc\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u32 __compat_uid_t; typedef u32 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; /* dev_t is 32 bits on parisc */ @@ -48,11 +34,11 @@ struct compat_stat { u16 st_reserved2; /* old st_gid */ compat_dev_t st_rdev; compat_off_t st_size; - compat_time_t st_atime; + old_time32_t st_atime; u32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; u32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; u32 st_ctime_nsec; s32 st_blksize; s32 st_blocks; diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h index 58e0f4620426..7cb595dcb7d7 100644 --- a/arch/parisc/include/asm/hugetlb.h +++ b/arch/parisc/include/asm/hugetlb.h @@ -3,12 +3,12 @@ #define _ASM_PARISC64_HUGETLB_H #include <asm/page.h> -#include <asm-generic/hugetlb.h> - +#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); +#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); @@ -22,6 +22,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, * If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ +#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE static inline int prepare_hugepage_range(struct file *file, unsigned long addr, unsigned long len) { @@ -32,43 +33,25 @@ static inline int prepare_hugepage_range(struct file *file, return 0; } -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { } -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty); -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } +#include <asm-generic/hugetlb.h> + #endif /* _ASM_PARISC64_HUGETLB_H */ diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 3d507d04eb4c..bc37a4953eaa 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -141,6 +141,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ return K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ } +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM @@ -151,11 +152,11 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_COMPAT_SYS_TIME #define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL #define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING diff --git a/arch/parisc/include/uapi/asm/Kbuild b/arch/parisc/include/uapi/asm/Kbuild index 286ef5a5904b..adb5c64831c7 100644 --- a/arch/parisc/include/uapi/asm/Kbuild +++ b/arch/parisc/include/uapi/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += kvm_para.h generic-y += param.h generic-y += poll.h generic-y += resource.h +generic-y += siginfo.h diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index aafb1c0ca0af..82d1148c6379 100644 --- a/arch/parisc/include/uapi/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h @@ -62,6 +62,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIOCLEX 0x5451 diff --git a/arch/parisc/include/uapi/asm/posix_types.h b/arch/parisc/include/uapi/asm/posix_types.h index 2785632c85e7..8dce56f5dcee 100644 --- a/arch/parisc/include/uapi/asm/posix_types.h +++ b/arch/parisc/include/uapi/asm/posix_types.h @@ -16,9 +16,6 @@ typedef unsigned short __kernel_mode_t; typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t -typedef int __kernel_suseconds_t; -#define __kernel_suseconds_t __kernel_suseconds_t - typedef long long __kernel_off64_t; typedef unsigned long long __kernel_ino64_t; diff --git a/arch/parisc/include/uapi/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h deleted file mode 100644 index 4a1062e05aaf..000000000000 --- a/arch/parisc/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _PARISC_SIGINFO_H -#define _PARISC_SIGINFO_H - -#if defined(__LP64__) -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#endif - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 1c60408a64ad..d5eb19efa65b 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -394,6 +394,7 @@ */ .macro space_check spc,tmp,fault mfsp %sr7,\tmp + /* check against %r0 which is same value as LINUX_GATEWAY_SPACE */ or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page * as kernel, so defeat the space * check if it is */ @@ -910,9 +911,9 @@ intr_check_sig: * Only do signals if we are returning to user space */ LDREG PT_IASQ0(%r16), %r20 - cmpib,COND(=),n 0,%r20,intr_restore /* backward */ + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ LDREG PT_IASQ1(%r16), %r20 - cmpib,COND(=),n 0,%r20,intr_restore /* backward */ + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ /* NOTE: We need to enable interrupts if we have to deliver * signals. We used to do this earlier but it caused kernel diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index f5f22ea9b97e..9505c317818d 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -2,7 +2,7 @@ * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * System call entry code / Linux gateway page - * Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai> + * Copyright (c) Matthew Wilcox 1999 <willy@infradead.org> * Licensed under the GNU GPL. * thanks to Philipp Rumpf, Mike Shaver and various others * sorry about the wall, puffin.. diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index e7e626bcd0be..f88a52b8531c 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -513,17 +513,15 @@ static void __init map_pages(unsigned long start_vaddr, void __init set_kernel_text_rw(int enable_read_write) { - unsigned long start = (unsigned long)_stext; + unsigned long start = (unsigned long)__init_begin; unsigned long end = (unsigned long)_etext; map_pages(start, __pa(start), end-start, PAGE_KERNEL_RWX, enable_read_write ? 1:0); - /* force the kernel to see the new TLB entries */ - __flush_tlb_range(0, start, end); - - /* dump old cached instructions */ - flush_icache_range(start, end); + /* force the kernel to see the new page table entries */ + flush_cache_all(); + flush_tlb_all(); } void __ref free_initmem(void) diff --git a/arch/powerpc/Kbuild b/arch/powerpc/Kbuild new file mode 100644 index 000000000000..1625a06802ca --- /dev/null +++ b/arch/powerpc/Kbuild @@ -0,0 +1,16 @@ +subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror + +obj-y += kernel/ +obj-y += mm/ +obj-y += lib/ +obj-y += sysdev/ +obj-y += platforms/ +obj-y += math-emu/ +obj-y += crypto/ +obj-y += net/ + +obj-$(CONFIG_XMON) += xmon/ +obj-$(CONFIG_KVM) += kvm/ + +obj-$(CONFIG_PERF_EVENTS) += perf/ +obj-$(CONFIG_KEXEC_FILE) += purgatory/ diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a80669209155..e84943d24e5c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -137,7 +137,7 @@ config PPC select ARCH_HAS_PMEM_API if PPC64 select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_MEMBARRIER_CALLBACKS - select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE + select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC64 select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION) select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST @@ -180,6 +180,8 @@ config PPC select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_CBPF_JIT if !PPC64 + select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13) + select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) select HAVE_CONTEXT_TRACKING if PPC64 select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_STACKOVERFLOW @@ -188,6 +190,7 @@ config PPC select HAVE_EBPF_JIT if PPC64 select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC @@ -285,12 +288,10 @@ config ARCH_MAY_HAVE_PC_FDC config PPC_UDBG_16550 bool - default n config GENERIC_TBSYNC bool default y if PPC32 && SMP - default n config AUDIT_ARCH bool @@ -309,13 +310,11 @@ config EPAPR_BOOT bool help Used to allow a board to specify it wants an ePAPR compliant wrapper. - default n config DEFAULT_UIMAGE bool help Used to allow a board to specify it wants a uImage built by default - default n config ARCH_HIBERNATION_POSSIBLE bool @@ -329,11 +328,9 @@ config ARCH_SUSPEND_POSSIBLE config PPC_DCR_NATIVE bool - default n config PPC_DCR_MMIO bool - default n config PPC_DCR bool @@ -344,7 +341,6 @@ config PPC_OF_PLATFORM_PCI bool depends on PCI depends on PPC64 # not supported on 32 bits yet - default n config ARCH_SUPPORTS_DEBUG_PAGEALLOC depends on PPC32 || PPC_BOOK3S_64 @@ -447,14 +443,12 @@ config PPC_TRANSACTIONAL_MEM depends on SMP select ALTIVEC select VSX - default n ---help--- Support user-mode Transactional Memory on POWERPC. config LD_HEAD_STUB_CATCH bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT depends on PPC64 - default n help Very large kernels can cause linker branch stubs to be generated by code in head_64.S, which moves the head text sections out of their @@ -557,7 +551,6 @@ config RELOCATABLE config RELOCATABLE_TEST bool "Test relocatable kernel" depends on (PPC64 && RELOCATABLE) - default n help This runs the relocatable kernel at the address it was initially loaded at, which tends to be non-zero and therefore test the @@ -769,7 +762,6 @@ config PPC_SUBPAGE_PROT config PPC_COPRO_BASE bool - default n config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" @@ -892,7 +884,6 @@ config PPC_INDIRECT_PCI bool depends on PCI default y if 40x || 44x - default n config EISA bool @@ -989,7 +980,6 @@ source "drivers/pcmcia/Kconfig" config HAS_RAPIDIO bool - default n config RAPIDIO tristate "RapidIO support" @@ -1012,7 +1002,6 @@ endmenu config NONSTATIC_KERNEL bool - default n menu "Advanced setup" depends on PPC32 diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index fd63cd914a74..f4961fbcb48d 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -2,7 +2,6 @@ config PPC_DISABLE_WERROR bool "Don't build arch/powerpc code with -Werror" - default n help This option tells the compiler NOT to build the code under arch/powerpc with the -Werror flag (which means warnings @@ -56,7 +55,6 @@ config PPC_EMULATED_STATS config CODE_PATCHING_SELFTEST bool "Run self-tests of the code-patching code" depends on DEBUG_KERNEL - default n config JUMP_LABEL_FEATURE_CHECKS bool "Enable use of jump label for cpu/mmu_has_feature()" @@ -70,7 +68,6 @@ config JUMP_LABEL_FEATURE_CHECKS config JUMP_LABEL_FEATURE_CHECK_DEBUG bool "Do extra check on feature fixup calls" depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS - default n help This tries to catch incorrect usage of cpu_has_feature() and mmu_has_feature() in the code. @@ -80,16 +77,13 @@ config JUMP_LABEL_FEATURE_CHECK_DEBUG config FTR_FIXUP_SELFTEST bool "Run self-tests of the feature-fixup code" depends on DEBUG_KERNEL - default n config MSI_BITMAP_SELFTEST bool "Run self-tests of the MSI bitmap code" depends on DEBUG_KERNEL - default n config PPC_IRQ_SOFT_MASK_DEBUG bool "Include extra checks for powerpc irq soft masking" - default n config XMON bool "Include xmon kernel debugger" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 11a1acba164a..17be664dafa2 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -112,6 +112,13 @@ KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION) KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET) endif +cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls +ifdef CONFIG_PPC64 +cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r13 +else +cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2 +endif + LDFLAGS_vmlinux-y := -Bstatic LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) @@ -160,8 +167,17 @@ else CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64 endif +ifdef CONFIG_FUNCTION_TRACER +CC_FLAGS_FTRACE := -pg ifdef CONFIG_MPROFILE_KERNEL - CC_FLAGS_FTRACE := -pg -mprofile-kernel +CC_FLAGS_FTRACE += -mprofile-kernel +endif +# Work around gcc code-gen bugs with -pg / -fno-omit-frame-pointer in gcc <= 4.8 +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44199 +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52828 +ifneq ($(cc-name),clang) +CC_FLAGS_FTRACE += $(call cc-ifversion, -lt, 0409, -mno-sched-epilog) +endif endif CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU)) @@ -229,16 +245,15 @@ ifdef CONFIG_6xx KBUILD_CFLAGS += -mcpu=powerpc endif -# Work around a gcc code-gen bug with -fno-omit-frame-pointer. -ifdef CONFIG_FUNCTION_TRACER -KBUILD_CFLAGS += -mno-sched-epilog -endif - cpu-as-$(CONFIG_4xx) += -Wa,-m405 cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) cpu-as-$(CONFIG_E200) += -Wa,-me200 cpu-as-$(CONFIG_E500) += -Wa,-me500 -cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 + +# When using '-many -mpower4' gas will first try and find a matching power4 +# mnemonic and failing that it will allow any valid mnemonic that GAS knows +# about. GCC will pass -many to GAS when assembling, clang does not. +cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 -Wa,-many cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc) KBUILD_AFLAGS += $(cpu-as-y) @@ -258,18 +273,8 @@ head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o head-$(CONFIG_ALTIVEC) += arch/powerpc/kernel/vector.o head-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += arch/powerpc/kernel/prom_init.o -core-y += arch/powerpc/kernel/ \ - arch/powerpc/mm/ \ - arch/powerpc/lib/ \ - arch/powerpc/sysdev/ \ - arch/powerpc/platforms/ \ - arch/powerpc/math-emu/ \ - arch/powerpc/crypto/ \ - arch/powerpc/net/ -core-$(CONFIG_XMON) += arch/powerpc/xmon/ -core-$(CONFIG_KVM) += arch/powerpc/kvm/ -core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/ -core-$(CONFIG_KEXEC_FILE) += arch/powerpc/purgatory/ +# See arch/powerpc/Kbuild for content of core part of the kernel +core-y += arch/powerpc/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ @@ -293,9 +298,6 @@ $(BOOT_TARGETS2): vmlinux bootwrapper_install: $(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@) -%.dtb: scripts - $(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@) - # Used to create 'merged defconfigs' # To use it $(call) it with the first argument as the base defconfig # and the second argument as a space separated list of .config files to merge, @@ -400,40 +402,20 @@ archclean: archprepare: checkbin -# Use the file '.tmp_gas_check' for binutils tests, as gas won't output -# to stdout and these checks are run even on install targets. -TOUT := .tmp_gas_check +ifdef CONFIG_STACKPROTECTOR +prepare: stack_protector_prepare + +stack_protector_prepare: prepare0 +ifdef CONFIG_PPC64 + $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h)) +else + $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h)) +endif +endif -# Check gcc and binutils versions: -# - gcc-3.4 and binutils-2.14 are a fatal combination -# - Require gcc 4.0 or above on 64-bit -# - gcc-4.2.0 has issues compiling modules on 64-bit +# Check toolchain versions: +# - gcc-4.6 is the minimum kernel-wide version so nothing required. checkbin: - @if test "$(cc-name)" != "clang" \ - && test "$(cc-version)" = "0304" ; then \ - if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ - echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \ - echo 'correctly with gcc-3.4 and your version of binutils.'; \ - echo '*** Please upgrade your binutils or downgrade your gcc'; \ - false; \ - fi ; \ - fi - @if test "$(cc-name)" != "clang" \ - && test "$(cc-version)" -lt "0400" \ - && test "x${CONFIG_PPC64}" = "xy" ; then \ - echo -n "Sorry, GCC v4.0 or above is required to build " ; \ - echo "the 64-bit powerpc kernel." ; \ - false ; \ - fi - @if test "$(cc-name)" != "clang" \ - && test "$(cc-fullversion)" = "040200" \ - && test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \ - echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \ - echo 'kernel with modules enabled.' ; \ - echo -n '*** Please use a different GCC version or ' ; \ - echo 'disable kernel modules' ; \ - false ; \ - fi @if test "x${CONFIG_CPU_LITTLE_ENDIAN}" = "xy" \ && $(LD) --version | head -1 | grep ' 2\.24$$' >/dev/null ; then \ echo -n '*** binutils 2.24 miscompiles weak symbols ' ; \ @@ -441,7 +423,3 @@ checkbin: echo -n '*** Please use a different binutils version.' ; \ false ; \ fi - - -CLEAN_FILES += $(TOUT) - diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index f92d0530ceb1..32034a0cc554 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -44,4 +44,5 @@ fdt_sw.c fdt_wip.c libfdt.h libfdt_internal.h +autoconf.h diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 0fb96c26136f..39354365f54a 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -32,8 +32,8 @@ else endif BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ - -fno-strict-aliasing -Os -msoft-float -pipe \ - -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ + -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \ + -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ -D$(compress-y) ifdef CONFIG_PPC64_BOOT_WRAPPER @@ -197,9 +197,14 @@ $(obj)/empty.c: $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S $(Q)cp $< $@ +$(obj)/serial.c: $(obj)/autoconf.h + +$(obj)/autoconf.h: $(obj)/%: $(objtree)/include/generated/% + $(Q)cp $< $@ + clean-files := $(zlib-) $(zlibheader-) $(zliblinuxheader-) \ $(zlib-decomp-) $(libfdt) $(libfdtheader) \ - empty.c zImage.coff.lds zImage.ps3.lds zImage.lds + autoconf.h empty.c zImage.coff.lds zImage.ps3.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< @@ -304,9 +309,9 @@ image-$(CONFIG_PPC_ADDER875) += cuImage.adder875-uboot \ dtbImage.adder875-redboot # Board ports in arch/powerpc/platform/52xx/Kconfig -image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200 lite5200.dtb -image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200b lite5200b.dtb -image-$(CONFIG_PPC_MEDIA5200) += cuImage.media5200 media5200.dtb +image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200 +image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200b +image-$(CONFIG_PPC_MEDIA5200) += cuImage.media5200 # Board ports in arch/powerpc/platform/82xx/Kconfig image-$(CONFIG_MPC8272_ADS) += cuImage.mpc8272ads @@ -381,11 +386,11 @@ $(addprefix $(obj)/, $(sort $(filter zImage.%, $(image-y)))): vmlinux $(wrapperb $(call if_changed,wrap,$(subst $(obj)/zImage.,,$@)) # dtbImage% - a dtbImage is a zImage with an embedded device tree blob -$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE - $(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) +$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/dts/%.dtb FORCE + $(call if_changed,wrap,$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE - $(call if_changed,wrap,$*,,$(obj)/$*.dtb) +$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/dts/%.dtb FORCE + $(call if_changed,wrap,$*,,$(obj)/dts/$*.dtb) # This cannot be in the root of $(src) as the zImage rule always adds a $(obj) # prefix @@ -395,36 +400,33 @@ $(obj)/vmlinux.strip: vmlinux $(obj)/uImage: vmlinux $(wrapperbits) FORCE $(call if_changed,wrap,uboot) -$(obj)/uImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) - -$(obj)/uImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb) +$(obj)/uImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,uboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) +$(obj)/uImage.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,uboot-$*,,$(obj)/dts/$*.dtb) -$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb) +$(obj)/cuImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,cuboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) +$(obj)/cuImage.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,cuboot-$*,,$(obj)/dts/$*.dtb) -$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb) +$(obj)/simpleImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,simpleboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) +$(obj)/simpleImage.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,simpleboot-$*,,$(obj)/dts/$*.dtb) -$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb) +$(obj)/treeImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,treeboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -# Rule to build device tree blobs -$(obj)/%.dtb: $(src)/dts/%.dts FORCE - $(call if_changed_dep,dtc) +$(obj)/treeImage.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE + $(call if_changed,wrap,treeboot-$*,,$(obj)/dts/$*.dtb) -$(obj)/%.dtb: $(src)/dts/fsl/%.dts FORCE - $(call if_changed_dep,dtc) +# Needed for the above targets to work with dts/fsl/ files +$(obj)/dts/%.dtb: $(obj)/dts/fsl/%.dtb + @cp $< $@ # If there isn't a platform selected then just strip the vmlinux. ifeq (,$(image-y)) diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index dcf2f15e6797..32dfe6d083f3 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -47,8 +47,10 @@ p_end: .long _end p_pstack: .long _platform_stack_top #endif - .weak _zimage_start .globl _zimage_start + /* Clang appears to require the .weak directive to be after the symbol + * is defined. See https://bugs.llvm.org/show_bug.cgi?id=38921 */ + .weak _zimage_start _zimage_start: .globl _zimage_start_lib _zimage_start_lib: diff --git a/arch/powerpc/boot/dts/Makefile b/arch/powerpc/boot/dts/Makefile new file mode 100644 index 000000000000..fb335d05aae8 --- /dev/null +++ b/arch/powerpc/boot/dts/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +subdir-y += fsl + +dtstree := $(srctree)/$(src) +dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) diff --git a/arch/powerpc/boot/dts/fsl/Makefile b/arch/powerpc/boot/dts/fsl/Makefile new file mode 100644 index 000000000000..3bae982641e9 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +dtstree := $(srctree)/$(src) +dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts)) diff --git a/arch/powerpc/boot/libfdt_env.h b/arch/powerpc/boot/libfdt_env.h index 2a0c8b1bf147..2abc8e83b95e 100644 --- a/arch/powerpc/boot/libfdt_env.h +++ b/arch/powerpc/boot/libfdt_env.h @@ -5,6 +5,8 @@ #include <types.h> #include <string.h> +#define INT_MAX ((int)(~0U>>1)) + #include "of.h" typedef unsigned long uintptr_t; diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c index 0272570d02de..dfb199ef5b94 100644 --- a/arch/powerpc/boot/opal.c +++ b/arch/powerpc/boot/opal.c @@ -13,8 +13,6 @@ #include <libfdt.h> #include "../include/asm/opal-api.h" -#ifdef CONFIG_PPC64_BOOT_WRAPPER - /* Global OPAL struct used by opal-call.S */ struct opal { u64 base; @@ -101,9 +99,3 @@ int opal_console_init(void *devp, struct serial_console_data *scdp) return 0; } -#else -int opal_console_init(void *devp, struct serial_console_data *scdp) -{ - return -1; -} -#endif /* __powerpc64__ */ diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index 48e3743faedf..f045f8494bf9 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c @@ -18,6 +18,7 @@ #include "stdio.h" #include "io.h" #include "ops.h" +#include "autoconf.h" static int serial_open(void) { diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 67c39f4acede..f686cc1eac0b 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -262,3 +262,4 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m # CONFIG_CRYPTO_HW is not set +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 59e47ec85336..f71eddafb02f 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -112,3 +112,4 @@ CONFIG_PPC_EARLY_DEBUG=y CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_HW is not set +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 6ab34e60495f..ef2ef98d3f28 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig @@ -44,6 +44,9 @@ CONFIG_PPC_MEMTRACE=y # CONFIG_PPC_PSERIES is not set # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_IDLE=y CONFIG_HZ_100=y CONFIG_BINFMT_MISC=m @@ -350,3 +353,4 @@ CONFIG_VIRTUALIZATION=y CONFIG_KVM_BOOK3S_64=m CONFIG_KVM_BOOK3S_64_HV=m CONFIG_VHOST_NET=m +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 5033e630afea..f2515674a1e2 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -40,6 +40,9 @@ CONFIG_PS3_LPM=m CONFIG_PPC_IBM_CELL_BLADE=y CONFIG_RTAS_FLASH=m CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_FREQ_PMAC64=y CONFIG_HZ_100=y CONFIG_BINFMT_MISC=m @@ -365,3 +368,4 @@ CONFIG_VIRTUALIZATION=y CONFIG_KVM_BOOK3S_64=m CONFIG_KVM_BOOK3S_64_HV=m CONFIG_VHOST_NET=m +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 187e2f7c12c8..cf8d55f67272 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -171,3 +171,4 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_LZO=m +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 0dd5cf7b566d..5e09a40cbcbf 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -325,3 +325,4 @@ CONFIG_VIRTUALIZATION=y CONFIG_KVM_BOOK3S_64=m CONFIG_KVM_BOOK3S_64_HV=m CONFIG_VHOST_NET=m +CONFIG_PRINTK_TIME=y diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig index 6bd5e7261335..cfdd08897a06 100644 --- a/arch/powerpc/configs/skiroot_defconfig +++ b/arch/powerpc/configs/skiroot_defconfig @@ -3,20 +3,17 @@ CONFIG_ALTIVEC=y CONFIG_VSX=y CONFIG_NR_CPUS=2048 CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_KERNEL_XZ=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_CPU_ISOLATION is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=20 -CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set @@ -24,8 +21,14 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZO is not set # CONFIG_RD_LZ4 is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_SHMEM is not set +# CONFIG_AIO is not set CONFIG_PERF_EVENTS=y # CONFIG_COMPAT_BRK is not set +CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_JUMP_LABEL=y CONFIG_STRICT_KERNEL_RWX=y CONFIG_MODULES=y @@ -35,7 +38,9 @@ CONFIG_MODULE_SIG_FORCE=y CONFIG_MODULE_SIG_SHA512=y CONFIG_PARTITION_ADVANCED=y # CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_PPC_VAS is not set # CONFIG_PPC_PSERIES is not set +# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y CONFIG_HZ_100=y @@ -48,8 +53,9 @@ CONFIG_NUMA=y CONFIG_PPC_64K_PAGES=y CONFIG_SCHED_SMT=y CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=tty0 console=hvc0 powersave=off" +CONFIG_CMDLINE="console=tty0 console=hvc0 ipr.fast_reboot=1 quiet" # CONFIG_SECCOMP is not set +# CONFIG_PPC_MEM_KEYS is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -60,7 +66,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_IPV6 is not set CONFIG_DNS_RESOLVER=y # CONFIG_WIRELESS is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" @@ -73,8 +78,10 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_NVME=m -CONFIG_EEPROM_AT24=y +CONFIG_NVME_MULTIPATH=y +CONFIG_EEPROM_AT24=m # CONFIG_CXL is not set +# CONFIG_OCXL is not set CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m CONFIG_BLK_DEV_SR_VENDOR=y @@ -85,7 +92,6 @@ CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_SCSI_CXGB4_ISCSI=m CONFIG_SCSI_BNX2_ISCSI=m -CONFIG_BE2ISCSI=m CONFIG_SCSI_AACRAID=m CONFIG_MEGARAID_NEWGEN=y CONFIG_MEGARAID_MM=m @@ -102,7 +108,7 @@ CONFIG_SCSI_VIRTIO=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_ALUA=m CONFIG_ATA=y -CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI=m # CONFIG_ATA_SFF is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m @@ -119,25 +125,72 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y -CONFIG_TIGON3=y +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +CONFIG_TIGON3=m CONFIG_BNX2X=m -CONFIG_CHELSIO_T1=y +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +CONFIG_CHELSIO_T1=m +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set CONFIG_BE2NET=m -CONFIG_S2IO=m -CONFIG_E100=m +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_HUAWEI is not set CONFIG_E1000=m -CONFIG_E1000E=m +CONFIG_IGB=m CONFIG_IXGB=m CONFIG_IXGBE=m +CONFIG_I40E=m +CONFIG_S2IO=m +# CONFIG_NET_VENDOR_MARVELL is not set CONFIG_MLX4_EN=m +# CONFIG_MLX4_CORE_GEN2 is not set CONFIG_MLX5_CORE=m -CONFIG_MLX5_CORE_EN=y +# CONFIG_NET_VENDOR_MICREL is not set CONFIG_MYRI10GE=m +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set CONFIG_QLGE=m CONFIG_NETXEN_NIC=m +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set CONFIG_SFC=m +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_PHYLIB=y # CONFIG_USB_NET_DRIVERS is not set # CONFIG_WLAN is not set CONFIG_INPUT_EVDEV=y @@ -149,39 +202,51 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_IPMI_HANDLER=y CONFIG_IPMI_DEVICE_INTERFACE=y CONFIG_IPMI_POWERNV=y +CONFIG_IPMI_WATCHDOG=y CONFIG_HW_RANDOM=y +CONFIG_TCG_TPM=y CONFIG_TCG_TIS_I2C_NUVOTON=y +CONFIG_I2C=y # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set -CONFIG_DRM=y -CONFIG_DRM_RADEON=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_OPAL=m +CONFIG_PPS=y +CONFIG_SENSORS_IBMPOWERNV=m +CONFIG_DRM=m CONFIG_DRM_AST=m +CONFIG_FB=y CONFIG_FIRMWARE_EDID=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_OF=y -CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G=y -# CONFIG_LCD_CLASS_DEVICE is not set -# CONFIG_BACKLIGHT_GENERIC is not set # CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_HID_GENERIC=m +CONFIG_HID_A4TECH=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_EZKEY=y +CONFIG_HID_ITE=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y CONFIG_USB_HIDDEV=y -CONFIG_USB=y -CONFIG_USB_MON=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y +CONFIG_USB=m +CONFIG_USB_XHCI_HCD=m +CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_HCD_PPC_OF is not set -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_STORAGE=y +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_STORAGE=m CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_OPAL=m CONFIG_RTC_DRV_GENERIC=m CONFIG_VIRT_DRIVERS=y -CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI=m # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT4_FS=m CONFIG_EXT4_FS_POSIX_ACL=y @@ -195,10 +260,9 @@ CONFIG_UDF_FS=m CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y @@ -207,26 +271,24 @@ CONFIG_NLS_UTF8=y CONFIG_CRC16=y CONFIG_CRC_ITU_T=y CONFIG_LIBCRC32C=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set CONFIG_PRINTK_TIME=y CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_SOFTLOCKUP_DETECTOR=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y CONFIG_WQ_WATCHDOG=y -CONFIG_SCHEDSTATS=y +# CONFIG_SCHED_DEBUG is not set # CONFIG_FTRACE is not set +# CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_XMON=y CONFIG_XMON_DEFAULT=y -CONFIG_SECURITY=y -CONFIG_IMA=y -CONFIG_EVM=y +CONFIG_ENCRYPTED_KEYS=y # CONFIG_CRYPTO_ECHAINIV is not set -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_CMAC=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_HW is not set diff --git a/arch/powerpc/include/asm/accounting.h b/arch/powerpc/include/asm/accounting.h index 3abcf98ed2e0..c607c5d835cc 100644 --- a/arch/powerpc/include/asm/accounting.h +++ b/arch/powerpc/include/asm/accounting.h @@ -15,8 +15,10 @@ struct cpu_accounting_data { /* Accumulated cputime values to flush on ticks*/ unsigned long utime; unsigned long stime; +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME unsigned long utime_scaled; unsigned long stime_scaled; +#endif unsigned long gtime; unsigned long hardirq_time; unsigned long softirq_time; @@ -25,8 +27,10 @@ struct cpu_accounting_data { /* Internal counters */ unsigned long starttime; /* TB value snapshot */ unsigned long starttime_user; /* TB value on exit to usermode */ +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME unsigned long startspurr; /* SPURR value snapshot */ unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ +#endif }; #endif diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h index 1f4691ce4126..ec691d489656 100644 --- a/arch/powerpc/include/asm/asm-prototypes.h +++ b/arch/powerpc/include/asm/asm-prototypes.h @@ -63,7 +63,6 @@ void program_check_exception(struct pt_regs *regs); void alignment_exception(struct pt_regs *regs); void slb_miss_bad_addr(struct pt_regs *regs); void StackOverflow(struct pt_regs *regs); -void nonrecoverable_exception(struct pt_regs *regs); void kernel_fp_unavailable_exception(struct pt_regs *regs); void altivec_unavailable_exception(struct pt_regs *regs); void vsx_unavailable_exception(struct pt_regs *regs); @@ -78,6 +77,8 @@ void kernel_bad_stack(struct pt_regs *regs); void system_reset_exception(struct pt_regs *regs); void machine_check_exception(struct pt_regs *regs); void emulation_assist_interrupt(struct pt_regs *regs); +long do_slb_fault(struct pt_regs *regs, unsigned long ea); +void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err); /* signals, syscalls and interrupts */ long sys_swapcontext(struct ucontext __user *old_ctx, @@ -150,4 +151,25 @@ extern s32 patch__memset_nocache, patch__memcpy_nocache; extern long flush_count_cache; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv); +void kvmppc_restore_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv); +#else +static inline void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, + bool preserve_nv) { } +static inline void kvmppc_restore_tm_hv(struct kvm_vcpu *vcpu, u64 msr, + bool preserve_nv) { } +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ + +void kvmhv_save_host_pmu(void); +void kvmhv_load_host_pmu(void); +void kvmhv_save_guest_pmu(struct kvm_vcpu *vcpu, bool pmu_in_use); +void kvmhv_load_guest_pmu(struct kvm_vcpu *vcpu); + +int __kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu); + +long kvmppc_h_set_dabr(struct kvm_vcpu *vcpu, unsigned long dabr); +long kvmppc_h_set_xdabr(struct kvm_vcpu *vcpu, unsigned long dabr, + unsigned long dabrx); + #endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 751cf931bb3f..c21d33704633 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -8,7 +8,97 @@ #include <asm/book3s/32/hash.h> /* And here we include common definitions */ -#include <asm/pte-common.h> + +#define _PAGE_KERNEL_RO 0 +#define _PAGE_KERNEL_ROX 0 +#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) +#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW) + +#define _PAGE_HPTEFLAGS _PAGE_HASHPTE + +#ifndef __ASSEMBLY__ + +static inline bool pte_user(pte_t pte) +{ + return pte_val(pte) & _PAGE_USER; +} +#endif /* __ASSEMBLY__ */ + +/* + * Location of the PFN in the PTE. Most 32-bit platforms use the same + * as _PAGE_SHIFT here (ie, naturally aligned). + * Platform who don't just pre-define the value so we don't override it here. + */ +#define PTE_RPN_SHIFT (PAGE_SHIFT) + +/* + * The mask covered by the RPN must be a ULL on 32-bit platforms with + * 64-bit PTEs. + */ +#ifdef CONFIG_PTE_64BIT +#define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) +#else +#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) +#endif + +/* + * _PAGE_CHG_MASK masks of bits that are to be preserved across + * pgprot changes. + */ +#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HASHPTE | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_SPECIAL) + +/* + * We define 2 sets of base prot bits, one for basic pages (ie, + * cacheable kernel and user pages) and one for non cacheable + * pages. We always set _PAGE_COHERENT when SMP is enabled or + * the processor might need it for DMA coherency. + */ +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) +#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) + +/* + * Permission masks used to generate the __P and __S table. + * + * Note:__pgprot is defined in arch/powerpc/include/asm/page.h + * + * Write permissions imply read permissions for now. + */ +#define PAGE_NONE __pgprot(_PAGE_BASE) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER) + +/* Permission masks used for kernel mappings */ +#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) +#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) +#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ + _PAGE_NO_CACHE | _PAGE_GUARDED) +#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) +#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) +#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) + +/* + * Protection used for kernel text. We want the debuggers to be able to + * set breakpoints anywhere, so don't write protect the kernel text + * on platforms where such control is possible. + */ +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ + defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) +#define PAGE_KERNEL_TEXT PAGE_KERNEL_X +#else +#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX +#endif + +/* Make modules code happy. We don't set RO yet */ +#define PAGE_KERNEL_EXEC PAGE_KERNEL_X + +/* Advertise special mapping type for AGP */ +#define PAGE_AGP (PAGE_KERNEL_NC) +#define HAVE_PAGE_AGP #define PTE_INDEX_SIZE PTE_SHIFT #define PMD_INDEX_SIZE 0 @@ -219,14 +309,8 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), _PAGE_RO); + pte_update(ptep, _PAGE_RW, 0); } -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, pte_t entry, @@ -234,10 +318,9 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, int psize) { unsigned long set = pte_val(entry) & - (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - unsigned long clr = ~pte_val(entry) & _PAGE_RO; + (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW); - pte_update(ptep, clr, set); + pte_update(ptep, 0, set); flush_tlb_page(vma, address); } @@ -292,7 +375,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) -int map_kernel_page(unsigned long va, phys_addr_t pa, int flags); +int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); /* Generic accessors to PTE bits */ static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);} @@ -301,13 +384,28 @@ static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); } static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); } static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } -static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } +static inline bool pte_exec(pte_t pte) { return true; } static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +static inline bool pte_hw_valid(pte_t pte) +{ + return pte_val(pte) & _PAGE_PRESENT; +} + +static inline bool pte_hashpte(pte_t pte) +{ + return !!(pte_val(pte) & _PAGE_HASHPTE); +} + +static inline bool pte_ci(pte_t pte) +{ + return !!(pte_val(pte) & _PAGE_NO_CACHE); +} + /* * We only find page table entry in the last level * Hence no need for other accessors @@ -315,17 +413,14 @@ static inline int pte_present(pte_t pte) #define pte_access_permitted pte_access_permitted static inline bool pte_access_permitted(pte_t pte, bool write) { - unsigned long pteval = pte_val(pte); /* * A read-only access is controlled by _PAGE_USER bit. * We have _PAGE_READ set for WRITE and EXECUTE */ - unsigned long need_pte_bits = _PAGE_PRESENT | _PAGE_USER; - - if (write) - need_pte_bits |= _PAGE_WRITE; + if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) + return false; - if ((pteval & need_pte_bits) != need_pte_bits) + if (write && !pte_write(pte)) return false; return true; @@ -354,6 +449,11 @@ static inline pte_t pte_wrprotect(pte_t pte) return __pte(pte_val(pte) & ~_PAGE_RW); } +static inline pte_t pte_exprotect(pte_t pte) +{ + return pte; +} + static inline pte_t pte_mkclean(pte_t pte) { return __pte(pte_val(pte) & ~_PAGE_DIRTY); @@ -364,6 +464,16 @@ static inline pte_t pte_mkold(pte_t pte) return __pte(pte_val(pte) & ~_PAGE_ACCESSED); } +static inline pte_t pte_mkexec(pte_t pte) +{ + return pte; +} + +static inline pte_t pte_mkpte(pte_t pte) +{ + return pte; +} + static inline pte_t pte_mkwrite(pte_t pte) { return __pte(pte_val(pte) | _PAGE_RW); @@ -389,6 +499,16 @@ static inline pte_t pte_mkhuge(pte_t pte) return pte; } +static inline pte_t pte_mkprivileged(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_USER); +} + +static inline pte_t pte_mkuser(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_USER); +} + static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index 9a3798660cef..15bc16b1dc9c 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h @@ -66,7 +66,7 @@ static inline int hash__hugepd_ok(hugepd_t hpd) * if it is not a pte and have hugepd shift mask * set, then it is a hugepd directory pointer */ - if (!(hpdval & _PAGE_PTE) && + if (!(hpdval & _PAGE_PTE) && (hpdval & _PAGE_PRESENT) && ((hpdval & HUGEPD_SHIFT_MASK) != 0)) return true; return false; diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index d52a51b2ce7b..247aff9cc6ba 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h @@ -18,6 +18,11 @@ #include <asm/book3s/64/hash-4k.h> #endif +/* Bits to set in a PMD/PUD/PGD entry valid bit*/ +#define HASH_PMD_VAL_BITS (0x8000000000000000UL) +#define HASH_PUD_VAL_BITS (0x8000000000000000UL) +#define HASH_PGD_VAL_BITS (0x8000000000000000UL) + /* * Size of EA range mapped by our pagetables. */ @@ -196,8 +201,7 @@ static inline void hpte_do_hugepage_flush(struct mm_struct *mm, #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -extern int hash__map_kernel_page(unsigned long ea, unsigned long pa, - unsigned long flags); +int hash__map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); extern int __meminit hash__vmemmap_create_mapping(unsigned long start, unsigned long page_size, unsigned long phys); diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h index 50888388a359..5b0177733994 100644 --- a/arch/powerpc/include/asm/book3s/64/hugetlb.h +++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h @@ -39,4 +39,7 @@ static inline bool gigantic_page_supported(void) } #endif +/* hugepd entry valid bit */ +#define HUGEPD_VAL_BITS (0x8000000000000000UL) + #endif diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index b3520b549cba..12e522807f9f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h @@ -30,7 +30,7 @@ * SLB */ -#define SLB_NUM_BOLTED 3 +#define SLB_NUM_BOLTED 2 #define SLB_CACHE_ENTRIES 8 #define SLB_MIN_SIZE 32 @@ -203,6 +203,18 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) BUG(); } +static inline unsigned int ap_to_shift(unsigned long ap) +{ + int psize; + + for (psize = 0; psize < MMU_PAGE_COUNT; psize++) { + if (mmu_psize_defs[psize].ap == ap) + return mmu_psize_defs[psize].shift; + } + + return -1; +} + static inline unsigned long get_sllp_encoding(int psize) { unsigned long sllp; @@ -487,6 +499,8 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, extern void pseries_add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); +extern void hash__setup_new_exec(void); + #ifdef CONFIG_PPC_PSERIES void hpte_init_pseries(void); #else @@ -495,11 +509,18 @@ static inline void hpte_init_pseries(void) { } extern void hpte_init_native(void); +struct slb_entry { + u64 esid; + u64 vsid; +}; + extern void slb_initialize(void); -extern void slb_flush_and_rebolt(void); +void slb_flush_and_restore_bolted(void); void slb_flush_all_realmode(void); void __slb_restore_bolted_realmode(void); void slb_restore_bolted_realmode(void); +void slb_save_contents(struct slb_entry *slb_ptr); +void slb_dump_contents(struct slb_entry *slb_ptr); extern void slb_vmalloc_update(void); extern void slb_set_size(u16 size); @@ -512,13 +533,9 @@ extern void slb_set_size(u16 size); * from mmu context id and effective segment id of the address. * * For user processes max context id is limited to MAX_USER_CONTEXT. - - * For kernel space, we use context ids 1-4 to map addresses as below: - * NOTE: each context only support 64TB now. - * 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ] - * 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ] - * 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ] - * 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ] + * more details in get_user_context + * + * For kernel space get_kernel_context * * The proto-VSIDs are then scrambled into real VSIDs with the * multiplicative hash: @@ -559,6 +576,21 @@ extern void slb_set_size(u16 size); #define ESID_BITS_1T_MASK ((1 << ESID_BITS_1T) - 1) /* + * Now certain config support MAX_PHYSMEM more than 512TB. Hence we will need + * to use more than one context for linear mapping the kernel. + * For vmalloc and memmap, we use just one context with 512TB. With 64 byte + * struct page size, we need ony 32 TB in memmap for 2PB (51 bits (MAX_PHYSMEM_BITS)). + */ +#if (MAX_PHYSMEM_BITS > MAX_EA_BITS_PER_CONTEXT) +#define MAX_KERNEL_CTX_CNT (1UL << (MAX_PHYSMEM_BITS - MAX_EA_BITS_PER_CONTEXT)) +#else +#define MAX_KERNEL_CTX_CNT 1 +#endif + +#define MAX_VMALLOC_CTX_CNT 1 +#define MAX_MEMMAP_CTX_CNT 1 + +/* * 256MB segment * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments * available for user + kernel mapping. VSID 0 is reserved as invalid, contexts @@ -568,12 +600,13 @@ extern void slb_set_size(u16 size); * We also need to avoid the last segment of the last context, because that * would give a protovsid of 0x1fffffffff. That will result in a VSID 0 * because of the modulo operation in vsid scramble. + * + * We add one extra context to MIN_USER_CONTEXT so that we can map kernel + * context easily. The +1 is to map the unused 0xe region mapping. */ #define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 2) -#define MIN_USER_CONTEXT (5) - -/* Would be nice to use KERNEL_REGION_ID here */ -#define KERNEL_REGION_CONTEXT_OFFSET (0xc - 1) +#define MIN_USER_CONTEXT (MAX_KERNEL_CTX_CNT + MAX_VMALLOC_CTX_CNT + \ + MAX_MEMMAP_CTX_CNT + 2) /* * For platforms that support on 65bit VA we limit the context bits @@ -734,6 +767,39 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea, } /* + * For kernel space, we use context ids as below + * below. Range is 512TB per context. + * + * 0x00001 - [ 0xc000000000000000 - 0xc001ffffffffffff] + * 0x00002 - [ 0xc002000000000000 - 0xc003ffffffffffff] + * 0x00003 - [ 0xc004000000000000 - 0xc005ffffffffffff] + * 0x00004 - [ 0xc006000000000000 - 0xc007ffffffffffff] + + * 0x00005 - [ 0xd000000000000000 - 0xd001ffffffffffff ] + * 0x00006 - Not used - Can map 0xe000000000000000 range. + * 0x00007 - [ 0xf000000000000000 - 0xf001ffffffffffff ] + * + * So we can compute the context from the region (top nibble) by + * subtracting 11, or 0xc - 1. + */ +static inline unsigned long get_kernel_context(unsigned long ea) +{ + unsigned long region_id = REGION_ID(ea); + unsigned long ctx; + /* + * For linear mapping we do support multiple context + */ + if (region_id == KERNEL_REGION_ID) { + /* + * We already verified ea to be not beyond the addr limit. + */ + ctx = 1 + ((ea & ~REGION_MASK) >> MAX_EA_BITS_PER_CONTEXT); + } else + ctx = (region_id - 0xc) + MAX_KERNEL_CTX_CNT; + return ctx; +} + +/* * This is only valid for addresses >= PAGE_OFFSET */ static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) @@ -743,20 +809,7 @@ static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) if (!is_kernel_addr(ea)) return 0; - /* - * For kernel space, we use context ids 1-4 to map the address space as - * below: - * - * 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ] - * 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ] - * 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ] - * 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ] - * - * So we can compute the context from the region (top nibble) by - * subtracting 11, or 0xc - 1. - */ - context = (ea >> 60) - KERNEL_REGION_CONTEXT_OFFSET; - + context = get_kernel_context(ea); return get_vsid(context, ea, ssize); } diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 9c8c669a6b6a..6328857f259f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -208,7 +208,7 @@ extern void radix_init_pseries(void); static inline void radix_init_pseries(void) { }; #endif -static inline int get_ea_context(mm_context_t *ctx, unsigned long ea) +static inline int get_user_context(mm_context_t *ctx, unsigned long ea) { int index = ea >> MAX_EA_BITS_PER_CONTEXT; @@ -223,7 +223,7 @@ static inline int get_ea_context(mm_context_t *ctx, unsigned long ea) static inline unsigned long get_user_vsid(mm_context_t *ctx, unsigned long ea, int ssize) { - unsigned long context = get_ea_context(ctx, ea); + unsigned long context = get_user_context(ctx, ea); return get_vsid(context, ea, ssize); } diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h index d7ee249d6890..e3d4dd4ae2fa 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h @@ -10,6 +10,9 @@ * * Defined in such a way that we can optimize away code block at build time * if CONFIG_HUGETLB_PAGE=n. + * + * returns true for pmd migration entries, THP, devmap, hugetlb + * But compile time dependent on CONFIG_HUGETLB_PAGE */ static inline int pmd_huge(pmd_t pmd) { diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 2a2486526d1f..6c99e846a8c9 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -14,10 +14,6 @@ */ #define _PAGE_BIT_SWAP_TYPE 0 -#define _PAGE_NA 0 -#define _PAGE_RO 0 -#define _PAGE_USER 0 - #define _PAGE_EXEC 0x00001 /* execute permission */ #define _PAGE_WRITE 0x00002 /* write access allowed */ #define _PAGE_READ 0x00004 /* read access allowed */ @@ -123,10 +119,6 @@ #define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | \ _PAGE_RW | _PAGE_EXEC) /* - * No page size encoding in the linux PTE - */ -#define _PAGE_PSIZE 0 -/* * _PAGE_CHG_MASK masks of bits that are to be preserved across * pgprot changes */ @@ -137,19 +129,12 @@ #define H_PTE_PKEY (H_PTE_PKEY_BIT0 | H_PTE_PKEY_BIT1 | H_PTE_PKEY_BIT2 | \ H_PTE_PKEY_BIT3 | H_PTE_PKEY_BIT4) /* - * Mask of bits returned by pte_pgprot() - */ -#define PAGE_PROT_BITS (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT | \ - H_PAGE_4K_PFN | _PAGE_PRIVILEGED | _PAGE_ACCESSED | \ - _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_EXEC | \ - _PAGE_SOFT_DIRTY | H_PTE_PKEY) -/* * We define 2 sets of base prot bits, one for basic pages (ie, * cacheable kernel and user pages) and one for non cacheable * pages. We always set _PAGE_COHERENT when SMP is enabled or * the processor might need it for DMA coherency. */ -#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) #define _PAGE_BASE (_PAGE_BASE_NC) /* Permission masks used to generate the __P and __S table, @@ -159,8 +144,6 @@ * Write permissions imply read permissions for now (we could make write-only * pages on BookE but we don't bother for now). Execute permission control is * possible on platforms that define _PAGE_EXEC - * - * Note due to the way vm flags are laid out, the bits are XWR */ #define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED) #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) @@ -170,24 +153,6 @@ #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) -#define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY -#define __P100 PAGE_READONLY_X -#define __P101 PAGE_READONLY_X -#define __P110 PAGE_COPY_X -#define __P111 PAGE_COPY_X - -#define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY_X -#define __S101 PAGE_READONLY_X -#define __S110 PAGE_SHARED_X -#define __S111 PAGE_SHARED_X - /* Permission masks used for kernel mappings */ #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ @@ -461,6 +426,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_update(mm, addr, ptep, 0, _PAGE_PRIVILEGED, 0); } +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -519,7 +485,11 @@ static inline int pte_special(pte_t pte) return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SPECIAL)); } -static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } +static inline bool pte_exec(pte_t pte) +{ + return !!(pte_raw(pte) & cpu_to_be64(_PAGE_EXEC)); +} + #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY static inline bool pte_soft_dirty(pte_t pte) @@ -529,12 +499,12 @@ static inline bool pte_soft_dirty(pte_t pte) static inline pte_t pte_mksoft_dirty(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SOFT_DIRTY); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SOFT_DIRTY)); } static inline pte_t pte_clear_soft_dirty(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_SOFT_DIRTY); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SOFT_DIRTY)); } #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ @@ -555,7 +525,7 @@ static inline pte_t pte_mk_savedwrite(pte_t pte) */ VM_BUG_ON((pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_RWX | _PAGE_PRIVILEGED)) != cpu_to_be64(_PAGE_PRESENT | _PAGE_PRIVILEGED)); - return __pte(pte_val(pte) & ~_PAGE_PRIVILEGED); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); } #define pte_clear_savedwrite pte_clear_savedwrite @@ -565,14 +535,14 @@ static inline pte_t pte_clear_savedwrite(pte_t pte) * Used by KSM subsystem to make a protnone pte readonly. */ VM_BUG_ON(!pte_protnone(pte)); - return __pte(pte_val(pte) | _PAGE_PRIVILEGED); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); } #else #define pte_clear_savedwrite pte_clear_savedwrite static inline pte_t pte_clear_savedwrite(pte_t pte) { VM_WARN_ON(1); - return __pte(pte_val(pte) & ~_PAGE_WRITE); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); } #endif /* CONFIG_NUMA_BALANCING */ @@ -587,6 +557,11 @@ static inline int pte_present(pte_t pte) return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)); } +static inline bool pte_hw_valid(pte_t pte) +{ + return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT)); +} + #ifdef CONFIG_PPC_MEM_KEYS extern bool arch_pte_access_permitted(u64 pte, bool write, bool execute); #else @@ -596,25 +571,22 @@ static inline bool arch_pte_access_permitted(u64 pte, bool write, bool execute) } #endif /* CONFIG_PPC_MEM_KEYS */ +static inline bool pte_user(pte_t pte) +{ + return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED)); +} + #define pte_access_permitted pte_access_permitted static inline bool pte_access_permitted(pte_t pte, bool write) { - unsigned long pteval = pte_val(pte); - /* Also check for pte_user */ - unsigned long clear_pte_bits = _PAGE_PRIVILEGED; /* * _PAGE_READ is needed for any access and will be * cleared for PROT_NONE */ - unsigned long need_pte_bits = _PAGE_PRESENT | _PAGE_READ; - - if (write) - need_pte_bits |= _PAGE_WRITE; - - if ((pteval & need_pte_bits) != need_pte_bits) + if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) return false; - if ((pteval & clear_pte_bits) == clear_pte_bits) + if (write && !pte_write(pte)) return false; return arch_pte_access_permitted(pte_val(pte), write, 0); @@ -643,17 +615,32 @@ static inline pte_t pte_wrprotect(pte_t pte) { if (unlikely(pte_savedwrite(pte))) return pte_clear_savedwrite(pte); - return __pte(pte_val(pte) & ~_PAGE_WRITE); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); +} + +static inline pte_t pte_exprotect(pte_t pte) +{ + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_EXEC)); } static inline pte_t pte_mkclean(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_DIRTY); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_DIRTY)); } static inline pte_t pte_mkold(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_ACCESSED); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_ACCESSED)); +} + +static inline pte_t pte_mkexec(pte_t pte) +{ + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_EXEC)); +} + +static inline pte_t pte_mkpte(pte_t pte) +{ + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PTE)); } static inline pte_t pte_mkwrite(pte_t pte) @@ -661,22 +648,22 @@ static inline pte_t pte_mkwrite(pte_t pte) /* * write implies read, hence set both */ - return __pte(pte_val(pte) | _PAGE_RW); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_RW)); } static inline pte_t pte_mkdirty(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_DIRTY | _PAGE_SOFT_DIRTY); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_DIRTY | _PAGE_SOFT_DIRTY)); } static inline pte_t pte_mkyoung(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_ACCESSED); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_ACCESSED)); } static inline pte_t pte_mkspecial(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SPECIAL); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL)); } static inline pte_t pte_mkhuge(pte_t pte) @@ -686,7 +673,17 @@ static inline pte_t pte_mkhuge(pte_t pte) static inline pte_t pte_mkdevmap(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SPECIAL|_PAGE_DEVMAP); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP)); +} + +static inline pte_t pte_mkprivileged(pte_t pte) +{ + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); +} + +static inline pte_t pte_mkuser(pte_t pte) +{ + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); } /* @@ -705,12 +702,8 @@ static inline int pte_devmap(pte_t pte) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { /* FIXME!! check whether this need to be a conditional */ - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); -} - -static inline bool pte_user(pte_t pte) -{ - return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED)); + return __pte_raw((pte_raw(pte) & cpu_to_be64(_PAGE_CHG_MASK)) | + cpu_to_be64(pgprot_val(newprot))); } /* Encode and de-code a swap entry */ @@ -723,9 +716,7 @@ static inline bool pte_user(pte_t pte) BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \ BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY); \ } while (0) -/* - * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT; - */ + #define SWP_TYPE_BITS 5 #define __swp_type(x) (((x).val >> _PAGE_BIT_SWAP_TYPE) \ & ((1UL << SWP_TYPE_BITS) - 1)) @@ -741,6 +732,8 @@ static inline bool pte_user(pte_t pte) */ #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE }) #define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE) +#define __pmd_to_swp_entry(pmd) (__pte_to_swp_entry(pmd_pte(pmd))) +#define __swp_entry_to_pmd(x) (pte_pmd(__swp_entry_to_pte(x))) #ifdef CONFIG_MEM_SOFT_DIRTY #define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) @@ -751,7 +744,7 @@ static inline bool pte_user(pte_t pte) #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY static inline pte_t pte_swp_mksoft_dirty(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SWP_SOFT_DIRTY); + return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_SOFT_DIRTY)); } static inline bool pte_swp_soft_dirty(pte_t pte) @@ -761,7 +754,7 @@ static inline bool pte_swp_soft_dirty(pte_t pte) static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_SWP_SOFT_DIRTY); + return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_SOFT_DIRTY)); } #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ @@ -850,10 +843,10 @@ static inline pgprot_t pgprot_writecombine(pgprot_t prot) */ static inline bool pte_ci(pte_t pte) { - unsigned long pte_v = pte_val(pte); + __be64 pte_v = pte_raw(pte); - if (((pte_v & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) || - ((pte_v & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT)) + if (((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_TOLERANT)) || + ((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_NON_IDEMPOTENT))) return true; return false; } @@ -875,8 +868,16 @@ static inline int pmd_none(pmd_t pmd) static inline int pmd_present(pmd_t pmd) { + /* + * A pmd is considerent present if _PAGE_PRESENT is set. + * We also need to consider the pmd present which is marked + * invalid during a split. Hence we look for _PAGE_INVALID + * if we find _PAGE_PRESENT cleared. + */ + if (pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) + return true; - return !pmd_none(pmd); + return false; } static inline int pmd_bad(pmd_t pmd) @@ -903,7 +904,7 @@ static inline int pud_none(pud_t pud) static inline int pud_present(pud_t pud) { - return !pud_none(pud); + return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT)); } extern struct page *pud_page(pud_t pud); @@ -950,7 +951,7 @@ static inline int pgd_none(pgd_t pgd) static inline int pgd_present(pgd_t pgd) { - return !pgd_none(pgd); + return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT)); } static inline pte_t pgd_pte(pgd_t pgd) @@ -1020,17 +1021,16 @@ extern struct page *pgd_page(pgd_t pgd); #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -static inline int map_kernel_page(unsigned long ea, unsigned long pa, - unsigned long flags) +static inline int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) { if (radix_enabled()) { #if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM) unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift; WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE"); #endif - return radix__map_kernel_page(ea, pa, __pgprot(flags), PAGE_SIZE); + return radix__map_kernel_page(ea, pa, prot, PAGE_SIZE); } - return hash__map_kernel_page(ea, pa, flags); + return hash__map_kernel_page(ea, pa, prot); } static inline int __meminit vmemmap_create_mapping(unsigned long start, @@ -1082,6 +1082,12 @@ static inline pte_t *pmdp_ptep(pmd_t *pmd) #define pmd_soft_dirty(pmd) pte_soft_dirty(pmd_pte(pmd)) #define pmd_mksoft_dirty(pmd) pte_pmd(pte_mksoft_dirty(pmd_pte(pmd))) #define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd))) + +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION +#define pmd_swp_mksoft_dirty(pmd) pte_pmd(pte_swp_mksoft_dirty(pmd_pte(pmd))) +#define pmd_swp_soft_dirty(pmd) pte_swp_soft_dirty(pmd_pte(pmd)) +#define pmd_swp_clear_soft_dirty(pmd) pte_pmd(pte_swp_clear_soft_dirty(pmd_pte(pmd))) +#endif #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ #ifdef CONFIG_NUMA_BALANCING @@ -1127,6 +1133,10 @@ pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set); } +/* + * returns true for pmd migration entries, THP, devmap, hugetlb + * But compile time dependent on THP config + */ static inline int pmd_large(pmd_t pmd) { return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)); @@ -1161,8 +1171,22 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, pmd_hugepage_update(mm, addr, pmdp, 0, _PAGE_PRIVILEGED); } +/* + * Only returns true for a THP. False for pmd migration entry. + * We also need to return true when we come across a pte that + * in between a thp split. While splitting THP, we mark the pmd + * invalid (pmdp_invalidate()) before we set it with pte page + * address. A pmd_trans_huge() check against a pmd entry during that time + * should return true. + * We should not call this on a hugetlb entry. We should check for HugeTLB + * entry using vma->vm_flags + * The page table walk rule is explained in Documentation/vm/transhuge.rst + */ static inline int pmd_trans_huge(pmd_t pmd) { + if (!pmd_present(pmd)) + return false; + if (radix_enabled()) return radix__pmd_trans_huge(pmd); return hash__pmd_trans_huge(pmd); diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h index 1154a6dc6d26..671316f9e95d 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h @@ -53,6 +53,7 @@ extern void radix__flush_tlb_lpid_page(unsigned int lpid, unsigned long addr, unsigned long page_size); extern void radix__flush_pwc_lpid(unsigned int lpid); +extern void radix__flush_tlb_lpid(unsigned int lpid); extern void radix__local_flush_tlb_lpid(unsigned int lpid); extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid); diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index fd06dbe7d7d3..fed7e6241349 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -133,7 +133,7 @@ struct pt_regs; extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long); extern void bad_page_fault(struct pt_regs *, unsigned long, int); extern void _exception(int, struct pt_regs *, int, unsigned long); -extern void _exception_pkey(int, struct pt_regs *, int, unsigned long, int); +extern void _exception_pkey(struct pt_regs *, unsigned long, int); extern void die(const char *, struct pt_regs *, long); extern bool die_will_crash(void); extern void panic_flush_kmsg_start(void); diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 85c8af2bb272..74d0db511099 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -8,6 +8,8 @@ #include <linux/types.h> #include <linux/sched.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #ifdef __BIG_ENDIAN__ #define COMPAT_UTS_MACHINE "ppc\0\0" @@ -15,34 +17,18 @@ #define COMPAT_UTS_MACHINE "ppcle\0\0" #endif -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u32 __compat_uid_t; typedef u32 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u32 compat_mode_t; -typedef u32 compat_ino_t; typedef u32 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; @@ -55,11 +41,11 @@ struct compat_stat { compat_off_t st_size; compat_off_t st_blksize; compat_off_t st_blocks; - compat_time_t st_atime; + old_time32_t st_atime; u32 st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; u32 st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; u32 st_ctime_nsec; u32 __unused4[2]; }; diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index d71a90924f3b..deb99fd6e060 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h @@ -23,11 +23,13 @@ extern int threads_per_core; extern int threads_per_subcore; extern int threads_shift; +extern bool has_big_cores; extern cpumask_t threads_core_mask; #else #define threads_per_core 1 #define threads_per_subcore 1 #define threads_shift 0 +#define has_big_cores 0 #define threads_core_mask (*get_cpu_mask(0)) #endif diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index 133672744b2e..ae73dc8da2d4 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h @@ -61,7 +61,6 @@ static inline void arch_vtime_task_switch(struct task_struct *prev) struct cpu_accounting_data *acct0 = get_accounting(prev); acct->starttime = acct0->starttime; - acct->startspurr = acct0->startspurr; } #endif diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h index ce242b9ea8c6..7c1d8e74b25d 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h @@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node, void (*func)(struct drmem_lmb *, const __be32 **)); #endif +static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) +{ + lmb->aa_index = 0xffffffff; +} + #endif /* _ASM_POWERPC_LMB_H */ diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 219637ea69a1..8b596d096ebe 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -43,7 +43,6 @@ struct pci_dn; #define EEH_VALID_PE_ZERO 0x10 /* PE#0 is valid */ #define EEH_ENABLE_IO_FOR_LOG 0x20 /* Enable IO for log */ #define EEH_EARLY_DUMP_LOG 0x40 /* Dump log immediately */ -#define EEH_POSTPONED_PROBE 0x80 /* Powernv may postpone device probe */ /* * Delay for PE reset, all in ms @@ -99,13 +98,13 @@ struct eeh_pe { atomic_t pass_dev_cnt; /* Count of passed through devs */ struct eeh_pe *parent; /* Parent PE */ void *data; /* PE auxillary data */ - struct list_head child_list; /* Link PE to the child list */ - struct list_head edevs; /* Link list of EEH devices */ - struct list_head child; /* Child PEs */ + struct list_head child_list; /* List of PEs below this PE */ + struct list_head child; /* Memb. child_list/eeh_phb_pe */ + struct list_head edevs; /* List of eeh_dev in this PE */ }; #define eeh_pe_for_each_dev(pe, edev, tmp) \ - list_for_each_entry_safe(edev, tmp, &pe->edevs, list) + list_for_each_entry_safe(edev, tmp, &pe->edevs, entry) #define eeh_for_each_pe(root, pe) \ for (pe = root; pe; pe = eeh_pe_next(pe, root)) @@ -142,13 +141,12 @@ struct eeh_dev { int aer_cap; /* Saved AER capability */ int af_cap; /* Saved AF capability */ struct eeh_pe *pe; /* Associated PE */ - struct list_head list; /* Form link list in the PE */ - struct list_head rmv_list; /* Record the removed edevs */ + struct list_head entry; /* Membership in eeh_pe.edevs */ + struct list_head rmv_entry; /* Membership in rmv_list */ struct pci_dn *pdn; /* Associated PCI device node */ struct pci_dev *pdev; /* Associated PCI device */ bool in_error; /* Error flag for edev */ struct pci_dev *physfn; /* Associated SRIOV PF */ - struct pci_bus *bus; /* PCI bus for partial hotplug */ }; static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) @@ -207,9 +205,8 @@ struct eeh_ops { void* (*probe)(struct pci_dn *pdn, void *data); int (*set_option)(struct eeh_pe *pe, int option); int (*get_pe_addr)(struct eeh_pe *pe); - int (*get_state)(struct eeh_pe *pe, int *state); + int (*get_state)(struct eeh_pe *pe, int *delay); int (*reset)(struct eeh_pe *pe, int option); - int (*wait_state)(struct eeh_pe *pe, int max_wait); int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len); int (*configure_bridge)(struct eeh_pe *pe); int (*err_inject)(struct eeh_pe *pe, int type, int func, @@ -243,11 +240,7 @@ static inline bool eeh_has_flag(int flag) static inline bool eeh_enabled(void) { - if (eeh_has_flag(EEH_FORCE_DISABLED) || - !eeh_has_flag(EEH_ENABLED)) - return false; - - return true; + return eeh_has_flag(EEH_ENABLED) && !eeh_has_flag(EEH_FORCE_DISABLED); } static inline void eeh_serialize_lock(unsigned long *flags) @@ -270,6 +263,7 @@ typedef void *(*eeh_edev_traverse_func)(struct eeh_dev *edev, void *flag); typedef void *(*eeh_pe_traverse_func)(struct eeh_pe *pe, void *flag); void eeh_set_pe_aux_size(int size); int eeh_phb_pe_create(struct pci_controller *phb); +int eeh_wait_state(struct eeh_pe *pe, int max_wait); struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, struct eeh_pe *root); struct eeh_pe *eeh_pe_get(struct pci_controller *phb, diff --git a/arch/powerpc/include/asm/error-injection.h b/arch/powerpc/include/asm/error-injection.h new file mode 100644 index 000000000000..62fd24739852 --- /dev/null +++ b/arch/powerpc/include/asm/error-injection.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _ASM_ERROR_INJECTION_H +#define _ASM_ERROR_INJECTION_H + +#include <linux/compiler.h> +#include <linux/linkage.h> +#include <asm/ptrace.h> +#include <asm-generic/error-injection.h> + +void override_function_with_return(struct pt_regs *regs); + +#endif /* _ASM_ERROR_INJECTION_H */ diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index a86feddddad0..3b4767ed3ec5 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -61,14 +61,6 @@ #define MAX_MCE_DEPTH 4 /* - * EX_LR is only used in EXSLB and where it does not overlap with EX_DAR - * EX_CCR similarly with DSISR, but being 4 byte registers there is a hole - * in the save area so it's not necessary to overlap them. Could be used - * for future savings though if another 4 byte register was to be saved. - */ -#define EX_LR EX_DAR - -/* * EX_R3 is only used by the bad_stack handler. bad_stack reloads and * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap * with EX_DAR. @@ -236,11 +228,10 @@ * PPR save/restore macros used in exceptions_64s.S * Used for P7 or later processors */ -#define SAVE_PPR(area, ra, rb) \ +#define SAVE_PPR(area, ra) \ BEGIN_FTR_SECTION_NESTED(940) \ - ld ra,PACACURRENT(r13); \ - ld rb,area+EX_PPR(r13); /* Read PPR from paca */ \ - std rb,TASKTHREADPPR(ra); \ + ld ra,area+EX_PPR(r13); /* Read PPR from paca */ \ + std ra,_PPR(r1); \ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) #define RESTORE_PPR_PACA(area, ra) \ @@ -508,7 +499,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) 3: EXCEPTION_PROLOG_COMMON_1(); \ beq 4f; /* if from kernel mode */ \ ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ - SAVE_PPR(area, r9, r10); \ + SAVE_PPR(area, r9); \ 4: EXCEPTION_PROLOG_COMMON_2(area) \ EXCEPTION_PROLOG_COMMON_3(n) \ ACCOUNT_STOLEN_TIME diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index 7a051bd21f87..00bc42d95679 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h @@ -52,6 +52,8 @@ #define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000) #define FW_FEATURE_DRMEM_V2 ASM_CONST(0x0000000400000000) #define FW_FEATURE_DRC_INFO ASM_CONST(0x0000000800000000) +#define FW_FEATURE_BLOCK_REMOVE ASM_CONST(0x0000001000000000) +#define FW_FEATURE_PAPR_SCM ASM_CONST(0x0000002000000000) #ifndef __ASSEMBLY__ @@ -69,7 +71,8 @@ enum { FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY | FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN | FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 | - FW_FEATURE_DRC_INFO, + FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE | + FW_FEATURE_PAPR_SCM, FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL, FW_FEATURE_POWERNV_ALWAYS = 0, diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h index 41cc15c14eee..b9fbed84ddca 100644 --- a/arch/powerpc/include/asm/fixmap.h +++ b/arch/powerpc/include/asm/fixmap.h @@ -72,7 +72,7 @@ enum fixed_addresses { static inline void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags) { - map_kernel_page(fix_to_virt(idx), phys, pgprot_val(flags)); + map_kernel_page(fix_to_virt(idx), phys, flags); } #endif /* !__ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index 2d00cc530083..383da1ab9e23 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h @@ -4,7 +4,6 @@ #ifdef CONFIG_HUGETLB_PAGE #include <asm/page.h> -#include <asm-generic/hugetlb.h> extern struct kmem_cache *hugepte_cache; @@ -110,31 +109,12 @@ static inline void flush_hugetlb_page(struct vm_area_struct *vma, void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr); #endif +#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); -/* - * If the arch doesn't supply something else, assume that hugepage - * size aligned regions are ok without further preparation. - */ -static inline int prepare_hugepage_range(struct file *file, - unsigned long addr, unsigned long len) -{ - struct hstate *h = hstate_file(file); - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (addr & ~huge_page_mask(h)) - return -EINVAL; - return 0; -} - -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - +#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -145,6 +125,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, #endif } +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { @@ -153,29 +134,17 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, flush_hugetlb_page(vma, addr); } -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - +#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty); -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } +#include <asm-generic/hugetlb.h> + #else /* ! CONFIG_HUGETLB_PAGE */ static inline void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr) diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index a0b17f9f1ea4..33a4fc891947 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -278,6 +278,7 @@ #define H_COP 0x304 #define H_GET_MPP_X 0x314 #define H_SET_MODE 0x31C +#define H_BLOCK_REMOVE 0x328 #define H_CLEAR_HPT 0x358 #define H_REQUEST_VMC 0x360 #define H_RESIZE_HPT_PREPARE 0x36C @@ -295,7 +296,15 @@ #define H_INT_ESB 0x3C8 #define H_INT_SYNC 0x3CC #define H_INT_RESET 0x3D0 -#define MAX_HCALL_OPCODE H_INT_RESET +#define H_SCM_READ_METADATA 0x3E4 +#define H_SCM_WRITE_METADATA 0x3E8 +#define H_SCM_BIND_MEM 0x3EC +#define H_SCM_UNBIND_MEM 0x3F0 +#define H_SCM_QUERY_BLOCK_MEM_BINDING 0x3F4 +#define H_SCM_QUERY_LOGICAL_MEM_BINDING 0x3F8 +#define H_SCM_MEM_QUERY 0x3FC +#define H_SCM_BLOCK_CLEAR 0x400 +#define MAX_HCALL_OPCODE H_SCM_BLOCK_CLEAR /* H_VIOCTL functions */ #define H_GET_VIOA_DUMP_SIZE 0x01 @@ -322,6 +331,11 @@ #define H_GET_24X7_DATA 0xF07C #define H_GET_PERF_COUNTER_INFO 0xF080 +/* Platform-specific hcalls used for nested HV KVM */ +#define H_SET_PARTITION_TABLE 0xF800 +#define H_ENTER_NESTED 0xF804 +#define H_TLB_INVALIDATE 0xF808 + /* Values for 2nd argument to H_SET_MODE */ #define H_SET_MODE_RESOURCE_SET_CIABR 1 #define H_SET_MODE_RESOURCE_SET_DAWR 2 @@ -461,6 +475,42 @@ struct h_cpu_char_result { u64 behaviour; }; +/* Register state for entering a nested guest with H_ENTER_NESTED */ +struct hv_guest_state { + u64 version; /* version of this structure layout */ + u32 lpid; + u32 vcpu_token; + /* These registers are hypervisor privileged (at least for writing) */ + u64 lpcr; + u64 pcr; + u64 amor; + u64 dpdes; + u64 hfscr; + s64 tb_offset; + u64 dawr0; + u64 dawrx0; + u64 ciabr; + u64 hdec_expiry; + u64 purr; + u64 spurr; + u64 ic; + u64 vtb; + u64 hdar; + u64 hdsisr; + u64 heir; + u64 asdr; + /* These are OS privileged but need to be set late in guest entry */ + u64 srr0; + u64 srr1; + u64 sprg[4]; + u64 pidr; + u64 cfar; + u64 ppr; +}; + +/* Latest version of hv_guest_state structure */ +#define HV_GUEST_STATE_VERSION 1 + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_HVCALL_H */ diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index e0331e754568..3ef40b703c4a 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -3,6 +3,9 @@ #ifdef __KERNEL__ #define ARCH_HAS_IOREMAP_WC +#ifdef CONFIG_PPC32 +#define ARCH_HAS_IOREMAP_WT +#endif /* * This program is free software; you can redistribute it and/or @@ -108,25 +111,6 @@ extern bool isa_io_special; #define IO_SET_SYNC_FLAG() #endif -/* gcc 4.0 and older doesn't have 'Z' constraint */ -#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) -#define DEF_MMIO_IN_X(name, size, insn) \ -static inline u##size name(const volatile u##size __iomem *addr) \ -{ \ - u##size ret; \ - __asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync" \ - : "=r" (ret) : "r" (addr), "m" (*addr) : "memory"); \ - return ret; \ -} - -#define DEF_MMIO_OUT_X(name, size, insn) \ -static inline void name(volatile u##size __iomem *addr, u##size val) \ -{ \ - __asm__ __volatile__("sync;"#insn" %1,0,%2" \ - : "=m" (*addr) : "r" (val), "r" (addr) : "memory"); \ - IO_SET_SYNC_FLAG(); \ -} -#else /* newer gcc */ #define DEF_MMIO_IN_X(name, size, insn) \ static inline u##size name(const volatile u##size __iomem *addr) \ { \ @@ -143,7 +127,6 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ : "=Z" (*addr) : "r" (val) : "memory"); \ IO_SET_SYNC_FLAG(); \ } -#endif #define DEF_MMIO_IN_D(name, size, insn) \ static inline u##size name(const volatile u##size __iomem *addr) \ @@ -746,6 +729,10 @@ static inline void iosync(void) * * * ioremap_wc enables write combining * + * * ioremap_wt enables write through + * + * * ioremap_coherent maps coherent cached memory + * * * iounmap undoes such a mapping and can be hooked * * * __ioremap_at (and the pending __iounmap_at) are low level functions to @@ -767,6 +754,8 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size); extern void __iomem *ioremap_prot(phys_addr_t address, unsigned long size, unsigned long flags); extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size); +void __iomem *ioremap_wt(phys_addr_t address, unsigned long size); +void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size); #define ioremap_nocache(addr, size) ioremap((addr), (size)) #define ioremap_uc(addr, size) ioremap((addr), (size)) #define ioremap_cache(addr, size) \ @@ -777,12 +766,12 @@ extern void iounmap(volatile void __iomem *addr); extern void __iomem *__ioremap(phys_addr_t, unsigned long size, unsigned long flags); extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size, - unsigned long flags, void *caller); + pgprot_t prot, void *caller); extern void __iounmap(volatile void __iomem *addr); extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea, - unsigned long size, unsigned long flags); + unsigned long size, pgprot_t prot); extern void __iounmap_at(void *ea, unsigned long size); /* diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 3d4b88cb8599..35db0cbc9222 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -126,7 +126,7 @@ struct iommu_table { int it_nid; }; -#define IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry) \ +#define IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry) \ ((tbl)->it_ops->useraddrptr((tbl), (entry), false)) #define IOMMU_TABLE_USERSPACE_ENTRY(tbl, entry) \ ((tbl)->it_ops->useraddrptr((tbl), (entry), true)) diff --git a/arch/powerpc/include/asm/kgdb.h b/arch/powerpc/include/asm/kgdb.h index 9db24e77b9f4..a9e098a3b881 100644 --- a/arch/powerpc/include/asm/kgdb.h +++ b/arch/powerpc/include/asm/kgdb.h @@ -26,9 +26,12 @@ #define BREAK_INSTR_SIZE 4 #define BUFMAX ((NUMREGBYTES * 2) + 512) #define OUTBUFMAX ((NUMREGBYTES * 2) + 512) + +#define BREAK_INSTR 0x7d821008 /* twge r2, r2 */ + static inline void arch_kgdb_breakpoint(void) { - asm(".long 0x7d821008"); /* twge r2, r2 */ + asm(stringify_in_c(.long BREAK_INSTR)); } #define CACHE_FLUSH_IS_SAFE 1 #define DBG_MAX_REG_NUM 70 diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index a790d5cf6ea3..1f321914676d 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -84,7 +84,6 @@ #define BOOK3S_INTERRUPT_INST_STORAGE 0x400 #define BOOK3S_INTERRUPT_INST_SEGMENT 0x480 #define BOOK3S_INTERRUPT_EXTERNAL 0x500 -#define BOOK3S_INTERRUPT_EXTERNAL_LEVEL 0x501 #define BOOK3S_INTERRUPT_EXTERNAL_HV 0x502 #define BOOK3S_INTERRUPT_ALIGNMENT 0x600 #define BOOK3S_INTERRUPT_PROGRAM 0x700 @@ -134,8 +133,7 @@ #define BOOK3S_IRQPRIO_EXTERNAL 14 #define BOOK3S_IRQPRIO_DECREMENTER 15 #define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 16 -#define BOOK3S_IRQPRIO_EXTERNAL_LEVEL 17 -#define BOOK3S_IRQPRIO_MAX 18 +#define BOOK3S_IRQPRIO_MAX 17 #define BOOK3S_HFLAG_DCBZ32 0x1 #define BOOK3S_HFLAG_SLB 0x2 diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index 83a9aa3cf689..09f8e9ba69bc 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -188,14 +188,37 @@ extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc); extern int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned long ea, unsigned long dsisr); +extern int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, u64 root, + u64 *pte_ret_p); +extern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, u64 table, + int table_index, u64 *pte_ret_p); extern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *gpte, bool data, bool iswrite); +extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, + unsigned int shift, struct kvm_memory_slot *memslot, + unsigned int lpid); +extern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, pgd_t *pgtable, + bool writing, unsigned long gpa, + unsigned int lpid); +extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, + unsigned long gpa, + struct kvm_memory_slot *memslot, + bool writing, bool kvm_ro, + pte_t *inserted_pte, unsigned int *levelp); extern int kvmppc_init_vm_radix(struct kvm *kvm); extern void kvmppc_free_radix(struct kvm *kvm); +extern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, + unsigned int lpid); extern int kvmppc_radix_init(void); extern void kvmppc_radix_exit(void); extern int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, unsigned long gfn); +extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, + unsigned long gpa, unsigned int shift, + struct kvm_memory_slot *memslot, + unsigned int lpid); extern int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, unsigned long gfn); extern int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, @@ -271,6 +294,21 @@ static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {} static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {} #endif +long kvmhv_nested_init(void); +void kvmhv_nested_exit(void); +void kvmhv_vm_nested_init(struct kvm *kvm); +long kvmhv_set_partition_table(struct kvm_vcpu *vcpu); +void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1); +void kvmhv_release_all_nested(struct kvm *kvm); +long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu); +long kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu); +int kvmhv_run_single_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu, + u64 time_limit, unsigned long lpcr); +void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr); +void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu, + struct hv_guest_state *hr); +long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu); + void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac); extern int kvm_irq_bypass; @@ -301,12 +339,12 @@ static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) { - vcpu->arch.cr = val; + vcpu->arch.regs.ccr = val; } static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) { - return vcpu->arch.cr; + return vcpu->arch.regs.ccr; } static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) @@ -384,9 +422,6 @@ extern int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu); /* TO = 31 for unconditional trap */ #define INS_TW 0x7fe00008 -/* LPIDs we support with this build -- runtime limit may be lower */ -#define KVMPPC_NR_LPIDS (LPID_RSVD + 1) - #define SPLIT_HACK_MASK 0xff000000 #define SPLIT_HACK_OFFS 0xfb000000 diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index dc435a5af7d6..6d298145d564 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -23,6 +23,108 @@ #include <linux/string.h> #include <asm/bitops.h> #include <asm/book3s/64/mmu-hash.h> +#include <asm/cpu_has_feature.h> +#include <asm/ppc-opcode.h> + +#ifdef CONFIG_PPC_PSERIES +static inline bool kvmhv_on_pseries(void) +{ + return !cpu_has_feature(CPU_FTR_HVMODE); +} +#else +static inline bool kvmhv_on_pseries(void) +{ + return false; +} +#endif + +/* + * Structure for a nested guest, that is, for a guest that is managed by + * one of our guests. + */ +struct kvm_nested_guest { + struct kvm *l1_host; /* L1 VM that owns this nested guest */ + int l1_lpid; /* lpid L1 guest thinks this guest is */ + int shadow_lpid; /* real lpid of this nested guest */ + pgd_t *shadow_pgtable; /* our page table for this guest */ + u64 l1_gr_to_hr; /* L1's addr of part'n-scoped table */ + u64 process_table; /* process table entry for this guest */ + long refcnt; /* number of pointers to this struct */ + struct mutex tlb_lock; /* serialize page faults and tlbies */ + struct kvm_nested_guest *next; + cpumask_t need_tlb_flush; + cpumask_t cpu_in_guest; + short prev_cpu[NR_CPUS]; +}; + +/* + * We define a nested rmap entry as a single 64-bit quantity + * 0xFFF0000000000000 12-bit lpid field + * 0x000FFFFFFFFFF000 40-bit guest 4k page frame number + * 0x0000000000000001 1-bit single entry flag + */ +#define RMAP_NESTED_LPID_MASK 0xFFF0000000000000UL +#define RMAP_NESTED_LPID_SHIFT (52) +#define RMAP_NESTED_GPA_MASK 0x000FFFFFFFFFF000UL +#define RMAP_NESTED_IS_SINGLE_ENTRY 0x0000000000000001UL + +/* Structure for a nested guest rmap entry */ +struct rmap_nested { + struct llist_node list; + u64 rmap; +}; + +/* + * for_each_nest_rmap_safe - iterate over the list of nested rmap entries + * safe against removal of the list entry or NULL list + * @pos: a (struct rmap_nested *) to use as a loop cursor + * @node: pointer to the first entry + * NOTE: this can be NULL + * @rmapp: an (unsigned long *) in which to return the rmap entries on each + * iteration + * NOTE: this must point to already allocated memory + * + * The nested_rmap is a llist of (struct rmap_nested) entries pointed to by the + * rmap entry in the memslot. The list is always terminated by a "single entry" + * stored in the list element of the final entry of the llist. If there is ONLY + * a single entry then this is itself in the rmap entry of the memslot, not a + * llist head pointer. + * + * Note that the iterator below assumes that a nested rmap entry is always + * non-zero. This is true for our usage because the LPID field is always + * non-zero (zero is reserved for the host). + * + * This should be used to iterate over the list of rmap_nested entries with + * processing done on the u64 rmap value given by each iteration. This is safe + * against removal of list entries and it is always safe to call free on (pos). + * + * e.g. + * struct rmap_nested *cursor; + * struct llist_node *first; + * unsigned long rmap; + * for_each_nest_rmap_safe(cursor, first, &rmap) { + * do_something(rmap); + * free(cursor); + * } + */ +#define for_each_nest_rmap_safe(pos, node, rmapp) \ + for ((pos) = llist_entry((node), typeof(*(pos)), list); \ + (node) && \ + (*(rmapp) = ((RMAP_NESTED_IS_SINGLE_ENTRY & ((u64) (node))) ? \ + ((u64) (node)) : ((pos)->rmap))) && \ + (((node) = ((RMAP_NESTED_IS_SINGLE_ENTRY & ((u64) (node))) ? \ + ((struct llist_node *) ((pos) = NULL)) : \ + (pos)->list.next)), true); \ + (pos) = llist_entry((node), typeof(*(pos)), list)) + +struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid, + bool create); +void kvmhv_put_nested(struct kvm_nested_guest *gp); +int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid); + +/* Encoding of first parameter for H_TLB_INVALIDATE */ +#define H_TLBIE_P1_ENC(ric, prs, r) (___PPC_RIC(ric) | ___PPC_PRS(prs) | \ + ___PPC_R(r)) /* Power architecture requires HPT is at least 256kiB, at most 64TiB */ #define PPC_MIN_HPT_ORDER 18 @@ -435,6 +537,7 @@ static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm) } extern void kvmppc_mmu_debugfs_init(struct kvm *kvm); +extern void kvmhv_radix_debugfs_init(struct kvm *kvm); extern void kvmhv_rm_send_ipi(int cpu); @@ -482,7 +585,7 @@ static inline u64 sanitize_msr(u64 msr) #ifdef CONFIG_PPC_TRANSACTIONAL_MEM static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu) { - vcpu->arch.cr = vcpu->arch.cr_tm; + vcpu->arch.regs.ccr = vcpu->arch.cr_tm; vcpu->arch.regs.xer = vcpu->arch.xer_tm; vcpu->arch.regs.link = vcpu->arch.lr_tm; vcpu->arch.regs.ctr = vcpu->arch.ctr_tm; @@ -499,7 +602,7 @@ static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu) static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu) { - vcpu->arch.cr_tm = vcpu->arch.cr; + vcpu->arch.cr_tm = vcpu->arch.regs.ccr; vcpu->arch.xer_tm = vcpu->arch.regs.xer; vcpu->arch.lr_tm = vcpu->arch.regs.link; vcpu->arch.ctr_tm = vcpu->arch.regs.ctr; @@ -515,6 +618,17 @@ static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu) } #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +extern int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, + unsigned long gpa, unsigned int level, + unsigned long mmu_seq, unsigned int lpid, + unsigned long *rmapp, struct rmap_nested **n_rmap); +extern void kvmhv_insert_nest_rmap(struct kvm *kvm, unsigned long *rmapp, + struct rmap_nested **n_rmap); +extern void kvmhv_remove_nest_rmap_range(struct kvm *kvm, + struct kvm_memory_slot *memslot, + unsigned long gpa, unsigned long hpa, + unsigned long nbytes); + #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ #endif /* __ASM_KVM_BOOK3S_64_H__ */ diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index d978fdf698af..eb3ba6390108 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -25,6 +25,9 @@ #define XICS_MFRR 0xc #define XICS_IPI 2 /* interrupt source # for IPIs */ +/* LPIDs we support with this build -- runtime limit may be lower */ +#define KVMPPC_NR_LPIDS (LPID_RSVD + 1) + /* Maximum number of threads per physical core */ #define MAX_SMT_THREADS 8 diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h index d513e3ed1c65..f0cef625f17c 100644 --- a/arch/powerpc/include/asm/kvm_booke.h +++ b/arch/powerpc/include/asm/kvm_booke.h @@ -46,12 +46,12 @@ static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) { - vcpu->arch.cr = val; + vcpu->arch.regs.ccr = val; } static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) { - return vcpu->arch.cr; + return vcpu->arch.regs.ccr; } static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 906bcbdfd2a1..fac6f631ed29 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -46,6 +46,7 @@ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #include <asm/kvm_book3s_asm.h> /* for MAX_SMT_THREADS */ #define KVM_MAX_VCPU_ID (MAX_SMT_THREADS * KVM_MAX_VCORES) +#define KVM_MAX_NESTED_GUESTS KVMPPC_NR_LPIDS #else #define KVM_MAX_VCPU_ID KVM_MAX_VCPUS @@ -94,6 +95,7 @@ struct dtl_entry; struct kvmppc_vcpu_book3s; struct kvmppc_book3s_shadow_vcpu; +struct kvm_nested_guest; struct kvm_vm_stat { ulong remote_tlb_flush; @@ -287,10 +289,12 @@ struct kvm_arch { u8 radix; u8 fwnmi_enabled; bool threads_indep; + bool nested_enable; pgd_t *pgtable; u64 process_table; struct dentry *debugfs_dir; struct dentry *htab_dentry; + struct dentry *radix_dentry; struct kvm_resize_hpt *resize_hpt; /* protected by kvm->lock */ #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE @@ -311,6 +315,9 @@ struct kvm_arch { #endif struct kvmppc_ops *kvm_ops; #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + u64 l1_ptcr; + int max_nested_lpid; + struct kvm_nested_guest *nested_guests[KVM_MAX_NESTED_GUESTS]; /* This array can grow quite large, keep it at the end */ struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; #endif @@ -360,7 +367,9 @@ struct kvmppc_pte { bool may_write : 1; bool may_execute : 1; unsigned long wimg; + unsigned long rc; u8 page_size; /* MMU_PAGE_xxx */ + u8 page_shift; }; struct kvmppc_mmu { @@ -537,8 +546,6 @@ struct kvm_vcpu_arch { ulong tar; #endif - u32 cr; - #ifdef CONFIG_PPC_BOOK3S ulong hflags; ulong guest_owned_ext; @@ -707,6 +714,7 @@ struct kvm_vcpu_arch { u8 hcall_needed; u8 epr_flags; /* KVMPPC_EPR_xxx */ u8 epr_needed; + u8 external_oneshot; /* clear external irq after delivery */ u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ @@ -781,6 +789,10 @@ struct kvm_vcpu_arch { u32 emul_inst; u32 online; + + /* For support of nested guests */ + struct kvm_nested_guest *nested; + u32 nested_vcpu_id; #endif #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index e991821dd7fa..9b89b1918dfc 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -194,9 +194,7 @@ extern struct kvmppc_spapr_tce_table *kvmppc_find_table( (iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \ (stt)->size, (ioba), (npages)) ? \ H_PARAMETER : H_SUCCESS) -extern long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *tt, - unsigned long tce); -extern long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, +extern long kvmppc_tce_to_ua(struct kvm *kvm, unsigned long tce, unsigned long *ua, unsigned long **prmap); extern void kvmppc_tce_put(struct kvmppc_spapr_tce_table *tt, unsigned long idx, unsigned long tce); @@ -327,6 +325,7 @@ struct kvmppc_ops { int (*set_smt_mode)(struct kvm *kvm, unsigned long mode, unsigned long flags); void (*giveup_ext)(struct kvm_vcpu *vcpu, ulong msr); + int (*enable_nested)(struct kvm *kvm); }; extern struct kvmppc_ops *kvmppc_hv_ops; @@ -585,6 +584,7 @@ extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval); extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status); +extern void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu); #else static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server, u32 priority) { return -1; } @@ -607,6 +607,7 @@ static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { retur static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status) { return -ENODEV; } +static inline void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) { } #endif /* CONFIG_KVM_XIVE */ /* @@ -652,6 +653,7 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, unsigned long mfrr); int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); +void kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu); /* * Host-side operations we want to set up while running in real diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index a47de82fb8e2..8311869005fa 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -35,7 +35,7 @@ struct machdep_calls { char *name; #ifdef CONFIG_PPC64 void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, - unsigned long flags, void *caller); + pgprot_t prot, void *caller); void (*iounmap)(volatile void __iomem *token); #ifdef CONFIG_PM @@ -108,6 +108,7 @@ struct machdep_calls { /* Early exception handlers called in realmode */ int (*hmi_exception_early)(struct pt_regs *regs); + long (*machine_check_early)(struct pt_regs *regs); /* Called during machine check exception to retrive fixup address. */ bool (*mce_check_early_recovery)(struct pt_regs *regs); diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index 3a1226e9b465..a8b8903e1844 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -210,4 +210,7 @@ extern void release_mce_event(void); extern void machine_check_queue_event(void); extern void machine_check_print_event_info(struct machine_check_event *evt, bool user_mode); +#ifdef CONFIG_PPC_BOOK3S_64 +void flush_and_reload_slb(void); +#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* __ASM_PPC64_MCE_H__ */ diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 13ea441ac531..eb20eb3b8fb0 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -309,6 +309,21 @@ static inline u16 get_mm_addr_key(struct mm_struct *mm, unsigned long address) */ #define MMU_PAGE_COUNT 16 +/* + * If we store section details in page->flags we can't increase the MAX_PHYSMEM_BITS + * if we increase SECTIONS_WIDTH we will not store node details in page->flags and + * page_to_nid does a page->section->node lookup + * Hence only increase for VMEMMAP. Further depending on SPARSEMEM_EXTREME reduce + * memory requirements with large number of sections. + * 51 bits is the max physical real address on POWER9 + */ +#if defined(CONFIG_SPARSEMEM_VMEMMAP) && defined(CONFIG_SPARSEMEM_EXTREME) && \ + defined (CONFIG_PPC_64K_PAGES) +#define MAX_PHYSMEM_BITS 51 +#else +#define MAX_PHYSMEM_BITS 46 +#endif + #ifdef CONFIG_PPC_BOOK3S_64 #include <asm/book3s/64/mmu.h> #else /* CONFIG_PPC_BOOK3S_64 */ diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b694d6af1150..0381394a425b 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -82,7 +82,7 @@ static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea) { int context_id; - context_id = get_ea_context(&mm->context, ea); + context_id = get_user_context(&mm->context, ea); if (!context_id) return true; return false; diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index fad8ddd697ac..0abf2e7fd222 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -393,7 +393,14 @@ extern struct bus_type mpic_subsys; #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ /* Get the version of primary MPIC */ +#ifdef CONFIG_MPIC extern u32 fsl_mpic_primary_get_version(void); +#else +static inline u32 fsl_mpic_primary_get_version(void) +{ + return 0; +} +#endif /* Allocate the controller structure and setup the linux irq descs * for the range if interrupts passed in. No HW initialization is diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index a507a65b0866..3ffb0ff5a038 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -128,14 +128,65 @@ extern int icache_44x_need_flush; #include <asm/nohash/32/pte-8xx.h> #endif -/* And here we include common definitions */ -#include <asm/pte-common.h> +/* + * Location of the PFN in the PTE. Most 32-bit platforms use the same + * as _PAGE_SHIFT here (ie, naturally aligned). + * Platform who don't just pre-define the value so we don't override it here. + */ +#ifndef PTE_RPN_SHIFT +#define PTE_RPN_SHIFT (PAGE_SHIFT) +#endif + +/* + * The mask covered by the RPN must be a ULL on 32-bit platforms with + * 64-bit PTEs. + */ +#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) +#define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) +#else +#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) +#endif + +/* + * _PAGE_CHG_MASK masks of bits that are to be preserved across + * pgprot changes. + */ +#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) #ifndef __ASSEMBLY__ #define pte_clear(mm, addr, ptep) \ do { pte_update(ptep, ~0, 0); } while (0) +#ifndef pte_mkwrite +static inline pte_t pte_mkwrite(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_RW); +} +#endif + +static inline pte_t pte_mkdirty(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_DIRTY); +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_ACCESSED); +} + +#ifndef pte_wrprotect +static inline pte_t pte_wrprotect(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_RW); +} +#endif + +static inline pte_t pte_mkexec(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_EXEC); +} + #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) #define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK) @@ -244,23 +295,21 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), _PAGE_RO); -} -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} + unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0))); + unsigned long set = pte_val(pte_wrprotect(__pte(0))); + pte_update(ptep, clr, set); +} static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, pte_t entry, unsigned long address, int psize) { - unsigned long set = pte_val(entry) & - (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - unsigned long clr = ~pte_val(entry) & (_PAGE_RO | _PAGE_NA); + pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0))))); + pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0))))); + unsigned long set = pte_val(entry) & pte_val(pte_set); + unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr); pte_update(ptep, clr, set); @@ -323,7 +372,7 @@ static inline int pte_young(pte_t pte) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) -int map_kernel_page(unsigned long va, phys_addr_t pa, int flags); +int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); #endif /* !__ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h index bb4b3a4b92a0..661f4599f2fc 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-40x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h @@ -50,13 +50,56 @@ #define _PAGE_EXEC 0x200 /* hardware: EX permission */ #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ +/* No page size encoding in the linux PTE */ +#define _PAGE_PSIZE 0 + +/* cache related flags non existing on 40x */ +#define _PAGE_COHERENT 0 + +#define _PAGE_KERNEL_RO 0 +#define _PAGE_KERNEL_ROX _PAGE_EXEC +#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) +#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE | _PAGE_EXEC) + #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ +#define _PMD_PRESENT_MASK _PMD_PRESENT #define _PMD_BAD 0x802 #define _PMD_SIZE_4M 0x0c0 #define _PMD_SIZE_16M 0x0e0 +#define _PMD_USER 0 + +#define _PTE_NONE_MASK 0 /* Until my rework is finished, 40x still needs atomic PTE updates */ #define PTE_ATOMIC_UPDATES 1 +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) +#define _PAGE_BASE (_PAGE_BASE_NC) + +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) + +#ifndef __ASSEMBLY__ +static inline pte_t pte_wrprotect(pte_t pte) +{ + return __pte(pte_val(pte) & ~(_PAGE_RW | _PAGE_HWWRITE)); +} + +#define pte_wrprotect pte_wrprotect + +static inline pte_t pte_mkclean(pte_t pte) +{ + return __pte(pte_val(pte) & ~(_PAGE_DIRTY | _PAGE_HWWRITE)); +} + +#define pte_mkclean pte_mkclean +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_40x_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-44x.h b/arch/powerpc/include/asm/nohash/32/pte-44x.h index f812c0272364..78bc304f750e 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-44x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-44x.h @@ -85,14 +85,44 @@ #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ +/* No page size encoding in the linux PTE */ +#define _PAGE_PSIZE 0 + +#define _PAGE_KERNEL_RO 0 +#define _PAGE_KERNEL_ROX _PAGE_EXEC +#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) +#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) + /* TODO: Add large page lowmem mapping support */ #define _PMD_PRESENT 0 #define _PMD_PRESENT_MASK (PAGE_MASK) #define _PMD_BAD (~PAGE_MASK) +#define _PMD_USER 0 /* ERPN in a PTE never gets cleared, ignore it */ #define _PTE_NONE_MASK 0xffffffff00000000ULL +/* + * We define 2 sets of base prot bits, one for basic pages (ie, + * cacheable kernel and user pages) and one for non cacheable + * pages. We always set _PAGE_COHERENT when SMP is enabled or + * the processor might need it for DMA coherency. + */ +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) +#if defined(CONFIG_SMP) +#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) +#else +#define _PAGE_BASE (_PAGE_BASE_NC) +#endif + +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_44x_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h index f04cb46ae8a1..6bfe041ef59d 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h @@ -29,10 +29,10 @@ */ /* Definitions for 8xx embedded chips. */ -#define _PAGE_PRESENT 0x0001 /* Page is valid */ -#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ -#define _PAGE_PRIVILEGED 0x0004 /* No ASID (context) compare */ -#define _PAGE_HUGE 0x0008 /* SPS: Small Page Size (1 if 16k, 512k or 8M)*/ +#define _PAGE_PRESENT 0x0001 /* V: Page is valid */ +#define _PAGE_NO_CACHE 0x0002 /* CI: cache inhibit */ +#define _PAGE_SH 0x0004 /* SH: No ASID (context) compare */ +#define _PAGE_SPS 0x0008 /* SPS: Small Page Size (1 if 16k, 512k or 8M)*/ #define _PAGE_DIRTY 0x0100 /* C: page changed */ /* These 4 software bits must be masked out when the L2 entry is loaded @@ -46,18 +46,95 @@ #define _PAGE_NA 0x0200 /* Supervisor NA, User no access */ #define _PAGE_RO 0x0600 /* Supervisor RO, User no access */ +/* cache related flags non existing on 8xx */ +#define _PAGE_COHERENT 0 +#define _PAGE_WRITETHRU 0 + +#define _PAGE_KERNEL_RO (_PAGE_SH | _PAGE_RO) +#define _PAGE_KERNEL_ROX (_PAGE_SH | _PAGE_RO | _PAGE_EXEC) +#define _PAGE_KERNEL_RW (_PAGE_SH | _PAGE_DIRTY) +#define _PAGE_KERNEL_RWX (_PAGE_SH | _PAGE_DIRTY | _PAGE_EXEC) + #define _PMD_PRESENT 0x0001 +#define _PMD_PRESENT_MASK _PMD_PRESENT #define _PMD_BAD 0x0fd0 #define _PMD_PAGE_MASK 0x000c #define _PMD_PAGE_8M 0x000c #define _PMD_PAGE_512K 0x0004 #define _PMD_USER 0x0020 /* APG 1 */ +#define _PTE_NONE_MASK 0 + /* Until my rework is finished, 8xx still needs atomic PTE updates */ #define PTE_ATOMIC_UPDATES 1 #ifdef CONFIG_PPC_16K_PAGES -#define _PAGE_PSIZE _PAGE_HUGE +#define _PAGE_PSIZE _PAGE_SPS +#else +#define _PAGE_PSIZE 0 +#endif + +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) +#define _PAGE_BASE (_PAGE_BASE_NC) + +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) +#define PAGE_SHARED __pgprot(_PAGE_BASE) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) + +#ifndef __ASSEMBLY__ +static inline pte_t pte_wrprotect(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_RO); +} + +#define pte_wrprotect pte_wrprotect + +static inline int pte_write(pte_t pte) +{ + return !(pte_val(pte) & _PAGE_RO); +} + +#define pte_write pte_write + +static inline pte_t pte_mkwrite(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_RO); +} + +#define pte_mkwrite pte_mkwrite + +static inline bool pte_user(pte_t pte) +{ + return !(pte_val(pte) & _PAGE_SH); +} + +#define pte_user pte_user + +static inline pte_t pte_mkprivileged(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_SH); +} + +#define pte_mkprivileged pte_mkprivileged + +static inline pte_t pte_mkuser(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_SH); +} + +#define pte_mkuser pte_mkuser + +static inline pte_t pte_mkhuge(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_SPS); +} + +#define pte_mkhuge pte_mkhuge #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h b/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h index d1ee24e9e137..0fc1bd42bb3e 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h +++ b/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h @@ -31,11 +31,44 @@ #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ #define _PAGE_SPECIAL 0x00800 /* S: Special page */ +#define _PAGE_KERNEL_RO 0 +#define _PAGE_KERNEL_ROX _PAGE_EXEC +#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) +#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) + +/* No page size encoding in the linux PTE */ +#define _PAGE_PSIZE 0 + #define _PMD_PRESENT 0 #define _PMD_PRESENT_MASK (PAGE_MASK) #define _PMD_BAD (~PAGE_MASK) +#define _PMD_USER 0 + +#define _PTE_NONE_MASK 0 #define PTE_WIMGE_SHIFT (6) +/* + * We define 2 sets of base prot bits, one for basic pages (ie, + * cacheable kernel and user pages) and one for non cacheable + * pages. We always set _PAGE_COHERENT when SMP is enabled or + * the processor might need it for DMA coherency. + */ +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) +#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) +#else +#define _PAGE_BASE (_PAGE_BASE_NC) +#endif + +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_FSL_BOOKE_H */ diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h index 7cd6809f4d33..e77ed9761632 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h @@ -89,11 +89,47 @@ * Include the PTE bits definitions */ #include <asm/nohash/pte-book3e.h> -#include <asm/pte-common.h> + +#define _PAGE_SAO 0 + +#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) + +/* + * _PAGE_CHG_MASK masks of bits that are to be preserved across + * pgprot changes. + */ +#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) + +#define H_PAGE_4K_PFN 0 #ifndef __ASSEMBLY__ /* pte_clear moved to later in this file */ +static inline pte_t pte_mkwrite(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_RW); +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_DIRTY); +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_ACCESSED); +} + +static inline pte_t pte_wrprotect(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_RW); +} + +static inline pte_t pte_mkexec(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_EXEC); +} + #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) @@ -239,6 +275,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); } +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -313,9 +350,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, #define MAX_SWAPFILES_CHECK() do { \ BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \ } while (0) -/* - * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT; - */ + #define SWP_TYPE_BITS 5 #define __swp_type(x) (((x).val >> _PAGE_BIT_SWAP_TYPE) \ & ((1UL << SWP_TYPE_BITS) - 1)) @@ -327,8 +362,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) #define __swp_entry_to_pte(x) __pte((x).val) -extern int map_kernel_page(unsigned long ea, unsigned long pa, - unsigned long flags); +int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); extern int __meminit vmemmap_create_mapping(unsigned long start, unsigned long page_size, unsigned long phys); diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index b321c82b3624..70ff23974b59 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -8,18 +8,50 @@ #include <asm/nohash/32/pgtable.h> #endif +/* Permission masks used for kernel mappings */ +#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) +#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) +#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ + _PAGE_NO_CACHE | _PAGE_GUARDED) +#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) +#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) +#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) + +/* + * Protection used for kernel text. We want the debuggers to be able to + * set breakpoints anywhere, so don't write protect the kernel text + * on platforms where such control is possible. + */ +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ + defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) +#define PAGE_KERNEL_TEXT PAGE_KERNEL_X +#else +#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX +#endif + +/* Make modules code happy. We don't set RO yet */ +#define PAGE_KERNEL_EXEC PAGE_KERNEL_X + +/* Advertise special mapping type for AGP */ +#define PAGE_AGP (PAGE_KERNEL_NC) +#define HAVE_PAGE_AGP + #ifndef __ASSEMBLY__ /* Generic accessors to PTE bits */ +#ifndef pte_write static inline int pte_write(pte_t pte) { - return (pte_val(pte) & (_PAGE_RW | _PAGE_RO)) != _PAGE_RO; + return pte_val(pte) & _PAGE_RW; } +#endif static inline int pte_read(pte_t pte) { return 1; } static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } -static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } +static inline bool pte_hashpte(pte_t pte) { return false; } +static inline bool pte_ci(pte_t pte) { return pte_val(pte) & _PAGE_NO_CACHE; } +static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } #ifdef CONFIG_NUMA_BALANCING /* @@ -29,8 +61,7 @@ static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PA */ static inline int pte_protnone(pte_t pte) { - return (pte_val(pte) & - (_PAGE_PRESENT | _PAGE_USER)) == _PAGE_PRESENT; + return pte_present(pte) && !pte_user(pte); } static inline int pmd_protnone(pmd_t pmd) @@ -44,6 +75,23 @@ static inline int pte_present(pte_t pte) return pte_val(pte) & _PAGE_PRESENT; } +static inline bool pte_hw_valid(pte_t pte) +{ + return pte_val(pte) & _PAGE_PRESENT; +} + +/* + * Don't just check for any non zero bits in __PAGE_USER, since for book3e + * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in + * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. + */ +#ifndef pte_user +static inline bool pte_user(pte_t pte) +{ + return (pte_val(pte) & _PAGE_USER) == _PAGE_USER; +} +#endif + /* * We only find page table entry in the last level * Hence no need for other accessors @@ -77,53 +125,53 @@ static inline unsigned long pte_pfn(pte_t pte) { return pte_val(pte) >> PTE_RPN_SHIFT; } /* Generic modifiers for PTE bits */ -static inline pte_t pte_wrprotect(pte_t pte) +static inline pte_t pte_exprotect(pte_t pte) { - pte_basic_t ptev; - - ptev = pte_val(pte) & ~(_PAGE_RW | _PAGE_HWWRITE); - ptev |= _PAGE_RO; - return __pte(ptev); + return __pte(pte_val(pte) & ~_PAGE_EXEC); } +#ifndef pte_mkclean static inline pte_t pte_mkclean(pte_t pte) { - return __pte(pte_val(pte) & ~(_PAGE_DIRTY | _PAGE_HWWRITE)); + return __pte(pte_val(pte) & ~_PAGE_DIRTY); } +#endif static inline pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~_PAGE_ACCESSED); } -static inline pte_t pte_mkwrite(pte_t pte) +static inline pte_t pte_mkpte(pte_t pte) { - pte_basic_t ptev; - - ptev = pte_val(pte) & ~_PAGE_RO; - ptev |= _PAGE_RW; - return __pte(ptev); + return pte; } -static inline pte_t pte_mkdirty(pte_t pte) +static inline pte_t pte_mkspecial(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_DIRTY); + return __pte(pte_val(pte) | _PAGE_SPECIAL); } -static inline pte_t pte_mkyoung(pte_t pte) +#ifndef pte_mkhuge +static inline pte_t pte_mkhuge(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_ACCESSED); + return __pte(pte_val(pte)); } +#endif -static inline pte_t pte_mkspecial(pte_t pte) +#ifndef pte_mkprivileged +static inline pte_t pte_mkprivileged(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_SPECIAL); + return __pte(pte_val(pte) & ~_PAGE_USER); } +#endif -static inline pte_t pte_mkhuge(pte_t pte) +#ifndef pte_mkuser +static inline pte_t pte_mkuser(pte_t pte) { - return __pte(pte_val(pte) | _PAGE_HUGE); + return __pte(pte_val(pte) | _PAGE_USER); } +#endif static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { @@ -197,6 +245,8 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre #if _PAGE_WRITETHRU != 0 #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ _PAGE_COHERENT | _PAGE_WRITETHRU)) +#else +#define pgprot_cached_wthru(prot) pgprot_noncached(prot) #endif #define pgprot_cached_noncoherent(prot) \ diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h index 12730b81cd98..dd40d200f274 100644 --- a/arch/powerpc/include/asm/nohash/pte-book3e.h +++ b/arch/powerpc/include/asm/nohash/pte-book3e.h @@ -77,7 +77,48 @@ #define _PMD_PRESENT 0 #define _PMD_PRESENT_MASK (PAGE_MASK) #define _PMD_BAD (~PAGE_MASK) +#define _PMD_USER 0 +#else +#define _PTE_NONE_MASK 0 +#endif + +/* + * We define 2 sets of base prot bits, one for basic pages (ie, + * cacheable kernel and user pages) and one for non cacheable + * pages. We always set _PAGE_COHERENT when SMP is enabled or + * the processor might need it for DMA coherency. + */ +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) +#if defined(CONFIG_SMP) +#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) +#else +#define _PAGE_BASE (_PAGE_BASE_NC) #endif +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) + +#ifndef __ASSEMBLY__ +static inline pte_t pte_mkprivileged(pte_t pte) +{ + return __pte((pte_val(pte) & ~_PAGE_USER) | _PAGE_PRIVILEGED); +} + +#define pte_mkprivileged pte_mkprivileged + +static inline pte_t pte_mkuser(pte_t pte) +{ + return __pte((pte_val(pte) & ~_PAGE_PRIVILEGED) | _PAGE_USER); +} + +#define pte_mkuser pte_mkuser +#endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_PTE_BOOK3E_H */ diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 8365353330b4..870fb7b239ea 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -1050,6 +1050,7 @@ enum OpalSysCooling { enum { OPAL_REBOOT_NORMAL = 0, OPAL_REBOOT_PLATFORM_ERROR = 1, + OPAL_REBOOT_FULL_IPL = 2, }; /* Argument to OPAL_PCI_TCE_KILL */ diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index ad4f16164619..e843bc5d1a0f 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -113,7 +113,13 @@ struct paca_struct { * on the linear mapping */ /* SLB related definitions */ u16 vmalloc_sllp; - u16 slb_cache_ptr; + u8 slb_cache_ptr; + u8 stab_rr; /* stab/slb round-robin counter */ +#ifdef CONFIG_DEBUG_VM + u8 in_kernel_slb_handler; +#endif + u32 slb_used_bitmap; /* Bitmaps for first 32 SLB entries. */ + u32 slb_kern_bitmap; u32 slb_cache[SLB_CACHE_ENTRIES]; #endif /* CONFIG_PPC_BOOK3S_64 */ @@ -160,7 +166,6 @@ struct paca_struct { */ struct task_struct *__current; /* Pointer to current */ u64 kstack; /* Saved Kernel stack addr */ - u64 stab_rr; /* stab/slb round-robin counter */ u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */ u64 saved_msr; /* MSR saved here by enter_rtas */ u16 trap_save; /* Used when bad stack is encountered */ @@ -250,6 +255,15 @@ struct paca_struct { #ifdef CONFIG_PPC_PSERIES u8 *mce_data_buf; /* buffer to hold per cpu rtas errlog */ #endif /* CONFIG_PPC_PSERIES */ + +#ifdef CONFIG_PPC_BOOK3S_64 + /* Capture SLB related old contents in MCE handler. */ + struct slb_entry *mce_faulty_slbs; + u16 slb_save_cache_ptr; +#endif /* CONFIG_PPC_BOOK3S_64 */ +#ifdef CONFIG_STACKPROTECTOR + unsigned long canary; +#endif } ____cacheline_aligned; extern void copy_mm_to_paca(struct mm_struct *mm); diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 14c79a7dc855..9679b7519a35 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -20,6 +20,25 @@ struct mm_struct; #include <asm/nohash/pgtable.h> #endif /* !CONFIG_PPC_BOOK3S */ +/* Note due to the way vm flags are laid out, the bits are XWR */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY_X +#define __P101 PAGE_READONLY_X +#define __P110 PAGE_COPY_X +#define __P111 PAGE_COPY_X + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY_X +#define __S101 PAGE_READONLY_X +#define __S110 PAGE_SHARED_X +#define __S111 PAGE_SHARED_X + #ifndef __ASSEMBLY__ #include <asm/tlbflush.h> @@ -27,6 +46,16 @@ struct mm_struct; /* Keep these as a macros to avoid include dependency mess */ #define pte_page(x) pfn_to_page(pte_pfn(x)) #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +/* + * Select all bits except the pfn + */ +static inline pgprot_t pte_pgprot(pte_t pte) +{ + unsigned long pte_flags; + + pte_flags = pte_val(pte) & ~PTE_RPN_MASK; + return __pgprot(pte_flags); +} /* * ZERO_PAGE is a global shared page that is always zero: used diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 7f627e3f4da4..630eb8b1b7ed 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -54,7 +54,6 @@ void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, struct pnv_php_slot { struct hotplug_slot slot; - struct hotplug_slot_info slot_info; uint64_t id; char *name; int slot_no; @@ -72,6 +71,7 @@ struct pnv_php_slot { struct pci_dev *pdev; struct pci_bus *bus; bool power_state_check; + u8 attention_state; void *fdt; void *dt; struct of_changeset ocs; diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 665af14850e4..6093bc8f74e5 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -104,6 +104,7 @@ #define OP_31_XOP_LHZUX 311 #define OP_31_XOP_MSGSNDP 142 #define OP_31_XOP_MSGCLRP 174 +#define OP_31_XOP_TLBIE 306 #define OP_31_XOP_MFSPR 339 #define OP_31_XOP_LWAX 341 #define OP_31_XOP_LHAX 343 diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 726288048652..f67da277d652 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -58,6 +58,7 @@ void eeh_save_bars(struct eeh_dev *edev); int rtas_write_config(struct pci_dn *, int where, int size, u32 val); int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); void eeh_pe_state_mark(struct eeh_pe *pe, int state); +void eeh_pe_mark_isolated(struct eeh_pe *pe); void eeh_pe_state_clear(struct eeh_pe *pe, int state); void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state); void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode); diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 52fadded5c1e..7d04d60a39c9 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -32,9 +32,9 @@ /* Default SMT priority is set to 3. Use 11- 13bits to save priority. */ #define PPR_PRIORITY 3 #ifdef __ASSEMBLY__ -#define INIT_PPR (PPR_PRIORITY << 50) +#define DEFAULT_PPR (PPR_PRIORITY << 50) #else -#define INIT_PPR ((u64)PPR_PRIORITY << 50) +#define DEFAULT_PPR ((u64)PPR_PRIORITY << 50) #endif /* __ASSEMBLY__ */ #endif /* CONFIG_PPC64 */ @@ -273,6 +273,7 @@ struct thread_struct { #endif /* CONFIG_HAVE_HW_BREAKPOINT */ struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ unsigned long trap_nr; /* last trap # on this thread */ + u8 load_slb; /* Ages out SLB preload cache entries */ u8 load_fp; #ifdef CONFIG_ALTIVEC u8 load_vec; @@ -341,7 +342,6 @@ struct thread_struct { * onwards. */ int dscr_inherit; - unsigned long ppr; /* used to save/restore SMT priority */ unsigned long tidr; #endif #ifdef CONFIG_PPC_BOOK3S_64 @@ -389,7 +389,6 @@ struct thread_struct { .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ .addr_limit = KERNEL_DS, \ .fpexc_mode = 0, \ - .ppr = INIT_PPR, \ .fscr = FSCR_TAR | FSCR_EBB \ } #endif diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h deleted file mode 100644 index bef56141a549..000000000000 --- a/arch/powerpc/include/asm/pte-common.h +++ /dev/null @@ -1,219 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Included from asm/pgtable-*.h only ! */ - -/* - * Some bits are only used on some cpu families... Make sure that all - * the undefined gets a sensible default - */ -#ifndef _PAGE_HASHPTE -#define _PAGE_HASHPTE 0 -#endif -#ifndef _PAGE_HWWRITE -#define _PAGE_HWWRITE 0 -#endif -#ifndef _PAGE_EXEC -#define _PAGE_EXEC 0 -#endif -#ifndef _PAGE_ENDIAN -#define _PAGE_ENDIAN 0 -#endif -#ifndef _PAGE_COHERENT -#define _PAGE_COHERENT 0 -#endif -#ifndef _PAGE_WRITETHRU -#define _PAGE_WRITETHRU 0 -#endif -#ifndef _PAGE_4K_PFN -#define _PAGE_4K_PFN 0 -#endif -#ifndef _PAGE_SAO -#define _PAGE_SAO 0 -#endif -#ifndef _PAGE_PSIZE -#define _PAGE_PSIZE 0 -#endif -/* _PAGE_RO and _PAGE_RW shall not be defined at the same time */ -#ifndef _PAGE_RO -#define _PAGE_RO 0 -#else -#define _PAGE_RW 0 -#endif - -#ifndef _PAGE_PTE -#define _PAGE_PTE 0 -#endif -/* At least one of _PAGE_PRIVILEGED or _PAGE_USER must be defined */ -#ifndef _PAGE_PRIVILEGED -#define _PAGE_PRIVILEGED 0 -#else -#ifndef _PAGE_USER -#define _PAGE_USER 0 -#endif -#endif -#ifndef _PAGE_NA -#define _PAGE_NA 0 -#endif -#ifndef _PAGE_HUGE -#define _PAGE_HUGE 0 -#endif - -#ifndef _PMD_PRESENT_MASK -#define _PMD_PRESENT_MASK _PMD_PRESENT -#endif -#ifndef _PMD_USER -#define _PMD_USER 0 -#endif -#ifndef _PAGE_KERNEL_RO -#define _PAGE_KERNEL_RO (_PAGE_PRIVILEGED | _PAGE_RO) -#endif -#ifndef _PAGE_KERNEL_ROX -#define _PAGE_KERNEL_ROX (_PAGE_PRIVILEGED | _PAGE_RO | _PAGE_EXEC) -#endif -#ifndef _PAGE_KERNEL_RW -#define _PAGE_KERNEL_RW (_PAGE_PRIVILEGED | _PAGE_DIRTY | _PAGE_RW | \ - _PAGE_HWWRITE) -#endif -#ifndef _PAGE_KERNEL_RWX -#define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | _PAGE_RW | \ - _PAGE_HWWRITE | _PAGE_EXEC) -#endif -#ifndef _PAGE_HPTEFLAGS -#define _PAGE_HPTEFLAGS _PAGE_HASHPTE -#endif -#ifndef _PTE_NONE_MASK -#define _PTE_NONE_MASK _PAGE_HPTEFLAGS -#endif - -#ifndef __ASSEMBLY__ - -/* - * Don't just check for any non zero bits in __PAGE_USER, since for book3e - * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in - * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. - */ -static inline bool pte_user(pte_t pte) -{ - return (pte_val(pte) & (_PAGE_USER | _PAGE_PRIVILEGED)) == _PAGE_USER; -} -#endif /* __ASSEMBLY__ */ - -/* Location of the PFN in the PTE. Most 32-bit platforms use the same - * as _PAGE_SHIFT here (ie, naturally aligned). - * Platform who don't just pre-define the value so we don't override it here - */ -#ifndef PTE_RPN_SHIFT -#define PTE_RPN_SHIFT (PAGE_SHIFT) -#endif - -/* The mask covered by the RPN must be a ULL on 32-bit platforms with - * 64-bit PTEs - */ -#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) -#define PTE_RPN_MASK (~((1ULL<<PTE_RPN_SHIFT)-1)) -#else -#define PTE_RPN_MASK (~((1UL<<PTE_RPN_SHIFT)-1)) -#endif - -/* _PAGE_CHG_MASK masks of bits that are to be preserved across - * pgprot changes - */ -#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \ - _PAGE_ACCESSED | _PAGE_SPECIAL) - -/* Mask of bits returned by pte_pgprot() */ -#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ - _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \ - _PAGE_USER | _PAGE_ACCESSED | _PAGE_RO | _PAGE_NA | \ - _PAGE_PRIVILEGED | \ - _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | _PAGE_EXEC) - -/* - * We define 2 sets of base prot bits, one for basic pages (ie, - * cacheable kernel and user pages) and one for non cacheable - * pages. We always set _PAGE_COHERENT when SMP is enabled or - * the processor might need it for DMA coherency. - */ -#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) -#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU) || \ - defined(CONFIG_PPC_E500MC) -#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) -#else -#define _PAGE_BASE (_PAGE_BASE_NC) -#endif - -/* Permission masks used to generate the __P and __S table, - * - * Note:__pgprot is defined in arch/powerpc/include/asm/page.h - * - * Write permissions imply read permissions for now (we could make write-only - * pages on BookE but we don't bother for now). Execute permission control is - * possible on platforms that define _PAGE_EXEC - * - * Note due to the way vm flags are laid out, the bits are XWR - */ -#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | \ - _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO | \ - _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO | \ - _PAGE_EXEC) - -#define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY -#define __P100 PAGE_READONLY_X -#define __P101 PAGE_READONLY_X -#define __P110 PAGE_COPY_X -#define __P111 PAGE_COPY_X - -#define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY_X -#define __S101 PAGE_READONLY_X -#define __S110 PAGE_SHARED_X -#define __S111 PAGE_SHARED_X - -/* Permission masks used for kernel mappings */ -#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) -#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ - _PAGE_NO_CACHE) -#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ - _PAGE_NO_CACHE | _PAGE_GUARDED) -#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) -#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) -#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) - -/* Protection used for kernel text. We want the debuggers to be able to - * set breakpoints anywhere, so don't write protect the kernel text - * on platforms where such control is possible. - */ -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ - defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) -#define PAGE_KERNEL_TEXT PAGE_KERNEL_X -#else -#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX -#endif - -/* Make modules code happy. We don't set RO yet */ -#define PAGE_KERNEL_EXEC PAGE_KERNEL_X - -/* Advertise special mapping type for AGP */ -#define PAGE_AGP (PAGE_KERNEL_NC) -#define HAVE_PAGE_AGP - -#ifndef _PAGE_READ -/* if not defined, we should not find _PAGE_WRITE too */ -#define _PAGE_READ 0 -#define _PAGE_WRITE _PAGE_RW -#endif - -#ifndef H_PAGE_4K_PFN -#define H_PAGE_4K_PFN 0 -#endif diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 447cbd1bee99..f73886a1a7f5 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -26,6 +26,37 @@ #include <uapi/asm/ptrace.h> #include <asm/asm-const.h> +#ifndef __ASSEMBLY__ +struct pt_regs +{ + union { + struct user_pt_regs user_regs; + struct { + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; +#ifdef CONFIG_PPC64 + unsigned long softe; +#else + unsigned long mq; +#endif + unsigned long trap; + unsigned long dar; + unsigned long dsisr; + unsigned long result; + }; + }; + +#ifdef CONFIG_PPC64 + unsigned long ppr; +#endif +}; +#endif #ifdef __powerpc64__ @@ -102,6 +133,11 @@ static inline long regs_return_value(struct pt_regs *regs) return -regs->gpr[3]; } +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) +{ + regs->gpr[3] = rc; +} + #ifdef __powerpc64__ #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) #else @@ -149,7 +185,7 @@ do { \ #define arch_has_single_step() (1) #define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601)) -#define ARCH_HAS_USER_SINGLE_STEP_INFO +#define ARCH_HAS_USER_SINGLE_STEP_REPORT /* * kprobe-based event tracer support diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index e5b314ed054e..de52c3166ba4 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -118,11 +118,16 @@ #define MSR_TS_S __MASK(MSR_TS_S_LG) /* Transaction Suspended */ #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ -#define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ #define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */ #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +#define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ +#else +#define MSR_TM_ACTIVE(x) 0 +#endif + #if defined(CONFIG_PPC_BOOK3S_64) #define MSR_64BIT MSR_SF @@ -415,6 +420,7 @@ #define HFSCR_DSCR __MASK(FSCR_DSCR_LG) #define HFSCR_VECVSX __MASK(FSCR_VECVSX_LG) #define HFSCR_FP __MASK(FSCR_FP_LG) +#define HFSCR_INTR_CAUSE (ASM_CONST(0xFF) << 56) /* interrupt cause */ #define SPRN_TAR 0x32f /* Target Address Register */ #define SPRN_LPCR 0x13E /* LPAR Control Register */ #define LPCR_VPM0 ASM_CONST(0x8000000000000000) @@ -766,6 +772,7 @@ #define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */ #define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */ #define HSRR1_DENORM 0x00100000 /* Denorm exception */ +#define HSRR1_HISI_WRITE 0x00010000 /* HISI bcs couldn't update mem */ #define SPRN_TBCTL 0x35f /* PA6T Timebase control register */ #define TBCTL_FREEZE 0x0000000000000000ull /* Freeze all tbs */ diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 71e393c46a49..bb38dd67d47d 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -125,6 +125,7 @@ struct rtas_suspend_me_data { #define RTAS_TYPE_INFO 0xE2 #define RTAS_TYPE_DEALLOC 0xE3 #define RTAS_TYPE_DUMP 0xE4 +#define RTAS_TYPE_HOTPLUG 0xE5 /* I don't add PowerMGM events right now, this is a different topic */ #define RTAS_TYPE_PMGM_POWER_SW_ON 0x60 #define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61 @@ -185,11 +186,23 @@ static inline uint8_t rtas_error_disposition(const struct rtas_error_log *elog) return (elog->byte1 & 0x18) >> 3; } +static inline +void rtas_set_disposition_recovered(struct rtas_error_log *elog) +{ + elog->byte1 &= ~0x18; + elog->byte1 |= (RTAS_DISP_FULLY_RECOVERED << 3); +} + static inline uint8_t rtas_error_extended(const struct rtas_error_log *elog) { return (elog->byte1 & 0x04) >> 2; } +static inline uint8_t rtas_error_initiator(const struct rtas_error_log *elog) +{ + return (elog->byte2 & 0xf0) >> 4; +} + #define rtas_error_type(x) ((x)->byte3) static inline @@ -275,6 +288,7 @@ inline uint32_t rtas_ext_event_company_id(struct rtas_ext_event_log_v6 *ext_log) #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') #define PSERIES_ELOG_SECT_ID_HOTPLUG (('H' << 8) | 'P') +#define PSERIES_ELOG_SECT_ID_MCE (('M' << 8) | 'C') /* Vendor specific Platform Event Log Format, Version 6, section header */ struct pseries_errorlog { @@ -316,6 +330,7 @@ struct pseries_hp_errorlog { #define PSERIES_HP_ELOG_RESOURCE_MEM 2 #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_ACTION_ADD 1 #define PSERIES_HP_ELOG_ACTION_REMOVE 2 diff --git a/arch/powerpc/include/asm/slice.h b/arch/powerpc/include/asm/slice.h index e40406cf5628..a595461c9cb0 100644 --- a/arch/powerpc/include/asm/slice.h +++ b/arch/powerpc/include/asm/slice.h @@ -32,6 +32,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start, unsigned long len, unsigned int psize); void slice_init_new_context_exec(struct mm_struct *mm); +void slice_setup_new_exec(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 95b66a0c639b..41695745032c 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -100,6 +100,7 @@ static inline void set_hard_smp_processor_id(int cpu, int phys) DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); DECLARE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); +DECLARE_PER_CPU(cpumask_var_t, cpu_smallcore_map); static inline struct cpumask *cpu_sibling_mask(int cpu) { @@ -116,6 +117,11 @@ static inline struct cpumask *cpu_l2_cache_mask(int cpu) return per_cpu(cpu_l2_cache_map, cpu); } +static inline struct cpumask *cpu_smallcore_mask(int cpu) +{ + return per_cpu(cpu_smallcore_map, cpu); +} + extern int cpu_to_core_id(int cpu); /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. @@ -166,6 +172,11 @@ static inline const struct cpumask *cpu_sibling_mask(int cpu) return cpumask_of(cpu); } +static inline const struct cpumask *cpu_smallcore_mask(int cpu) +{ + return cpumask_of(cpu); +} + #endif /* CONFIG_SMP */ #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h index 28f5dae25db6..68da49320592 100644 --- a/arch/powerpc/include/asm/sparsemem.h +++ b/arch/powerpc/include/asm/sparsemem.h @@ -9,17 +9,6 @@ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space */ #define SECTION_SIZE_BITS 24 -/* - * If we store section details in page->flags we can't increase the MAX_PHYSMEM_BITS - * if we increase SECTIONS_WIDTH we will not store node details in page->flags and - * page_to_nid does a page->section->node lookup - * Hence only increase for VMEMMAP. - */ -#ifdef CONFIG_SPARSEMEM_VMEMMAP -#define MAX_PHYSMEM_BITS 47 -#else -#define MAX_PHYSMEM_BITS 46 -#endif #endif /* CONFIG_SPARSEMEM */ diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h new file mode 100644 index 000000000000..1c8460e23583 --- /dev/null +++ b/arch/powerpc/include/asm/stackprotector.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * GCC stack protector support. + * + */ + +#ifndef _ASM_STACKPROTECTOR_H +#define _ASM_STACKPROTECTOR_H + +#include <linux/random.h> +#include <linux/version.h> +#include <asm/reg.h> +#include <asm/current.h> +#include <asm/paca.h> + +/* + * Initialize the stackprotector canary value. + * + * NOTE: this must only be called from functions that never return, + * and it must always be inlined. + */ +static __always_inline void boot_init_stack_canary(void) +{ + unsigned long canary; + + /* Try to get a semi random initial value. */ + canary = get_random_canary(); + canary ^= mftb(); + canary ^= LINUX_VERSION_CODE; + canary &= CANARY_MASK; + + current->stack_canary = canary; +#ifdef CONFIG_PPC64 + get_paca()->canary = canary; +#endif +} + +#endif /* _ASM_STACKPROTECTOR_H */ diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 3c0002044bc9..544cac0474cb 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -29,6 +29,7 @@ #include <asm/page.h> #include <asm/accounting.h> +#define SLB_PRELOAD_NR 16U /* * low level task data. */ @@ -44,6 +45,10 @@ struct thread_info { #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) struct cpu_accounting_data accounting; #endif + unsigned char slb_preload_nr; + unsigned char slb_preload_tail; + u32 slb_preload_esid[SLB_PRELOAD_NR]; + /* low level flags - has atomic operations done on it */ unsigned long flags ____cacheline_aligned_in_smp; }; @@ -72,6 +77,12 @@ static inline struct thread_info *current_thread_info(void) } extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); + +#ifdef CONFIG_PPC_BOOK3S_64 +void arch_setup_new_exec(void); +#define arch_setup_new_exec arch_setup_new_exec +#endif + #endif /* __ASSEMBLY__ */ /* @@ -81,7 +92,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src #define TIF_SIGPENDING 1 /* signal pending */ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_FSCHECK 3 /* Check FS is USER_DS on return */ -#define TIF_32BIT 4 /* 32 bit binary */ +#define TIF_SYSCALL_EMU 4 /* syscall emulation active */ #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ #define TIF_PATCH_PENDING 6 /* pending live patching update */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ @@ -100,6 +111,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src #define TIF_ELF2ABI 18 /* function descriptors must die! */ #endif #define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_32BIT 20 /* 32 bit binary */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) @@ -120,9 +132,10 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) #define _TIF_NOHZ (1<<TIF_NOHZ) #define _TIF_FSCHECK (1<<TIF_FSCHECK) +#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU) #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ) + _TIF_NOHZ | _TIF_SYSCALL_EMU) #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index d018e8602694..58ef8c43a89d 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h @@ -201,6 +201,21 @@ TRACE_EVENT(tlbie, __entry->r) ); +TRACE_EVENT(tlbia, + + TP_PROTO(unsigned long id), + TP_ARGS(id), + TP_STRUCT__entry( + __field(unsigned long, id) + ), + + TP_fast_assign( + __entry->id = id; + ), + + TP_printk("ctx.id=0x%lx", __entry->id) +); + #endif /* _TRACE_POWERPC_H */ #undef TRACE_INCLUDE_PATH diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index bac225bb7f64..15bea9a0f260 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -260,7 +260,7 @@ do { \ ({ \ long __gu_err; \ __long_type(*(ptr)) __gu_val; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ __chk_user_ptr(ptr); \ if (!is_kernel_addr((unsigned long)__gu_addr)) \ might_fault(); \ @@ -274,7 +274,7 @@ do { \ ({ \ long __gu_err = -EFAULT; \ __long_type(*(ptr)) __gu_val = 0; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ might_fault(); \ if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ barrier_nospec(); \ @@ -288,7 +288,7 @@ do { \ ({ \ long __gu_err; \ __long_type(*(ptr)) __gu_val; \ - const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ __chk_user_ptr(ptr); \ barrier_nospec(); \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index c19379f0a32e..b0de85b477e1 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -22,6 +22,7 @@ #include <linux/compiler.h> #include <linux/linkage.h> +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM @@ -35,7 +36,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_UNAME @@ -47,6 +47,7 @@ #endif #ifdef CONFIG_PPC64 #define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_SYS_NEWFSTATAT #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif diff --git a/arch/powerpc/include/asm/user.h b/arch/powerpc/include/asm/user.h index 5c0e082eae7b..99443b8594e7 100644 --- a/arch/powerpc/include/asm/user.h +++ b/arch/powerpc/include/asm/user.h @@ -31,7 +31,7 @@ * to write an integer number of pages. */ struct user { - struct pt_regs regs; /* entire machine state */ + struct user_pt_regs regs; /* entire machine state */ size_t u_tsize; /* text size (pages) */ size_t u_dsize; /* data size (pages) */ size_t u_ssize; /* stack size (pages) */ diff --git a/arch/powerpc/include/uapi/asm/Kbuild b/arch/powerpc/include/uapi/asm/Kbuild index 1a6ed5919ffd..a658091a19f9 100644 --- a/arch/powerpc/include/uapi/asm/Kbuild +++ b/arch/powerpc/include/uapi/asm/Kbuild @@ -7,3 +7,4 @@ generic-y += poll.h generic-y += resource.h generic-y += sockios.h generic-y += statfs.h +generic-y += siginfo.h diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h index 41b1a5c15734..2c145da3b774 100644 --- a/arch/powerpc/include/uapi/asm/ioctls.h +++ b/arch/powerpc/include/uapi/asm/ioctls.h @@ -102,6 +102,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 1b32b56a03d3..8c876c166ef2 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h @@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char { #define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe) #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf) +#define KVM_REG_PPC_PTCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0) /* Transactional Memory checkpointed state: * This is all GPRs, all VSX regs and a subset of SPRs diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h index 5e3edc2a7634..f5f1ccc740fc 100644 --- a/arch/powerpc/include/uapi/asm/ptrace.h +++ b/arch/powerpc/include/uapi/asm/ptrace.h @@ -29,7 +29,12 @@ #ifndef __ASSEMBLY__ -struct pt_regs { +#ifdef __KERNEL__ +struct user_pt_regs +#else +struct pt_regs +#endif +{ unsigned long gpr[32]; unsigned long nip; unsigned long msr; @@ -160,6 +165,10 @@ struct pt_regs { #define PTRACE_GETVSRREGS 0x1b #define PTRACE_SETVSRREGS 0x1c +/* Syscall emulation defines */ +#define PTRACE_SYSEMU 0x1d +#define PTRACE_SYSEMU_SINGLESTEP 0x1e + /* * Get or set a debug register. The first 16 are DABR registers and the * second 16 are IABR registers. diff --git a/arch/powerpc/include/uapi/asm/sigcontext.h b/arch/powerpc/include/uapi/asm/sigcontext.h index 2fbe485acdb4..630aeda56d59 100644 --- a/arch/powerpc/include/uapi/asm/sigcontext.h +++ b/arch/powerpc/include/uapi/asm/sigcontext.h @@ -22,7 +22,11 @@ struct sigcontext { #endif unsigned long handler; unsigned long oldmask; - struct pt_regs __user *regs; +#ifdef __KERNEL__ + struct user_pt_regs __user *regs; +#else + struct pt_regs *regs; +#endif #ifdef __powerpc64__ elf_gregset_t gp_regs; elf_fpregset_t fp_regs; diff --git a/arch/powerpc/include/uapi/asm/siginfo.h b/arch/powerpc/include/uapi/asm/siginfo.h deleted file mode 100644 index 1d51d9b88221..000000000000 --- a/arch/powerpc/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -#ifndef _ASM_POWERPC_SIGINFO_H -#define _ASM_POWERPC_SIGINFO_H - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifdef __powerpc64__ -# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#endif - -#include <asm-generic/siginfo.h> - -#endif /* _ASM_POWERPC_SIGINFO_H */ diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 3b66f2c19c84..53d4b8d5b54d 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -5,7 +5,8 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror +# Disable clang warning for using setjmp without setjmp.h header +CFLAGS_crash.o += $(call cc-disable-warning, builtin-requires-header) ifdef CONFIG_PPC64 CFLAGS_prom_init.o += $(NO_MINIMAL_TOC) @@ -20,12 +21,14 @@ CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector) + ifdef CONFIG_FUNCTION_TRACER # Do not trace early boot code -CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) -CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) -CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) -CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_cputable.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_prom_init.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_btext.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_prom.o = $(CC_FLAGS_FTRACE) endif obj-y := cputable.o ptrace.o syscalls.o \ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 89cf15566c4e..9ffc72ded73a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -79,11 +79,16 @@ int main(void) { OFFSET(THREAD, task_struct, thread); OFFSET(MM, task_struct, mm); +#ifdef CONFIG_STACKPROTECTOR + OFFSET(TASK_CANARY, task_struct, stack_canary); +#ifdef CONFIG_PPC64 + OFFSET(PACA_CANARY, paca_struct, canary); +#endif +#endif OFFSET(MMCONTEXTID, mm_struct, context.id); #ifdef CONFIG_PPC64 DEFINE(SIGSEGV, SIGSEGV); DEFINE(NMI_MASK, NMI_MASK); - OFFSET(TASKTHREADPPR, task_struct, thread.ppr); #else OFFSET(THREAD_INFO, task_struct, stack); DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16)); @@ -173,7 +178,6 @@ int main(void) OFFSET(PACAKSAVE, paca_struct, kstack); OFFSET(PACACURRENT, paca_struct, __current); OFFSET(PACASAVEDMSR, paca_struct, saved_msr); - OFFSET(PACASTABRR, paca_struct, stab_rr); OFFSET(PACAR1, paca_struct, saved_r1); OFFSET(PACATOC, paca_struct, kernel_toc); OFFSET(PACAKBASE, paca_struct, kernelbase); @@ -212,6 +216,7 @@ int main(void) #ifdef CONFIG_PPC_BOOK3S_64 OFFSET(PACASLBCACHE, paca_struct, slb_cache); OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); + OFFSET(PACASTABRR, paca_struct, stab_rr); OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); #ifdef CONFIG_PPC_MM_SLICES OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp); @@ -274,11 +279,6 @@ int main(void) /* Interrupt register frame */ DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); -#ifdef CONFIG_PPC64 - /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ - DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); - DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); -#endif /* CONFIG_PPC64 */ STACK_PT_REGS_OFFSET(GPR0, gpr[0]); STACK_PT_REGS_OFFSET(GPR1, gpr[1]); STACK_PT_REGS_OFFSET(GPR2, gpr[2]); @@ -322,10 +322,7 @@ int main(void) STACK_PT_REGS_OFFSET(_ESR, dsisr); #else /* CONFIG_PPC64 */ STACK_PT_REGS_OFFSET(SOFTE, softe); - - /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ - DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); - DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); + STACK_PT_REGS_OFFSET(_PPR, ppr); #endif /* CONFIG_PPC64 */ #if defined(CONFIG_PPC32) @@ -387,12 +384,12 @@ int main(void) OFFSET(CFG_SYSCALL_MAP64, vdso_data, syscall_map_64); OFFSET(TVAL64_TV_SEC, timeval, tv_sec); OFFSET(TVAL64_TV_USEC, timeval, tv_usec); - OFFSET(TVAL32_TV_SEC, compat_timeval, tv_sec); - OFFSET(TVAL32_TV_USEC, compat_timeval, tv_usec); + OFFSET(TVAL32_TV_SEC, old_timeval32, tv_sec); + OFFSET(TVAL32_TV_USEC, old_timeval32, tv_usec); OFFSET(TSPC64_TV_SEC, timespec, tv_sec); OFFSET(TSPC64_TV_NSEC, timespec, tv_nsec); - OFFSET(TSPC32_TV_SEC, compat_timespec, tv_sec); - OFFSET(TSPC32_TV_NSEC, compat_timespec, tv_nsec); + OFFSET(TSPC32_TV_SEC, old_timespec32, tv_sec); + OFFSET(TSPC32_TV_NSEC, old_timespec32, tv_nsec); #else OFFSET(TVAL32_TV_SEC, timeval, tv_sec); OFFSET(TVAL32_TV_USEC, timeval, tv_usec); @@ -438,7 +435,7 @@ int main(void) #ifdef CONFIG_PPC_BOOK3S OFFSET(VCPU_TAR, kvm_vcpu, arch.tar); #endif - OFFSET(VCPU_CR, kvm_vcpu, arch.cr); + OFFSET(VCPU_CR, kvm_vcpu, arch.regs.ccr); OFFSET(VCPU_PC, kvm_vcpu, arch.regs.nip); #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE OFFSET(VCPU_MSR, kvm_vcpu, arch.shregs.msr); @@ -503,6 +500,7 @@ int main(void) OFFSET(VCPU_VPA, kvm_vcpu, arch.vpa.pinned_addr); OFFSET(VCPU_VPA_DIRTY, kvm_vcpu, arch.vpa.dirty); OFFSET(VCPU_HEIR, kvm_vcpu, arch.emul_inst); + OFFSET(VCPU_NESTED, kvm_vcpu, arch.nested); OFFSET(VCPU_CPU, kvm_vcpu, cpu); OFFSET(VCPU_THREAD_CPU, kvm_vcpu, arch.thread_cpu); #endif @@ -695,7 +693,7 @@ int main(void) #endif /* CONFIG_PPC_BOOK3S_64 */ #else /* CONFIG_PPC_BOOK3S */ - OFFSET(VCPU_CR, kvm_vcpu, arch.cr); + OFFSET(VCPU_CR, kvm_vcpu, arch.regs.ccr); OFFSET(VCPU_XER, kvm_vcpu, arch.regs.xer); OFFSET(VCPU_LR, kvm_vcpu, arch.regs.link); OFFSET(VCPU_CTR, kvm_vcpu, arch.regs.ctr); diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index b2072d5bbf2b..b4241ed1456e 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -163,7 +163,7 @@ void btext_map(void) offset = ((unsigned long) dispDeviceBase) - base; size = dispDeviceRowBytes * dispDeviceRect[3] + offset + dispDeviceRect[0]; - vbase = __ioremap(base, size, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); + vbase = ioremap_wc(base, size); if (!vbase) return; logicalDisplayBase = vbase + offset; diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index a8f20e5928e1..be57bd07596d 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -20,6 +20,8 @@ #include <linux/percpu.h> #include <linux/slab.h> #include <asm/prom.h> +#include <asm/cputhreads.h> +#include <asm/smp.h> #include "cacheinfo.h" @@ -627,17 +629,48 @@ static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char * static struct kobj_attribute cache_level_attr = __ATTR(level, 0444, level_show, NULL); +static unsigned int index_dir_to_cpu(struct cache_index_dir *index) +{ + struct kobject *index_dir_kobj = &index->kobj; + struct kobject *cache_dir_kobj = index_dir_kobj->parent; + struct kobject *cpu_dev_kobj = cache_dir_kobj->parent; + struct device *dev = kobj_to_dev(cpu_dev_kobj); + + return dev->id; +} + +/* + * On big-core systems, each core has two groups of CPUs each of which + * has its own L1-cache. The thread-siblings which share l1-cache with + * @cpu can be obtained via cpu_smallcore_mask(). + */ +static const struct cpumask *get_big_core_shared_cpu_map(int cpu, struct cache *cache) +{ + if (cache->level == 1) + return cpu_smallcore_mask(cpu); + + return &cache->shared_cpu_map; +} + static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf) { struct cache_index_dir *index; struct cache *cache; - int ret; + const struct cpumask *mask; + int ret, cpu; index = kobj_to_cache_index_dir(k); cache = index->cache; + if (has_big_cores) { + cpu = index_dir_to_cpu(index); + mask = get_big_core_shared_cpu_map(cpu, cache); + } else { + mask = &cache->shared_cpu_map; + } + ret = scnprintf(buf, PAGE_SIZE - 1, "%*pb\n", - cpumask_pr_args(&cache->shared_cpu_map)); + cpumask_pr_args(mask)); buf[ret++] = '\n'; buf[ret] = '\0'; return ret; diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index 458b928dbd84..c317080db771 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -147,8 +147,8 @@ __init_hvmode_206: rldicl. r0,r3,4,63 bnelr ld r5,CPU_SPEC_FEATURES(r4) - LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE) - xor r5,r5,r6 + LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST) + andc r5,r5,r6 std r5,CPU_SPEC_FEATURES(r4) blr diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index d10ad258d41a..bbdc4706c159 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -110,7 +110,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, vaddr = __va(paddr); csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); } else { - vaddr = __ioremap(paddr, PAGE_SIZE, 0); + vaddr = ioremap_cache(paddr, PAGE_SIZE); csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); iounmap(vaddr); } diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index 88f3963ca30f..5fc335f4d9cd 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -11,7 +11,7 @@ * */ -#include <linux/dma-mapping.h> +#include <linux/dma-direct.h> #include <linux/memblock.h> #include <linux/pfn.h> #include <linux/of_platform.h> @@ -59,7 +59,7 @@ const struct dma_map_ops powerpc_swiotlb_dma_ops = { .sync_single_for_device = swiotlb_sync_single_for_device, .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, .sync_sg_for_device = swiotlb_sync_sg_for_device, - .mapping_error = swiotlb_dma_mapping_error, + .mapping_error = dma_direct_mapping_error, .get_required_mask = swiotlb_powerpc_get_required, }; diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 6ebba3e48b01..6cae6b56ffd6 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -169,6 +169,11 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) int n = 0, l = 0; char buffer[128]; + if (!pdn) { + pr_warn("EEH: Note: No error log for absent device.\n"); + return 0; + } + n += scnprintf(buf+n, len-n, "%04x:%02x:%02x.%01x\n", pdn->phb->global_number, pdn->busno, PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); @@ -399,7 +404,7 @@ static int eeh_phb_check_failure(struct eeh_pe *pe) } /* Isolate the PHB and send event */ - eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(phb_pe); eeh_serialize_unlock(flags); pr_err("EEH: PHB#%x failure detected, location: %s\n", @@ -558,7 +563,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev) * with other functions on this device, and functions under * bridges. */ - eeh_pe_state_mark(pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(pe); eeh_serialize_unlock(flags); /* Most EEH events are due to device driver bugs. Having @@ -676,7 +681,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function) /* Check if the request is finished successfully */ if (active_flag) { - rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); + rc = eeh_wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); if (rc < 0) return rc; @@ -825,7 +830,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat eeh_pe_state_clear(pe, EEH_PE_ISOLATED); break; case pcie_hot_reset: - eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(pe); + eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); if (!(pe->type & EEH_PE_VF)) @@ -833,7 +839,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat eeh_ops->reset(pe, EEH_RESET_HOT); break; case pcie_warm_reset: - eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(pe); + eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); if (!(pe->type & EEH_PE_VF)) @@ -913,16 +920,15 @@ int eeh_pe_reset_full(struct eeh_pe *pe) break; /* Wait until the PE is in a functioning state */ - state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); - if (eeh_state_active(state)) - break; - + state = eeh_wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); if (state < 0) { pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x", __func__, pe->phb->global_number, pe->addr); ret = -ENOTRECOVERABLE; break; } + if (eeh_state_active(state)) + break; /* Set error in case this is our last attempt */ ret = -EIO; @@ -1036,6 +1042,11 @@ void eeh_probe_devices(void) pdn = hose->pci_data; traverse_pci_dn(pdn, eeh_ops->probe, NULL); } + if (eeh_enabled()) + pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); + else + pr_info("EEH: No capable adapters found\n"); + } /** @@ -1079,18 +1090,7 @@ static int eeh_init(void) eeh_dev_phb_init_dynamic(hose); /* Initialize EEH event */ - ret = eeh_event_init(); - if (ret) - return ret; - - eeh_probe_devices(); - - if (eeh_enabled()) - pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); - else if (!eeh_has_flag(EEH_POSTPONED_PROBE)) - pr_info("EEH: No capable adapters found\n"); - - return ret; + return eeh_event_init(); } core_initcall_sync(eeh_init); diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index a34e6912c15e..d8c90f3284b5 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c @@ -60,8 +60,6 @@ struct eeh_dev *eeh_dev_init(struct pci_dn *pdn) /* Associate EEH device with OF node */ pdn->edev = edev; edev->pdn = pdn; - INIT_LIST_HEAD(&edev->list); - INIT_LIST_HEAD(&edev->rmv_list); return edev; } diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 67619b4b3f96..9446248eb6b8 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -35,8 +35,8 @@ #include <asm/rtas.h> struct eeh_rmv_data { - struct list_head edev_list; - int removed; + struct list_head removed_vf_list; + int removed_dev_count; }; static int eeh_result_priority(enum pci_ers_result result) @@ -281,6 +281,10 @@ static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn, struct pci_driver *driver; enum pci_ers_result new_result; + if (!edev->pdev) { + eeh_edev_info(edev, "no device"); + return; + } device_lock(&edev->pdev->dev); if (eeh_edev_actionable(edev)) { driver = eeh_pcid_get(edev->pdev); @@ -400,7 +404,7 @@ static void *eeh_dev_restore_state(struct eeh_dev *edev, void *userdata) * EEH device is created. */ if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) { - if (list_is_last(&edev->list, &edev->pe->edevs)) + if (list_is_last(&edev->entry, &edev->pe->edevs)) eeh_pe_restore_bars(edev->pe); return NULL; @@ -465,10 +469,9 @@ static enum pci_ers_result eeh_report_failure(struct eeh_dev *edev, return rc; } -static void *eeh_add_virt_device(void *data, void *userdata) +static void *eeh_add_virt_device(struct eeh_dev *edev) { struct pci_driver *driver; - struct eeh_dev *edev = (struct eeh_dev *)data; struct pci_dev *dev = eeh_dev_to_pci_dev(edev); struct pci_dn *pdn = eeh_dev_to_pdn(edev); @@ -499,7 +502,6 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) struct pci_driver *driver; struct pci_dev *dev = eeh_dev_to_pci_dev(edev); struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata; - int *removed = rmv_data ? &rmv_data->removed : NULL; /* * Actually, we should remove the PCI bridges as well. @@ -521,7 +523,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) if (eeh_dev_removed(edev)) return NULL; - if (removed) { + if (rmv_data) { if (eeh_pe_passed(edev->pe)) return NULL; driver = eeh_pcid_get(dev); @@ -539,10 +541,9 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) /* Remove it from PCI subsystem */ pr_debug("EEH: Removing %s without EEH sensitive driver\n", pci_name(dev)); - edev->bus = dev->bus; edev->mode |= EEH_DEV_DISCONNECTED; - if (removed) - (*removed)++; + if (rmv_data) + rmv_data->removed_dev_count++; if (edev->physfn) { #ifdef CONFIG_PCI_IOV @@ -558,7 +559,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) pdn->pe_number = IODA_INVALID_PE; #endif if (rmv_data) - list_add(&edev->rmv_list, &rmv_data->edev_list); + list_add(&edev->rmv_entry, &rmv_data->removed_vf_list); } else { pci_lock_rescan_remove(); pci_stop_and_remove_bus_device(dev); @@ -727,7 +728,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, * the device up before the scripts have taken it down, * potentially weird things happen. */ - if (!driver_eeh_aware || rmv_data->removed) { + if (!driver_eeh_aware || rmv_data->removed_dev_count) { pr_info("EEH: Sleep 5s ahead of %s hotplug\n", (driver_eeh_aware ? "partial" : "complete")); ssleep(5); @@ -737,10 +738,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, * PE. We should disconnect it so the binding can be * rebuilt when adding PCI devices. */ - edev = list_first_entry(&pe->edevs, struct eeh_dev, list); + edev = list_first_entry(&pe->edevs, struct eeh_dev, entry); eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); if (pe->type & EEH_PE_VF) { - eeh_add_virt_device(edev, NULL); + eeh_add_virt_device(edev); } else { if (!driver_eeh_aware) eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); @@ -789,7 +790,8 @@ void eeh_handle_normal_event(struct eeh_pe *pe) struct eeh_pe *tmp_pe; int rc = 0; enum pci_ers_result result = PCI_ERS_RESULT_NONE; - struct eeh_rmv_data rmv_data = {LIST_HEAD_INIT(rmv_data.edev_list), 0}; + struct eeh_rmv_data rmv_data = + {LIST_HEAD_INIT(rmv_data.removed_vf_list), 0}; bus = eeh_pe_bus_get(pe); if (!bus) { @@ -806,10 +808,8 @@ void eeh_handle_normal_event(struct eeh_pe *pe) pr_err("EEH: PHB#%x-PE#%x has failed %d times in the last hour and has been permanently disabled.\n", pe->phb->global_number, pe->addr, pe->freeze_count); - goto hard_fail; + result = PCI_ERS_RESULT_DISCONNECT; } - pr_warn("EEH: This PCI device has failed %d times in the last hour and will be permanently disabled after %d failures.\n", - pe->freeze_count, eeh_max_freezes); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -821,31 +821,39 @@ void eeh_handle_normal_event(struct eeh_pe *pe) * the error. Override the result if necessary to have partially * hotplug for this case. */ - pr_info("EEH: Notify device drivers to shutdown\n"); - eeh_set_channel_state(pe, pci_channel_io_frozen); - eeh_set_irq_state(pe, false); - eeh_pe_report("error_detected(IO frozen)", pe, eeh_report_error, - &result); - if ((pe->type & EEH_PE_PHB) && - result != PCI_ERS_RESULT_NONE && - result != PCI_ERS_RESULT_NEED_RESET) - result = PCI_ERS_RESULT_NEED_RESET; + if (result != PCI_ERS_RESULT_DISCONNECT) { + pr_warn("EEH: This PCI device has failed %d times in the last hour and will be permanently disabled after %d failures.\n", + pe->freeze_count, eeh_max_freezes); + pr_info("EEH: Notify device drivers to shutdown\n"); + eeh_set_channel_state(pe, pci_channel_io_frozen); + eeh_set_irq_state(pe, false); + eeh_pe_report("error_detected(IO frozen)", pe, + eeh_report_error, &result); + if ((pe->type & EEH_PE_PHB) && + result != PCI_ERS_RESULT_NONE && + result != PCI_ERS_RESULT_NEED_RESET) + result = PCI_ERS_RESULT_NEED_RESET; + } /* Get the current PCI slot state. This can take a long time, * sometimes over 300 seconds for certain systems. */ - rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); - if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { - pr_warn("EEH: Permanent failure\n"); - goto hard_fail; + if (result != PCI_ERS_RESULT_DISCONNECT) { + rc = eeh_wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); + if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { + pr_warn("EEH: Permanent failure\n"); + result = PCI_ERS_RESULT_DISCONNECT; + } } /* Since rtas may enable MMIO when posting the error log, * don't post the error log until after all dev drivers * have been informed. */ - pr_info("EEH: Collect temporary log\n"); - eeh_slot_error_detail(pe, EEH_LOG_TEMP); + if (result != PCI_ERS_RESULT_DISCONNECT) { + pr_info("EEH: Collect temporary log\n"); + eeh_slot_error_detail(pe, EEH_LOG_TEMP); + } /* If all device drivers were EEH-unaware, then shut * down all of the device drivers, and hope they @@ -857,7 +865,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) if (rc) { pr_warn("%s: Unable to reset, err=%d\n", __func__, rc); - goto hard_fail; + result = PCI_ERS_RESULT_DISCONNECT; } } @@ -866,9 +874,9 @@ void eeh_handle_normal_event(struct eeh_pe *pe) pr_info("EEH: Enable I/O for affected devices\n"); rc = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); - if (rc < 0) - goto hard_fail; - if (rc) { + if (rc < 0) { + result = PCI_ERS_RESULT_DISCONNECT; + } else if (rc) { result = PCI_ERS_RESULT_NEED_RESET; } else { pr_info("EEH: Notify device drivers to resume I/O\n"); @@ -882,9 +890,9 @@ void eeh_handle_normal_event(struct eeh_pe *pe) pr_info("EEH: Enabled DMA for affected devices\n"); rc = eeh_pci_enable(pe, EEH_OPT_THAW_DMA); - if (rc < 0) - goto hard_fail; - if (rc) { + if (rc < 0) { + result = PCI_ERS_RESULT_DISCONNECT; + } else if (rc) { result = PCI_ERS_RESULT_NEED_RESET; } else { /* @@ -897,12 +905,6 @@ void eeh_handle_normal_event(struct eeh_pe *pe) } } - /* If any device has a hard failure, then shut off everything. */ - if (result == PCI_ERS_RESULT_DISCONNECT) { - pr_warn("EEH: Device driver gave up\n"); - goto hard_fail; - } - /* If any device called out for a reset, then reset the slot */ if (result == PCI_ERS_RESULT_NEED_RESET) { pr_info("EEH: Reset without hotplug activity\n"); @@ -910,88 +912,81 @@ void eeh_handle_normal_event(struct eeh_pe *pe) if (rc) { pr_warn("%s: Cannot reset, err=%d\n", __func__, rc); - goto hard_fail; + result = PCI_ERS_RESULT_DISCONNECT; + } else { + result = PCI_ERS_RESULT_NONE; + eeh_set_channel_state(pe, pci_channel_io_normal); + eeh_set_irq_state(pe, true); + eeh_pe_report("slot_reset", pe, eeh_report_reset, + &result); } - - pr_info("EEH: Notify device drivers " - "the completion of reset\n"); - result = PCI_ERS_RESULT_NONE; - eeh_set_channel_state(pe, pci_channel_io_normal); - eeh_set_irq_state(pe, true); - eeh_pe_report("slot_reset", pe, eeh_report_reset, &result); - } - - /* All devices should claim they have recovered by now. */ - if ((result != PCI_ERS_RESULT_RECOVERED) && - (result != PCI_ERS_RESULT_NONE)) { - pr_warn("EEH: Not recovered\n"); - goto hard_fail; - } - - /* - * For those hot removed VFs, we should add back them after PF get - * recovered properly. - */ - list_for_each_entry_safe(edev, tmp, &rmv_data.edev_list, rmv_list) { - eeh_add_virt_device(edev, NULL); - list_del(&edev->rmv_list); } - /* Tell all device drivers that they can resume operations */ - pr_info("EEH: Notify device driver to resume\n"); - eeh_set_channel_state(pe, pci_channel_io_normal); - eeh_set_irq_state(pe, true); - eeh_pe_report("resume", pe, eeh_report_resume, NULL); - eeh_for_each_pe(pe, tmp_pe) { - eeh_pe_for_each_dev(tmp_pe, edev, tmp) { - edev->mode &= ~EEH_DEV_NO_HANDLER; - edev->in_error = false; + if ((result == PCI_ERS_RESULT_RECOVERED) || + (result == PCI_ERS_RESULT_NONE)) { + /* + * For those hot removed VFs, we should add back them after PF + * get recovered properly. + */ + list_for_each_entry_safe(edev, tmp, &rmv_data.removed_vf_list, + rmv_entry) { + eeh_add_virt_device(edev); + list_del(&edev->rmv_entry); } - } - pr_info("EEH: Recovery successful.\n"); - goto final; + /* Tell all device drivers that they can resume operations */ + pr_info("EEH: Notify device driver to resume\n"); + eeh_set_channel_state(pe, pci_channel_io_normal); + eeh_set_irq_state(pe, true); + eeh_pe_report("resume", pe, eeh_report_resume, NULL); + eeh_for_each_pe(pe, tmp_pe) { + eeh_pe_for_each_dev(tmp_pe, edev, tmp) { + edev->mode &= ~EEH_DEV_NO_HANDLER; + edev->in_error = false; + } + } -hard_fail: - /* - * About 90% of all real-life EEH failures in the field - * are due to poorly seated PCI cards. Only 10% or so are - * due to actual, failed cards. - */ - pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" - "Please try reseating or replacing it\n", - pe->phb->global_number, pe->addr); + pr_info("EEH: Recovery successful.\n"); + } else { + /* + * About 90% of all real-life EEH failures in the field + * are due to poorly seated PCI cards. Only 10% or so are + * due to actual, failed cards. + */ + pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" + "Please try reseating or replacing it\n", + pe->phb->global_number, pe->addr); - eeh_slot_error_detail(pe, EEH_LOG_PERM); + eeh_slot_error_detail(pe, EEH_LOG_PERM); - /* Notify all devices that they're about to go down. */ - eeh_set_channel_state(pe, pci_channel_io_perm_failure); - eeh_set_irq_state(pe, false); - eeh_pe_report("error_detected(permanent failure)", pe, - eeh_report_failure, NULL); + /* Notify all devices that they're about to go down. */ + eeh_set_channel_state(pe, pci_channel_io_perm_failure); + eeh_set_irq_state(pe, false); + eeh_pe_report("error_detected(permanent failure)", pe, + eeh_report_failure, NULL); - /* Mark the PE to be removed permanently */ - eeh_pe_state_mark(pe, EEH_PE_REMOVED); + /* Mark the PE to be removed permanently */ + eeh_pe_state_mark(pe, EEH_PE_REMOVED); - /* - * Shut down the device drivers for good. We mark - * all removed devices correctly to avoid access - * the their PCI config any more. - */ - if (pe->type & EEH_PE_VF) { - eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); - eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); - } else { - eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); - eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); + /* + * Shut down the device drivers for good. We mark + * all removed devices correctly to avoid access + * the their PCI config any more. + */ + if (pe->type & EEH_PE_VF) { + eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); + eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); + } else { + eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); + eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); - pci_lock_rescan_remove(); - pci_hp_remove_devices(bus); - pci_unlock_rescan_remove(); - /* The passed PE should no longer be used */ - return; + pci_lock_rescan_remove(); + pci_hp_remove_devices(bus); + pci_unlock_rescan_remove(); + /* The passed PE should no longer be used */ + return; + } } -final: eeh_pe_state_clear(pe, EEH_PE_RECOVERING); } @@ -1026,7 +1021,7 @@ void eeh_handle_special_event(void) phb_pe = eeh_phb_pe_get(hose); if (!phb_pe) continue; - eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(phb_pe); } eeh_serialize_unlock(flags); @@ -1041,11 +1036,9 @@ void eeh_handle_special_event(void) /* Purge all events of the PHB */ eeh_remove_event(pe, true); - if (rc == EEH_NEXT_ERR_DEAD_PHB) - eeh_pe_state_mark(pe, EEH_PE_ISOLATED); - else - eeh_pe_state_mark(pe, - EEH_PE_ISOLATED | EEH_PE_RECOVERING); + if (rc != EEH_NEXT_ERR_DEAD_PHB) + eeh_pe_state_mark(pe, EEH_PE_RECOVERING); + eeh_pe_mark_isolated(pe); eeh_serialize_unlock(flags); diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 1b238ecc553e..6fa2032e0594 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -75,7 +75,6 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) pe->type = type; pe->phb = phb; INIT_LIST_HEAD(&pe->child_list); - INIT_LIST_HEAD(&pe->child); INIT_LIST_HEAD(&pe->edevs); pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe), @@ -110,6 +109,57 @@ int eeh_phb_pe_create(struct pci_controller *phb) } /** + * eeh_wait_state - Wait for PE state + * @pe: EEH PE + * @max_wait: maximal period in millisecond + * + * Wait for the state of associated PE. It might take some time + * to retrieve the PE's state. + */ +int eeh_wait_state(struct eeh_pe *pe, int max_wait) +{ + int ret; + int mwait; + + /* + * According to PAPR, the state of PE might be temporarily + * unavailable. Under the circumstance, we have to wait + * for indicated time determined by firmware. The maximal + * wait time is 5 minutes, which is acquired from the original + * EEH implementation. Also, the original implementation + * also defined the minimal wait time as 1 second. + */ +#define EEH_STATE_MIN_WAIT_TIME (1000) +#define EEH_STATE_MAX_WAIT_TIME (300 * 1000) + + while (1) { + ret = eeh_ops->get_state(pe, &mwait); + + if (ret != EEH_STATE_UNAVAILABLE) + return ret; + + if (max_wait <= 0) { + pr_warn("%s: Timeout when getting PE's state (%d)\n", + __func__, max_wait); + return EEH_STATE_NOT_SUPPORT; + } + + if (mwait < EEH_STATE_MIN_WAIT_TIME) { + pr_warn("%s: Firmware returned bad wait value %d\n", + __func__, mwait); + mwait = EEH_STATE_MIN_WAIT_TIME; + } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { + pr_warn("%s: Firmware returned too long wait value %d\n", + __func__, mwait); + mwait = EEH_STATE_MAX_WAIT_TIME; + } + + msleep(min(mwait, max_wait)); + max_wait -= mwait; + } +} + +/** * eeh_phb_pe_get - Retrieve PHB PE based on the given PHB * @phb: PCI controller * @@ -360,7 +410,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) edev->pe = pe; /* Put the edev to PE */ - list_add_tail(&edev->list, &pe->edevs); + list_add_tail(&edev->entry, &pe->edevs); pr_debug("EEH: Add %04x:%02x:%02x.%01x to Bus PE#%x\n", pdn->phb->global_number, pdn->busno, @@ -369,7 +419,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) pe->addr); return 0; } else if (pe && (pe->type & EEH_PE_INVALID)) { - list_add_tail(&edev->list, &pe->edevs); + list_add_tail(&edev->entry, &pe->edevs); edev->pe = pe; /* * We're running to here because of PCI hotplug caused by @@ -379,7 +429,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) while (parent) { if (!(parent->type & EEH_PE_INVALID)) break; - parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP); + parent->type &= ~EEH_PE_INVALID; parent = parent->parent; } @@ -429,7 +479,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) * link the EEH device accordingly. */ list_add_tail(&pe->child, &parent->child_list); - list_add_tail(&edev->list, &pe->edevs); + list_add_tail(&edev->entry, &pe->edevs); edev->pe = pe; pr_debug("EEH: Add %04x:%02x:%02x.%01x to " "Device PE#%x, Parent PE#%x\n", @@ -457,7 +507,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) int cnt; struct pci_dn *pdn = eeh_dev_to_pdn(edev); - if (!edev->pe) { + pe = eeh_dev_to_pe(edev); + if (!pe) { pr_debug("%s: No PE found for device %04x:%02x:%02x.%01x\n", __func__, pdn->phb->global_number, pdn->busno, @@ -467,9 +518,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) } /* Remove the EEH device */ - pe = eeh_dev_to_pe(edev); edev->pe = NULL; - list_del(&edev->list); + list_del(&edev->entry); /* * Check if the parent PE includes any EEH devices. @@ -541,56 +591,50 @@ void eeh_pe_update_time_stamp(struct eeh_pe *pe) } /** - * __eeh_pe_state_mark - Mark the state for the PE - * @data: EEH PE - * @flag: state + * eeh_pe_state_mark - Mark specified state for PE and its associated device + * @pe: EEH PE * - * The function is used to mark the indicated state for the given - * PE. Also, the associated PCI devices will be put into IO frozen - * state as well. + * EEH error affects the current PE and its child PEs. The function + * is used to mark appropriate state for the affected PEs and the + * associated devices. */ -static void *__eeh_pe_state_mark(struct eeh_pe *pe, void *flag) +void eeh_pe_state_mark(struct eeh_pe *root, int state) { - int state = *((int *)flag); - struct eeh_dev *edev, *tmp; - struct pci_dev *pdev; - - /* Keep the state of permanently removed PE intact */ - if (pe->state & EEH_PE_REMOVED) - return NULL; - - pe->state |= state; - - /* Offline PCI devices if applicable */ - if (!(state & EEH_PE_ISOLATED)) - return NULL; - - eeh_pe_for_each_dev(pe, edev, tmp) { - pdev = eeh_dev_to_pci_dev(edev); - if (pdev) - pdev->error_state = pci_channel_io_frozen; - } - - /* Block PCI config access if required */ - if (pe->state & EEH_PE_CFG_RESTRICTED) - pe->state |= EEH_PE_CFG_BLOCKED; + struct eeh_pe *pe; - return NULL; + eeh_for_each_pe(root, pe) + if (!(pe->state & EEH_PE_REMOVED)) + pe->state |= state; } +EXPORT_SYMBOL_GPL(eeh_pe_state_mark); /** - * eeh_pe_state_mark - Mark specified state for PE and its associated device + * eeh_pe_mark_isolated * @pe: EEH PE * - * EEH error affects the current PE and its child PEs. The function - * is used to mark appropriate state for the affected PEs and the - * associated devices. + * Record that a PE has been isolated by marking the PE and it's children as + * EEH_PE_ISOLATED (and EEH_PE_CFG_BLOCKED, if required) and their PCI devices + * as pci_channel_io_frozen. */ -void eeh_pe_state_mark(struct eeh_pe *pe, int state) +void eeh_pe_mark_isolated(struct eeh_pe *root) { - eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); + struct eeh_pe *pe; + struct eeh_dev *edev; + struct pci_dev *pdev; + + eeh_pe_state_mark(root, EEH_PE_ISOLATED); + eeh_for_each_pe(root, pe) { + list_for_each_entry(edev, &pe->edevs, entry) { + pdev = eeh_dev_to_pci_dev(edev); + if (pdev) + pdev->error_state = pci_channel_io_frozen; + } + /* Block PCI config access if required */ + if (pe->state & EEH_PE_CFG_RESTRICTED) + pe->state |= EEH_PE_CFG_BLOCKED; + } } -EXPORT_SYMBOL_GPL(eeh_pe_state_mark); +EXPORT_SYMBOL_GPL(eeh_pe_mark_isolated); static void *__eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag) { @@ -671,28 +715,6 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state) eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); } -/** - * eeh_pe_state_mark_with_cfg - Mark PE state with unblocked config space - * @pe: PE - * @state: PE state to be set - * - * Set specified flag to PE and its child PEs. The PCI config space - * of some PEs is blocked automatically when EEH_PE_ISOLATED is set, - * which isn't needed in some situations. The function allows to set - * the specified flag to indicated PEs without blocking their PCI - * config space. - */ -void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state) -{ - eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); - if (!(state & EEH_PE_ISOLATED)) - return; - - /* Clear EEH_PE_CFG_BLOCKED, which might be set just now */ - state = EEH_PE_CFG_BLOCKED; - eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); -} - /* * Some PCI bridges (e.g. PLX bridges) have primary/secondary * buses assigned explicitly by firmware, and we probably have @@ -945,7 +967,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) return pe->bus; /* Retrieve the parent PCI bus of first (top) PCI device */ - edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list); + edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); pdev = eeh_dev_to_pci_dev(edev); if (pdev) return pdev->bus; diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index e58c3f467db5..77decded1175 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -794,7 +794,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) lis r10,MSR_KERNEL@h ori r10,r10,MSR_KERNEL@l bl transfer_to_handler_full - .long nonrecoverable_exception + .long unrecoverable_exception .long ret_from_except #endif @@ -1297,7 +1297,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) rlwinm r3,r3,0,0,30 stw r3,_TRAP(r1) 4: addi r3,r1,STACK_FRAME_OVERHEAD - bl nonrecoverable_exception + bl unrecoverable_exception /* shouldn't return */ b 4b diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2206912ea4f0..7b1693adff2a 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -171,7 +171,7 @@ system_call: /* label this so stack traces look sane */ * based on caller's run-mode / personality. */ ld r11,SYS_CALL_TABLE@toc(2) - andi. r10,r10,_TIF_32BIT + andis. r10,r10,_TIF_32BIT@h beq 15f addi r11,r11,8 /* use 32-bit syscall entries */ clrldi r3,r3,32 @@ -386,10 +386,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) 4: /* Anything else left to do? */ BEGIN_FTR_SECTION - lis r3,INIT_PPR@highest /* Set thread.ppr = 3 */ - ld r10,PACACURRENT(r13) + lis r3,DEFAULT_PPR@highest /* Set default PPR */ sldi r3,r3,32 /* bits 11-13 are used for ppr */ - std r3,TASKTHREADPPR(r10) + std r3,_PPR(r1) END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) andi. r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP) @@ -624,6 +623,10 @@ _GLOBAL(_switch) addi r6,r4,-THREAD /* Convert THREAD to 'current' */ std r6,PACACURRENT(r13) /* Set new 'current' */ +#if defined(CONFIG_STACKPROTECTOR) + ld r6, TASK_CANARY(r6) + std r6, PACA_CANARY(r13) +#endif ld r8,KSP(r4) /* new stack pointer */ #ifdef CONFIG_PPC_BOOK3S_64 @@ -672,7 +675,9 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) isync slbie r6 +BEGIN_FTR_SECTION slbie r6 /* Workaround POWER5 < DD2.1 issue */ +END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) slbmte r7,r0 isync 2: @@ -936,12 +941,6 @@ fast_exception_return: andi. r0,r3,MSR_RI beq- .Lunrecov_restore - /* Load PPR from thread struct before we clear MSR:RI */ -BEGIN_FTR_SECTION - ld r2,PACACURRENT(r13) - ld r2,TASKTHREADPPR(r2) -END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) - /* * Clear RI before restoring r13. If we are returning to * userspace and we take an exception after restoring r13, @@ -962,7 +961,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) andi. r0,r3,MSR_PR beq 1f BEGIN_FTR_SECTION - mtspr SPRN_PPR,r2 /* Restore PPR */ + /* Restore PPR */ + ld r2,_PPR(r1) + mtspr SPRN_PPR,r2 END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) ACCOUNT_CPU_USER_EXIT(r13, r2, r4) REST_GPR(13, r1) @@ -1118,7 +1119,7 @@ _ASM_NOKPROBE_SYMBOL(fast_exception_return); _GLOBAL(enter_rtas) mflr r0 std r0,16(r1) - stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */ + stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ /* Because RTAS is running in 32b mode, it clobbers the high order half * of all registers that it saves. We therefore save those registers @@ -1250,7 +1251,7 @@ rtas_restore_regs: ld r8,_DSISR(r1) mtdsisr r8 - addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */ + addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ ld r0,16(r1) /* get return address */ mtlr r0 @@ -1261,7 +1262,7 @@ rtas_restore_regs: _GLOBAL(enter_prom) mflr r0 std r0,16(r1) - stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */ + stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space */ /* Because PROM is running in 32b mode, it clobbers the high order half * of all registers that it saves. We therefore save those registers @@ -1318,8 +1319,8 @@ _GLOBAL(enter_prom) REST_10GPRS(22, r1) ld r4,_CCR(r1) mtcr r4 - - addi r1,r1,PROM_FRAME_SIZE + + addi r1,r1,SWITCH_FRAME_SIZE ld r0,16(r1) mtlr r0 blr diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 2d8fc8c9da7a..89d32bb79d5e 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -244,14 +244,13 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x100) SET_SCRATCH0(r13) /* save r13 */ EXCEPTION_PROLOG_0(PACA_EXMC) BEGIN_FTR_SECTION - b machine_check_powernv_early + b machine_check_common_early FTR_SECTION_ELSE b machine_check_pSeries_0 ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) EXC_REAL_END(machine_check, 0x200, 0x100) EXC_VIRT_NONE(0x4200, 0x100) -TRAMP_REAL_BEGIN(machine_check_powernv_early) -BEGIN_FTR_SECTION +TRAMP_REAL_BEGIN(machine_check_common_early) EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200) /* * Register contents: @@ -305,7 +304,9 @@ BEGIN_FTR_SECTION /* Save r9 through r13 from EXMC save area to stack frame. */ EXCEPTION_PROLOG_COMMON_2(PACA_EXMC) mfmsr r11 /* get MSR value */ +BEGIN_FTR_SECTION ori r11,r11,MSR_ME /* turn on ME bit */ +END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) ori r11,r11,MSR_RI /* turn on RI bit */ LOAD_HANDLER(r12, machine_check_handle_early) 1: mtspr SPRN_SRR0,r12 @@ -324,13 +325,15 @@ BEGIN_FTR_SECTION andc r11,r11,r10 /* Turn off MSR_ME */ b 1b b . /* prevent speculative execution */ -END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) TRAMP_REAL_BEGIN(machine_check_pSeries) .globl machine_check_fwnmi machine_check_fwnmi: SET_SCRATCH0(r13) /* save r13 */ EXCEPTION_PROLOG_0(PACA_EXMC) +BEGIN_FTR_SECTION + b machine_check_common_early +END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) machine_check_pSeries_0: EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST_PR, 0x200) /* @@ -440,6 +443,9 @@ EXC_COMMON_BEGIN(machine_check_handle_early) bl machine_check_early std r3,RESULT(r1) /* Save result */ ld r12,_MSR(r1) +BEGIN_FTR_SECTION + b 4f +END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) #ifdef CONFIG_PPC_P7_NAP /* @@ -463,11 +469,12 @@ EXC_COMMON_BEGIN(machine_check_handle_early) */ rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */ beq 5f - andi. r11,r12,MSR_PR /* See if coming from user. */ +4: andi. r11,r12,MSR_PR /* See if coming from user. */ bne 9f /* continue in V mode if we are. */ 5: #ifdef CONFIG_KVM_BOOK3S_64_HANDLER +BEGIN_FTR_SECTION /* * We are coming from kernel context. Check if we are coming from * guest. if yes, then we can continue. We will fall through @@ -476,6 +483,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) lbz r11,HSTATE_IN_GUEST(r13) cmpwi r11,0 /* Check if coming from guest */ bne 9f /* continue if we are. */ +END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) #endif /* * At this point we are not sure about what context we come from. @@ -510,6 +518,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) cmpdi r3,0 /* see if we handled MCE successfully */ beq 1b /* if !handled then panic */ +BEGIN_FTR_SECTION /* * Return from MC interrupt. * Queue up the MCE event so that we can log it later, while @@ -518,10 +527,24 @@ EXC_COMMON_BEGIN(machine_check_handle_early) bl machine_check_queue_event MACHINE_CHECK_HANDLER_WINDUP RFI_TO_USER_OR_KERNEL +FTR_SECTION_ELSE + /* + * pSeries: Return from MC interrupt. Before that stay on emergency + * stack and call machine_check_exception to log the MCE event. + */ + LOAD_HANDLER(r10,mce_return) + mtspr SPRN_SRR0,r10 + ld r10,PACAKMSR(r13) + mtspr SPRN_SRR1,r10 + RFI_TO_KERNEL + b . +ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) 9: /* Deliver the machine check to host kernel in V mode. */ MACHINE_CHECK_HANDLER_WINDUP - b machine_check_pSeries + SET_SCRATCH0(r13) /* save r13 */ + EXCEPTION_PROLOG_0(PACA_EXMC) + b machine_check_pSeries_0 EXC_COMMON_BEGIN(unrecover_mce) /* Invoke machine_check_exception to print MCE event and panic. */ @@ -535,6 +558,13 @@ EXC_COMMON_BEGIN(unrecover_mce) bl unrecoverable_exception b 1b +EXC_COMMON_BEGIN(mce_return) + /* Invoke machine_check_exception to print MCE event and return. */ + addi r3,r1,STACK_FRAME_OVERHEAD + bl machine_check_exception + MACHINE_CHECK_HANDLER_WINDUP + RFI_TO_KERNEL + b . EXC_REAL(data_access, 0x300, 0x80) EXC_VIRT(data_access, 0x4300, 0x80, 0x300) @@ -566,28 +596,36 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) - SET_SCRATCH0(r13) - EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380) - mr r12,r3 /* save r3 */ - mfspr r3,SPRN_DAR - mfspr r11,SPRN_SRR1 - crset 4*cr6+eq - BRANCH_TO_COMMON(r10, slb_miss_common) +EXCEPTION_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, KVMTEST_PR, 0x380); EXC_REAL_END(data_access_slb, 0x380, 0x80) EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) - SET_SCRATCH0(r13) - EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380) - mr r12,r3 /* save r3 */ - mfspr r3,SPRN_DAR - mfspr r11,SPRN_SRR1 - crset 4*cr6+eq - BRANCH_TO_COMMON(r10, slb_miss_common) +EXCEPTION_RELON_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, NOTEST, 0x380); EXC_VIRT_END(data_access_slb, 0x4380, 0x80) + TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) +EXC_COMMON_BEGIN(data_access_slb_common) + mfspr r10,SPRN_DAR + std r10,PACA_EXSLB+EX_DAR(r13) + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB) + ld r4,PACA_EXSLB+EX_DAR(r13) + std r4,_DAR(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_slb_fault + cmpdi r3,0 + bne- 1f + b fast_exception_return +1: /* Error case */ + std r3,RESULT(r1) + bl save_nvgprs + RECONCILE_IRQ_STATE(r10, r11) + ld r4,_DAR(r1) + ld r5,RESULT(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_bad_slb_fault + b ret_from_except + EXC_REAL(instruction_access, 0x400, 0x80) EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400) @@ -610,160 +648,34 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80) - SET_SCRATCH0(r13) - EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) - mr r12,r3 /* save r3 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - mfspr r11,SPRN_SRR1 - crclr 4*cr6+eq - BRANCH_TO_COMMON(r10, slb_miss_common) +EXCEPTION_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, KVMTEST_PR, 0x480); EXC_REAL_END(instruction_access_slb, 0x480, 0x80) EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) - SET_SCRATCH0(r13) - EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480) - mr r12,r3 /* save r3 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - mfspr r11,SPRN_SRR1 - crclr 4*cr6+eq - BRANCH_TO_COMMON(r10, slb_miss_common) +EXCEPTION_RELON_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, NOTEST, 0x480); EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80) -TRAMP_KVM(PACA_EXSLB, 0x480) - - -/* - * This handler is used by the 0x380 and 0x480 SLB miss interrupts, as well as - * the virtual mode 0x4380 and 0x4480 interrupts if AIL is enabled. - */ -EXC_COMMON_BEGIN(slb_miss_common) - /* - * r13 points to the PACA, r9 contains the saved CR, - * r12 contains the saved r3, - * r11 contain the saved SRR1, SRR0 is still ready for return - * r3 has the faulting address - * r9 - r13 are saved in paca->exslb. - * cr6.eq is set for a D-SLB miss, clear for a I-SLB miss - * We assume we aren't going to take any exceptions during this - * procedure. - */ - mflr r10 - stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ - - andi. r9,r11,MSR_PR // Check for exception from userspace - cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later - - /* - * Test MSR_RI before calling slb_allocate_realmode, because the - * MSR in r11 gets clobbered. However we still want to allocate - * SLB in case MSR_RI=0, to minimise the risk of getting stuck in - * recursive SLB faults. So use cr5 for this, which is preserved. - */ - andi. r11,r11,MSR_RI /* check for unrecoverable exception */ - cmpdi cr5,r11,MSR_RI - - crset 4*cr0+eq -#ifdef CONFIG_PPC_BOOK3S_64 -BEGIN_MMU_FTR_SECTION - bl slb_allocate -END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) -#endif - - ld r10,PACA_EXSLB+EX_LR(r13) - lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ - mtlr r10 - - /* - * Large address, check whether we have to allocate new contexts. - */ - beq- 8f - bne- cr5,2f /* if unrecoverable exception, oops */ - - /* All done -- return from exception. */ - - bne cr4,1f /* returning to kernel */ - - mtcrf 0x80,r9 - mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */ - mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */ - mtcrf 0x02,r9 /* I/D indication is in cr6 */ - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ - - RESTORE_CTR(r9, PACA_EXSLB) - RESTORE_PPR_PACA(PACA_EXSLB, r9) - mr r3,r12 - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - RFI_TO_USER - b . /* prevent speculative execution */ -1: - mtcrf 0x80,r9 - mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */ - mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */ - mtcrf 0x02,r9 /* I/D indication is in cr6 */ - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ - - RESTORE_CTR(r9, PACA_EXSLB) - RESTORE_PPR_PACA(PACA_EXSLB, r9) - mr r3,r12 - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - RFI_TO_KERNEL - b . /* prevent speculative execution */ - - -2: std r3,PACA_EXSLB+EX_DAR(r13) - mr r3,r12 - mfspr r11,SPRN_SRR0 - mfspr r12,SPRN_SRR1 - LOAD_HANDLER(r10,unrecov_slb) - mtspr SPRN_SRR0,r10 - ld r10,PACAKMSR(r13) - mtspr SPRN_SRR1,r10 - RFI_TO_KERNEL - b . - -8: std r3,PACA_EXSLB+EX_DAR(r13) - mr r3,r12 - mfspr r11,SPRN_SRR0 - mfspr r12,SPRN_SRR1 - LOAD_HANDLER(r10, large_addr_slb) - mtspr SPRN_SRR0,r10 - ld r10,PACAKMSR(r13) - mtspr SPRN_SRR1,r10 - RFI_TO_KERNEL - b . +TRAMP_KVM(PACA_EXSLB, 0x480) -EXC_COMMON_BEGIN(unrecov_slb) - EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) - RECONCILE_IRQ_STATE(r10, r11) +EXC_COMMON_BEGIN(instruction_access_slb_common) + EXCEPTION_PROLOG_COMMON(0x480, PACA_EXSLB) + ld r4,_NIP(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_slb_fault + cmpdi r3,0 + bne- 1f + b fast_exception_return +1: /* Error case */ + std r3,RESULT(r1) bl save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl unrecoverable_exception - b 1b - -EXC_COMMON_BEGIN(large_addr_slb) - EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB) RECONCILE_IRQ_STATE(r10, r11) - ld r3, PACA_EXSLB+EX_DAR(r13) - std r3, _DAR(r1) - beq cr6, 2f - li r10, 0x481 /* fix trap number for I-SLB miss */ - std r10, _TRAP(r1) -2: bl save_nvgprs - addi r3, r1, STACK_FRAME_OVERHEAD - bl slb_miss_large_addr + ld r4,_NIP(r1) + ld r5,RESULT(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_bad_slb_fault b ret_from_except + EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100) .globl hardware_interrupt_hv; hardware_interrupt_hv: diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index a711d22339ea..761b28b1427d 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -1444,8 +1444,8 @@ static ssize_t fadump_register_store(struct kobject *kobj, break; case 1: if (fw_dump.dump_registered == 1) { - ret = -EEXIST; - goto unlock_out; + /* Un-register Firmware-assisted dump */ + fadump_unregister_dump(&fdm); } /* Register Firmware-assisted dump */ ret = register_fadump(); diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 6582f824d620..134a573a9f2d 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -642,7 +642,7 @@ DTLBMissIMMR: mtspr SPRN_MD_TWC, r10 mfspr r10, SPRN_IMMR /* Get current IMMR */ rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */ - ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ + ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ _PAGE_PRESENT | _PAGE_NO_CACHE mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ @@ -660,7 +660,7 @@ DTLBMissLinear: li r11, MD_PS8MEG | MD_SVALID | M_APG2 mtspr SPRN_MD_TWC, r11 rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ - ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ + ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ _PAGE_PRESENT mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ @@ -679,7 +679,7 @@ ITLBMissLinear: li r11, MI_PS8MEG | MI_SVALID | M_APG2 mtspr SPRN_MI_TWC, r11 rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ - ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ + ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ _PAGE_PRESENT mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ diff --git a/arch/powerpc/kernel/io-workarounds.c b/arch/powerpc/kernel/io-workarounds.c index aa9f1b8261db..7e89d02a84e1 100644 --- a/arch/powerpc/kernel/io-workarounds.c +++ b/arch/powerpc/kernel/io-workarounds.c @@ -153,10 +153,10 @@ static const struct ppc_pci_io iowa_pci_io = { #ifdef CONFIG_PPC_INDIRECT_MMIO static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size, - unsigned long flags, void *caller) + pgprot_t prot, void *caller) { struct iowa_bus *bus; - void __iomem *res = __ioremap_caller(addr, size, flags, caller); + void __iomem *res = __ioremap_caller(addr, size, prot, caller); int busno; bus = iowa_pci_find(0, (unsigned long)addr); diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 19b4c628f3be..f0dc680e659a 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -785,9 +785,9 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl, vaddr = page_address(page) + offset; uaddr = (unsigned long)vaddr; - npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl)); if (tbl) { + npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl)); align = 0; if (tbl->it_page_shift < PAGE_SHIFT && size >= PAGE_SIZE && ((unsigned long)vaddr & ~PAGE_MASK) == 0) diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 1df6c74aa731..fda3ae48480c 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -110,14 +110,14 @@ static void pci_process_ISA_OF_ranges(struct device_node *isa_node, size = 0x10000; __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, - size, pgprot_val(pgprot_noncached(__pgprot(0)))); + size, pgprot_noncached(PAGE_KERNEL)); return; inval_range: printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " "mapping 64k\n"); __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, - 0x10000, pgprot_val(pgprot_noncached(__pgprot(0)))); + 0x10000, pgprot_noncached(PAGE_KERNEL)); } @@ -253,7 +253,7 @@ void __init isa_bridge_init_non_pci(struct device_node *np) */ isa_io_base = ISA_IO_BASE; __ioremap_at(pbase, (void *)ISA_IO_BASE, - size, pgprot_val(pgprot_noncached(__pgprot(0)))); + size, pgprot_noncached(PAGE_KERNEL)); pr_debug("ISA: Non-PCI bridge is %pOF\n", np); } diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 35e240a0a408..59c578f865aa 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c @@ -24,6 +24,7 @@ #include <asm/processor.h> #include <asm/machdep.h> #include <asm/debug.h> +#include <asm/code-patching.h> #include <linux/slab.h> /* @@ -144,7 +145,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) return 0; - if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) + if (*(u32 *)regs->nip == BREAK_INSTR) regs->nip += BREAK_INSTR_SIZE; return 1; @@ -441,16 +442,42 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, return -1; } +int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) +{ + int err; + unsigned int instr; + unsigned int *addr = (unsigned int *)bpt->bpt_addr; + + err = probe_kernel_address(addr, instr); + if (err) + return err; + + err = patch_instruction(addr, BREAK_INSTR); + if (err) + return -EFAULT; + + *(unsigned int *)bpt->saved_instr = instr; + + return 0; +} + +int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) +{ + int err; + unsigned int instr = *(unsigned int *)bpt->saved_instr; + unsigned int *addr = (unsigned int *)bpt->bpt_addr; + + err = patch_instruction(addr, instr); + if (err) + return -EFAULT; + + return 0; +} + /* * Global data */ -struct kgdb_arch arch_kgdb_ops = { -#ifdef __LITTLE_ENDIAN__ - .gdb_bpt_instr = {0x08, 0x10, 0x82, 0x7d}, -#else - .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08}, -#endif -}; +struct kgdb_arch arch_kgdb_ops; static int kgdb_not_implemented(struct pt_regs *regs) { diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index efdd16a79075..bd933a75f0bc 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -488,10 +488,11 @@ long machine_check_early(struct pt_regs *regs) { long handled = 0; - __this_cpu_inc(irq_stat.mce_exceptions); - - if (cur_cpu_spec && cur_cpu_spec->machine_check_early) - handled = cur_cpu_spec->machine_check_early(regs); + /* + * See if platform is capable of handling machine check. + */ + if (ppc_md.machine_check_early) + handled = ppc_md.machine_check_early(regs); return handled; } diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 3497c8329c1d..6b800eec31f2 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -60,7 +60,7 @@ static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) /* flush SLBs and reload */ #ifdef CONFIG_PPC_BOOK3S_64 -static void flush_and_reload_slb(void) +void flush_and_reload_slb(void) { /* Invalidate all SLBs */ slb_flush_all_realmode(); @@ -89,6 +89,13 @@ static void flush_and_reload_slb(void) static void flush_erat(void) { +#ifdef CONFIG_PPC_BOOK3S_64 + if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { + flush_and_reload_slb(); + return; + } +#endif + /* PPC_INVALIDATE_ERAT can only be used on ISA v3 and newer */ asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); } diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 77371c9ef3d8..2d861a36662e 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c @@ -74,6 +74,14 @@ int module_finalize(const Elf_Ehdr *hdr, (void *)sect->sh_addr + sect->sh_size); #endif /* CONFIG_PPC64 */ +#ifdef PPC64_ELF_ABI_v1 + sect = find_section(hdr, sechdrs, ".opd"); + if (sect != NULL) { + me->arch.start_opd = sect->sh_addr; + me->arch.end_opd = sect->sh_addr + sect->sh_size; + } +#endif /* PPC64_ELF_ABI_v1 */ + #ifdef CONFIG_PPC_BARRIER_NOSPEC sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); if (sect != NULL) diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index b8d61e019d06..8661eea78503 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -360,11 +360,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr, else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) dedotify_versions((void *)hdr + sechdrs[i].sh_offset, sechdrs[i].sh_size); - else if (!strcmp(secstrings + sechdrs[i].sh_name, ".opd")) { - me->arch.start_opd = sechdrs[i].sh_addr; - me->arch.end_opd = sechdrs[i].sh_addr + - sechdrs[i].sh_size; - } /* We don't handle .init for the moment: rename to _init */ while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) @@ -685,7 +680,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, case R_PPC64_REL32: /* 32 bits relative (used by relative exception tables) */ - *(u32 *)location = value - (unsigned long)location; + /* Convert value to relative */ + value -= (unsigned long)location; + if (value + 0x80000000 > 0xffffffff) { + pr_err("%s: REL32 %li out of range!\n", + me->name, (long int)value); + return -ENOEXEC; + } + *(u32 *)location = value; break; case R_PPC64_TOCSAVE: diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d63b488d34d7..4da8ed576229 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -17,7 +17,6 @@ #include <linux/of.h> #include <linux/slab.h> #include <linux/export.h> -#include <linux/syscalls.h> #include <asm/processor.h> #include <asm/io.h> diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index dff28f903512..9d8c10d55407 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -159,7 +159,7 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose) /* Establish the mapping */ if (__ioremap_at(phys_page, area->addr, size_page, - pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL) + pgprot_noncached(PAGE_KERNEL)) == NULL) return -ENOMEM; /* Fixup hose IO resource */ diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index bb6ac471a784..4d5322cfad25 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -43,6 +43,7 @@ #include <linux/uaccess.h> #include <linux/elf-randomize.h> #include <linux/pkeys.h> +#include <linux/seq_buf.h> #include <asm/pgtable.h> #include <asm/io.h> @@ -65,6 +66,7 @@ #include <asm/livepatch.h> #include <asm/cpu_has_feature.h> #include <asm/asm-prototypes.h> +#include <asm/stacktrace.h> #include <linux/kprobes.h> #include <linux/kdebug.h> @@ -102,24 +104,18 @@ static void check_if_tm_restore_required(struct task_struct *tsk) } } -static inline bool msr_tm_active(unsigned long msr) -{ - return MSR_TM_ACTIVE(msr); -} - static bool tm_active_with_fp(struct task_struct *tsk) { - return msr_tm_active(tsk->thread.regs->msr) && + return MSR_TM_ACTIVE(tsk->thread.regs->msr) && (tsk->thread.ckpt_regs.msr & MSR_FP); } static bool tm_active_with_altivec(struct task_struct *tsk) { - return msr_tm_active(tsk->thread.regs->msr) && + return MSR_TM_ACTIVE(tsk->thread.regs->msr) && (tsk->thread.ckpt_regs.msr & MSR_VEC); } #else -static inline bool msr_tm_active(unsigned long msr) { return false; } static inline void check_if_tm_restore_required(struct task_struct *tsk) { } static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; } static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; } @@ -247,7 +243,8 @@ void enable_kernel_fp(void) * giveup as this would save to the 'live' structure not the * checkpointed structure. */ - if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + if (!MSR_TM_ACTIVE(cpumsr) && + MSR_TM_ACTIVE(current->thread.regs->msr)) return; __giveup_fpu(current); } @@ -311,7 +308,8 @@ void enable_kernel_altivec(void) * giveup as this would save to the 'live' structure not the * checkpointed structure. */ - if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + if (!MSR_TM_ACTIVE(cpumsr) && + MSR_TM_ACTIVE(current->thread.regs->msr)) return; __giveup_altivec(current); } @@ -397,7 +395,8 @@ void enable_kernel_vsx(void) * giveup as this would save to the 'live' structure not the * checkpointed structure. */ - if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) + if (!MSR_TM_ACTIVE(cpumsr) && + MSR_TM_ACTIVE(current->thread.regs->msr)) return; __giveup_vsx(current); } @@ -530,7 +529,7 @@ void restore_math(struct pt_regs *regs) { unsigned long msr; - if (!msr_tm_active(regs->msr) && + if (!MSR_TM_ACTIVE(regs->msr) && !current->thread.load_fp && !loadvec(current->thread)) return; @@ -620,8 +619,6 @@ void do_send_trap(struct pt_regs *regs, unsigned long address, void do_break (struct pt_regs *regs, unsigned long address, unsigned long error_code) { - siginfo_t info; - current->thread.trap_nr = TRAP_HWBKPT; if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, 11, SIGSEGV) == NOTIFY_STOP) @@ -634,12 +631,7 @@ void do_break (struct pt_regs *regs, unsigned long address, hw_breakpoint_disable(); /* Deliver the signal to userspace */ - clear_siginfo(&info); - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_HWBKPT; - info.si_addr = (void __user *)address; - force_sig_info(SIGTRAP, &info, current); + force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)address, current); } #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ @@ -1259,17 +1251,16 @@ struct task_struct *__switch_to(struct task_struct *prev, return last; } -static int instructions_to_print = 16; +#define NR_INSN_TO_PRINT 16 static void show_instructions(struct pt_regs *regs) { int i; - unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 * - sizeof(int)); + unsigned long pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); printk("Instruction dump:"); - for (i = 0; i < instructions_to_print; i++) { + for (i = 0; i < NR_INSN_TO_PRINT; i++) { int instr; if (!(i % 8)) @@ -1284,7 +1275,7 @@ static void show_instructions(struct pt_regs *regs) #endif if (!__kernel_text_address(pc) || - probe_kernel_address((unsigned int __user *)pc, instr)) { + probe_kernel_address((const void *)pc, instr)) { pr_cont("XXXXXXXX "); } else { if (regs->nip == pc) @@ -1302,43 +1293,43 @@ static void show_instructions(struct pt_regs *regs) void show_user_instructions(struct pt_regs *regs) { unsigned long pc; - int i; + int n = NR_INSN_TO_PRINT; + struct seq_buf s; + char buf[96]; /* enough for 8 times 9 + 2 chars */ - pc = regs->nip - (instructions_to_print * 3 / 4 * sizeof(int)); + pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); /* * Make sure the NIP points at userspace, not kernel text/data or * elsewhere. */ - if (!__access_ok(pc, instructions_to_print * sizeof(int), USER_DS)) { + if (!__access_ok(pc, NR_INSN_TO_PRINT * sizeof(int), USER_DS)) { pr_info("%s[%d]: Bad NIP, not dumping instructions.\n", current->comm, current->pid); return; } - pr_info("%s[%d]: code: ", current->comm, current->pid); + seq_buf_init(&s, buf, sizeof(buf)); - for (i = 0; i < instructions_to_print; i++) { - int instr; + while (n) { + int i; - if (!(i % 8) && (i > 0)) { - pr_cont("\n"); - pr_info("%s[%d]: code: ", current->comm, current->pid); - } + seq_buf_clear(&s); - if (probe_kernel_address((unsigned int __user *)pc, instr)) { - pr_cont("XXXXXXXX "); - } else { - if (regs->nip == pc) - pr_cont("<%08x> ", instr); - else - pr_cont("%08x ", instr); + for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) { + int instr; + + if (probe_kernel_address((const void *)pc, instr)) { + seq_buf_printf(&s, "XXXXXXXX "); + continue; + } + seq_buf_printf(&s, regs->nip == pc ? "<%08x> " : "%08x ", instr); } - pc += sizeof(int); + if (!seq_buf_has_overflowed(&s)) + pr_info("%s[%d]: code: %s\n", current->comm, + current->pid, s.buffer); } - - pr_cont("\n"); } struct regbit { @@ -1492,6 +1483,15 @@ void flush_thread(void) #endif /* CONFIG_HAVE_HW_BREAKPOINT */ } +#ifdef CONFIG_PPC_BOOK3S_64 +void arch_setup_new_exec(void) +{ + if (radix_enabled()) + return; + hash__setup_new_exec(); +} +#endif + int set_thread_uses_vas(void) { #ifdef CONFIG_PPC_BOOK3S_64 @@ -1712,7 +1712,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.dscr = mfspr(SPRN_DSCR); } if (cpu_has_feature(CPU_FTR_HAS_PPR)) - p->thread.ppr = INIT_PPR; + childregs->ppr = DEFAULT_PPR; p->thread.tidr = 0; #endif @@ -1720,6 +1720,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } +void preload_new_slb_context(unsigned long start, unsigned long sp); + /* * Set up a thread for executing a new program */ @@ -1727,6 +1729,10 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) { #ifdef CONFIG_PPC64 unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */ + +#ifdef CONFIG_PPC_BOOK3S_64 + preload_new_slb_context(start, sp); +#endif #endif /* @@ -1817,6 +1823,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) #ifdef CONFIG_VSX current->thread.used_vsr = 0; #endif + current->thread.load_slb = 0; current->thread.load_fp = 0; memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); current->thread.fp_save_area = NULL; diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 9b38a2e5dd35..f33ff4163a51 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -43,11 +43,13 @@ #include <asm/btext.h> #include <asm/sections.h> #include <asm/machdep.h> -#include <asm/opal.h> #include <asm/asm-prototypes.h> #include <linux/linux_logo.h> +/* All of prom_init bss lives here */ +#define __prombss __section(.bss.prominit) + /* * Eventually bump that one up */ @@ -87,7 +89,7 @@ #define OF_WORKAROUNDS 0 #else #define OF_WORKAROUNDS of_workarounds -int of_workarounds; +static int of_workarounds __prombss; #endif #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ @@ -148,29 +150,31 @@ extern void copy_and_flush(unsigned long dest, unsigned long src, unsigned long size, unsigned long offset); /* prom structure */ -static struct prom_t __initdata prom; +static struct prom_t __prombss prom; -static unsigned long prom_entry __initdata; +static unsigned long __prombss prom_entry; #define PROM_SCRATCH_SIZE 256 -static char __initdata of_stdout_device[256]; -static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; +static char __prombss of_stdout_device[256]; +static char __prombss prom_scratch[PROM_SCRATCH_SIZE]; -static unsigned long __initdata dt_header_start; -static unsigned long __initdata dt_struct_start, dt_struct_end; -static unsigned long __initdata dt_string_start, dt_string_end; +static unsigned long __prombss dt_header_start; +static unsigned long __prombss dt_struct_start, dt_struct_end; +static unsigned long __prombss dt_string_start, dt_string_end; -static unsigned long __initdata prom_initrd_start, prom_initrd_end; +static unsigned long __prombss prom_initrd_start, prom_initrd_end; #ifdef CONFIG_PPC64 -static int __initdata prom_iommu_force_on; -static int __initdata prom_iommu_off; -static unsigned long __initdata prom_tce_alloc_start; -static unsigned long __initdata prom_tce_alloc_end; +static int __prombss prom_iommu_force_on; +static int __prombss prom_iommu_off; +static unsigned long __prombss prom_tce_alloc_start; +static unsigned long __prombss prom_tce_alloc_end; #endif -static bool prom_radix_disable __initdata = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); +#ifdef CONFIG_PPC_PSERIES +static bool __prombss prom_radix_disable; +#endif struct platform_support { bool hash_mmu; @@ -188,26 +192,25 @@ struct platform_support { #define PLATFORM_LPAR 0x0001 #define PLATFORM_POWERMAC 0x0400 #define PLATFORM_GENERIC 0x0500 -#define PLATFORM_OPAL 0x0600 -static int __initdata of_platform; +static int __prombss of_platform; -static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; +static char __prombss prom_cmd_line[COMMAND_LINE_SIZE]; -static unsigned long __initdata prom_memory_limit; +static unsigned long __prombss prom_memory_limit; -static unsigned long __initdata alloc_top; -static unsigned long __initdata alloc_top_high; -static unsigned long __initdata alloc_bottom; -static unsigned long __initdata rmo_top; -static unsigned long __initdata ram_top; +static unsigned long __prombss alloc_top; +static unsigned long __prombss alloc_top_high; +static unsigned long __prombss alloc_bottom; +static unsigned long __prombss rmo_top; +static unsigned long __prombss ram_top; -static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; -static int __initdata mem_reserve_cnt; +static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE]; +static int __prombss mem_reserve_cnt; -static cell_t __initdata regbuf[1024]; +static cell_t __prombss regbuf[1024]; -static bool rtas_has_query_cpu_stopped; +static bool __prombss rtas_has_query_cpu_stopped; /* @@ -522,8 +525,8 @@ static void add_string(char **str, const char *q) static char *tohex(unsigned int x) { - static char digits[] = "0123456789abcdef"; - static char result[9]; + static const char digits[] __initconst = "0123456789abcdef"; + static char result[9] __prombss; int i; result[8] = 0; @@ -664,6 +667,8 @@ static void __init early_cmdline_parse(void) #endif } +#ifdef CONFIG_PPC_PSERIES + prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); opt = strstr(prom_cmd_line, "disable_radix"); if (opt) { opt += 13; @@ -679,9 +684,10 @@ static void __init early_cmdline_parse(void) } if (prom_radix_disable) prom_debug("Radix disabled from cmdline\n"); +#endif /* CONFIG_PPC_PSERIES */ } -#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) +#ifdef CONFIG_PPC_PSERIES /* * The architecture vector has an array of PVR mask/value pairs, * followed by # option vectors - 1, followed by the option vectors. @@ -782,7 +788,7 @@ struct ibm_arch_vec { struct option_vector6 vec6; } __packed; -struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { +static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = { .pvrs = { { .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */ @@ -920,9 +926,11 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { }, }; +static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned; + /* Old method - ELF header with PT_NOTE sections only works on BE */ #ifdef __BIG_ENDIAN__ -static struct fake_elf { +static const struct fake_elf { Elf32_Ehdr elfhdr; Elf32_Phdr phdr[2]; struct chrpnote { @@ -955,7 +963,7 @@ static struct fake_elf { u32 ignore_me; } rpadesc; } rpanote; -} fake_elf = { +} fake_elf __initconst = { .elfhdr = { .e_ident = { 0x7f, 'E', 'L', 'F', ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, @@ -1129,14 +1137,21 @@ static void __init prom_check_platform_support(void) }; int prop_len = prom_getproplen(prom.chosen, "ibm,arch-vec-5-platform-support"); + + /* First copy the architecture vec template */ + ibm_architecture_vec = ibm_architecture_vec_template; + if (prop_len > 1) { int i; - u8 vec[prop_len]; + u8 vec[8]; prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", prop_len); + if (prop_len > sizeof(vec)) + prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n", + prop_len); prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", &vec, sizeof(vec)); - for (i = 0; i < prop_len; i += 2) { + for (i = 0; i < sizeof(vec); i += 2) { prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 , vec[i] , vec[i + 1]); @@ -1225,7 +1240,7 @@ static void __init prom_send_capabilities(void) } #endif /* __BIG_ENDIAN__ */ } -#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ +#endif /* CONFIG_PPC_PSERIES */ /* * Memory allocation strategy... our layout is normally: @@ -1562,88 +1577,6 @@ static void __init prom_close_stdin(void) } } -#ifdef CONFIG_PPC_POWERNV - -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL -static u64 __initdata prom_opal_base; -static u64 __initdata prom_opal_entry; -#endif - -/* - * Allocate room for and instantiate OPAL - */ -static void __init prom_instantiate_opal(void) -{ - phandle opal_node; - ihandle opal_inst; - u64 base, entry; - u64 size = 0, align = 0x10000; - __be64 val64; - u32 rets[2]; - - prom_debug("prom_instantiate_opal: start...\n"); - - opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal")); - prom_debug("opal_node: %x\n", opal_node); - if (!PHANDLE_VALID(opal_node)) - return; - - val64 = 0; - prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64)); - size = be64_to_cpu(val64); - if (size == 0) - return; - val64 = 0; - prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64)); - align = be64_to_cpu(val64); - - base = alloc_down(size, align, 0); - if (base == 0) { - prom_printf("OPAL allocation failed !\n"); - return; - } - - opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal")); - if (!IHANDLE_VALID(opal_inst)) { - prom_printf("opening opal package failed (%x)\n", opal_inst); - return; - } - - prom_printf("instantiating opal at 0x%llx...", base); - - if (call_prom_ret("call-method", 4, 3, rets, - ADDR("load-opal-runtime"), - opal_inst, - base >> 32, base & 0xffffffff) != 0 - || (rets[0] == 0 && rets[1] == 0)) { - prom_printf(" failed\n"); - return; - } - entry = (((u64)rets[0]) << 32) | rets[1]; - - prom_printf(" done\n"); - - reserve_mem(base, size); - - prom_debug("opal base = 0x%llx\n", base); - prom_debug("opal align = 0x%llx\n", align); - prom_debug("opal entry = 0x%llx\n", entry); - prom_debug("opal size = 0x%llx\n", size); - - prom_setprop(opal_node, "/ibm,opal", "opal-base-address", - &base, sizeof(base)); - prom_setprop(opal_node, "/ibm,opal", "opal-entry-address", - &entry, sizeof(entry)); - -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL - prom_opal_base = base; - prom_opal_entry = entry; -#endif - prom_debug("prom_instantiate_opal: end...\n"); -} - -#endif /* CONFIG_PPC_POWERNV */ - /* * Allocate room for and instantiate RTAS */ @@ -2150,10 +2083,6 @@ static int __init prom_find_machine_type(void) } } #ifdef CONFIG_PPC64 - /* Try to detect OPAL */ - if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal")))) - return PLATFORM_OPAL; - /* Try to figure out if it's an IBM pSeries or any other * PAPR compliant platform. We assume it is if : * - /device_type is "chrp" (please, do NOT use that for future @@ -2202,7 +2131,7 @@ static void __init prom_check_displays(void) ihandle ih; int i; - static unsigned char default_colors[] = { + static const unsigned char default_colors[] __initconst = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0x00, @@ -2398,7 +2327,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; unsigned long soff; unsigned char *valp; - static char pname[MAX_PROPERTY_NAME]; + static char pname[MAX_PROPERTY_NAME] __prombss; int l, room, has_phandle = 0; dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); @@ -2481,14 +2410,11 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, has_phandle = 1; } - /* Add a "linux,phandle" property if no "phandle" property already - * existed (can happen with OPAL) - */ + /* Add a "phandle" property if none already exist */ if (!has_phandle) { - soff = dt_find_string("linux,phandle"); + soff = dt_find_string("phandle"); if (soff == 0) - prom_printf("WARNING: Can't find string index for" - " <linux-phandle> node %s\n", path); + prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path); else { dt_push_token(OF_DT_PROP, mem_start, mem_end); dt_push_token(4, mem_start, mem_end); @@ -2548,9 +2474,9 @@ static void __init flatten_device_tree(void) dt_string_start = mem_start; mem_start += 4; /* hole */ - /* Add "linux,phandle" in there, we'll need it */ + /* Add "phandle" in there, we'll need it */ namep = make_room(&mem_start, &mem_end, 16, 1); - strcpy(namep, "linux,phandle"); + strcpy(namep, "phandle"); mem_start = (unsigned long)namep + strlen(namep) + 1; /* Build string array */ @@ -3172,7 +3098,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, */ early_cmdline_parse(); -#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) +#ifdef CONFIG_PPC_PSERIES /* * On pSeries, inform the firmware about our capabilities */ @@ -3216,15 +3142,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * On non-powermacs, try to instantiate RTAS. PowerMacs don't * have a usable RTAS implementation. */ - if (of_platform != PLATFORM_POWERMAC && - of_platform != PLATFORM_OPAL) + if (of_platform != PLATFORM_POWERMAC) prom_instantiate_rtas(); -#ifdef CONFIG_PPC_POWERNV - if (of_platform == PLATFORM_OPAL) - prom_instantiate_opal(); -#endif /* CONFIG_PPC_POWERNV */ - #ifdef CONFIG_PPC64 /* instantiate sml */ prom_instantiate_sml(); @@ -3237,8 +3157,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * * (This must be done after instanciating RTAS) */ - if (of_platform != PLATFORM_POWERMAC && - of_platform != PLATFORM_OPAL) + if (of_platform != PLATFORM_POWERMAC) prom_hold_cpus(); /* @@ -3282,11 +3201,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, /* * in case stdin is USB and still active on IBM machines... * Unfortunately quiesce crashes on some powermacs if we have - * closed stdin already (in particular the powerbook 101). It - * appears that the OPAL version of OFW doesn't like it either. + * closed stdin already (in particular the powerbook 101). */ - if (of_platform != PLATFORM_POWERMAC && - of_platform != PLATFORM_OPAL) + if (of_platform != PLATFORM_POWERMAC) prom_close_stdin(); /* @@ -3304,10 +3221,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, hdr = dt_header_start; /* Don't print anything after quiesce under OPAL, it crashes OFW */ - if (of_platform != PLATFORM_OPAL) { - prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); - prom_debug("->dt_header_start=0x%lx\n", hdr); - } + prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); + prom_debug("->dt_header_start=0x%lx\n", hdr); #ifdef CONFIG_PPC32 reloc_got2(-offset); @@ -3315,13 +3230,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unreloc_toc(); #endif -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL - /* OPAL early debug gets the OPAL base & entry in r8 and r9 */ - __start(hdr, kbase, 0, 0, 0, - prom_opal_base, prom_opal_entry); -#else __start(hdr, kbase, 0, 0, 0, 0, 0); -#endif return 0; } diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index acb6b9226352..667df97d2595 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh @@ -28,6 +28,18 @@ OBJ="$2" ERROR=0 +function check_section() +{ + file=$1 + section=$2 + size=$(objdump -h -j $section $file 2>/dev/null | awk "\$2 == \"$section\" {print \$3}") + size=${size:-0} + if [ $size -ne 0 ]; then + ERROR=1 + echo "Error: Section $section not empty in prom_init.c" >&2 + fi +} + for UNDEF in $($NM -u $OBJ | awk '{print $2}') do # On 64-bit nm gives us the function descriptors, which have @@ -66,4 +78,8 @@ do fi done +check_section $OBJ .data +check_section $OBJ .bss +check_section $OBJ .init.data + exit $ERROR diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 9667666eb18e..afb819f4ca68 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -297,7 +297,7 @@ int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data) } #endif - if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { + if (regno < (sizeof(struct user_pt_regs) / sizeof(unsigned long))) { *data = ((unsigned long *)task->thread.regs)[regno]; return 0; } @@ -360,10 +360,10 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.regs->orig_gpr3, offsetof(struct pt_regs, orig_gpr3), - sizeof(struct pt_regs)); + sizeof(struct user_pt_regs)); if (!ret) ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - sizeof(struct pt_regs), -1); + sizeof(struct user_pt_regs), -1); return ret; } @@ -853,10 +853,10 @@ static int tm_cgpr_get(struct task_struct *target, ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.ckpt_regs.orig_gpr3, offsetof(struct pt_regs, orig_gpr3), - sizeof(struct pt_regs)); + sizeof(struct user_pt_regs)); if (!ret) ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - sizeof(struct pt_regs), -1); + sizeof(struct user_pt_regs), -1); return ret; } @@ -1609,7 +1609,7 @@ static int ppr_get(struct task_struct *target, void *kbuf, void __user *ubuf) { return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.ppr, 0, sizeof(u64)); + &target->thread.regs->ppr, 0, sizeof(u64)); } static int ppr_set(struct task_struct *target, @@ -1618,7 +1618,7 @@ static int ppr_set(struct task_struct *target, const void *kbuf, const void __user *ubuf) { return user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &target->thread.ppr, 0, sizeof(u64)); + &target->thread.regs->ppr, 0, sizeof(u64)); } static int dscr_get(struct task_struct *target, @@ -2508,6 +2508,7 @@ void ptrace_disable(struct task_struct *child) { /* make sure the single step bit is not set. */ user_disable_single_step(child); + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); } #ifdef CONFIG_PPC_ADV_DEBUG_REGS @@ -3130,7 +3131,7 @@ long arch_ptrace(struct task_struct *child, long request, case PTRACE_GETREGS: /* Get all pt_regs from the child. */ return copy_regset_to_user(child, &user_ppc_native_view, REGSET_GPR, - 0, sizeof(struct pt_regs), + 0, sizeof(struct user_pt_regs), datavp); #ifdef CONFIG_PPC64 @@ -3139,7 +3140,7 @@ long arch_ptrace(struct task_struct *child, long request, case PTRACE_SETREGS: /* Set all gp regs in the child. */ return copy_regset_from_user(child, &user_ppc_native_view, REGSET_GPR, - 0, sizeof(struct pt_regs), + 0, sizeof(struct user_pt_regs), datavp); case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ @@ -3264,6 +3265,16 @@ long do_syscall_trace_enter(struct pt_regs *regs) { user_exit(); + if (test_thread_flag(TIF_SYSCALL_EMU)) { + ptrace_report_syscall(regs); + /* + * Returning -1 will skip the syscall execution. We want to + * avoid clobbering any register also, thus, not 'gotoing' + * skip label. + */ + return -1; + } + /* * The tracer may decide to abort the syscall, if so tracehook * will return !0. Note that the tracer may also just change @@ -3324,3 +3335,42 @@ void do_syscall_trace_leave(struct pt_regs *regs) user_enter(); } + +void __init pt_regs_check(void) +{ + BUILD_BUG_ON(offsetof(struct pt_regs, gpr) != + offsetof(struct user_pt_regs, gpr)); + BUILD_BUG_ON(offsetof(struct pt_regs, nip) != + offsetof(struct user_pt_regs, nip)); + BUILD_BUG_ON(offsetof(struct pt_regs, msr) != + offsetof(struct user_pt_regs, msr)); + BUILD_BUG_ON(offsetof(struct pt_regs, msr) != + offsetof(struct user_pt_regs, msr)); + BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != + offsetof(struct user_pt_regs, orig_gpr3)); + BUILD_BUG_ON(offsetof(struct pt_regs, ctr) != + offsetof(struct user_pt_regs, ctr)); + BUILD_BUG_ON(offsetof(struct pt_regs, link) != + offsetof(struct user_pt_regs, link)); + BUILD_BUG_ON(offsetof(struct pt_regs, xer) != + offsetof(struct user_pt_regs, xer)); + BUILD_BUG_ON(offsetof(struct pt_regs, ccr) != + offsetof(struct user_pt_regs, ccr)); +#ifdef __powerpc64__ + BUILD_BUG_ON(offsetof(struct pt_regs, softe) != + offsetof(struct user_pt_regs, softe)); +#else + BUILD_BUG_ON(offsetof(struct pt_regs, mq) != + offsetof(struct user_pt_regs, mq)); +#endif + BUILD_BUG_ON(offsetof(struct pt_regs, trap) != + offsetof(struct user_pt_regs, trap)); + BUILD_BUG_ON(offsetof(struct pt_regs, dar) != + offsetof(struct user_pt_regs, dar)); + BUILD_BUG_ON(offsetof(struct pt_regs, dsisr) != + offsetof(struct user_pt_regs, dsisr)); + BUILD_BUG_ON(offsetof(struct pt_regs, result) != + offsetof(struct user_pt_regs, result)); + + BUILD_BUG_ON(sizeof(struct user_pt_regs) > sizeof(struct pt_regs)); +} diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8afd146bc9c7..de35bd8f047f 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -981,7 +981,15 @@ int rtas_ibm_suspend_me(u64 handle) goto out; } - stop_topology_update(); + cpu_hotplug_disable(); + + /* Check if we raced with a CPU-Offline Operation */ + if (unlikely(!cpumask_equal(cpu_present_mask, cpu_online_mask))) { + pr_err("%s: Raced against a concurrent CPU-Offline\n", + __func__); + atomic_set(&data.error, -EBUSY); + goto out_hotplug_enable; + } /* Call function on all CPUs. One of us will make the * rtas call @@ -994,7 +1002,8 @@ int rtas_ibm_suspend_me(u64 handle) if (atomic_read(&data.error) != 0) printk(KERN_ERR "Error doing global join\n"); - start_topology_update(); +out_hotplug_enable: + cpu_hotplug_enable(); /* Take down CPUs not online prior to suspend */ cpuret = rtas_offline_cpus_mask(offline_mask); diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..38cadae4ca4f 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -91,6 +91,8 @@ static char *rtas_event_type(int type) return "Dump Notification Event"; case RTAS_TYPE_PRRN: return "Platform Resource Reassignment Event"; + case RTAS_TYPE_HOTPLUG: + return "Hotplug Event"; } return rtas_type[0]; @@ -150,8 +152,10 @@ static void printk_log_rtas(char *buf, int len) } else { struct rtas_error_log *errlog = (struct rtas_error_log *)buf; - printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", - error_log_cnt, rtas_event_type(rtas_error_type(errlog)), + printk(RTAS_DEBUG "event: %d, Type: %s (%d), Severity: %d\n", + error_log_cnt, + rtas_event_type(rtas_error_type(errlog)), + rtas_error_type(errlog), rtas_error_severity(errlog)); } } @@ -274,27 +278,16 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) } #ifdef CONFIG_PPC_PSERIES -static s32 prrn_update_scope; - -static void prrn_work_fn(struct work_struct *work) +static void handle_prrn_event(s32 scope) { /* * For PRRN, we must pass the negative of the scope value in * the RTAS event. */ - pseries_devicetree_update(-prrn_update_scope); + pseries_devicetree_update(-scope); numa_update_cpu_topology(false); } -static DECLARE_WORK(prrn_work, prrn_work_fn); - -static void prrn_schedule_update(u32 scope) -{ - flush_work(&prrn_work); - prrn_update_scope = scope; - schedule_work(&prrn_work); -} - static void handle_rtas_event(const struct rtas_error_log *log) { if (rtas_error_type(log) != RTAS_TYPE_PRRN || !prrn_is_enabled()) @@ -303,7 +296,7 @@ static void handle_rtas_event(const struct rtas_error_log *log) /* For PRRN Events the extended log length is used to denote * the scope for calling rtas update-nodes. */ - prrn_schedule_update(rtas_error_extended_log_length(log)); + handle_prrn_event(rtas_error_extended_log_length(log)); } #else diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 93fa0c99681e..9ca9db707bcb 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -33,6 +33,7 @@ #include <linux/serial_8250.h> #include <linux/percpu.h> #include <linux/memblock.h> +#include <linux/bootmem.h> #include <linux/of_platform.h> #include <linux/hugetlb.h> #include <asm/debugfs.h> @@ -966,6 +967,8 @@ void __init setup_arch(char **cmdline_p) initmem_init(); + early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); + #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6a501b25dd85..faf00222b324 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -243,13 +243,19 @@ static void cpu_ready_for_interrupts(void) } /* - * Fixup HFSCR:TM based on CPU features. The bit is set by our - * early asm init because at that point we haven't updated our - * CPU features from firmware and device-tree. Here we have, - * so let's do it. + * Set HFSCR:TM based on CPU features: + * In the special case of TM no suspend (P9N DD2.1), Linux is + * told TM is off via the dt-ftrs but told to (partially) use + * it via OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED. So HFSCR[TM] + * will be off from dt-ftrs but we need to turn it on for the + * no suspend case. */ - if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP)) - mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); + if (cpu_has_feature(CPU_FTR_HVMODE)) { + if (cpu_has_feature(CPU_FTR_TM_COMP)) + mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) | HFSCR_TM); + else + mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); + } /* Set IR and DR in PACA MSR */ get_paca()->kernel_msr = MSR_KERNEL; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 61c1fadbc644..3f15edf25a0d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -34,6 +34,8 @@ #include <linux/topology.h> #include <linux/profile.h> #include <linux/processor.h> +#include <linux/random.h> +#include <linux/stackprotector.h> #include <asm/ptrace.h> #include <linux/atomic.h> @@ -74,14 +76,32 @@ static DEFINE_PER_CPU(int, cpu_state) = { 0 }; #endif struct thread_info *secondary_ti; +bool has_big_cores; DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); +DEFINE_PER_CPU(cpumask_var_t, cpu_smallcore_map); DEFINE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); EXPORT_PER_CPU_SYMBOL(cpu_l2_cache_map); EXPORT_PER_CPU_SYMBOL(cpu_core_map); +EXPORT_SYMBOL_GPL(has_big_cores); + +#define MAX_THREAD_LIST_SIZE 8 +#define THREAD_GROUP_SHARE_L1 1 +struct thread_groups { + unsigned int property; + unsigned int nr_groups; + unsigned int threads_per_group; + unsigned int thread_list[MAX_THREAD_LIST_SIZE]; +}; + +/* + * On big-cores system, cpu_l1_cache_map for each CPU corresponds to + * the set its siblings that share the L1-cache. + */ +DEFINE_PER_CPU(cpumask_var_t, cpu_l1_cache_map); /* SMP operations for this machine */ struct smp_ops_t *smp_ops; @@ -674,6 +694,185 @@ static void set_cpus_unrelated(int i, int j, } #endif +/* + * parse_thread_groups: Parses the "ibm,thread-groups" device tree + * property for the CPU device node @dn and stores + * the parsed output in the thread_groups + * structure @tg if the ibm,thread-groups[0] + * matches @property. + * + * @dn: The device node of the CPU device. + * @tg: Pointer to a thread group structure into which the parsed + * output of "ibm,thread-groups" is stored. + * @property: The property of the thread-group that the caller is + * interested in. + * + * ibm,thread-groups[0..N-1] array defines which group of threads in + * the CPU-device node can be grouped together based on the property. + * + * ibm,thread-groups[0] tells us the property based on which the + * threads are being grouped together. If this value is 1, it implies + * that the threads in the same group share L1, translation cache. + * + * ibm,thread-groups[1] tells us how many such thread groups exist. + * + * ibm,thread-groups[2] tells us the number of threads in each such + * group. + * + * ibm,thread-groups[3..N-1] is the list of threads identified by + * "ibm,ppc-interrupt-server#s" arranged as per their membership in + * the grouping. + * + * Example: If ibm,thread-groups = [1,2,4,5,6,7,8,9,10,11,12] it + * implies that there are 2 groups of 4 threads each, where each group + * of threads share L1, translation cache. + * + * The "ibm,ppc-interrupt-server#s" of the first group is {5,6,7,8} + * and the "ibm,ppc-interrupt-server#s" of the second group is {9, 10, + * 11, 12} structure + * + * Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + */ +static int parse_thread_groups(struct device_node *dn, + struct thread_groups *tg, + unsigned int property) +{ + int i; + u32 thread_group_array[3 + MAX_THREAD_LIST_SIZE]; + u32 *thread_list; + size_t total_threads; + int ret; + + ret = of_property_read_u32_array(dn, "ibm,thread-groups", + thread_group_array, 3); + if (ret) + return ret; + + tg->property = thread_group_array[0]; + tg->nr_groups = thread_group_array[1]; + tg->threads_per_group = thread_group_array[2]; + if (tg->property != property || + tg->nr_groups < 1 || + tg->threads_per_group < 1) + return -ENODATA; + + total_threads = tg->nr_groups * tg->threads_per_group; + + ret = of_property_read_u32_array(dn, "ibm,thread-groups", + thread_group_array, + 3 + total_threads); + if (ret) + return ret; + + thread_list = &thread_group_array[3]; + + for (i = 0 ; i < total_threads; i++) + tg->thread_list[i] = thread_list[i]; + + return 0; +} + +/* + * get_cpu_thread_group_start : Searches the thread group in tg->thread_list + * that @cpu belongs to. + * + * @cpu : The logical CPU whose thread group is being searched. + * @tg : The thread-group structure of the CPU node which @cpu belongs + * to. + * + * Returns the index to tg->thread_list that points to the the start + * of the thread_group that @cpu belongs to. + * + * Returns -1 if cpu doesn't belong to any of the groups pointed to by + * tg->thread_list. + */ +static int get_cpu_thread_group_start(int cpu, struct thread_groups *tg) +{ + int hw_cpu_id = get_hard_smp_processor_id(cpu); + int i, j; + + for (i = 0; i < tg->nr_groups; i++) { + int group_start = i * tg->threads_per_group; + + for (j = 0; j < tg->threads_per_group; j++) { + int idx = group_start + j; + + if (tg->thread_list[idx] == hw_cpu_id) + return group_start; + } + } + + return -1; +} + +static int init_cpu_l1_cache_map(int cpu) + +{ + struct device_node *dn = of_get_cpu_node(cpu, NULL); + struct thread_groups tg = {.property = 0, + .nr_groups = 0, + .threads_per_group = 0}; + int first_thread = cpu_first_thread_sibling(cpu); + int i, cpu_group_start = -1, err = 0; + + if (!dn) + return -ENODATA; + + err = parse_thread_groups(dn, &tg, THREAD_GROUP_SHARE_L1); + if (err) + goto out; + + zalloc_cpumask_var_node(&per_cpu(cpu_l1_cache_map, cpu), + GFP_KERNEL, + cpu_to_node(cpu)); + + cpu_group_start = get_cpu_thread_group_start(cpu, &tg); + + if (unlikely(cpu_group_start == -1)) { + WARN_ON_ONCE(1); + err = -ENODATA; + goto out; + } + + for (i = first_thread; i < first_thread + threads_per_core; i++) { + int i_group_start = get_cpu_thread_group_start(i, &tg); + + if (unlikely(i_group_start == -1)) { + WARN_ON_ONCE(1); + err = -ENODATA; + goto out; + } + + if (i_group_start == cpu_group_start) + cpumask_set_cpu(i, per_cpu(cpu_l1_cache_map, cpu)); + } + +out: + of_node_put(dn); + return err; +} + +static int init_big_cores(void) +{ + int cpu; + + for_each_possible_cpu(cpu) { + int err = init_cpu_l1_cache_map(cpu); + + if (err) + return err; + + zalloc_cpumask_var_node(&per_cpu(cpu_smallcore_map, cpu), + GFP_KERNEL, + cpu_to_node(cpu)); + } + + has_big_cores = true; + return 0; +} + void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int cpu; @@ -712,6 +911,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus) cpumask_set_cpu(boot_cpuid, cpu_l2_cache_mask(boot_cpuid)); cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid)); + init_big_cores(); + if (has_big_cores) { + cpumask_set_cpu(boot_cpuid, + cpu_smallcore_mask(boot_cpuid)); + } + if (smp_ops && smp_ops->probe) smp_ops->probe(); } @@ -995,10 +1200,28 @@ static void remove_cpu_from_masks(int cpu) set_cpus_unrelated(cpu, i, cpu_core_mask); set_cpus_unrelated(cpu, i, cpu_l2_cache_mask); set_cpus_unrelated(cpu, i, cpu_sibling_mask); + if (has_big_cores) + set_cpus_unrelated(cpu, i, cpu_smallcore_mask); } } #endif +static inline void add_cpu_to_smallcore_masks(int cpu) +{ + struct cpumask *this_l1_cache_map = per_cpu(cpu_l1_cache_map, cpu); + int i, first_thread = cpu_first_thread_sibling(cpu); + + if (!has_big_cores) + return; + + cpumask_set_cpu(cpu, cpu_smallcore_mask(cpu)); + + for (i = first_thread; i < first_thread + threads_per_core; i++) { + if (cpu_online(i) && cpumask_test_cpu(i, this_l1_cache_map)) + set_cpus_related(i, cpu, cpu_smallcore_mask); + } +} + static void add_cpu_to_masks(int cpu) { int first_thread = cpu_first_thread_sibling(cpu); @@ -1015,6 +1238,7 @@ static void add_cpu_to_masks(int cpu) if (cpu_online(i)) set_cpus_related(i, cpu, cpu_sibling_mask); + add_cpu_to_smallcore_masks(cpu); /* * Copy the thread sibling mask into the cache sibling mask * and mark any CPUs that share an L2 with this CPU. @@ -1044,6 +1268,7 @@ static bool shared_caches; void start_secondary(void *unused) { unsigned int cpu = smp_processor_id(); + struct cpumask *(*sibling_mask)(int) = cpu_sibling_mask; mmgrab(&init_mm); current->active_mm = &init_mm; @@ -1069,11 +1294,13 @@ void start_secondary(void *unused) /* Update topology CPU masks */ add_cpu_to_masks(cpu); + if (has_big_cores) + sibling_mask = cpu_smallcore_mask; /* * Check for any shared caches. Note that this must be done on a * per-core basis because one core in the pair might be disabled. */ - if (!cpumask_equal(cpu_l2_cache_mask(cpu), cpu_sibling_mask(cpu))) + if (!cpumask_equal(cpu_l2_cache_mask(cpu), sibling_mask(cpu))) shared_caches = true; set_numa_node(numa_cpu_lookup_table[cpu]); @@ -1083,6 +1310,8 @@ void start_secondary(void *unused) notify_cpu_starting(cpu); set_cpu_online(cpu, true); + boot_init_stack_canary(); + local_irq_enable(); /* We can enable ftrace for secondary cpus now */ @@ -1140,6 +1369,13 @@ static const struct cpumask *shared_cache_mask(int cpu) return cpu_l2_cache_mask(cpu); } +#ifdef CONFIG_SCHED_SMT +static const struct cpumask *smallcore_smt_mask(int cpu) +{ + return cpu_smallcore_mask(cpu); +} +#endif + static struct sched_domain_topology_level power9_topology[] = { #ifdef CONFIG_SCHED_SMT { cpu_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT) }, @@ -1167,6 +1403,13 @@ void __init smp_cpus_done(unsigned int max_cpus) shared_proc_topology_init(); dump_numa_cpu_topology(); +#ifdef CONFIG_SCHED_SMT + if (has_big_cores) { + pr_info("Using small cores at SMT level\n"); + power9_topology[0].mask = smallcore_smt_mask; + powerpc_topology[0].mask = smallcore_smt_mask; + } +#endif /* * If any CPU detects that it's sharing a cache with another CPU then * use the deeper topology that is aware of this sharing. diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S index f83bf6f72cb0..185216becb8b 100644 --- a/arch/powerpc/kernel/swsusp_asm64.S +++ b/arch/powerpc/kernel/swsusp_asm64.S @@ -262,7 +262,7 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) addi r1,r1,-128 #ifdef CONFIG_PPC_BOOK3S_64 - bl slb_flush_and_rebolt + bl slb_flush_and_restore_bolted #endif bl do_after_copyback addi r1,r1,128 diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 70f145e02487..3646affae963 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -111,6 +111,7 @@ struct clock_event_device decrementer_clockevent = { .rating = 200, .irq = 0, .set_next_event = decrementer_set_next_event, + .set_state_oneshot_stopped = decrementer_shutdown, .set_state_shutdown = decrementer_shutdown, .tick_resume = decrementer_shutdown, .features = CLOCK_EVT_FEAT_ONESHOT | @@ -175,7 +176,7 @@ static void calc_cputime_factors(void) * Read the SPURR on systems that have it, otherwise the PURR, * or if that doesn't exist return the timebase value passed in. */ -static unsigned long read_spurr(unsigned long tb) +static inline unsigned long read_spurr(unsigned long tb) { if (cpu_has_feature(CPU_FTR_SPURR)) return mfspr(SPRN_SPURR); @@ -281,26 +282,17 @@ static inline u64 calculate_stolen_time(u64 stop_tb) * Account time for a transition between system, hard irq * or soft irq state. */ -static unsigned long vtime_delta(struct task_struct *tsk, - unsigned long *stime_scaled, - unsigned long *steal_time) +static unsigned long vtime_delta_scaled(struct cpu_accounting_data *acct, + unsigned long now, unsigned long stime) { - unsigned long now, nowscaled, deltascaled; - unsigned long stime; + unsigned long stime_scaled = 0; +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME + unsigned long nowscaled, deltascaled; unsigned long utime, utime_scaled; - struct cpu_accounting_data *acct = get_accounting(tsk); - WARN_ON_ONCE(!irqs_disabled()); - - now = mftb(); nowscaled = read_spurr(now); - stime = now - acct->starttime; - acct->starttime = now; deltascaled = nowscaled - acct->startspurr; acct->startspurr = nowscaled; - - *steal_time = calculate_stolen_time(now); - utime = acct->utime - acct->utime_sspurr; acct->utime_sspurr = acct->utime; @@ -314,17 +306,38 @@ static unsigned long vtime_delta(struct task_struct *tsk, * the user ticks get saved up in paca->user_time_scaled to be * used by account_process_tick. */ - *stime_scaled = stime; + stime_scaled = stime; utime_scaled = utime; if (deltascaled != stime + utime) { if (utime) { - *stime_scaled = deltascaled * stime / (stime + utime); - utime_scaled = deltascaled - *stime_scaled; + stime_scaled = deltascaled * stime / (stime + utime); + utime_scaled = deltascaled - stime_scaled; } else { - *stime_scaled = deltascaled; + stime_scaled = deltascaled; } } acct->utime_scaled += utime_scaled; +#endif + + return stime_scaled; +} + +static unsigned long vtime_delta(struct task_struct *tsk, + unsigned long *stime_scaled, + unsigned long *steal_time) +{ + unsigned long now, stime; + struct cpu_accounting_data *acct = get_accounting(tsk); + + WARN_ON_ONCE(!irqs_disabled()); + + now = mftb(); + stime = now - acct->starttime; + acct->starttime = now; + + *stime_scaled = vtime_delta_scaled(acct, now, stime); + + *steal_time = calculate_stolen_time(now); return stime; } @@ -341,7 +354,9 @@ void vtime_account_system(struct task_struct *tsk) if ((tsk->flags & PF_VCPU) && !irq_count()) { acct->gtime += stime; +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME acct->utime_scaled += stime_scaled; +#endif } else { if (hardirq_count()) acct->hardirq_time += stime; @@ -350,7 +365,9 @@ void vtime_account_system(struct task_struct *tsk) else acct->stime += stime; +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME acct->stime_scaled += stime_scaled; +#endif } } EXPORT_SYMBOL_GPL(vtime_account_system); @@ -364,6 +381,21 @@ void vtime_account_idle(struct task_struct *tsk) acct->idle_time += stime + steal_time; } +static void vtime_flush_scaled(struct task_struct *tsk, + struct cpu_accounting_data *acct) +{ +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME + if (acct->utime_scaled) + tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled); + if (acct->stime_scaled) + tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled); + + acct->utime_scaled = 0; + acct->utime_sspurr = 0; + acct->stime_scaled = 0; +#endif +} + /* * Account the whole cputime accumulated in the paca * Must be called with interrupts disabled. @@ -378,14 +410,13 @@ void vtime_flush(struct task_struct *tsk) if (acct->utime) account_user_time(tsk, cputime_to_nsecs(acct->utime)); - if (acct->utime_scaled) - tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled); - if (acct->gtime) account_guest_time(tsk, cputime_to_nsecs(acct->gtime)); - if (acct->steal_time) + if (IS_ENABLED(CONFIG_PPC_SPLPAR) && acct->steal_time) { account_steal_time(cputime_to_nsecs(acct->steal_time)); + acct->steal_time = 0; + } if (acct->idle_time) account_idle_time(cputime_to_nsecs(acct->idle_time)); @@ -393,8 +424,6 @@ void vtime_flush(struct task_struct *tsk) if (acct->stime) account_system_index_time(tsk, cputime_to_nsecs(acct->stime), CPUTIME_SYSTEM); - if (acct->stime_scaled) - tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled); if (acct->hardirq_time) account_system_index_time(tsk, cputime_to_nsecs(acct->hardirq_time), @@ -403,14 +432,12 @@ void vtime_flush(struct task_struct *tsk) account_system_index_time(tsk, cputime_to_nsecs(acct->softirq_time), CPUTIME_SOFTIRQ); + vtime_flush_scaled(tsk, acct); + acct->utime = 0; - acct->utime_scaled = 0; - acct->utime_sspurr = 0; acct->gtime = 0; - acct->steal_time = 0; acct->idle_time = 0; acct->stime = 0; - acct->stime_scaled = 0; acct->hardirq_time = 0; acct->softirq_time = 0; } @@ -984,10 +1011,14 @@ static void register_decrementer_clockevent(int cpu) *dec = decrementer_clockevent; dec->cpumask = cpumask_of(cpu); + clockevents_config_and_register(dec, ppc_tb_freq, 2, decrementer_max); + printk_once(KERN_DEBUG "clockevent: %s mult[%x] shift[%d] cpu[%d]\n", dec->name, dec->mult, dec->shift, cpu); - clockevents_register_device(dec); + /* Set values for KVM, see kvm_emulate_dec() */ + decrementer_clockevent.mult = dec->mult; + decrementer_clockevent.shift = dec->shift; } static void enable_large_decrementer(void) @@ -1035,18 +1066,7 @@ static void __init set_decrementer_max(void) static void __init init_decrementer_clockevent(void) { - int cpu = smp_processor_id(); - - clockevents_calc_mult_shift(&decrementer_clockevent, ppc_tb_freq, 4); - - decrementer_clockevent.max_delta_ns = - clockevent_delta2ns(decrementer_max, &decrementer_clockevent); - decrementer_clockevent.max_delta_ticks = decrementer_max; - decrementer_clockevent.min_delta_ns = - clockevent_delta2ns(2, &decrementer_clockevent); - decrementer_clockevent.min_delta_ticks = 2; - - register_decrementer_clockevent(cpu); + register_decrementer_clockevent(smp_processor_id()); } void secondary_cpu_time_init(void) diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 7716374786bd..9fabdce255cd 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S @@ -92,13 +92,14 @@ _GLOBAL(tm_abort) blr EXPORT_SYMBOL_GPL(tm_abort); -/* void tm_reclaim(struct thread_struct *thread, +/* + * void tm_reclaim(struct thread_struct *thread, * uint8_t cause) * * - Performs a full reclaim. This destroys outstanding - * transactions and updates thread->regs.tm_ckpt_* with the - * original checkpointed state. Note that thread->regs is - * unchanged. + * transactions and updates thread.ckpt_regs, thread.ckfp_state and + * thread.ckvr_state with the original checkpointed state. Note that + * thread->regs is unchanged. * * Purpose is to both abort transactions of, and preserve the state of, * a transactions at a context switch. We preserve/restore both sets of process @@ -163,15 +164,16 @@ _GLOBAL(tm_reclaim) */ TRECLAIM(R4) /* Cause in r4 */ - /* ******************** GPRs ******************** */ - /* Stash the checkpointed r13 away in the scratch SPR and get the real - * paca + /* + * ******************** GPRs ******************** + * Stash the checkpointed r13 in the scratch SPR and get the real paca. */ SET_SCRATCH0(r13) GET_PACA(r13) - /* Stash the checkpointed r1 away in paca tm_scratch and get the real - * stack pointer back + /* + * Stash the checkpointed r1 away in paca->tm_scratch and get the real + * stack pointer back into r1. */ std r1, PACATMSCRATCH(r13) ld r1, PACAR1(r13) @@ -209,14 +211,15 @@ _GLOBAL(tm_reclaim) addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ - /* Make r7 look like an exception frame so that we - * can use the neat GPRx(n) macros. r7 is NOT a pt_regs ptr! + /* + * Make r7 look like an exception frame so that we can use the neat + * GPRx(n) macros. r7 is NOT a pt_regs ptr! */ subi r7, r7, STACK_FRAME_OVERHEAD /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ SAVE_GPR(0, r7) /* user r0 */ - SAVE_GPR(2, r7) /* user r2 */ + SAVE_GPR(2, r7) /* user r2 */ SAVE_4GPRS(3, r7) /* user r3-r6 */ SAVE_GPR(8, r7) /* user r8 */ SAVE_GPR(9, r7) /* user r9 */ @@ -237,7 +240,8 @@ _GLOBAL(tm_reclaim) /* ******************** NIP ******************** */ mfspr r3, SPRN_TFHAR std r3, _NIP(r7) /* Returns to failhandler */ - /* The checkpointed NIP is ignored when rescheduling/rechkpting, + /* + * The checkpointed NIP is ignored when rescheduling/rechkpting, * but is used in signal return to 'wind back' to the abort handler. */ @@ -260,12 +264,13 @@ _GLOBAL(tm_reclaim) std r3, THREAD_TM_TAR(r12) std r4, THREAD_TM_DSCR(r12) - /* MSR and flags: We don't change CRs, and we don't need to alter - * MSR. + /* + * MSR and flags: We don't change CRs, and we don't need to alter MSR. */ - /* ******************** FPR/VR/VSRs ************ + /* + * ******************** FPR/VR/VSRs ************ * After reclaiming, capture the checkpointed FPRs/VRs. * * We enabled VEC/FP/VSX in the msr above, so we can execute these @@ -275,7 +280,7 @@ _GLOBAL(tm_reclaim) /* Altivec (VEC/VMX/VR)*/ addi r7, r3, THREAD_CKVRSTATE - SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ + SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 ckvr_state */ mfvscr v0 li r6, VRSTATE_VSCR stvx v0, r7, r6 @@ -286,12 +291,13 @@ _GLOBAL(tm_reclaim) /* Floating Point (FP) */ addi r7, r3, THREAD_CKFPSTATE - SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ + SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 ckfp_state */ mffs fr0 stfd fr0,FPSTATE_FPSCR(r7) - /* TM regs, incl TEXASR -- these live in thread_struct. Note they've + /* + * TM regs, incl TEXASR -- these live in thread_struct. Note they've * been updated by the treclaim, to explain to userland the failure * cause (aborted). */ @@ -327,7 +333,7 @@ _GLOBAL(tm_reclaim) blr - /* + /* * void __tm_recheckpoint(struct thread_struct *thread) * - Restore the checkpointed register state saved by tm_reclaim * when we switch_to a process. @@ -343,7 +349,8 @@ _GLOBAL(__tm_recheckpoint) std r2, STK_GOT(r1) stdu r1, -TM_FRAME_SIZE(r1) - /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. + /* + * We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. * This is used for backing up the NVGPRs: */ SAVE_NVGPRS(r1) @@ -352,8 +359,9 @@ _GLOBAL(__tm_recheckpoint) addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ - /* Make r7 look like an exception frame so that we - * can use the neat GPRx(n) macros. r7 is now NOT a pt_regs ptr! + /* + * Make r7 look like an exception frame so that we can use the neat + * GPRx(n) macros. r7 is now NOT a pt_regs ptr! */ subi r7, r7, STACK_FRAME_OVERHEAD @@ -421,14 +429,15 @@ restore_gprs: REST_NVGPRS(r7) /* GPR14-31 */ - /* Load up PPR and DSCR here so we don't run with user values for long - */ + /* Load up PPR and DSCR here so we don't run with user values for long */ mtspr SPRN_DSCR, r5 mtspr SPRN_PPR, r6 - /* Do final sanity check on TEXASR to make sure FS is set. Do this + /* + * Do final sanity check on TEXASR to make sure FS is set. Do this * here before we load up the userspace r1 so any bugs we hit will get - * a call chain */ + * a call chain. + */ mfspr r5, SPRN_TEXASR srdi r5, r5, 16 li r6, (TEXASR_FS)@h @@ -436,8 +445,9 @@ restore_gprs: 1: tdeqi r6, 0 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 - /* Do final sanity check on MSR to make sure we are not transactional - * or suspended + /* + * Do final sanity check on MSR to make sure we are not transactional + * or suspended. */ mfmsr r6 li r5, (MSR_TS_MASK)@higher @@ -453,8 +463,8 @@ restore_gprs: REST_GPR(6, r7) /* - * Store r1 and r5 on the stack so that we can access them - * after we clear MSR RI. + * Store r1 and r5 on the stack so that we can access them after we + * clear MSR RI. */ REST_GPR(5, r7) @@ -484,7 +494,8 @@ restore_gprs: HMT_MEDIUM - /* Our transactional state has now changed. + /* + * Our transactional state has now changed. * * Now just get out of here. Transactional (current) state will be * updated once restore is called on the return path in the _switch-ed diff --git a/arch/powerpc/kernel/trace/Makefile b/arch/powerpc/kernel/trace/Makefile index d22d8bafb643..b1725ad3e13d 100644 --- a/arch/powerpc/kernel/trace/Makefile +++ b/arch/powerpc/kernel/trace/Makefile @@ -3,11 +3,9 @@ # Makefile for the powerpc trace subsystem # -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - ifdef CONFIG_FUNCTION_TRACER # do not trace tracer code -CFLAGS_REMOVE_ftrace.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) endif obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_32.o diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 4bfbb54dee51..4bf051d3e21e 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -30,6 +30,16 @@ #ifdef CONFIG_DYNAMIC_FTRACE + +/* + * We generally only have a single long_branch tramp and at most 2 or 3 plt + * tramps generated. But, we don't use the plt tramps currently. We also allot + * 2 tramps after .text and .init.text. So, we only end up with around 3 usable + * tramps in total. Set aside 8 just to be sure. + */ +#define NUM_FTRACE_TRAMPS 8 +static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS]; + static unsigned int ftrace_call_replace(unsigned long ip, unsigned long addr, int link) { @@ -85,13 +95,16 @@ static int test_24bit_addr(unsigned long ip, unsigned long addr) return create_branch((unsigned int *)ip, addr, 0); } -#ifdef CONFIG_MODULES - static int is_bl_op(unsigned int op) { return (op & 0xfc000003) == 0x48000001; } +static int is_b_op(unsigned int op) +{ + return (op & 0xfc000003) == 0x48000000; +} + static unsigned long find_bl_target(unsigned long ip, unsigned int op) { static int offset; @@ -104,6 +117,7 @@ static unsigned long find_bl_target(unsigned long ip, unsigned int op) return ip + (long)offset; } +#ifdef CONFIG_MODULES #ifdef CONFIG_PPC64 static int __ftrace_make_nop(struct module *mod, @@ -270,6 +284,146 @@ __ftrace_make_nop(struct module *mod, #endif /* PPC64 */ #endif /* CONFIG_MODULES */ +static unsigned long find_ftrace_tramp(unsigned long ip) +{ + int i; + + /* + * We have the compiler generated long_branch tramps at the end + * and we prefer those + */ + for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--) + if (!ftrace_tramps[i]) + continue; + else if (create_branch((void *)ip, ftrace_tramps[i], 0)) + return ftrace_tramps[i]; + + return 0; +} + +static int add_ftrace_tramp(unsigned long tramp) +{ + int i; + + for (i = 0; i < NUM_FTRACE_TRAMPS; i++) + if (!ftrace_tramps[i]) { + ftrace_tramps[i] = tramp; + return 0; + } + + return -1; +} + +/* + * If this is a compiler generated long_branch trampoline (essentially, a + * trampoline that has a branch to _mcount()), we re-write the branch to + * instead go to ftrace_[regs_]caller() and note down the location of this + * trampoline. + */ +static int setup_mcount_compiler_tramp(unsigned long tramp) +{ + int i, op; + unsigned long ptr; + static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS]; + + /* Is this a known long jump tramp? */ + for (i = 0; i < NUM_FTRACE_TRAMPS; i++) + if (!ftrace_tramps[i]) + break; + else if (ftrace_tramps[i] == tramp) + return 0; + + /* Is this a known plt tramp? */ + for (i = 0; i < NUM_FTRACE_TRAMPS; i++) + if (!ftrace_plt_tramps[i]) + break; + else if (ftrace_plt_tramps[i] == tramp) + return -1; + + /* New trampoline -- read where this goes */ + if (probe_kernel_read(&op, (void *)tramp, sizeof(int))) { + pr_debug("Fetching opcode failed.\n"); + return -1; + } + + /* Is this a 24 bit branch? */ + if (!is_b_op(op)) { + pr_debug("Trampoline is not a long branch tramp.\n"); + return -1; + } + + /* lets find where the pointer goes */ + ptr = find_bl_target(tramp, op); + + if (ptr != ppc_global_function_entry((void *)_mcount)) { + pr_debug("Trampoline target %p is not _mcount\n", (void *)ptr); + return -1; + } + + /* Let's re-write the tramp to go to ftrace_[regs_]caller */ +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + ptr = ppc_global_function_entry((void *)ftrace_regs_caller); +#else + ptr = ppc_global_function_entry((void *)ftrace_caller); +#endif + if (!create_branch((void *)tramp, ptr, 0)) { + pr_debug("%ps is not reachable from existing mcount tramp\n", + (void *)ptr); + return -1; + } + + if (patch_branch((unsigned int *)tramp, ptr, 0)) { + pr_debug("REL24 out of range!\n"); + return -1; + } + + if (add_ftrace_tramp(tramp)) { + pr_debug("No tramp locations left\n"); + return -1; + } + + return 0; +} + +static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned long tramp, ip = rec->ip; + unsigned int op; + + /* Read where this goes */ + if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { + pr_err("Fetching opcode failed.\n"); + return -EFAULT; + } + + /* Make sure that that this is still a 24bit jump */ + if (!is_bl_op(op)) { + pr_err("Not expected bl: opcode is %x\n", op); + return -EINVAL; + } + + /* Let's find where the pointer goes */ + tramp = find_bl_target(ip, op); + + pr_devel("ip:%lx jumps to %lx", ip, tramp); + + if (setup_mcount_compiler_tramp(tramp)) { + /* Are other trampolines reachable? */ + if (!find_ftrace_tramp(ip)) { + pr_err("No ftrace trampolines reachable from %ps\n", + (void *)ip); + return -EINVAL; + } + } + + if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) { + pr_err("Patching NOP failed.\n"); + return -EPERM; + } + + return 0; +} + int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { @@ -286,7 +440,8 @@ int ftrace_make_nop(struct module *mod, old = ftrace_call_replace(ip, addr, 1); new = PPC_INST_NOP; return ftrace_modify_code(ip, old, new); - } + } else if (core_kernel_text(ip)) + return __ftrace_make_nop_kernel(rec, addr); #ifdef CONFIG_MODULES /* @@ -456,6 +611,53 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) #endif /* CONFIG_PPC64 */ #endif /* CONFIG_MODULES */ +static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned int op; + void *ip = (void *)rec->ip; + unsigned long tramp, entry, ptr; + + /* Make sure we're being asked to patch branch to a known ftrace addr */ + entry = ppc_global_function_entry((void *)ftrace_caller); + ptr = ppc_global_function_entry((void *)addr); + + if (ptr != entry) { +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + entry = ppc_global_function_entry((void *)ftrace_regs_caller); + if (ptr != entry) { +#endif + pr_err("Unknown ftrace addr to patch: %ps\n", (void *)ptr); + return -EINVAL; +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + } +#endif + } + + /* Make sure we have a nop */ + if (probe_kernel_read(&op, ip, sizeof(op))) { + pr_err("Unable to read ftrace location %p\n", ip); + return -EFAULT; + } + + if (op != PPC_INST_NOP) { + pr_err("Unexpected call sequence at %p: %x\n", ip, op); + return -EINVAL; + } + + tramp = find_ftrace_tramp((unsigned long)ip); + if (!tramp) { + pr_err("No ftrace trampolines reachable from %ps\n", ip); + return -EINVAL; + } + + if (patch_branch(ip, tramp, BRANCH_SET_LINK)) { + pr_err("Error patching branch to ftrace tramp!\n"); + return -EINVAL; + } + + return 0; +} + int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { unsigned long ip = rec->ip; @@ -471,7 +673,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) old = PPC_INST_NOP; new = ftrace_call_replace(ip, addr, 1); return ftrace_modify_code(ip, old, new); - } + } else if (core_kernel_text(ip)) + return __ftrace_make_call_kernel(rec, addr); #ifdef CONFIG_MODULES /* @@ -603,6 +806,12 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, old = ftrace_call_replace(ip, old_addr, 1); new = ftrace_call_replace(ip, addr, 1); return ftrace_modify_code(ip, old, new); + } else if (core_kernel_text(ip)) { + /* + * We always patch out of range locations to go to the regs + * variant, so there is nothing to do here + */ + return 0; } #ifdef CONFIG_MODULES @@ -654,10 +863,54 @@ void arch_ftrace_update_code(int command) ftrace_modify_all_code(command); } +#ifdef CONFIG_PPC64 +#define PACATOC offsetof(struct paca_struct, kernel_toc) + +#define PPC_LO(v) ((v) & 0xffff) +#define PPC_HI(v) (((v) >> 16) & 0xffff) +#define PPC_HA(v) PPC_HI ((v) + 0x8000) + +extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; + +int __init ftrace_dyn_arch_init(void) +{ + int i; + unsigned int *tramp[] = { ftrace_tramp_text, ftrace_tramp_init }; + u32 stub_insns[] = { + 0xe98d0000 | PACATOC, /* ld r12,PACATOC(r13) */ + 0x3d8c0000, /* addis r12,r12,<high> */ + 0x398c0000, /* addi r12,r12,<low> */ + 0x7d8903a6, /* mtctr r12 */ + 0x4e800420, /* bctr */ + }; +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + unsigned long addr = ppc_global_function_entry((void *)ftrace_regs_caller); +#else + unsigned long addr = ppc_global_function_entry((void *)ftrace_caller); +#endif + long reladdr = addr - kernel_toc_addr(); + + if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { + pr_err("Address of %ps out of range of kernel_toc.\n", + (void *)addr); + return -1; + } + + for (i = 0; i < 2; i++) { + memcpy(tramp[i], stub_insns, sizeof(stub_insns)); + tramp[i][1] |= PPC_HA(reladdr); + tramp[i][2] |= PPC_LO(reladdr); + add_ftrace_tramp((unsigned long)tramp[i]); + } + + return 0; +} +#else int __init ftrace_dyn_arch_init(void) { return 0; } +#endif #endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER diff --git a/arch/powerpc/kernel/trace/ftrace_64.S b/arch/powerpc/kernel/trace/ftrace_64.S index e25f77c10a72..1782af2d1496 100644 --- a/arch/powerpc/kernel/trace/ftrace_64.S +++ b/arch/powerpc/kernel/trace/ftrace_64.S @@ -14,6 +14,18 @@ #include <asm/ppc-opcode.h> #include <asm/export.h> +.pushsection ".tramp.ftrace.text","aw",@progbits; +.globl ftrace_tramp_text +ftrace_tramp_text: + .space 64 +.popsection + +.pushsection ".tramp.ftrace.init","aw",@progbits; +.globl ftrace_tramp_init +ftrace_tramp_init: + .space 64 +.popsection + _GLOBAL(mcount) _GLOBAL(_mcount) EXPORT_SYMBOL(_mcount) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index c85adb858271..9a86572db1ef 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -247,8 +247,6 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, mdelay(MSEC_PER_SEC); } - if (in_interrupt()) - panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); do_exit(signr); @@ -307,12 +305,9 @@ void die(const char *str, struct pt_regs *regs, long err) } NOKPROBE_SYMBOL(die); -void user_single_step_siginfo(struct task_struct *tsk, - struct pt_regs *regs, siginfo_t *info) +void user_single_step_report(struct pt_regs *regs) { - info->si_signo = SIGTRAP; - info->si_code = TRAP_TRACE; - info->si_addr = (void __user *)regs->nip; + force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)regs->nip, current); } static void show_signal_msg(int signr, struct pt_regs *regs, int code, @@ -341,14 +336,12 @@ static void show_signal_msg(int signr, struct pt_regs *regs, int code, show_user_instructions(regs); } -void _exception_pkey(int signr, struct pt_regs *regs, int code, - unsigned long addr, int key) +static bool exception_common(int signr, struct pt_regs *regs, int code, + unsigned long addr) { - siginfo_t info; - if (!user_mode(regs)) { die("Exception in kernel mode", regs, signr); - return; + return false; } show_signal_msg(signr, regs, code, addr); @@ -364,18 +357,23 @@ void _exception_pkey(int signr, struct pt_regs *regs, int code, */ thread_pkey_regs_save(¤t->thread); - clear_siginfo(&info); - info.si_signo = signr; - info.si_code = code; - info.si_addr = (void __user *) addr; - info.si_pkey = key; + return true; +} - force_sig_info(signr, &info, current); +void _exception_pkey(struct pt_regs *regs, unsigned long addr, int key) +{ + if (!exception_common(SIGSEGV, regs, SEGV_PKUERR, addr)) + return; + + force_sig_pkuerr((void __user *) addr, key); } void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { - _exception_pkey(signr, regs, code, addr, 0); + if (!exception_common(signr, regs, code, addr)) + return; + + force_sig_fault(signr, code, (void __user *)addr, current); } void system_reset_exception(struct pt_regs *regs) @@ -535,10 +533,10 @@ int machine_check_e500mc(struct pt_regs *regs) printk("Caused by (from MCSR=%lx): ", reason); if (reason & MCSR_MCP) - printk("Machine Check Signal\n"); + pr_cont("Machine Check Signal\n"); if (reason & MCSR_ICPERR) { - printk("Instruction Cache Parity Error\n"); + pr_cont("Instruction Cache Parity Error\n"); /* * This is recoverable by invalidating the i-cache. @@ -556,7 +554,7 @@ int machine_check_e500mc(struct pt_regs *regs) } if (reason & MCSR_DCPERR_MC) { - printk("Data Cache Parity Error\n"); + pr_cont("Data Cache Parity Error\n"); /* * In write shadow mode we auto-recover from the error, but it @@ -575,38 +573,38 @@ int machine_check_e500mc(struct pt_regs *regs) } if (reason & MCSR_L2MMU_MHIT) { - printk("Hit on multiple TLB entries\n"); + pr_cont("Hit on multiple TLB entries\n"); recoverable = 0; } if (reason & MCSR_NMI) - printk("Non-maskable interrupt\n"); + pr_cont("Non-maskable interrupt\n"); if (reason & MCSR_IF) { - printk("Instruction Fetch Error Report\n"); + pr_cont("Instruction Fetch Error Report\n"); recoverable = 0; } if (reason & MCSR_LD) { - printk("Load Error Report\n"); + pr_cont("Load Error Report\n"); recoverable = 0; } if (reason & MCSR_ST) { - printk("Store Error Report\n"); + pr_cont("Store Error Report\n"); recoverable = 0; } if (reason & MCSR_LDG) { - printk("Guarded Load Error Report\n"); + pr_cont("Guarded Load Error Report\n"); recoverable = 0; } if (reason & MCSR_TLBSYNC) - printk("Simultaneous tlbsync operations\n"); + pr_cont("Simultaneous tlbsync operations\n"); if (reason & MCSR_BSL2_ERR) { - printk("Level 2 Cache Error\n"); + pr_cont("Level 2 Cache Error\n"); recoverable = 0; } @@ -616,7 +614,7 @@ int machine_check_e500mc(struct pt_regs *regs) addr = mfspr(SPRN_MCAR); addr |= (u64)mfspr(SPRN_MCARU) << 32; - printk("Machine Check %s Address: %#llx\n", + pr_cont("Machine Check %s Address: %#llx\n", reason & MCSR_MEA ? "Effective" : "Physical", addr); } @@ -640,29 +638,29 @@ int machine_check_e500(struct pt_regs *regs) printk("Caused by (from MCSR=%lx): ", reason); if (reason & MCSR_MCP) - printk("Machine Check Signal\n"); + pr_cont("Machine Check Signal\n"); if (reason & MCSR_ICPERR) - printk("Instruction Cache Parity Error\n"); + pr_cont("Instruction Cache Parity Error\n"); if (reason & MCSR_DCP_PERR) - printk("Data Cache Push Parity Error\n"); + pr_cont("Data Cache Push Parity Error\n"); if (reason & MCSR_DCPERR) - printk("Data Cache Parity Error\n"); + pr_cont("Data Cache Parity Error\n"); if (reason & MCSR_BUS_IAERR) - printk("Bus - Instruction Address Error\n"); + pr_cont("Bus - Instruction Address Error\n"); if (reason & MCSR_BUS_RAERR) - printk("Bus - Read Address Error\n"); + pr_cont("Bus - Read Address Error\n"); if (reason & MCSR_BUS_WAERR) - printk("Bus - Write Address Error\n"); + pr_cont("Bus - Write Address Error\n"); if (reason & MCSR_BUS_IBERR) - printk("Bus - Instruction Data Error\n"); + pr_cont("Bus - Instruction Data Error\n"); if (reason & MCSR_BUS_RBERR) - printk("Bus - Read Data Bus Error\n"); + pr_cont("Bus - Read Data Bus Error\n"); if (reason & MCSR_BUS_WBERR) - printk("Bus - Write Data Bus Error\n"); + pr_cont("Bus - Write Data Bus Error\n"); if (reason & MCSR_BUS_IPERR) - printk("Bus - Instruction Parity Error\n"); + pr_cont("Bus - Instruction Parity Error\n"); if (reason & MCSR_BUS_RPERR) - printk("Bus - Read Parity Error\n"); + pr_cont("Bus - Read Parity Error\n"); return 0; } @@ -680,19 +678,19 @@ int machine_check_e200(struct pt_regs *regs) printk("Caused by (from MCSR=%lx): ", reason); if (reason & MCSR_MCP) - printk("Machine Check Signal\n"); + pr_cont("Machine Check Signal\n"); if (reason & MCSR_CP_PERR) - printk("Cache Push Parity Error\n"); + pr_cont("Cache Push Parity Error\n"); if (reason & MCSR_CPERR) - printk("Cache Parity Error\n"); + pr_cont("Cache Parity Error\n"); if (reason & MCSR_EXCP_ERR) - printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n"); + pr_cont("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n"); if (reason & MCSR_BUS_IRERR) - printk("Bus - Read Bus Error on instruction fetch\n"); + pr_cont("Bus - Read Bus Error on instruction fetch\n"); if (reason & MCSR_BUS_DRERR) - printk("Bus - Read Bus Error on data load\n"); + pr_cont("Bus - Read Bus Error on data load\n"); if (reason & MCSR_BUS_WRERR) - printk("Bus - Write Bus Error on buffered store or cache line push\n"); + pr_cont("Bus - Write Bus Error on buffered store or cache line push\n"); return 0; } @@ -705,30 +703,30 @@ int machine_check_generic(struct pt_regs *regs) printk("Caused by (from SRR1=%lx): ", reason); switch (reason & 0x601F0000) { case 0x80000: - printk("Machine check signal\n"); + pr_cont("Machine check signal\n"); break; case 0: /* for 601 */ case 0x40000: case 0x140000: /* 7450 MSS error and TEA */ - printk("Transfer error ack signal\n"); + pr_cont("Transfer error ack signal\n"); break; case 0x20000: - printk("Data parity error signal\n"); + pr_cont("Data parity error signal\n"); break; case 0x10000: - printk("Address parity error signal\n"); + pr_cont("Address parity error signal\n"); break; case 0x20000000: - printk("L1 Data Cache error\n"); + pr_cont("L1 Data Cache error\n"); break; case 0x40000000: - printk("L1 Instruction Cache error\n"); + pr_cont("L1 Instruction Cache error\n"); break; case 0x00100000: - printk("L2 data cache parity error\n"); + pr_cont("L2 data cache parity error\n"); break; default: - printk("Unknown values in msr\n"); + pr_cont("Unknown values in msr\n"); } return 0; } @@ -741,9 +739,7 @@ void machine_check_exception(struct pt_regs *regs) if (!nested) nmi_enter(); - /* 64s accounts the mce in machine_check_early when in HVMODE */ - if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !cpu_has_feature(CPU_FTR_HVMODE)) - __this_cpu_inc(irq_stat.mce_exceptions); + __this_cpu_inc(irq_stat.mce_exceptions); add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); @@ -767,12 +763,17 @@ void machine_check_exception(struct pt_regs *regs) if (check_io_access(regs)) goto bail; - die("Machine check", regs, SIGBUS); - /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) nmi_panic(regs, "Unrecoverable Machine check"); + if (!nested) + nmi_exit(); + + die("Machine check", regs, SIGBUS); + + return; + bail: if (!nested) nmi_exit(); @@ -1433,7 +1434,7 @@ void program_check_exception(struct pt_regs *regs) goto bail; } else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " - "at %lx (msr 0x%x)\n", regs->nip, reason); + "at %lx (msr 0x%lx)\n", regs->nip, regs->msr); die("Unrecoverable exception", regs, SIGABRT); } } @@ -1547,14 +1548,6 @@ void StackOverflow(struct pt_regs *regs) panic("kernel stack overflow"); } -void nonrecoverable_exception(struct pt_regs *regs) -{ - printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n", - regs->nip, regs->msr); - debugger(regs); - die("nonrecoverable exception", regs, SIGKILL); -} - void kernel_fp_unavailable_exception(struct pt_regs *regs) { enum ctx_state prev_state = exception_enter(); @@ -1750,16 +1743,20 @@ void fp_unavailable_tm(struct pt_regs *regs) * checkpointed FP registers need to be loaded. */ tm_reclaim_current(TM_CAUSE_FAC_UNAV); - /* Reclaim didn't save out any FPRs to transact_fprs. */ + + /* + * Reclaim initially saved out bogus (lazy) FPRs to ckfp_state, and + * then it was overwrite by the thr->fp_state by tm_reclaim_thread(). + * + * At this point, ck{fp,vr}_state contains the exact values we want to + * recheckpoint. + */ /* Enable FP for the task: */ current->thread.load_fp = 1; - /* This loads and recheckpoints the FP registers from - * thread.fpr[]. They will remain in registers after the - * checkpoint so we don't need to reload them after. - * If VMX is in use, the VRs now hold checkpointed values, - * so we don't want to load the VRs from the thread_struct. + /* + * Recheckpoint all the checkpointed ckpt, ck{fp, vr}_state registers. */ tm_recheckpoint(¤t->thread); } @@ -2086,8 +2083,8 @@ void SPEFloatingPointRoundException(struct pt_regs *regs) */ void unrecoverable_exception(struct pt_regs *regs) { - printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", - regs->trap, regs->nip); + pr_emerg("Unrecoverable exception %lx at %lx (msr=%lx)\n", + regs->trap, regs->nip, regs->msr); die("Unrecoverable exception", regs, SIGABRT); } NOKPROBE_SYMBOL(unrecoverable_exception); diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S index 3745113fcc65..2a7eb5452aba 100644 --- a/arch/powerpc/kernel/vdso32/datapage.S +++ b/arch/powerpc/kernel/vdso32/datapage.S @@ -37,6 +37,7 @@ data_page_branch: mtlr r0 addi r3, r3, __kernel_datapage_offset-data_page_branch lwz r0,0(r3) + .cfi_restore lr add r3,r0,r3 blr .cfi_endproc diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index 769c2624e0a6..1e0bc5955a40 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S @@ -139,6 +139,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) */ 99: li r0,__NR_clock_gettime + .cfi_restore lr sc blr .cfi_endproc diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S index abf17feffe40..bf9668691511 100644 --- a/arch/powerpc/kernel/vdso64/datapage.S +++ b/arch/powerpc/kernel/vdso64/datapage.S @@ -37,6 +37,7 @@ data_page_branch: mtlr r0 addi r3, r3, __kernel_datapage_offset-data_page_branch lwz r0,0(r3) + .cfi_restore lr add r3,r0,r3 blr .cfi_endproc diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index c002adcc694c..a4ed9edfd5f0 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -169,6 +169,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) */ 99: li r0,__NR_clock_gettime + .cfi_restore lr sc blr .cfi_endproc diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 07ae018e550e..434581bcd5b4 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -4,6 +4,9 @@ #else #define PROVIDE32(x) PROVIDE(x) #endif + +#define BSS_FIRST_SECTIONS *(.bss.prominit) + #include <asm/page.h> #include <asm-generic/vmlinux.lds.h> #include <asm/cache.h> @@ -99,6 +102,9 @@ SECTIONS #endif /* careful! __ftr_alt_* sections need to be close to .text */ *(.text.hot TEXT_MAIN .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text); +#ifdef CONFIG_PPC64 + *(.tramp.ftrace.text); +#endif SCHED_TEXT CPUIDLE_TEXT LOCK_TEXT @@ -181,7 +187,15 @@ SECTIONS */ . = ALIGN(STRICT_ALIGN_SIZE); __init_begin = .; - INIT_TEXT_SECTION(PAGE_SIZE) :kernel + . = ALIGN(PAGE_SIZE); + .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { + _sinittext = .; + INIT_TEXT + _einittext = .; +#ifdef CONFIG_PPC64 + *(.tramp.ftrace.init); +#endif + } :kernel /* .exit.text is discarded at runtime, not link time, * to deal with references from __bug_table @@ -212,8 +226,6 @@ SECTIONS CON_INITCALL } - SECURITY_INIT - . = ALIGN(8); __ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) { __start___ftr_fixup = .; diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index f872c04bb5b1..64f1135e7732 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -3,8 +3,6 @@ # Makefile for Kernel-based Virtual Machine module # -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm KVM := ../../../virt/kvm @@ -75,7 +73,8 @@ kvm-hv-y += \ book3s_hv.o \ book3s_hv_interrupts.o \ book3s_64_mmu_hv.o \ - book3s_64_mmu_radix.o + book3s_64_mmu_radix.o \ + book3s_hv_nested.o kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \ book3s_hv_tm.o diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 87348e498c89..fd9893bc7aa1 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -78,8 +78,11 @@ void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu) { if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) { ulong pc = kvmppc_get_pc(vcpu); + ulong lr = kvmppc_get_lr(vcpu); if ((pc & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS) kvmppc_set_pc(vcpu, pc & ~SPLIT_HACK_MASK); + if ((lr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS) + kvmppc_set_lr(vcpu, lr & ~SPLIT_HACK_MASK); vcpu->arch.hflags &= ~BOOK3S_HFLAG_SPLIT_HACK; } } @@ -150,7 +153,6 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec) case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break; case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break; case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break; - case 0x501: prio = BOOK3S_IRQPRIO_EXTERNAL_LEVEL; break; case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break; case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break; case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break; @@ -236,18 +238,35 @@ EXPORT_SYMBOL_GPL(kvmppc_core_dequeue_dec); void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) { - unsigned int vec = BOOK3S_INTERRUPT_EXTERNAL; - - if (irq->irq == KVM_INTERRUPT_SET_LEVEL) - vec = BOOK3S_INTERRUPT_EXTERNAL_LEVEL; + /* + * This case (KVM_INTERRUPT_SET) should never actually arise for + * a pseries guest (because pseries guests expect their interrupt + * controllers to continue asserting an external interrupt request + * until it is acknowledged at the interrupt controller), but is + * included to avoid ABI breakage and potentially for other + * sorts of guest. + * + * There is a subtlety here: HV KVM does not test the + * external_oneshot flag in the code that synthesizes + * external interrupts for the guest just before entering + * the guest. That is OK even if userspace did do a + * KVM_INTERRUPT_SET on a pseries guest vcpu, because the + * caller (kvm_vcpu_ioctl_interrupt) does a kvm_vcpu_kick() + * which ends up doing a smp_send_reschedule(), which will + * pull the guest all the way out to the host, meaning that + * we will call kvmppc_core_prepare_to_enter() before entering + * the guest again, and that will handle the external_oneshot + * flag correctly. + */ + if (irq->irq == KVM_INTERRUPT_SET) + vcpu->arch.external_oneshot = 1; - kvmppc_book3s_queue_irqprio(vcpu, vec); + kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); } void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu) { kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); - kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL); } void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar, @@ -278,7 +297,6 @@ static int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, vec = BOOK3S_INTERRUPT_DECREMENTER; break; case BOOK3S_IRQPRIO_EXTERNAL: - case BOOK3S_IRQPRIO_EXTERNAL_LEVEL: deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit; vec = BOOK3S_INTERRUPT_EXTERNAL; break; @@ -352,8 +370,16 @@ static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority) case BOOK3S_IRQPRIO_DECREMENTER: /* DEC interrupts get cleared by mtdec */ return false; - case BOOK3S_IRQPRIO_EXTERNAL_LEVEL: - /* External interrupts get cleared by userspace */ + case BOOK3S_IRQPRIO_EXTERNAL: + /* + * External interrupts get cleared by userspace + * except when set by the KVM_INTERRUPT ioctl with + * KVM_INTERRUPT_SET (not KVM_INTERRUPT_SET_LEVEL). + */ + if (vcpu->arch.external_oneshot) { + vcpu->arch.external_oneshot = 0; + return true; + } return false; } diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 68e14afecac8..c615617e78ac 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -268,14 +268,13 @@ int kvmppc_mmu_hv_init(void) { unsigned long host_lpid, rsvd_lpid; - if (!cpu_has_feature(CPU_FTR_HVMODE)) - return -EINVAL; - if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) return -EINVAL; /* POWER7 has 10-bit LPIDs (12-bit in POWER8) */ - host_lpid = mfspr(SPRN_LPID); + host_lpid = 0; + if (cpu_has_feature(CPU_FTR_HVMODE)) + host_lpid = mfspr(SPRN_LPID); rsvd_lpid = LPID_RSVD; kvmppc_init_lpid(rsvd_lpid + 1); diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 998f8d089ac7..d68162ee159b 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -10,6 +10,9 @@ #include <linux/string.h> #include <linux/kvm.h> #include <linux/kvm_host.h> +#include <linux/anon_inodes.h> +#include <linux/file.h> +#include <linux/debugfs.h> #include <asm/kvm_ppc.h> #include <asm/kvm_book3s.h> @@ -26,87 +29,74 @@ */ static int p9_supported_radix_bits[4] = { 5, 9, 9, 13 }; -int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, - struct kvmppc_pte *gpte, bool data, bool iswrite) +int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, u64 root, + u64 *pte_ret_p) { struct kvm *kvm = vcpu->kvm; - u32 pid; int ret, level, ps; - __be64 prte, rpte; - unsigned long ptbl; - unsigned long root, pte, index; - unsigned long rts, bits, offset; - unsigned long gpa; - unsigned long proc_tbl_size; - - /* Work out effective PID */ - switch (eaddr >> 62) { - case 0: - pid = vcpu->arch.pid; - break; - case 3: - pid = 0; - break; - default: - return -EINVAL; - } - proc_tbl_size = 1 << ((kvm->arch.process_table & PRTS_MASK) + 12); - if (pid * 16 >= proc_tbl_size) - return -EINVAL; - - /* Read partition table to find root of tree for effective PID */ - ptbl = (kvm->arch.process_table & PRTB_MASK) + (pid * 16); - ret = kvm_read_guest(kvm, ptbl, &prte, sizeof(prte)); - if (ret) - return ret; + unsigned long rts, bits, offset, index; + u64 pte, base, gpa; + __be64 rpte; - root = be64_to_cpu(prte); rts = ((root & RTS1_MASK) >> (RTS1_SHIFT - 3)) | ((root & RTS2_MASK) >> RTS2_SHIFT); bits = root & RPDS_MASK; - root = root & RPDB_MASK; + base = root & RPDB_MASK; offset = rts + 31; - /* current implementations only support 52-bit space */ + /* Current implementations only support 52-bit space */ if (offset != 52) return -EINVAL; + /* Walk each level of the radix tree */ for (level = 3; level >= 0; --level) { + u64 addr; + /* Check a valid size */ if (level && bits != p9_supported_radix_bits[level]) return -EINVAL; if (level == 0 && !(bits == 5 || bits == 9)) return -EINVAL; offset -= bits; index = (eaddr >> offset) & ((1UL << bits) - 1); - /* check that low bits of page table base are zero */ - if (root & ((1UL << (bits + 3)) - 1)) + /* Check that low bits of page table base are zero */ + if (base & ((1UL << (bits + 3)) - 1)) return -EINVAL; - ret = kvm_read_guest(kvm, root + index * 8, - &rpte, sizeof(rpte)); - if (ret) + /* Read the entry from guest memory */ + addr = base + (index * sizeof(rpte)); + ret = kvm_read_guest(kvm, addr, &rpte, sizeof(rpte)); + if (ret) { + if (pte_ret_p) + *pte_ret_p = addr; return ret; + } pte = __be64_to_cpu(rpte); if (!(pte & _PAGE_PRESENT)) return -ENOENT; + /* Check if a leaf entry */ if (pte & _PAGE_PTE) break; - bits = pte & 0x1f; - root = pte & 0x0fffffffffffff00ul; + /* Get ready to walk the next level */ + base = pte & RPDB_MASK; + bits = pte & RPDS_MASK; } - /* need a leaf at lowest level; 512GB pages not supported */ + + /* Need a leaf at lowest level; 512GB pages not supported */ if (level < 0 || level == 3) return -EINVAL; - /* offset is now log base 2 of the page size */ + /* We found a valid leaf PTE */ + /* Offset is now log base 2 of the page size */ gpa = pte & 0x01fffffffffff000ul; if (gpa & ((1ul << offset) - 1)) return -EINVAL; - gpa += eaddr & ((1ul << offset) - 1); + gpa |= eaddr & ((1ul << offset) - 1); for (ps = MMU_PAGE_4K; ps < MMU_PAGE_COUNT; ++ps) if (offset == mmu_psize_defs[ps].shift) break; gpte->page_size = ps; + gpte->page_shift = offset; gpte->eaddr = eaddr; gpte->raddr = gpa; @@ -115,6 +105,77 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, gpte->may_read = !!(pte & _PAGE_READ); gpte->may_write = !!(pte & _PAGE_WRITE); gpte->may_execute = !!(pte & _PAGE_EXEC); + + gpte->rc = pte & (_PAGE_ACCESSED | _PAGE_DIRTY); + + if (pte_ret_p) + *pte_ret_p = pte; + + return 0; +} + +/* + * Used to walk a partition or process table radix tree in guest memory + * Note: We exploit the fact that a partition table and a process + * table have the same layout, a partition-scoped page table and a + * process-scoped page table have the same layout, and the 2nd + * doubleword of a partition table entry has the same layout as + * the PTCR register. + */ +int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, u64 table, + int table_index, u64 *pte_ret_p) +{ + struct kvm *kvm = vcpu->kvm; + int ret; + unsigned long size, ptbl, root; + struct prtb_entry entry; + + if ((table & PRTS_MASK) > 24) + return -EINVAL; + size = 1ul << ((table & PRTS_MASK) + 12); + + /* Is the table big enough to contain this entry? */ + if ((table_index * sizeof(entry)) >= size) + return -EINVAL; + + /* Read the table to find the root of the radix tree */ + ptbl = (table & PRTB_MASK) + (table_index * sizeof(entry)); + ret = kvm_read_guest(kvm, ptbl, &entry, sizeof(entry)); + if (ret) + return ret; + + /* Root is stored in the first double word */ + root = be64_to_cpu(entry.prtb0); + + return kvmppc_mmu_walk_radix_tree(vcpu, eaddr, gpte, root, pte_ret_p); +} + +int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, + struct kvmppc_pte *gpte, bool data, bool iswrite) +{ + u32 pid; + u64 pte; + int ret; + + /* Work out effective PID */ + switch (eaddr >> 62) { + case 0: + pid = vcpu->arch.pid; + break; + case 3: + pid = 0; + break; + default: + return -EINVAL; + } + + ret = kvmppc_mmu_radix_translate_table(vcpu, eaddr, gpte, + vcpu->kvm->arch.process_table, pid, &pte); + if (ret) + return ret; + + /* Check privilege (applies only to process scoped translations) */ if (kvmppc_get_msr(vcpu) & MSR_PR) { if (pte & _PAGE_PRIVILEGED) { gpte->may_read = 0; @@ -137,20 +198,46 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, } static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, - unsigned int pshift) + unsigned int pshift, unsigned int lpid) { unsigned long psize = PAGE_SIZE; + int psi; + long rc; + unsigned long rb; if (pshift) psize = 1UL << pshift; + else + pshift = PAGE_SHIFT; addr &= ~(psize - 1); - radix__flush_tlb_lpid_page(kvm->arch.lpid, addr, psize); + + if (!kvmhv_on_pseries()) { + radix__flush_tlb_lpid_page(lpid, addr, psize); + return; + } + + psi = shift_to_mmu_psize(pshift); + rb = addr | (mmu_get_ap(psi) << PPC_BITLSHIFT(58)); + rc = plpar_hcall_norets(H_TLB_INVALIDATE, H_TLBIE_P1_ENC(0, 0, 1), + lpid, rb); + if (rc) + pr_err("KVM: TLB page invalidation hcall failed, rc=%ld\n", rc); } -static void kvmppc_radix_flush_pwc(struct kvm *kvm) +static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned int lpid) { - radix__flush_pwc_lpid(kvm->arch.lpid); + long rc; + + if (!kvmhv_on_pseries()) { + radix__flush_pwc_lpid(lpid); + return; + } + + rc = plpar_hcall_norets(H_TLB_INVALIDATE, H_TLBIE_P1_ENC(1, 0, 1), + lpid, TLBIEL_INVAL_SET_LPID); + if (rc) + pr_err("KVM: TLB PWC invalidation hcall failed, rc=%ld\n", rc); } static unsigned long kvmppc_radix_update_pte(struct kvm *kvm, pte_t *ptep, @@ -195,23 +282,38 @@ static void kvmppc_pmd_free(pmd_t *pmdp) kmem_cache_free(kvm_pmd_cache, pmdp); } -static void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, - unsigned long gpa, unsigned int shift) +/* Called with kvm->mmu_lock held */ +void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, + unsigned int shift, struct kvm_memory_slot *memslot, + unsigned int lpid) { - unsigned long page_size = 1ul << shift; unsigned long old; + unsigned long gfn = gpa >> PAGE_SHIFT; + unsigned long page_size = PAGE_SIZE; + unsigned long hpa; old = kvmppc_radix_update_pte(kvm, pte, ~0UL, 0, gpa, shift); - kvmppc_radix_tlbie_page(kvm, gpa, shift); - if (old & _PAGE_DIRTY) { - unsigned long gfn = gpa >> PAGE_SHIFT; - struct kvm_memory_slot *memslot; + kvmppc_radix_tlbie_page(kvm, gpa, shift, lpid); + + /* The following only applies to L1 entries */ + if (lpid != kvm->arch.lpid) + return; + if (!memslot) { memslot = gfn_to_memslot(kvm, gfn); - if (memslot && memslot->dirty_bitmap) - kvmppc_update_dirty_map(memslot, gfn, page_size); + if (!memslot) + return; } + if (shift) + page_size = 1ul << shift; + + gpa &= ~(page_size - 1); + hpa = old & PTE_RPN_MASK; + kvmhv_remove_nest_rmap_range(kvm, memslot, gpa, hpa, page_size); + + if ((old & _PAGE_DIRTY) && memslot->dirty_bitmap) + kvmppc_update_dirty_map(memslot, gfn, page_size); } /* @@ -224,7 +326,8 @@ static void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, * and emit a warning if encountered, but there may already be data * corruption due to the unexpected mappings. */ -static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full) +static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full, + unsigned int lpid) { if (full) { memset(pte, 0, sizeof(long) << PTE_INDEX_SIZE); @@ -238,14 +341,15 @@ static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full) WARN_ON_ONCE(1); kvmppc_unmap_pte(kvm, p, pte_pfn(*p) << PAGE_SHIFT, - PAGE_SHIFT); + PAGE_SHIFT, NULL, lpid); } } kvmppc_pte_free(pte); } -static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full) +static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full, + unsigned int lpid) { unsigned long im; pmd_t *p = pmd; @@ -260,20 +364,21 @@ static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full) WARN_ON_ONCE(1); kvmppc_unmap_pte(kvm, (pte_t *)p, pte_pfn(*(pte_t *)p) << PAGE_SHIFT, - PMD_SHIFT); + PMD_SHIFT, NULL, lpid); } } else { pte_t *pte; pte = pte_offset_map(p, 0); - kvmppc_unmap_free_pte(kvm, pte, full); + kvmppc_unmap_free_pte(kvm, pte, full, lpid); pmd_clear(p); } } kvmppc_pmd_free(pmd); } -static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud) +static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud, + unsigned int lpid) { unsigned long iu; pud_t *p = pud; @@ -287,36 +392,40 @@ static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud) pmd_t *pmd; pmd = pmd_offset(p, 0); - kvmppc_unmap_free_pmd(kvm, pmd, true); + kvmppc_unmap_free_pmd(kvm, pmd, true, lpid); pud_clear(p); } } pud_free(kvm->mm, pud); } -void kvmppc_free_radix(struct kvm *kvm) +void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, unsigned int lpid) { unsigned long ig; - pgd_t *pgd; - if (!kvm->arch.pgtable) - return; - pgd = kvm->arch.pgtable; for (ig = 0; ig < PTRS_PER_PGD; ++ig, ++pgd) { pud_t *pud; if (!pgd_present(*pgd)) continue; pud = pud_offset(pgd, 0); - kvmppc_unmap_free_pud(kvm, pud); + kvmppc_unmap_free_pud(kvm, pud, lpid); pgd_clear(pgd); } - pgd_free(kvm->mm, kvm->arch.pgtable); - kvm->arch.pgtable = NULL; +} + +void kvmppc_free_radix(struct kvm *kvm) +{ + if (kvm->arch.pgtable) { + kvmppc_free_pgtable_radix(kvm, kvm->arch.pgtable, + kvm->arch.lpid); + pgd_free(kvm->mm, kvm->arch.pgtable); + kvm->arch.pgtable = NULL; + } } static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd, - unsigned long gpa) + unsigned long gpa, unsigned int lpid) { pte_t *pte = pte_offset_kernel(pmd, 0); @@ -326,13 +435,13 @@ static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd, * flushing the PWC again. */ pmd_clear(pmd); - kvmppc_radix_flush_pwc(kvm); + kvmppc_radix_flush_pwc(kvm, lpid); - kvmppc_unmap_free_pte(kvm, pte, false); + kvmppc_unmap_free_pte(kvm, pte, false, lpid); } static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud, - unsigned long gpa) + unsigned long gpa, unsigned int lpid) { pmd_t *pmd = pmd_offset(pud, 0); @@ -342,9 +451,9 @@ static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud, * so can be freed without flushing the PWC again. */ pud_clear(pud); - kvmppc_radix_flush_pwc(kvm); + kvmppc_radix_flush_pwc(kvm, lpid); - kvmppc_unmap_free_pmd(kvm, pmd, false); + kvmppc_unmap_free_pmd(kvm, pmd, false, lpid); } /* @@ -356,8 +465,10 @@ static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud, */ #define PTE_BITS_MUST_MATCH (~(_PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)) -static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, - unsigned int level, unsigned long mmu_seq) +int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, + unsigned long gpa, unsigned int level, + unsigned long mmu_seq, unsigned int lpid, + unsigned long *rmapp, struct rmap_nested **n_rmap) { pgd_t *pgd; pud_t *pud, *new_pud = NULL; @@ -366,7 +477,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, int ret; /* Traverse the guest's 2nd-level tree, allocate new levels needed */ - pgd = kvm->arch.pgtable + pgd_index(gpa); + pgd = pgtable + pgd_index(gpa); pud = NULL; if (pgd_present(*pgd)) pud = pud_offset(pgd, gpa); @@ -423,7 +534,8 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, goto out_unlock; } /* Valid 1GB page here already, remove it */ - kvmppc_unmap_pte(kvm, (pte_t *)pud, hgpa, PUD_SHIFT); + kvmppc_unmap_pte(kvm, (pte_t *)pud, hgpa, PUD_SHIFT, NULL, + lpid); } if (level == 2) { if (!pud_none(*pud)) { @@ -432,9 +544,11 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, * install a large page, so remove and free the page * table page. */ - kvmppc_unmap_free_pud_entry_table(kvm, pud, gpa); + kvmppc_unmap_free_pud_entry_table(kvm, pud, gpa, lpid); } kvmppc_radix_set_pte_at(kvm, gpa, (pte_t *)pud, pte); + if (rmapp && n_rmap) + kvmhv_insert_nest_rmap(kvm, rmapp, n_rmap); ret = 0; goto out_unlock; } @@ -458,7 +572,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, WARN_ON_ONCE((pmd_val(*pmd) ^ pte_val(pte)) & PTE_BITS_MUST_MATCH); kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd), - 0, pte_val(pte), lgpa, PMD_SHIFT); + 0, pte_val(pte), lgpa, PMD_SHIFT); ret = 0; goto out_unlock; } @@ -472,7 +586,8 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, goto out_unlock; } /* Valid 2MB page here already, remove it */ - kvmppc_unmap_pte(kvm, pmdp_ptep(pmd), lgpa, PMD_SHIFT); + kvmppc_unmap_pte(kvm, pmdp_ptep(pmd), lgpa, PMD_SHIFT, NULL, + lpid); } if (level == 1) { if (!pmd_none(*pmd)) { @@ -481,9 +596,11 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, * install a large page, so remove and free the page * table page. */ - kvmppc_unmap_free_pmd_entry_table(kvm, pmd, gpa); + kvmppc_unmap_free_pmd_entry_table(kvm, pmd, gpa, lpid); } kvmppc_radix_set_pte_at(kvm, gpa, pmdp_ptep(pmd), pte); + if (rmapp && n_rmap) + kvmhv_insert_nest_rmap(kvm, rmapp, n_rmap); ret = 0; goto out_unlock; } @@ -508,6 +625,8 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, goto out_unlock; } kvmppc_radix_set_pte_at(kvm, gpa, ptep, pte); + if (rmapp && n_rmap) + kvmhv_insert_nest_rmap(kvm, rmapp, n_rmap); ret = 0; out_unlock: @@ -521,95 +640,49 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, return ret; } -int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, - unsigned long ea, unsigned long dsisr) +bool kvmppc_hv_handle_set_rc(struct kvm *kvm, pgd_t *pgtable, bool writing, + unsigned long gpa, unsigned int lpid) +{ + unsigned long pgflags; + unsigned int shift; + pte_t *ptep; + + /* + * Need to set an R or C bit in the 2nd-level tables; + * since we are just helping out the hardware here, + * it is sufficient to do what the hardware does. + */ + pgflags = _PAGE_ACCESSED; + if (writing) + pgflags |= _PAGE_DIRTY; + /* + * We are walking the secondary (partition-scoped) page table here. + * We can do this without disabling irq because the Linux MM + * subsystem doesn't do THP splits and collapses on this tree. + */ + ptep = __find_linux_pte(pgtable, gpa, NULL, &shift); + if (ptep && pte_present(*ptep) && (!writing || pte_write(*ptep))) { + kvmppc_radix_update_pte(kvm, ptep, 0, pgflags, gpa, shift); + return true; + } + return false; +} + +int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, + unsigned long gpa, + struct kvm_memory_slot *memslot, + bool writing, bool kvm_ro, + pte_t *inserted_pte, unsigned int *levelp) { struct kvm *kvm = vcpu->kvm; - unsigned long mmu_seq; - unsigned long gpa, gfn, hva; - struct kvm_memory_slot *memslot; struct page *page = NULL; - long ret; - bool writing; + unsigned long mmu_seq; + unsigned long hva, gfn = gpa >> PAGE_SHIFT; bool upgrade_write = false; bool *upgrade_p = &upgrade_write; pte_t pte, *ptep; - unsigned long pgflags; unsigned int shift, level; - - /* Check for unusual errors */ - if (dsisr & DSISR_UNSUPP_MMU) { - pr_err("KVM: Got unsupported MMU fault\n"); - return -EFAULT; - } - if (dsisr & DSISR_BADACCESS) { - /* Reflect to the guest as DSI */ - pr_err("KVM: Got radix HV page fault with DSISR=%lx\n", dsisr); - kvmppc_core_queue_data_storage(vcpu, ea, dsisr); - return RESUME_GUEST; - } - - /* Translate the logical address and get the page */ - gpa = vcpu->arch.fault_gpa & ~0xfffUL; - gpa &= ~0xF000000000000000ul; - gfn = gpa >> PAGE_SHIFT; - if (!(dsisr & DSISR_PRTABLE_FAULT)) - gpa |= ea & 0xfff; - memslot = gfn_to_memslot(kvm, gfn); - - /* No memslot means it's an emulated MMIO region */ - if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) { - if (dsisr & (DSISR_PRTABLE_FAULT | DSISR_BADACCESS | - DSISR_SET_RC)) { - /* - * Bad address in guest page table tree, or other - * unusual error - reflect it to the guest as DSI. - */ - kvmppc_core_queue_data_storage(vcpu, ea, dsisr); - return RESUME_GUEST; - } - return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea, - dsisr & DSISR_ISSTORE); - } - - writing = (dsisr & DSISR_ISSTORE) != 0; - if (memslot->flags & KVM_MEM_READONLY) { - if (writing) { - /* give the guest a DSI */ - dsisr = DSISR_ISSTORE | DSISR_PROTFAULT; - kvmppc_core_queue_data_storage(vcpu, ea, dsisr); - return RESUME_GUEST; - } - upgrade_p = NULL; - } - - if (dsisr & DSISR_SET_RC) { - /* - * Need to set an R or C bit in the 2nd-level tables; - * since we are just helping out the hardware here, - * it is sufficient to do what the hardware does. - */ - pgflags = _PAGE_ACCESSED; - if (writing) - pgflags |= _PAGE_DIRTY; - /* - * We are walking the secondary page table here. We can do this - * without disabling irq. - */ - spin_lock(&kvm->mmu_lock); - ptep = __find_linux_pte(kvm->arch.pgtable, - gpa, NULL, &shift); - if (ptep && pte_present(*ptep) && - (!writing || pte_write(*ptep))) { - kvmppc_radix_update_pte(kvm, ptep, 0, pgflags, - gpa, shift); - dsisr &= ~DSISR_SET_RC; - } - spin_unlock(&kvm->mmu_lock); - if (!(dsisr & (DSISR_BAD_FAULT_64S | DSISR_NOHPTE | - DSISR_PROTFAULT | DSISR_SET_RC))) - return RESUME_GUEST; - } + int ret; /* used to check for invalidations in progress */ mmu_seq = kvm->mmu_notifier_seq; @@ -622,7 +695,7 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, * is that the page is writable. */ hva = gfn_to_hva_memslot(memslot, gfn); - if (upgrade_p && __get_user_pages_fast(hva, 1, 1, &page) == 1) { + if (!kvm_ro && __get_user_pages_fast(hva, 1, 1, &page) == 1) { upgrade_write = true; } else { unsigned long pfn; @@ -690,7 +763,12 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, } /* Allocate space in the tree and write the PTE */ - ret = kvmppc_create_pte(kvm, pte, gpa, level, mmu_seq); + ret = kvmppc_create_pte(kvm, kvm->arch.pgtable, pte, gpa, level, + mmu_seq, kvm->arch.lpid, NULL, NULL); + if (inserted_pte) + *inserted_pte = pte; + if (levelp) + *levelp = level; if (page) { if (!ret && (pte_val(pte) & _PAGE_WRITE)) @@ -698,6 +776,82 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, put_page(page); } + return ret; +} + +int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned long ea, unsigned long dsisr) +{ + struct kvm *kvm = vcpu->kvm; + unsigned long gpa, gfn; + struct kvm_memory_slot *memslot; + long ret; + bool writing = !!(dsisr & DSISR_ISSTORE); + bool kvm_ro = false; + + /* Check for unusual errors */ + if (dsisr & DSISR_UNSUPP_MMU) { + pr_err("KVM: Got unsupported MMU fault\n"); + return -EFAULT; + } + if (dsisr & DSISR_BADACCESS) { + /* Reflect to the guest as DSI */ + pr_err("KVM: Got radix HV page fault with DSISR=%lx\n", dsisr); + kvmppc_core_queue_data_storage(vcpu, ea, dsisr); + return RESUME_GUEST; + } + + /* Translate the logical address */ + gpa = vcpu->arch.fault_gpa & ~0xfffUL; + gpa &= ~0xF000000000000000ul; + gfn = gpa >> PAGE_SHIFT; + if (!(dsisr & DSISR_PRTABLE_FAULT)) + gpa |= ea & 0xfff; + + /* Get the corresponding memslot */ + memslot = gfn_to_memslot(kvm, gfn); + + /* No memslot means it's an emulated MMIO region */ + if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) { + if (dsisr & (DSISR_PRTABLE_FAULT | DSISR_BADACCESS | + DSISR_SET_RC)) { + /* + * Bad address in guest page table tree, or other + * unusual error - reflect it to the guest as DSI. + */ + kvmppc_core_queue_data_storage(vcpu, ea, dsisr); + return RESUME_GUEST; + } + return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea, writing); + } + + if (memslot->flags & KVM_MEM_READONLY) { + if (writing) { + /* give the guest a DSI */ + kvmppc_core_queue_data_storage(vcpu, ea, DSISR_ISSTORE | + DSISR_PROTFAULT); + return RESUME_GUEST; + } + kvm_ro = true; + } + + /* Failed to set the reference/change bits */ + if (dsisr & DSISR_SET_RC) { + spin_lock(&kvm->mmu_lock); + if (kvmppc_hv_handle_set_rc(kvm, kvm->arch.pgtable, + writing, gpa, kvm->arch.lpid)) + dsisr &= ~DSISR_SET_RC; + spin_unlock(&kvm->mmu_lock); + + if (!(dsisr & (DSISR_BAD_FAULT_64S | DSISR_NOHPTE | + DSISR_PROTFAULT | DSISR_SET_RC))) + return RESUME_GUEST; + } + + /* Try to insert a pte */ + ret = kvmppc_book3s_instantiate_page(vcpu, gpa, memslot, writing, + kvm_ro, NULL, NULL); + if (ret == 0 || ret == -EAGAIN) ret = RESUME_GUEST; return ret; @@ -710,20 +864,11 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, pte_t *ptep; unsigned long gpa = gfn << PAGE_SHIFT; unsigned int shift; - unsigned long old; ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift); - if (ptep && pte_present(*ptep)) { - old = kvmppc_radix_update_pte(kvm, ptep, ~0UL, 0, - gpa, shift); - kvmppc_radix_tlbie_page(kvm, gpa, shift); - if ((old & _PAGE_DIRTY) && memslot->dirty_bitmap) { - unsigned long psize = PAGE_SIZE; - if (shift) - psize = 1ul << shift; - kvmppc_update_dirty_map(memslot, gfn, psize); - } - } + if (ptep && pte_present(*ptep)) + kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot, + kvm->arch.lpid); return 0; } @@ -778,7 +923,7 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm, ret = 1 << (shift - PAGE_SHIFT); kvmppc_radix_update_pte(kvm, ptep, _PAGE_DIRTY, 0, gpa, shift); - kvmppc_radix_tlbie_page(kvm, gpa, shift); + kvmppc_radix_tlbie_page(kvm, gpa, shift, kvm->arch.lpid); } return ret; } @@ -863,6 +1008,215 @@ static void pmd_ctor(void *addr) memset(addr, 0, RADIX_PMD_TABLE_SIZE); } +struct debugfs_radix_state { + struct kvm *kvm; + struct mutex mutex; + unsigned long gpa; + int lpid; + int chars_left; + int buf_index; + char buf[128]; + u8 hdr; +}; + +static int debugfs_radix_open(struct inode *inode, struct file *file) +{ + struct kvm *kvm = inode->i_private; + struct debugfs_radix_state *p; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + kvm_get_kvm(kvm); + p->kvm = kvm; + mutex_init(&p->mutex); + file->private_data = p; + + return nonseekable_open(inode, file); +} + +static int debugfs_radix_release(struct inode *inode, struct file *file) +{ + struct debugfs_radix_state *p = file->private_data; + + kvm_put_kvm(p->kvm); + kfree(p); + return 0; +} + +static ssize_t debugfs_radix_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + struct debugfs_radix_state *p = file->private_data; + ssize_t ret, r; + unsigned long n; + struct kvm *kvm; + unsigned long gpa; + pgd_t *pgt; + struct kvm_nested_guest *nested; + pgd_t pgd, *pgdp; + pud_t pud, *pudp; + pmd_t pmd, *pmdp; + pte_t *ptep; + int shift; + unsigned long pte; + + kvm = p->kvm; + if (!kvm_is_radix(kvm)) + return 0; + + ret = mutex_lock_interruptible(&p->mutex); + if (ret) + return ret; + + if (p->chars_left) { + n = p->chars_left; + if (n > len) + n = len; + r = copy_to_user(buf, p->buf + p->buf_index, n); + n -= r; + p->chars_left -= n; + p->buf_index += n; + buf += n; + len -= n; + ret = n; + if (r) { + if (!n) + ret = -EFAULT; + goto out; + } + } + + gpa = p->gpa; + nested = NULL; + pgt = NULL; + while (len != 0 && p->lpid >= 0) { + if (gpa >= RADIX_PGTABLE_RANGE) { + gpa = 0; + pgt = NULL; + if (nested) { + kvmhv_put_nested(nested); + nested = NULL; + } + p->lpid = kvmhv_nested_next_lpid(kvm, p->lpid); + p->hdr = 0; + if (p->lpid < 0) + break; + } + if (!pgt) { + if (p->lpid == 0) { + pgt = kvm->arch.pgtable; + } else { + nested = kvmhv_get_nested(kvm, p->lpid, false); + if (!nested) { + gpa = RADIX_PGTABLE_RANGE; + continue; + } + pgt = nested->shadow_pgtable; + } + } + n = 0; + if (!p->hdr) { + if (p->lpid > 0) + n = scnprintf(p->buf, sizeof(p->buf), + "\nNested LPID %d: ", p->lpid); + n += scnprintf(p->buf + n, sizeof(p->buf) - n, + "pgdir: %lx\n", (unsigned long)pgt); + p->hdr = 1; + goto copy; + } + + pgdp = pgt + pgd_index(gpa); + pgd = READ_ONCE(*pgdp); + if (!(pgd_val(pgd) & _PAGE_PRESENT)) { + gpa = (gpa & PGDIR_MASK) + PGDIR_SIZE; + continue; + } + + pudp = pud_offset(&pgd, gpa); + pud = READ_ONCE(*pudp); + if (!(pud_val(pud) & _PAGE_PRESENT)) { + gpa = (gpa & PUD_MASK) + PUD_SIZE; + continue; + } + if (pud_val(pud) & _PAGE_PTE) { + pte = pud_val(pud); + shift = PUD_SHIFT; + goto leaf; + } + + pmdp = pmd_offset(&pud, gpa); + pmd = READ_ONCE(*pmdp); + if (!(pmd_val(pmd) & _PAGE_PRESENT)) { + gpa = (gpa & PMD_MASK) + PMD_SIZE; + continue; + } + if (pmd_val(pmd) & _PAGE_PTE) { + pte = pmd_val(pmd); + shift = PMD_SHIFT; + goto leaf; + } + + ptep = pte_offset_kernel(&pmd, gpa); + pte = pte_val(READ_ONCE(*ptep)); + if (!(pte & _PAGE_PRESENT)) { + gpa += PAGE_SIZE; + continue; + } + shift = PAGE_SHIFT; + leaf: + n = scnprintf(p->buf, sizeof(p->buf), + " %lx: %lx %d\n", gpa, pte, shift); + gpa += 1ul << shift; + copy: + p->chars_left = n; + if (n > len) + n = len; + r = copy_to_user(buf, p->buf, n); + n -= r; + p->chars_left -= n; + p->buf_index = n; + buf += n; + len -= n; + ret += n; + if (r) { + if (!ret) + ret = -EFAULT; + break; + } + } + p->gpa = gpa; + if (nested) + kvmhv_put_nested(nested); + + out: + mutex_unlock(&p->mutex); + return ret; +} + +static ssize_t debugfs_radix_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + return -EACCES; +} + +static const struct file_operations debugfs_radix_fops = { + .owner = THIS_MODULE, + .open = debugfs_radix_open, + .release = debugfs_radix_release, + .read = debugfs_radix_read, + .write = debugfs_radix_write, + .llseek = generic_file_llseek, +}; + +void kvmhv_radix_debugfs_init(struct kvm *kvm) +{ + kvm->arch.radix_dentry = debugfs_create_file("radix", 0400, + kvm->arch.debugfs_dir, kvm, + &debugfs_radix_fops); +} + int kvmppc_radix_init(void) { unsigned long size = sizeof(void *) << RADIX_PTE_INDEX_SIZE; diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 9a3f2646ecc7..62a8d03ba7e9 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -363,6 +363,40 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, return ret; } +static long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, + unsigned long tce) +{ + unsigned long gpa = tce & ~(TCE_PCI_READ | TCE_PCI_WRITE); + enum dma_data_direction dir = iommu_tce_direction(tce); + struct kvmppc_spapr_tce_iommu_table *stit; + unsigned long ua = 0; + + /* Allow userspace to poison TCE table */ + if (dir == DMA_NONE) + return H_SUCCESS; + + if (iommu_tce_check_gpa(stt->page_shift, gpa)) + return H_TOO_HARD; + + if (kvmppc_tce_to_ua(stt->kvm, tce, &ua, NULL)) + return H_TOO_HARD; + + list_for_each_entry_rcu(stit, &stt->iommu_tables, next) { + unsigned long hpa = 0; + struct mm_iommu_table_group_mem_t *mem; + long shift = stit->tbl->it_page_shift; + + mem = mm_iommu_lookup(stt->kvm->mm, ua, 1ULL << shift); + if (!mem) + return H_TOO_HARD; + + if (mm_iommu_ua_to_hpa(mem, ua, shift, &hpa)) + return H_TOO_HARD; + } + + return H_SUCCESS; +} + static void kvmppc_clear_tce(struct iommu_table *tbl, unsigned long entry) { unsigned long hpa = 0; @@ -376,11 +410,10 @@ static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm, { struct mm_iommu_table_group_mem_t *mem = NULL; const unsigned long pgsize = 1ULL << tbl->it_page_shift; - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY(tbl, entry); + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); if (!pua) - /* it_userspace allocation might be delayed */ - return H_TOO_HARD; + return H_SUCCESS; mem = mm_iommu_lookup(kvm->mm, be64_to_cpu(*pua), pgsize); if (!mem) @@ -401,7 +434,7 @@ static long kvmppc_tce_iommu_do_unmap(struct kvm *kvm, long ret; if (WARN_ON_ONCE(iommu_tce_xchg(tbl, entry, &hpa, &dir))) - return H_HARDWARE; + return H_TOO_HARD; if (dir == DMA_NONE) return H_SUCCESS; @@ -449,15 +482,15 @@ long kvmppc_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl, return H_TOO_HARD; if (WARN_ON_ONCE(mm_iommu_ua_to_hpa(mem, ua, tbl->it_page_shift, &hpa))) - return H_HARDWARE; + return H_TOO_HARD; if (mm_iommu_mapped_inc(mem)) - return H_CLOSED; + return H_TOO_HARD; ret = iommu_tce_xchg(tbl, entry, &hpa, &dir); if (WARN_ON_ONCE(ret)) { mm_iommu_mapped_dec(mem); - return H_HARDWARE; + return H_TOO_HARD; } if (dir != DMA_NONE) @@ -517,8 +550,7 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, idx = srcu_read_lock(&vcpu->kvm->srcu); - if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm, - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) { + if ((dir != DMA_NONE) && kvmppc_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) { ret = H_PARAMETER; goto unlock_exit; } @@ -533,14 +565,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl, entry, ua, dir); - if (ret == H_SUCCESS) - continue; - - if (ret == H_TOO_HARD) + if (ret != H_SUCCESS) { + kvmppc_clear_tce(stit->tbl, entry); goto unlock_exit; - - WARN_ON_ONCE(1); - kvmppc_clear_tce(stit->tbl, entry); + } } kvmppc_tce_put(stt, entry, tce); @@ -583,7 +611,7 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, return ret; idx = srcu_read_lock(&vcpu->kvm->srcu); - if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, NULL)) { + if (kvmppc_tce_to_ua(vcpu->kvm, tce_list, &ua, NULL)) { ret = H_TOO_HARD; goto unlock_exit; } @@ -599,10 +627,26 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, ret = kvmppc_tce_validate(stt, tce); if (ret != H_SUCCESS) goto unlock_exit; + } + + for (i = 0; i < npages; ++i) { + /* + * This looks unsafe, because we validate, then regrab + * the TCE from userspace which could have been changed by + * another thread. + * + * But it actually is safe, because the relevant checks will be + * re-executed in the following code. If userspace tries to + * change this dodgily it will result in a messier failure mode + * but won't threaten the host. + */ + if (get_user(tce, tces + i)) { + ret = H_TOO_HARD; + goto unlock_exit; + } + tce = be64_to_cpu(tce); - if (kvmppc_gpa_to_ua(vcpu->kvm, - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), - &ua, NULL)) + if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) return H_PARAMETER; list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { @@ -610,14 +654,10 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, stit->tbl, entry + i, ua, iommu_tce_direction(tce)); - if (ret == H_SUCCESS) - continue; - - if (ret == H_TOO_HARD) + if (ret != H_SUCCESS) { + kvmppc_clear_tce(stit->tbl, entry); goto unlock_exit; - - WARN_ON_ONCE(1); - kvmppc_clear_tce(stit->tbl, entry); + } } kvmppc_tce_put(stt, entry + i, tce); diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index 6821ead4b4eb..2206bc729b9a 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c @@ -87,6 +87,7 @@ struct kvmppc_spapr_tce_table *kvmppc_find_table(struct kvm *kvm, } EXPORT_SYMBOL_GPL(kvmppc_find_table); +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* * Validates TCE address. * At the moment flags and page mask are validated. @@ -94,14 +95,14 @@ EXPORT_SYMBOL_GPL(kvmppc_find_table); * to the table and user space is supposed to process them), we can skip * checking other things (such as TCE is a guest RAM address or the page * was actually allocated). - * - * WARNING: This will be called in real-mode on HV KVM and virtual - * mode on PR KVM */ -long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) +static long kvmppc_rm_tce_validate(struct kvmppc_spapr_tce_table *stt, + unsigned long tce) { unsigned long gpa = tce & ~(TCE_PCI_READ | TCE_PCI_WRITE); enum dma_data_direction dir = iommu_tce_direction(tce); + struct kvmppc_spapr_tce_iommu_table *stit; + unsigned long ua = 0; /* Allow userspace to poison TCE table */ if (dir == DMA_NONE) @@ -110,9 +111,25 @@ long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) if (iommu_tce_check_gpa(stt->page_shift, gpa)) return H_PARAMETER; + if (kvmppc_tce_to_ua(stt->kvm, tce, &ua, NULL)) + return H_TOO_HARD; + + list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { + unsigned long hpa = 0; + struct mm_iommu_table_group_mem_t *mem; + long shift = stit->tbl->it_page_shift; + + mem = mm_iommu_lookup_rm(stt->kvm->mm, ua, 1ULL << shift); + if (!mem) + return H_TOO_HARD; + + if (mm_iommu_ua_to_hpa_rm(mem, ua, shift, &hpa)) + return H_TOO_HARD; + } + return H_SUCCESS; } -EXPORT_SYMBOL_GPL(kvmppc_tce_validate); +#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ /* Note on the use of page_address() in real mode, * @@ -164,10 +181,10 @@ void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt, } EXPORT_SYMBOL_GPL(kvmppc_tce_put); -long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, +long kvmppc_tce_to_ua(struct kvm *kvm, unsigned long tce, unsigned long *ua, unsigned long **prmap) { - unsigned long gfn = gpa >> PAGE_SHIFT; + unsigned long gfn = tce >> PAGE_SHIFT; struct kvm_memory_slot *memslot; memslot = search_memslots(kvm_memslots(kvm), gfn); @@ -175,7 +192,7 @@ long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, return -EINVAL; *ua = __gfn_to_hva_memslot(memslot, gfn) | - (gpa & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); + (tce & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE if (prmap) @@ -184,7 +201,7 @@ long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, return 0; } -EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua); +EXPORT_SYMBOL_GPL(kvmppc_tce_to_ua); #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE static long iommu_tce_xchg_rm(struct mm_struct *mm, struct iommu_table *tbl, @@ -197,7 +214,7 @@ static long iommu_tce_xchg_rm(struct mm_struct *mm, struct iommu_table *tbl, if (!ret && ((*direction == DMA_FROM_DEVICE) || (*direction == DMA_BIDIRECTIONAL))) { - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); /* * kvmppc_rm_tce_iommu_do_map() updates the UA cache after * calling this so we still get here a valid UA. @@ -223,7 +240,7 @@ static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, { struct mm_iommu_table_group_mem_t *mem = NULL; const unsigned long pgsize = 1ULL << tbl->it_page_shift; - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); if (!pua) /* it_userspace allocation might be delayed */ @@ -287,7 +304,7 @@ static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl, { long ret; unsigned long hpa = 0; - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); struct mm_iommu_table_group_mem_t *mem; if (!pua) @@ -300,10 +317,10 @@ static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl, if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, tbl->it_page_shift, &hpa))) - return H_HARDWARE; + return H_TOO_HARD; if (WARN_ON_ONCE_RM(mm_iommu_mapped_inc(mem))) - return H_CLOSED; + return H_TOO_HARD; ret = iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir); if (ret) { @@ -368,13 +385,12 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, if (ret != H_SUCCESS) return ret; - ret = kvmppc_tce_validate(stt, tce); + ret = kvmppc_rm_tce_validate(stt, tce); if (ret != H_SUCCESS) return ret; dir = iommu_tce_direction(tce); - if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm, - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) + if ((dir != DMA_NONE) && kvmppc_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) return H_PARAMETER; entry = ioba >> stt->page_shift; @@ -387,14 +403,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, stit->tbl, entry, ua, dir); - if (ret == H_SUCCESS) - continue; - - if (ret == H_TOO_HARD) + if (ret != H_SUCCESS) { + kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); return ret; - - WARN_ON_ONCE_RM(1); - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); + } } kvmppc_tce_put(stt, entry, tce); @@ -480,7 +492,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, */ struct mm_iommu_table_group_mem_t *mem; - if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, NULL)) + if (kvmppc_tce_to_ua(vcpu->kvm, tce_list, &ua, NULL)) return H_TOO_HARD; mem = mm_iommu_lookup_rm(vcpu->kvm->mm, ua, IOMMU_PAGE_SIZE_4K); @@ -496,12 +508,12 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, * We do not require memory to be preregistered in this case * so lock rmap and do __find_linux_pte_or_hugepte(). */ - if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, &rmap)) + if (kvmppc_tce_to_ua(vcpu->kvm, tce_list, &ua, &rmap)) return H_TOO_HARD; rmap = (void *) vmalloc_to_phys(rmap); if (WARN_ON_ONCE_RM(!rmap)) - return H_HARDWARE; + return H_TOO_HARD; /* * Synchronize with the MMU notifier callbacks in @@ -521,14 +533,16 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, for (i = 0; i < npages; ++i) { unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); - ret = kvmppc_tce_validate(stt, tce); + ret = kvmppc_rm_tce_validate(stt, tce); if (ret != H_SUCCESS) goto unlock_exit; + } + + for (i = 0; i < npages; ++i) { + unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); ua = 0; - if (kvmppc_gpa_to_ua(vcpu->kvm, - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), - &ua, NULL)) + if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) return H_PARAMETER; list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { @@ -536,14 +550,11 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, stit->tbl, entry + i, ua, iommu_tce_direction(tce)); - if (ret == H_SUCCESS) - continue; - - if (ret == H_TOO_HARD) + if (ret != H_SUCCESS) { + kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, + entry); goto unlock_exit; - - WARN_ON_ONCE_RM(1); - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); + } } kvmppc_tce_put(stt, entry + i, tce); diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index 36b11c5a0dbb..8c7e933e942e 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -36,7 +36,6 @@ #define OP_31_XOP_MTSR 210 #define OP_31_XOP_MTSRIN 242 #define OP_31_XOP_TLBIEL 274 -#define OP_31_XOP_TLBIE 306 /* Opcode is officially reserved, reuse it as sc 1 when sc 1 doesn't trap */ #define OP_31_XOP_FAKE_SC1 308 #define OP_31_XOP_SLBMTE 402 @@ -110,7 +109,7 @@ static inline void kvmppc_copyto_vcpu_tm(struct kvm_vcpu *vcpu) vcpu->arch.ctr_tm = vcpu->arch.regs.ctr; vcpu->arch.tar_tm = vcpu->arch.tar; vcpu->arch.lr_tm = vcpu->arch.regs.link; - vcpu->arch.cr_tm = vcpu->arch.cr; + vcpu->arch.cr_tm = vcpu->arch.regs.ccr; vcpu->arch.xer_tm = vcpu->arch.regs.xer; vcpu->arch.vrsave_tm = vcpu->arch.vrsave; } @@ -129,7 +128,7 @@ static inline void kvmppc_copyfrom_vcpu_tm(struct kvm_vcpu *vcpu) vcpu->arch.regs.ctr = vcpu->arch.ctr_tm; vcpu->arch.tar = vcpu->arch.tar_tm; vcpu->arch.regs.link = vcpu->arch.lr_tm; - vcpu->arch.cr = vcpu->arch.cr_tm; + vcpu->arch.regs.ccr = vcpu->arch.cr_tm; vcpu->arch.regs.xer = vcpu->arch.xer_tm; vcpu->arch.vrsave = vcpu->arch.vrsave_tm; } @@ -141,7 +140,7 @@ static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val) uint64_t texasr; /* CR0 = 0 | MSR[TS] | 0 */ - vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & ~(CR0_MASK << CR0_SHIFT)) | (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) << CR0_SHIFT); @@ -220,7 +219,7 @@ void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val) tm_abort(ra_val); /* CR0 = 0 | MSR[TS] | 0 */ - vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) | + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & ~(CR0_MASK << CR0_SHIFT)) | (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1)) << CR0_SHIFT); @@ -494,8 +493,8 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, if (!(kvmppc_get_msr(vcpu) & MSR_PR)) { preempt_disable(); - vcpu->arch.cr = (CR0_TBEGIN_FAILURE | - (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT))); + vcpu->arch.regs.ccr = (CR0_TBEGIN_FAILURE | + (vcpu->arch.regs.ccr & ~(CR0_MASK << CR0_SHIFT))); vcpu->arch.texasr = (TEXASR_FS | TEXASR_EXACT | (((u64)(TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT)) diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 3e3a71594e63..bf8def2159c3 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -50,6 +50,7 @@ #include <asm/reg.h> #include <asm/ppc-opcode.h> #include <asm/asm-prototypes.h> +#include <asm/archrandom.h> #include <asm/debug.h> #include <asm/disassemble.h> #include <asm/cputable.h> @@ -104,6 +105,10 @@ static bool indep_threads_mode = true; module_param(indep_threads_mode, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(indep_threads_mode, "Independent-threads mode (only on POWER9)"); +static bool one_vm_per_core; +module_param(one_vm_per_core, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(one_vm_per_core, "Only run vCPUs from the same VM on a core (requires indep_threads_mode=N)"); + #ifdef CONFIG_KVM_XICS static struct kernel_param_ops module_param_ops = { .set = param_set_int, @@ -117,6 +122,16 @@ module_param_cb(h_ipi_redirect, &module_param_ops, &h_ipi_redirect, 0644); MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core"); #endif +/* If set, guests are allowed to create and control nested guests */ +static bool nested = true; +module_param(nested, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(nested, "Enable nested virtualization (only on POWER9)"); + +static inline bool nesting_enabled(struct kvm *kvm) +{ + return kvm->arch.nested_enable && kvm_is_radix(kvm); +} + /* If set, the threads on each CPU core have to be in the same MMU mode */ static bool no_mixing_hpt_and_radix; @@ -173,6 +188,10 @@ static bool kvmppc_ipi_thread(int cpu) { unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); + /* If we're a nested hypervisor, fall back to ordinary IPIs for now */ + if (kvmhv_on_pseries()) + return false; + /* On POWER9 we can use msgsnd to IPI any cpu */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { msg |= get_hard_smp_processor_id(cpu); @@ -410,8 +429,8 @@ static void kvmppc_dump_regs(struct kvm_vcpu *vcpu) vcpu->arch.shregs.sprg0, vcpu->arch.shregs.sprg1); pr_err("sprg2 = %.16llx sprg3 = %.16llx\n", vcpu->arch.shregs.sprg2, vcpu->arch.shregs.sprg3); - pr_err("cr = %.8x xer = %.16lx dsisr = %.8x\n", - vcpu->arch.cr, vcpu->arch.regs.xer, vcpu->arch.shregs.dsisr); + pr_err("cr = %.8lx xer = %.16lx dsisr = %.8x\n", + vcpu->arch.regs.ccr, vcpu->arch.regs.xer, vcpu->arch.shregs.dsisr); pr_err("dar = %.16llx\n", vcpu->arch.shregs.dar); pr_err("fault dar = %.16lx dsisr = %.8x\n", vcpu->arch.fault_dar, vcpu->arch.fault_dsisr); @@ -730,8 +749,7 @@ static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu) /* * Ensure that the read of vcore->dpdes comes after the read * of vcpu->doorbell_request. This barrier matches the - * lwsync in book3s_hv_rmhandlers.S just before the - * fast_guest_return label. + * smb_wmb() in kvmppc_guest_entry_inject(). */ smp_rmb(); vc = vcpu->arch.vcore; @@ -912,6 +930,19 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) break; } return RESUME_HOST; + case H_SET_DABR: + ret = kvmppc_h_set_dabr(vcpu, kvmppc_get_gpr(vcpu, 4)); + break; + case H_SET_XDABR: + ret = kvmppc_h_set_xdabr(vcpu, kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5)); + break; + case H_GET_TCE: + ret = kvmppc_h_get_tce(vcpu, kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5)); + if (ret == H_TOO_HARD) + return RESUME_HOST; + break; case H_PUT_TCE: ret = kvmppc_h_put_tce(vcpu, kvmppc_get_gpr(vcpu, 4), kvmppc_get_gpr(vcpu, 5), @@ -935,6 +966,32 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) if (ret == H_TOO_HARD) return RESUME_HOST; break; + case H_RANDOM: + if (!powernv_get_random_long(&vcpu->arch.regs.gpr[4])) + ret = H_HARDWARE; + break; + + case H_SET_PARTITION_TABLE: + ret = H_FUNCTION; + if (nesting_enabled(vcpu->kvm)) + ret = kvmhv_set_partition_table(vcpu); + break; + case H_ENTER_NESTED: + ret = H_FUNCTION; + if (!nesting_enabled(vcpu->kvm)) + break; + ret = kvmhv_enter_nested_guest(vcpu); + if (ret == H_INTERRUPT) { + kvmppc_set_gpr(vcpu, 3, 0); + return -EINTR; + } + break; + case H_TLB_INVALIDATE: + ret = H_FUNCTION; + if (nesting_enabled(vcpu->kvm)) + ret = kvmhv_do_nested_tlbie(vcpu); + break; + default: return RESUME_HOST; } @@ -943,6 +1000,24 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) return RESUME_GUEST; } +/* + * Handle H_CEDE in the nested virtualization case where we haven't + * called the real-mode hcall handlers in book3s_hv_rmhandlers.S. + * This has to be done early, not in kvmppc_pseries_do_hcall(), so + * that the cede logic in kvmppc_run_single_vcpu() works properly. + */ +static void kvmppc_nested_cede(struct kvm_vcpu *vcpu) +{ + vcpu->arch.shregs.msr |= MSR_EE; + vcpu->arch.ceded = 1; + smp_mb(); + if (vcpu->arch.prodded) { + vcpu->arch.prodded = 0; + smp_mb(); + vcpu->arch.ceded = 0; + } +} + static int kvmppc_hcall_impl_hv(unsigned long cmd) { switch (cmd) { @@ -1085,7 +1160,6 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu) return RESUME_GUEST; } -/* Called with vcpu->arch.vcore->lock held */ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, struct task_struct *tsk) { @@ -1190,7 +1264,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, break; case BOOK3S_INTERRUPT_H_INST_STORAGE: vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); - vcpu->arch.fault_dsisr = 0; + vcpu->arch.fault_dsisr = vcpu->arch.shregs.msr & + DSISR_SRR1_MATCH_64S; + if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) + vcpu->arch.fault_dsisr |= DSISR_ISSTORE; r = RESUME_PAGE_FAULT; break; /* @@ -1206,10 +1283,7 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, swab32(vcpu->arch.emul_inst) : vcpu->arch.emul_inst; if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) { - /* Need vcore unlocked to call kvmppc_get_last_inst */ - spin_unlock(&vcpu->arch.vcore->lock); r = kvmppc_emulate_debug_inst(run, vcpu); - spin_lock(&vcpu->arch.vcore->lock); } else { kvmppc_core_queue_program(vcpu, SRR1_PROGILL); r = RESUME_GUEST; @@ -1225,12 +1299,8 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: r = EMULATE_FAIL; if (((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) && - cpu_has_feature(CPU_FTR_ARCH_300)) { - /* Need vcore unlocked to call kvmppc_get_last_inst */ - spin_unlock(&vcpu->arch.vcore->lock); + cpu_has_feature(CPU_FTR_ARCH_300)) r = kvmppc_emulate_doorbell_instr(vcpu); - spin_lock(&vcpu->arch.vcore->lock); - } if (r == EMULATE_FAIL) { kvmppc_core_queue_program(vcpu, SRR1_PROGILL); r = RESUME_GUEST; @@ -1265,6 +1335,104 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, return r; } +static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) +{ + int r; + int srcu_idx; + + vcpu->stat.sum_exits++; + + /* + * This can happen if an interrupt occurs in the last stages + * of guest entry or the first stages of guest exit (i.e. after + * setting paca->kvm_hstate.in_guest to KVM_GUEST_MODE_GUEST_HV + * and before setting it to KVM_GUEST_MODE_HOST_HV). + * That can happen due to a bug, or due to a machine check + * occurring at just the wrong time. + */ + if (vcpu->arch.shregs.msr & MSR_HV) { + pr_emerg("KVM trap in HV mode while nested!\n"); + pr_emerg("trap=0x%x | pc=0x%lx | msr=0x%llx\n", + vcpu->arch.trap, kvmppc_get_pc(vcpu), + vcpu->arch.shregs.msr); + kvmppc_dump_regs(vcpu); + return RESUME_HOST; + } + switch (vcpu->arch.trap) { + /* We're good on these - the host merely wanted to get our attention */ + case BOOK3S_INTERRUPT_HV_DECREMENTER: + vcpu->stat.dec_exits++; + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_EXTERNAL: + vcpu->stat.ext_intr_exits++; + r = RESUME_HOST; + break; + case BOOK3S_INTERRUPT_H_DOORBELL: + case BOOK3S_INTERRUPT_H_VIRT: + vcpu->stat.ext_intr_exits++; + r = RESUME_GUEST; + break; + /* SR/HMI/PMI are HV interrupts that host has handled. Resume guest.*/ + case BOOK3S_INTERRUPT_HMI: + case BOOK3S_INTERRUPT_PERFMON: + case BOOK3S_INTERRUPT_SYSTEM_RESET: + r = RESUME_GUEST; + break; + case BOOK3S_INTERRUPT_MACHINE_CHECK: + /* Pass the machine check to the L1 guest */ + r = RESUME_HOST; + /* Print the MCE event to host console. */ + machine_check_print_event_info(&vcpu->arch.mce_evt, false); + break; + /* + * We get these next two if the guest accesses a page which it thinks + * it has mapped but which is not actually present, either because + * it is for an emulated I/O device or because the corresonding + * host page has been paged out. + */ + case BOOK3S_INTERRUPT_H_DATA_STORAGE: + srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); + r = kvmhv_nested_page_fault(vcpu); + srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); + break; + case BOOK3S_INTERRUPT_H_INST_STORAGE: + vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); + vcpu->arch.fault_dsisr = kvmppc_get_msr(vcpu) & + DSISR_SRR1_MATCH_64S; + if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) + vcpu->arch.fault_dsisr |= DSISR_ISSTORE; + srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); + r = kvmhv_nested_page_fault(vcpu); + srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); + break; + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + case BOOK3S_INTERRUPT_HV_SOFTPATCH: + /* + * This occurs for various TM-related instructions that + * we need to emulate on POWER9 DD2.2. We have already + * handled the cases where the guest was in real-suspend + * mode and was transitioning to transactional state. + */ + r = kvmhv_p9_tm_emulation(vcpu); + break; +#endif + + case BOOK3S_INTERRUPT_HV_RM_HARD: + vcpu->arch.trap = 0; + r = RESUME_GUEST; + if (!xive_enabled()) + kvmppc_xics_rm_complete(vcpu, 0); + break; + default: + r = RESUME_HOST; + break; + } + + return r; +} + static int kvm_arch_vcpu_ioctl_get_sregs_hv(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { @@ -1555,6 +1723,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_ONLINE: *val = get_reg_val(id, vcpu->arch.online); break; + case KVM_REG_PPC_PTCR: + *val = get_reg_val(id, vcpu->kvm->arch.l1_ptcr); + break; default: r = -EINVAL; break; @@ -1786,6 +1957,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, atomic_dec(&vcpu->arch.vcore->online_count); vcpu->arch.online = i; break; + case KVM_REG_PPC_PTCR: + vcpu->kvm->arch.l1_ptcr = set_reg_val(id, *val); + break; default: r = -EINVAL; break; @@ -2019,15 +2193,18 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, * Set the default HFSCR for the guest from the host value. * This value is only used on POWER9. * On POWER9, we want to virtualize the doorbell facility, so we - * turn off the HFSCR bit, which causes those instructions to trap. + * don't set the HFSCR_MSGP bit, and that causes those instructions + * to trap and then we emulate them. */ - vcpu->arch.hfscr = mfspr(SPRN_HFSCR); - if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) + vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | + HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP; + if (cpu_has_feature(CPU_FTR_HVMODE)) { + vcpu->arch.hfscr &= mfspr(SPRN_HFSCR); + if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) + vcpu->arch.hfscr |= HFSCR_TM; + } + if (cpu_has_feature(CPU_FTR_TM_COMP)) vcpu->arch.hfscr |= HFSCR_TM; - else if (!cpu_has_feature(CPU_FTR_TM_COMP)) - vcpu->arch.hfscr &= ~HFSCR_TM; - if (cpu_has_feature(CPU_FTR_ARCH_300)) - vcpu->arch.hfscr &= ~HFSCR_MSGP; kvmppc_mmu_book3s_hv_init(vcpu); @@ -2242,10 +2419,18 @@ static void kvmppc_release_hwthread(int cpu) static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) { + struct kvm_nested_guest *nested = vcpu->arch.nested; + cpumask_t *cpu_in_guest; int i; cpu = cpu_first_thread_sibling(cpu); - cpumask_set_cpu(cpu, &kvm->arch.need_tlb_flush); + if (nested) { + cpumask_set_cpu(cpu, &nested->need_tlb_flush); + cpu_in_guest = &nested->cpu_in_guest; + } else { + cpumask_set_cpu(cpu, &kvm->arch.need_tlb_flush); + cpu_in_guest = &kvm->arch.cpu_in_guest; + } /* * Make sure setting of bit in need_tlb_flush precedes * testing of cpu_in_guest bits. The matching barrier on @@ -2253,13 +2438,23 @@ static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) */ smp_mb(); for (i = 0; i < threads_per_core; ++i) - if (cpumask_test_cpu(cpu + i, &kvm->arch.cpu_in_guest)) + if (cpumask_test_cpu(cpu + i, cpu_in_guest)) smp_call_function_single(cpu + i, do_nothing, NULL, 1); } static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu) { + struct kvm_nested_guest *nested = vcpu->arch.nested; struct kvm *kvm = vcpu->kvm; + int prev_cpu; + + if (!cpu_has_feature(CPU_FTR_HVMODE)) + return; + + if (nested) + prev_cpu = nested->prev_cpu[vcpu->arch.nested_vcpu_id]; + else + prev_cpu = vcpu->arch.prev_cpu; /* * With radix, the guest can do TLB invalidations itself, @@ -2273,12 +2468,46 @@ static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu) * ran to flush the TLB. The TLB is shared between threads, * so we use a single bit in .need_tlb_flush for all 4 threads. */ - if (vcpu->arch.prev_cpu != pcpu) { - if (vcpu->arch.prev_cpu >= 0 && - cpu_first_thread_sibling(vcpu->arch.prev_cpu) != + if (prev_cpu != pcpu) { + if (prev_cpu >= 0 && + cpu_first_thread_sibling(prev_cpu) != cpu_first_thread_sibling(pcpu)) - radix_flush_cpu(kvm, vcpu->arch.prev_cpu, vcpu); - vcpu->arch.prev_cpu = pcpu; + radix_flush_cpu(kvm, prev_cpu, vcpu); + if (nested) + nested->prev_cpu[vcpu->arch.nested_vcpu_id] = pcpu; + else + vcpu->arch.prev_cpu = pcpu; + } +} + +static void kvmppc_radix_check_need_tlb_flush(struct kvm *kvm, int pcpu, + struct kvm_nested_guest *nested) +{ + cpumask_t *need_tlb_flush; + int lpid; + + if (!cpu_has_feature(CPU_FTR_HVMODE)) + return; + + if (cpu_has_feature(CPU_FTR_ARCH_300)) + pcpu &= ~0x3UL; + + if (nested) { + lpid = nested->shadow_lpid; + need_tlb_flush = &nested->need_tlb_flush; + } else { + lpid = kvm->arch.lpid; + need_tlb_flush = &kvm->arch.need_tlb_flush; + } + + mtspr(SPRN_LPID, lpid); + isync(); + smp_mb(); + + if (cpumask_test_cpu(pcpu, need_tlb_flush)) { + radix__local_flush_tlb_lpid_guest(lpid); + /* Clear the bit after the TLB flush */ + cpumask_clear_cpu(pcpu, need_tlb_flush); } } @@ -2493,6 +2722,10 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip) if (!cpu_has_feature(CPU_FTR_ARCH_207S)) return false; + /* In one_vm_per_core mode, require all vcores to be from the same vm */ + if (one_vm_per_core && vc->kvm != cip->vc[0]->kvm) + return false; + /* Some POWER9 chips require all threads to be in the same MMU mode */ if (no_mixing_hpt_and_radix && kvm_is_radix(vc->kvm) != kvm_is_radix(cip->vc[0]->kvm)) @@ -2600,6 +2833,14 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master) spin_lock(&vc->lock); now = get_tb(); for_each_runnable_thread(i, vcpu, vc) { + /* + * It's safe to unlock the vcore in the loop here, because + * for_each_runnable_thread() is safe against removal of + * the vcpu, and the vcore state is VCORE_EXITING here, + * so any vcpus becoming runnable will have their arch.trap + * set to zero and can't actually run in the guest. + */ + spin_unlock(&vc->lock); /* cancel pending dec exception if dec is positive */ if (now < vcpu->arch.dec_expires && kvmppc_core_pending_dec(vcpu)) @@ -2615,6 +2856,7 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master) vcpu->arch.ret = ret; vcpu->arch.trap = 0; + spin_lock(&vc->lock); if (is_kvmppc_resume_guest(vcpu->arch.ret)) { if (vcpu->arch.pending_exceptions) kvmppc_core_prepare_to_enter(vcpu); @@ -2963,8 +3205,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) spin_unlock(&core_info.vc[sub]->lock); if (kvm_is_radix(vc->kvm)) { - int tmp = pcpu; - /* * Do we need to flush the process scoped TLB for the LPAR? * @@ -2975,17 +3215,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) * * Hash must be flushed in realmode in order to use tlbiel. */ - mtspr(SPRN_LPID, vc->kvm->arch.lpid); - isync(); - - if (cpu_has_feature(CPU_FTR_ARCH_300)) - tmp &= ~0x3UL; - - if (cpumask_test_cpu(tmp, &vc->kvm->arch.need_tlb_flush)) { - radix__local_flush_tlb_lpid_guest(vc->kvm->arch.lpid); - /* Clear the bit after the TLB flush */ - cpumask_clear_cpu(tmp, &vc->kvm->arch.need_tlb_flush); - } + kvmppc_radix_check_need_tlb_flush(vc->kvm, pcpu, NULL); } /* @@ -3080,6 +3310,300 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) } /* + * Load up hypervisor-mode registers on P9. + */ +static int kvmhv_load_hv_regs_and_go(struct kvm_vcpu *vcpu, u64 time_limit, + unsigned long lpcr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + s64 hdec; + u64 tb, purr, spurr; + int trap; + unsigned long host_hfscr = mfspr(SPRN_HFSCR); + unsigned long host_ciabr = mfspr(SPRN_CIABR); + unsigned long host_dawr = mfspr(SPRN_DAWR); + unsigned long host_dawrx = mfspr(SPRN_DAWRX); + unsigned long host_psscr = mfspr(SPRN_PSSCR); + unsigned long host_pidr = mfspr(SPRN_PID); + + hdec = time_limit - mftb(); + if (hdec < 0) + return BOOK3S_INTERRUPT_HV_DECREMENTER; + mtspr(SPRN_HDEC, hdec); + + if (vc->tb_offset) { + u64 new_tb = mftb() + vc->tb_offset; + mtspr(SPRN_TBU40, new_tb); + tb = mftb(); + if ((tb & 0xffffff) < (new_tb & 0xffffff)) + mtspr(SPRN_TBU40, new_tb + 0x1000000); + vc->tb_offset_applied = vc->tb_offset; + } + + if (vc->pcr) + mtspr(SPRN_PCR, vc->pcr); + mtspr(SPRN_DPDES, vc->dpdes); + mtspr(SPRN_VTB, vc->vtb); + + local_paca->kvm_hstate.host_purr = mfspr(SPRN_PURR); + local_paca->kvm_hstate.host_spurr = mfspr(SPRN_SPURR); + mtspr(SPRN_PURR, vcpu->arch.purr); + mtspr(SPRN_SPURR, vcpu->arch.spurr); + + if (cpu_has_feature(CPU_FTR_DAWR)) { + mtspr(SPRN_DAWR, vcpu->arch.dawr); + mtspr(SPRN_DAWRX, vcpu->arch.dawrx); + } + mtspr(SPRN_CIABR, vcpu->arch.ciabr); + mtspr(SPRN_IC, vcpu->arch.ic); + mtspr(SPRN_PID, vcpu->arch.pid); + + mtspr(SPRN_PSSCR, vcpu->arch.psscr | PSSCR_EC | + (local_paca->kvm_hstate.fake_suspend << PSSCR_FAKE_SUSPEND_LG)); + + mtspr(SPRN_HFSCR, vcpu->arch.hfscr); + + mtspr(SPRN_SPRG0, vcpu->arch.shregs.sprg0); + mtspr(SPRN_SPRG1, vcpu->arch.shregs.sprg1); + mtspr(SPRN_SPRG2, vcpu->arch.shregs.sprg2); + mtspr(SPRN_SPRG3, vcpu->arch.shregs.sprg3); + + mtspr(SPRN_AMOR, ~0UL); + + mtspr(SPRN_LPCR, lpcr); + isync(); + + kvmppc_xive_push_vcpu(vcpu); + + mtspr(SPRN_SRR0, vcpu->arch.shregs.srr0); + mtspr(SPRN_SRR1, vcpu->arch.shregs.srr1); + + trap = __kvmhv_vcpu_entry_p9(vcpu); + + /* Advance host PURR/SPURR by the amount used by guest */ + purr = mfspr(SPRN_PURR); + spurr = mfspr(SPRN_SPURR); + mtspr(SPRN_PURR, local_paca->kvm_hstate.host_purr + + purr - vcpu->arch.purr); + mtspr(SPRN_SPURR, local_paca->kvm_hstate.host_spurr + + spurr - vcpu->arch.spurr); + vcpu->arch.purr = purr; + vcpu->arch.spurr = spurr; + + vcpu->arch.ic = mfspr(SPRN_IC); + vcpu->arch.pid = mfspr(SPRN_PID); + vcpu->arch.psscr = mfspr(SPRN_PSSCR) & PSSCR_GUEST_VIS; + + vcpu->arch.shregs.sprg0 = mfspr(SPRN_SPRG0); + vcpu->arch.shregs.sprg1 = mfspr(SPRN_SPRG1); + vcpu->arch.shregs.sprg2 = mfspr(SPRN_SPRG2); + vcpu->arch.shregs.sprg3 = mfspr(SPRN_SPRG3); + + mtspr(SPRN_PSSCR, host_psscr); + mtspr(SPRN_HFSCR, host_hfscr); + mtspr(SPRN_CIABR, host_ciabr); + mtspr(SPRN_DAWR, host_dawr); + mtspr(SPRN_DAWRX, host_dawrx); + mtspr(SPRN_PID, host_pidr); + + /* + * Since this is radix, do a eieio; tlbsync; ptesync sequence in + * case we interrupted the guest between a tlbie and a ptesync. + */ + asm volatile("eieio; tlbsync; ptesync"); + + mtspr(SPRN_LPID, vcpu->kvm->arch.host_lpid); /* restore host LPID */ + isync(); + + vc->dpdes = mfspr(SPRN_DPDES); + vc->vtb = mfspr(SPRN_VTB); + mtspr(SPRN_DPDES, 0); + if (vc->pcr) + mtspr(SPRN_PCR, 0); + + if (vc->tb_offset_applied) { + u64 new_tb = mftb() - vc->tb_offset_applied; + mtspr(SPRN_TBU40, new_tb); + tb = mftb(); + if ((tb & 0xffffff) < (new_tb & 0xffffff)) + mtspr(SPRN_TBU40, new_tb + 0x1000000); + vc->tb_offset_applied = 0; + } + + mtspr(SPRN_HDEC, 0x7fffffff); + mtspr(SPRN_LPCR, vcpu->kvm->arch.host_lpcr); + + return trap; +} + +/* + * Virtual-mode guest entry for POWER9 and later when the host and + * guest are both using the radix MMU. The LPIDR has already been set. + */ +int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, + unsigned long lpcr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + unsigned long host_dscr = mfspr(SPRN_DSCR); + unsigned long host_tidr = mfspr(SPRN_TIDR); + unsigned long host_iamr = mfspr(SPRN_IAMR); + s64 dec; + u64 tb; + int trap, save_pmu; + + dec = mfspr(SPRN_DEC); + tb = mftb(); + if (dec < 512) + return BOOK3S_INTERRUPT_HV_DECREMENTER; + local_paca->kvm_hstate.dec_expires = dec + tb; + if (local_paca->kvm_hstate.dec_expires < time_limit) + time_limit = local_paca->kvm_hstate.dec_expires; + + vcpu->arch.ceded = 0; + + kvmhv_save_host_pmu(); /* saves it to PACA kvm_hstate */ + + kvmppc_subcore_enter_guest(); + + vc->entry_exit_map = 1; + vc->in_guest = 1; + + if (vcpu->arch.vpa.pinned_addr) { + struct lppaca *lp = vcpu->arch.vpa.pinned_addr; + u32 yield_count = be32_to_cpu(lp->yield_count) + 1; + lp->yield_count = cpu_to_be32(yield_count); + vcpu->arch.vpa.dirty = 1; + } + + if (cpu_has_feature(CPU_FTR_TM) || + cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) + kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true); + + kvmhv_load_guest_pmu(vcpu); + + msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); + load_fp_state(&vcpu->arch.fp); +#ifdef CONFIG_ALTIVEC + load_vr_state(&vcpu->arch.vr); +#endif + + mtspr(SPRN_DSCR, vcpu->arch.dscr); + mtspr(SPRN_IAMR, vcpu->arch.iamr); + mtspr(SPRN_PSPB, vcpu->arch.pspb); + mtspr(SPRN_FSCR, vcpu->arch.fscr); + mtspr(SPRN_TAR, vcpu->arch.tar); + mtspr(SPRN_EBBHR, vcpu->arch.ebbhr); + mtspr(SPRN_EBBRR, vcpu->arch.ebbrr); + mtspr(SPRN_BESCR, vcpu->arch.bescr); + mtspr(SPRN_WORT, vcpu->arch.wort); + mtspr(SPRN_TIDR, vcpu->arch.tid); + mtspr(SPRN_DAR, vcpu->arch.shregs.dar); + mtspr(SPRN_DSISR, vcpu->arch.shregs.dsisr); + mtspr(SPRN_AMR, vcpu->arch.amr); + mtspr(SPRN_UAMOR, vcpu->arch.uamor); + + if (!(vcpu->arch.ctrl & 1)) + mtspr(SPRN_CTRLT, mfspr(SPRN_CTRLF) & ~1); + + mtspr(SPRN_DEC, vcpu->arch.dec_expires - mftb()); + + if (kvmhv_on_pseries()) { + /* call our hypervisor to load up HV regs and go */ + struct hv_guest_state hvregs; + + kvmhv_save_hv_regs(vcpu, &hvregs); + hvregs.lpcr = lpcr; + vcpu->arch.regs.msr = vcpu->arch.shregs.msr; + hvregs.version = HV_GUEST_STATE_VERSION; + if (vcpu->arch.nested) { + hvregs.lpid = vcpu->arch.nested->shadow_lpid; + hvregs.vcpu_token = vcpu->arch.nested_vcpu_id; + } else { + hvregs.lpid = vcpu->kvm->arch.lpid; + hvregs.vcpu_token = vcpu->vcpu_id; + } + hvregs.hdec_expiry = time_limit; + trap = plpar_hcall_norets(H_ENTER_NESTED, __pa(&hvregs), + __pa(&vcpu->arch.regs)); + kvmhv_restore_hv_return_state(vcpu, &hvregs); + vcpu->arch.shregs.msr = vcpu->arch.regs.msr; + vcpu->arch.shregs.dar = mfspr(SPRN_DAR); + vcpu->arch.shregs.dsisr = mfspr(SPRN_DSISR); + + /* H_CEDE has to be handled now, not later */ + if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested && + kvmppc_get_gpr(vcpu, 3) == H_CEDE) { + kvmppc_nested_cede(vcpu); + trap = 0; + } + } else { + trap = kvmhv_load_hv_regs_and_go(vcpu, time_limit, lpcr); + } + + vcpu->arch.slb_max = 0; + dec = mfspr(SPRN_DEC); + tb = mftb(); + vcpu->arch.dec_expires = dec + tb; + vcpu->cpu = -1; + vcpu->arch.thread_cpu = -1; + vcpu->arch.ctrl = mfspr(SPRN_CTRLF); + + vcpu->arch.iamr = mfspr(SPRN_IAMR); + vcpu->arch.pspb = mfspr(SPRN_PSPB); + vcpu->arch.fscr = mfspr(SPRN_FSCR); + vcpu->arch.tar = mfspr(SPRN_TAR); + vcpu->arch.ebbhr = mfspr(SPRN_EBBHR); + vcpu->arch.ebbrr = mfspr(SPRN_EBBRR); + vcpu->arch.bescr = mfspr(SPRN_BESCR); + vcpu->arch.wort = mfspr(SPRN_WORT); + vcpu->arch.tid = mfspr(SPRN_TIDR); + vcpu->arch.amr = mfspr(SPRN_AMR); + vcpu->arch.uamor = mfspr(SPRN_UAMOR); + vcpu->arch.dscr = mfspr(SPRN_DSCR); + + mtspr(SPRN_PSPB, 0); + mtspr(SPRN_WORT, 0); + mtspr(SPRN_AMR, 0); + mtspr(SPRN_UAMOR, 0); + mtspr(SPRN_DSCR, host_dscr); + mtspr(SPRN_TIDR, host_tidr); + mtspr(SPRN_IAMR, host_iamr); + mtspr(SPRN_PSPB, 0); + + msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); + store_fp_state(&vcpu->arch.fp); +#ifdef CONFIG_ALTIVEC + store_vr_state(&vcpu->arch.vr); +#endif + + if (cpu_has_feature(CPU_FTR_TM) || + cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) + kvmppc_save_tm_hv(vcpu, vcpu->arch.shregs.msr, true); + + save_pmu = 1; + if (vcpu->arch.vpa.pinned_addr) { + struct lppaca *lp = vcpu->arch.vpa.pinned_addr; + u32 yield_count = be32_to_cpu(lp->yield_count) + 1; + lp->yield_count = cpu_to_be32(yield_count); + vcpu->arch.vpa.dirty = 1; + save_pmu = lp->pmcregs_in_use; + } + + kvmhv_save_guest_pmu(vcpu, save_pmu); + + vc->entry_exit_map = 0x101; + vc->in_guest = 0; + + mtspr(SPRN_DEC, local_paca->kvm_hstate.dec_expires - mftb()); + + kvmhv_load_host_pmu(); + + kvmppc_subcore_exit_guest(); + + return trap; +} + +/* * Wait for some other vcpu thread to execute us, and * wake us up when we need to handle something in the host. */ @@ -3256,6 +3780,11 @@ out: trace_kvmppc_vcore_wakeup(do_sleep, block_ns); } +/* + * This never fails for a radix guest, as none of the operations it does + * for a radix guest can fail or have a way to report failure. + * kvmhv_run_single_vcpu() relies on this fact. + */ static int kvmhv_setup_mmu(struct kvm_vcpu *vcpu) { int r = 0; @@ -3405,6 +3934,171 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) return vcpu->arch.ret; } +int kvmhv_run_single_vcpu(struct kvm_run *kvm_run, + struct kvm_vcpu *vcpu, u64 time_limit, + unsigned long lpcr) +{ + int trap, r, pcpu; + int srcu_idx; + struct kvmppc_vcore *vc; + struct kvm *kvm = vcpu->kvm; + struct kvm_nested_guest *nested = vcpu->arch.nested; + + trace_kvmppc_run_vcpu_enter(vcpu); + + kvm_run->exit_reason = 0; + vcpu->arch.ret = RESUME_GUEST; + vcpu->arch.trap = 0; + + vc = vcpu->arch.vcore; + vcpu->arch.ceded = 0; + vcpu->arch.run_task = current; + vcpu->arch.kvm_run = kvm_run; + vcpu->arch.stolen_logged = vcore_stolen_time(vc, mftb()); + vcpu->arch.state = KVMPPC_VCPU_RUNNABLE; + vcpu->arch.busy_preempt = TB_NIL; + vcpu->arch.last_inst = KVM_INST_FETCH_FAILED; + vc->runnable_threads[0] = vcpu; + vc->n_runnable = 1; + vc->runner = vcpu; + + /* See if the MMU is ready to go */ + if (!kvm->arch.mmu_ready) + kvmhv_setup_mmu(vcpu); + + if (need_resched()) + cond_resched(); + + kvmppc_update_vpas(vcpu); + + init_vcore_to_run(vc); + vc->preempt_tb = TB_NIL; + + preempt_disable(); + pcpu = smp_processor_id(); + vc->pcpu = pcpu; + kvmppc_prepare_radix_vcpu(vcpu, pcpu); + + local_irq_disable(); + hard_irq_disable(); + if (signal_pending(current)) + goto sigpend; + if (lazy_irq_pending() || need_resched() || !kvm->arch.mmu_ready) + goto out; + + if (!nested) { + kvmppc_core_prepare_to_enter(vcpu); + if (vcpu->arch.doorbell_request) { + vc->dpdes = 1; + smp_wmb(); + vcpu->arch.doorbell_request = 0; + } + if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, + &vcpu->arch.pending_exceptions)) + lpcr |= LPCR_MER; + } else if (vcpu->arch.pending_exceptions || + vcpu->arch.doorbell_request || + xive_interrupt_pending(vcpu)) { + vcpu->arch.ret = RESUME_HOST; + goto out; + } + + kvmppc_clear_host_core(pcpu); + + local_paca->kvm_hstate.tid = 0; + local_paca->kvm_hstate.napping = 0; + local_paca->kvm_hstate.kvm_split_mode = NULL; + kvmppc_start_thread(vcpu, vc); + kvmppc_create_dtl_entry(vcpu, vc); + trace_kvm_guest_enter(vcpu); + + vc->vcore_state = VCORE_RUNNING; + trace_kvmppc_run_core(vc, 0); + + if (cpu_has_feature(CPU_FTR_HVMODE)) + kvmppc_radix_check_need_tlb_flush(kvm, pcpu, nested); + + trace_hardirqs_on(); + guest_enter_irqoff(); + + srcu_idx = srcu_read_lock(&kvm->srcu); + + this_cpu_disable_ftrace(); + + trap = kvmhv_p9_guest_entry(vcpu, time_limit, lpcr); + vcpu->arch.trap = trap; + + this_cpu_enable_ftrace(); + + srcu_read_unlock(&kvm->srcu, srcu_idx); + + if (cpu_has_feature(CPU_FTR_HVMODE)) { + mtspr(SPRN_LPID, kvm->arch.host_lpid); + isync(); + } + + trace_hardirqs_off(); + set_irq_happened(trap); + + kvmppc_set_host_core(pcpu); + + local_irq_enable(); + guest_exit(); + + cpumask_clear_cpu(pcpu, &kvm->arch.cpu_in_guest); + + preempt_enable(); + + /* cancel pending decrementer exception if DEC is now positive */ + if (get_tb() < vcpu->arch.dec_expires && kvmppc_core_pending_dec(vcpu)) + kvmppc_core_dequeue_dec(vcpu); + + trace_kvm_guest_exit(vcpu); + r = RESUME_GUEST; + if (trap) { + if (!nested) + r = kvmppc_handle_exit_hv(kvm_run, vcpu, current); + else + r = kvmppc_handle_nested_exit(vcpu); + } + vcpu->arch.ret = r; + + if (is_kvmppc_resume_guest(r) && vcpu->arch.ceded && + !kvmppc_vcpu_woken(vcpu)) { + kvmppc_set_timer(vcpu); + while (vcpu->arch.ceded && !kvmppc_vcpu_woken(vcpu)) { + if (signal_pending(current)) { + vcpu->stat.signal_exits++; + kvm_run->exit_reason = KVM_EXIT_INTR; + vcpu->arch.ret = -EINTR; + break; + } + spin_lock(&vc->lock); + kvmppc_vcore_blocked(vc); + spin_unlock(&vc->lock); + } + } + vcpu->arch.ceded = 0; + + vc->vcore_state = VCORE_INACTIVE; + trace_kvmppc_run_core(vc, 1); + + done: + kvmppc_remove_runnable(vc, vcpu); + trace_kvmppc_run_vcpu_exit(vcpu, kvm_run); + + return vcpu->arch.ret; + + sigpend: + vcpu->stat.signal_exits++; + kvm_run->exit_reason = KVM_EXIT_INTR; + vcpu->arch.ret = -EINTR; + out: + local_irq_enable(); + preempt_enable(); + goto done; +} + static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) { int r; @@ -3480,7 +4174,20 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; do { - r = kvmppc_run_vcpu(run, vcpu); + /* + * The early POWER9 chips that can't mix radix and HPT threads + * on the same core also need the workaround for the problem + * where the TLB would prefetch entries in the guest exit path + * for radix guests using the guest PIDR value and LPID 0. + * The workaround is in the old path (kvmppc_run_vcpu()) + * but not the new path (kvmhv_run_single_vcpu()). + */ + if (kvm->arch.threads_indep && kvm_is_radix(kvm) && + !no_mixing_hpt_and_radix) + r = kvmhv_run_single_vcpu(run, vcpu, ~(u64)0, + vcpu->arch.vcore->lpcr); + else + r = kvmppc_run_vcpu(run, vcpu); if (run->exit_reason == KVM_EXIT_PAPR_HCALL && !(vcpu->arch.shregs.msr & MSR_PR)) { @@ -3559,6 +4266,10 @@ static int kvm_vm_ioctl_get_smmu_info_hv(struct kvm *kvm, kvmppc_add_seg_page_size(&sps, 16, SLB_VSID_L | SLB_VSID_LP_01); kvmppc_add_seg_page_size(&sps, 24, SLB_VSID_L); + /* If running as a nested hypervisor, we don't support HPT guests */ + if (kvmhv_on_pseries()) + info->flags |= KVM_PPC_NO_HASH; + return 0; } @@ -3723,8 +4434,7 @@ void kvmppc_setup_partition_table(struct kvm *kvm) __pa(kvm->arch.pgtable) | RADIX_PGD_INDEX_SIZE; dw1 = PATB_GR | kvm->arch.process_table; } - - mmu_partition_table_set_entry(kvm->arch.lpid, dw0, dw1); + kvmhv_set_ptbl_entry(kvm->arch.lpid, dw0, dw1); } /* @@ -3820,6 +4530,8 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) /* Must be called with kvm->lock held and mmu_ready = 0 and no vcpus running */ int kvmppc_switch_mmu_to_hpt(struct kvm *kvm) { + if (nesting_enabled(kvm)) + kvmhv_release_all_nested(kvm); kvmppc_free_radix(kvm); kvmppc_update_lpcr(kvm, LPCR_VPM1, LPCR_VPM1 | LPCR_UPRT | LPCR_GTSE | LPCR_HR); @@ -3841,6 +4553,7 @@ int kvmppc_switch_mmu_to_radix(struct kvm *kvm) kvmppc_free_hpt(&kvm->arch.hpt); kvmppc_update_lpcr(kvm, LPCR_UPRT | LPCR_GTSE | LPCR_HR, LPCR_VPM1 | LPCR_UPRT | LPCR_GTSE | LPCR_HR); + kvmppc_rmap_reset(kvm); kvm->arch.radix = 1; return 0; } @@ -3940,6 +4653,8 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) kvmppc_alloc_host_rm_ops(); + kvmhv_vm_nested_init(kvm); + /* * Since we don't flush the TLB when tearing down a VM, * and this lpid might have previously been used, @@ -3958,9 +4673,13 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); /* Init LPCR for virtual RMA mode */ - kvm->arch.host_lpid = mfspr(SPRN_LPID); - kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR); - lpcr &= LPCR_PECE | LPCR_LPES; + if (cpu_has_feature(CPU_FTR_HVMODE)) { + kvm->arch.host_lpid = mfspr(SPRN_LPID); + kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR); + lpcr &= LPCR_PECE | LPCR_LPES; + } else { + lpcr = 0; + } lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE | LPCR_VPM0 | LPCR_VPM1; kvm->arch.vrma_slb_v = SLB_VSID_B_1T | @@ -4027,8 +4746,14 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) * On POWER9, we only need to do this if the "indep_threads_mode" * module parameter has been set to N. */ - if (cpu_has_feature(CPU_FTR_ARCH_300)) - kvm->arch.threads_indep = indep_threads_mode; + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + if (!indep_threads_mode && !cpu_has_feature(CPU_FTR_HVMODE)) { + pr_warn("KVM: Ignoring indep_threads_mode=N in nested hypervisor\n"); + kvm->arch.threads_indep = true; + } else { + kvm->arch.threads_indep = indep_threads_mode; + } + } if (!kvm->arch.threads_indep) kvm_hv_vm_activated(); @@ -4051,6 +4776,8 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) snprintf(buf, sizeof(buf), "vm%d", current->pid); kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir); kvmppc_mmu_debugfs_init(kvm); + if (radix_enabled()) + kvmhv_radix_debugfs_init(kvm); return 0; } @@ -4073,13 +4800,21 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm) kvmppc_free_vcores(kvm); - kvmppc_free_lpid(kvm->arch.lpid); if (kvm_is_radix(kvm)) kvmppc_free_radix(kvm); else kvmppc_free_hpt(&kvm->arch.hpt); + /* Perform global invalidation and return lpid to the pool */ + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + if (nesting_enabled(kvm)) + kvmhv_release_all_nested(kvm); + kvm->arch.process_table = 0; + kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0); + } + kvmppc_free_lpid(kvm->arch.lpid); + kvmppc_free_pimap(kvm); } @@ -4104,11 +4839,15 @@ static int kvmppc_core_emulate_mfspr_hv(struct kvm_vcpu *vcpu, int sprn, static int kvmppc_core_check_processor_compat_hv(void) { - if (!cpu_has_feature(CPU_FTR_HVMODE) || - !cpu_has_feature(CPU_FTR_ARCH_206)) - return -EIO; + if (cpu_has_feature(CPU_FTR_HVMODE) && + cpu_has_feature(CPU_FTR_ARCH_206)) + return 0; - return 0; + /* POWER9 in radix mode is capable of being a nested hypervisor. */ + if (cpu_has_feature(CPU_FTR_ARCH_300) && radix_enabled()) + return 0; + + return -EIO; } #ifdef CONFIG_KVM_XICS @@ -4426,6 +5165,10 @@ static int kvmhv_configure_mmu(struct kvm *kvm, struct kvm_ppc_mmuv3_cfg *cfg) if (radix && !radix_enabled()) return -EINVAL; + /* If we're a nested hypervisor, we currently only support radix */ + if (kvmhv_on_pseries() && !radix) + return -EINVAL; + mutex_lock(&kvm->lock); if (radix != kvm_is_radix(kvm)) { if (kvm->arch.mmu_ready) { @@ -4458,6 +5201,19 @@ static int kvmhv_configure_mmu(struct kvm *kvm, struct kvm_ppc_mmuv3_cfg *cfg) return err; } +static int kvmhv_enable_nested(struct kvm *kvm) +{ + if (!nested) + return -EPERM; + if (!cpu_has_feature(CPU_FTR_ARCH_300) || no_mixing_hpt_and_radix) + return -ENODEV; + + /* kvm == NULL means the caller is testing if the capability exists */ + if (kvm) + kvm->arch.nested_enable = true; + return 0; +} + static struct kvmppc_ops kvm_ops_hv = { .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, @@ -4497,6 +5253,7 @@ static struct kvmppc_ops kvm_ops_hv = { .configure_mmu = kvmhv_configure_mmu, .get_rmmu_info = kvmhv_get_rmmu_info, .set_smt_mode = kvmhv_set_smt_mode, + .enable_nested = kvmhv_enable_nested, }; static int kvm_init_subcore_bitmap(void) @@ -4547,6 +5304,10 @@ static int kvmppc_book3s_init_hv(void) if (r < 0) return -ENODEV; + r = kvmhv_nested_init(); + if (r) + return r; + r = kvm_init_subcore_bitmap(); if (r) return r; @@ -4557,7 +5318,8 @@ static int kvmppc_book3s_init_hv(void) * indirectly, via OPAL. */ #ifdef CONFIG_SMP - if (!xive_enabled() && !local_paca->kvm_hstate.xics_phys) { + if (!xive_enabled() && !kvmhv_on_pseries() && + !local_paca->kvm_hstate.xics_phys) { struct device_node *np; np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); @@ -4605,6 +5367,7 @@ static void kvmppc_book3s_exit_hv(void) if (kvmppc_radix_possible()) kvmppc_radix_exit(); kvmppc_hv_ops = NULL; + kvmhv_nested_exit(); } module_init(kvmppc_book3s_init_hv); diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index fc6bb9630a9c..a71e2fc00a4e 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -231,6 +231,15 @@ void kvmhv_rm_send_ipi(int cpu) void __iomem *xics_phys; unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); + /* For a nested hypervisor, use the XICS via hcall */ + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, get_hard_smp_processor_id(cpu), + IPI_PRIORITY); + return; + } + /* On POWER9 we can use msgsnd for any destination cpu. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) { msg |= get_hard_smp_processor_id(cpu); @@ -460,12 +469,19 @@ static long kvmppc_read_one_intr(bool *again) return 1; /* Now read the interrupt from the ICP */ - xics_phys = local_paca->kvm_hstate.xics_phys; - rc = 0; - if (!xics_phys) - rc = opal_int_get_xirr(&xirr, false); - else - xirr = __raw_rm_readl(xics_phys + XICS_XIRR); + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + rc = plpar_hcall_raw(H_XIRR, retbuf, 0xFF); + xirr = cpu_to_be32(retbuf[0]); + } else { + xics_phys = local_paca->kvm_hstate.xics_phys; + rc = 0; + if (!xics_phys) + rc = opal_int_get_xirr(&xirr, false); + else + xirr = __raw_rm_readl(xics_phys + XICS_XIRR); + } if (rc < 0) return 1; @@ -494,7 +510,13 @@ static long kvmppc_read_one_intr(bool *again) */ if (xisr == XICS_IPI) { rc = 0; - if (xics_phys) { + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, + hard_smp_processor_id(), 0xff); + plpar_hcall_raw(H_EOI, retbuf, h_xirr); + } else if (xics_phys) { __raw_rm_writeb(0xff, xics_phys + XICS_MFRR); __raw_rm_writel(xirr, xics_phys + XICS_XIRR); } else { @@ -520,7 +542,13 @@ static long kvmppc_read_one_intr(bool *again) /* We raced with the host, * we need to resend that IPI, bummer */ - if (xics_phys) + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + plpar_hcall_raw(H_IPI, retbuf, + hard_smp_processor_id(), + IPI_PRIORITY); + } else if (xics_phys) __raw_rm_writeb(IPI_PRIORITY, xics_phys + XICS_MFRR); else @@ -729,3 +757,51 @@ void kvmhv_p9_restore_lpcr(struct kvm_split_mode *sip) smp_mb(); local_paca->kvm_hstate.kvm_split_mode = NULL; } + +/* + * Is there a PRIV_DOORBELL pending for the guest (on POWER9)? + * Can we inject a Decrementer or a External interrupt? + */ +void kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu) +{ + int ext; + unsigned long vec = 0; + unsigned long lpcr; + + /* Insert EXTERNAL bit into LPCR at the MER bit position */ + ext = (vcpu->arch.pending_exceptions >> BOOK3S_IRQPRIO_EXTERNAL) & 1; + lpcr = mfspr(SPRN_LPCR); + lpcr |= ext << LPCR_MER_SH; + mtspr(SPRN_LPCR, lpcr); + isync(); + + if (vcpu->arch.shregs.msr & MSR_EE) { + if (ext) { + vec = BOOK3S_INTERRUPT_EXTERNAL; + } else { + long int dec = mfspr(SPRN_DEC); + if (!(lpcr & LPCR_LD)) + dec = (int) dec; + if (dec < 0) + vec = BOOK3S_INTERRUPT_DECREMENTER; + } + } + if (vec) { + unsigned long msr, old_msr = vcpu->arch.shregs.msr; + + kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu)); + kvmppc_set_srr1(vcpu, old_msr); + kvmppc_set_pc(vcpu, vec); + msr = vcpu->arch.intr_msr; + if (MSR_TM_ACTIVE(old_msr)) + msr |= MSR_TS_S; + vcpu->arch.shregs.msr = msr; + } + + if (vcpu->arch.doorbell_request) { + mtspr(SPRN_DPDES, 1); + vcpu->arch.vcore->dpdes = 1; + smp_wmb(); + vcpu->arch.doorbell_request = 0; + } +} diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S index 666b91c79eb4..a6d10010d9e8 100644 --- a/arch/powerpc/kvm/book3s_hv_interrupts.S +++ b/arch/powerpc/kvm/book3s_hv_interrupts.S @@ -64,52 +64,7 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) /* Save host PMU registers */ -BEGIN_FTR_SECTION - /* Work around P8 PMAE bug */ - li r3, -1 - clrrdi r3, r3, 10 - mfspr r8, SPRN_MMCR2 - mtspr SPRN_MMCR2, r3 /* freeze all counters using MMCR2 */ - isync -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - li r3, 1 - sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ - mfspr r7, SPRN_MMCR0 /* save MMCR0 */ - mtspr SPRN_MMCR0, r3 /* freeze all counters, disable interrupts */ - mfspr r6, SPRN_MMCRA - /* Clear MMCRA in order to disable SDAR updates */ - li r5, 0 - mtspr SPRN_MMCRA, r5 - isync - lbz r5, PACA_PMCINUSE(r13) /* is the host using the PMU? */ - cmpwi r5, 0 - beq 31f /* skip if not */ - mfspr r5, SPRN_MMCR1 - mfspr r9, SPRN_SIAR - mfspr r10, SPRN_SDAR - std r7, HSTATE_MMCR0(r13) - std r5, HSTATE_MMCR1(r13) - std r6, HSTATE_MMCRA(r13) - std r9, HSTATE_SIAR(r13) - std r10, HSTATE_SDAR(r13) -BEGIN_FTR_SECTION - mfspr r9, SPRN_SIER - std r8, HSTATE_MMCR2(r13) - std r9, HSTATE_SIER(r13) -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - mfspr r3, SPRN_PMC1 - mfspr r5, SPRN_PMC2 - mfspr r6, SPRN_PMC3 - mfspr r7, SPRN_PMC4 - mfspr r8, SPRN_PMC5 - mfspr r9, SPRN_PMC6 - stw r3, HSTATE_PMC1(r13) - stw r5, HSTATE_PMC2(r13) - stw r6, HSTATE_PMC3(r13) - stw r7, HSTATE_PMC4(r13) - stw r8, HSTATE_PMC5(r13) - stw r9, HSTATE_PMC6(r13) -31: + bl kvmhv_save_host_pmu /* * Put whatever is in the decrementer into the @@ -161,3 +116,51 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) ld r0, PPC_LR_STKOFF(r1) mtlr r0 blr + +_GLOBAL(kvmhv_save_host_pmu) +BEGIN_FTR_SECTION + /* Work around P8 PMAE bug */ + li r3, -1 + clrrdi r3, r3, 10 + mfspr r8, SPRN_MMCR2 + mtspr SPRN_MMCR2, r3 /* freeze all counters using MMCR2 */ + isync +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + li r3, 1 + sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ + mfspr r7, SPRN_MMCR0 /* save MMCR0 */ + mtspr SPRN_MMCR0, r3 /* freeze all counters, disable interrupts */ + mfspr r6, SPRN_MMCRA + /* Clear MMCRA in order to disable SDAR updates */ + li r5, 0 + mtspr SPRN_MMCRA, r5 + isync + lbz r5, PACA_PMCINUSE(r13) /* is the host using the PMU? */ + cmpwi r5, 0 + beq 31f /* skip if not */ + mfspr r5, SPRN_MMCR1 + mfspr r9, SPRN_SIAR + mfspr r10, SPRN_SDAR + std r7, HSTATE_MMCR0(r13) + std r5, HSTATE_MMCR1(r13) + std r6, HSTATE_MMCRA(r13) + std r9, HSTATE_SIAR(r13) + std r10, HSTATE_SDAR(r13) +BEGIN_FTR_SECTION + mfspr r9, SPRN_SIER + std r8, HSTATE_MMCR2(r13) + std r9, HSTATE_SIER(r13) +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + mfspr r3, SPRN_PMC1 + mfspr r5, SPRN_PMC2 + mfspr r6, SPRN_PMC3 + mfspr r7, SPRN_PMC4 + mfspr r8, SPRN_PMC5 + mfspr r9, SPRN_PMC6 + stw r3, HSTATE_PMC1(r13) + stw r5, HSTATE_PMC2(r13) + stw r6, HSTATE_PMC3(r13) + stw r7, HSTATE_PMC4(r13) + stw r8, HSTATE_PMC5(r13) + stw r9, HSTATE_PMC6(r13) +31: blr diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c new file mode 100644 index 000000000000..401d2ecbebc5 --- /dev/null +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -0,0 +1,1291 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corporation, 2018 + * Authors Suraj Jitindar Singh <sjitindarsingh@gmail.com> + * Paul Mackerras <paulus@ozlabs.org> + * + * Description: KVM functions specific to running nested KVM-HV guests + * on Book3S processors (specifically POWER9 and later). + */ + +#include <linux/kernel.h> +#include <linux/kvm_host.h> +#include <linux/llist.h> + +#include <asm/kvm_ppc.h> +#include <asm/kvm_book3s.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> +#include <asm/pte-walk.h> +#include <asm/reg.h> + +static struct patb_entry *pseries_partition_tb; + +static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp); +static void kvmhv_free_memslot_nest_rmap(struct kvm_memory_slot *free); + +void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + hr->pcr = vc->pcr; + hr->dpdes = vc->dpdes; + hr->hfscr = vcpu->arch.hfscr; + hr->tb_offset = vc->tb_offset; + hr->dawr0 = vcpu->arch.dawr; + hr->dawrx0 = vcpu->arch.dawrx; + hr->ciabr = vcpu->arch.ciabr; + hr->purr = vcpu->arch.purr; + hr->spurr = vcpu->arch.spurr; + hr->ic = vcpu->arch.ic; + hr->vtb = vc->vtb; + hr->srr0 = vcpu->arch.shregs.srr0; + hr->srr1 = vcpu->arch.shregs.srr1; + hr->sprg[0] = vcpu->arch.shregs.sprg0; + hr->sprg[1] = vcpu->arch.shregs.sprg1; + hr->sprg[2] = vcpu->arch.shregs.sprg2; + hr->sprg[3] = vcpu->arch.shregs.sprg3; + hr->pidr = vcpu->arch.pid; + hr->cfar = vcpu->arch.cfar; + hr->ppr = vcpu->arch.ppr; +} + +static void byteswap_pt_regs(struct pt_regs *regs) +{ + unsigned long *addr = (unsigned long *) regs; + + for (; addr < ((unsigned long *) (regs + 1)); addr++) + *addr = swab64(*addr); +} + +static void byteswap_hv_regs(struct hv_guest_state *hr) +{ + hr->version = swab64(hr->version); + hr->lpid = swab32(hr->lpid); + hr->vcpu_token = swab32(hr->vcpu_token); + hr->lpcr = swab64(hr->lpcr); + hr->pcr = swab64(hr->pcr); + hr->amor = swab64(hr->amor); + hr->dpdes = swab64(hr->dpdes); + hr->hfscr = swab64(hr->hfscr); + hr->tb_offset = swab64(hr->tb_offset); + hr->dawr0 = swab64(hr->dawr0); + hr->dawrx0 = swab64(hr->dawrx0); + hr->ciabr = swab64(hr->ciabr); + hr->hdec_expiry = swab64(hr->hdec_expiry); + hr->purr = swab64(hr->purr); + hr->spurr = swab64(hr->spurr); + hr->ic = swab64(hr->ic); + hr->vtb = swab64(hr->vtb); + hr->hdar = swab64(hr->hdar); + hr->hdsisr = swab64(hr->hdsisr); + hr->heir = swab64(hr->heir); + hr->asdr = swab64(hr->asdr); + hr->srr0 = swab64(hr->srr0); + hr->srr1 = swab64(hr->srr1); + hr->sprg[0] = swab64(hr->sprg[0]); + hr->sprg[1] = swab64(hr->sprg[1]); + hr->sprg[2] = swab64(hr->sprg[2]); + hr->sprg[3] = swab64(hr->sprg[3]); + hr->pidr = swab64(hr->pidr); + hr->cfar = swab64(hr->cfar); + hr->ppr = swab64(hr->ppr); +} + +static void save_hv_return_state(struct kvm_vcpu *vcpu, int trap, + struct hv_guest_state *hr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + hr->dpdes = vc->dpdes; + hr->hfscr = vcpu->arch.hfscr; + hr->purr = vcpu->arch.purr; + hr->spurr = vcpu->arch.spurr; + hr->ic = vcpu->arch.ic; + hr->vtb = vc->vtb; + hr->srr0 = vcpu->arch.shregs.srr0; + hr->srr1 = vcpu->arch.shregs.srr1; + hr->sprg[0] = vcpu->arch.shregs.sprg0; + hr->sprg[1] = vcpu->arch.shregs.sprg1; + hr->sprg[2] = vcpu->arch.shregs.sprg2; + hr->sprg[3] = vcpu->arch.shregs.sprg3; + hr->pidr = vcpu->arch.pid; + hr->cfar = vcpu->arch.cfar; + hr->ppr = vcpu->arch.ppr; + switch (trap) { + case BOOK3S_INTERRUPT_H_DATA_STORAGE: + hr->hdar = vcpu->arch.fault_dar; + hr->hdsisr = vcpu->arch.fault_dsisr; + hr->asdr = vcpu->arch.fault_gpa; + break; + case BOOK3S_INTERRUPT_H_INST_STORAGE: + hr->asdr = vcpu->arch.fault_gpa; + break; + case BOOK3S_INTERRUPT_H_EMUL_ASSIST: + hr->heir = vcpu->arch.emul_inst; + break; + } +} + +static void sanitise_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr) +{ + /* + * Don't let L1 enable features for L2 which we've disabled for L1, + * but preserve the interrupt cause field. + */ + hr->hfscr &= (HFSCR_INTR_CAUSE | vcpu->arch.hfscr); + + /* Don't let data address watchpoint match in hypervisor state */ + hr->dawrx0 &= ~DAWRX_HYP; + + /* Don't let completed instruction address breakpt match in HV state */ + if ((hr->ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER) + hr->ciabr &= ~CIABR_PRIV; +} + +static void restore_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + vc->pcr = hr->pcr; + vc->dpdes = hr->dpdes; + vcpu->arch.hfscr = hr->hfscr; + vcpu->arch.dawr = hr->dawr0; + vcpu->arch.dawrx = hr->dawrx0; + vcpu->arch.ciabr = hr->ciabr; + vcpu->arch.purr = hr->purr; + vcpu->arch.spurr = hr->spurr; + vcpu->arch.ic = hr->ic; + vc->vtb = hr->vtb; + vcpu->arch.shregs.srr0 = hr->srr0; + vcpu->arch.shregs.srr1 = hr->srr1; + vcpu->arch.shregs.sprg0 = hr->sprg[0]; + vcpu->arch.shregs.sprg1 = hr->sprg[1]; + vcpu->arch.shregs.sprg2 = hr->sprg[2]; + vcpu->arch.shregs.sprg3 = hr->sprg[3]; + vcpu->arch.pid = hr->pidr; + vcpu->arch.cfar = hr->cfar; + vcpu->arch.ppr = hr->ppr; +} + +void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu, + struct hv_guest_state *hr) +{ + struct kvmppc_vcore *vc = vcpu->arch.vcore; + + vc->dpdes = hr->dpdes; + vcpu->arch.hfscr = hr->hfscr; + vcpu->arch.purr = hr->purr; + vcpu->arch.spurr = hr->spurr; + vcpu->arch.ic = hr->ic; + vc->vtb = hr->vtb; + vcpu->arch.fault_dar = hr->hdar; + vcpu->arch.fault_dsisr = hr->hdsisr; + vcpu->arch.fault_gpa = hr->asdr; + vcpu->arch.emul_inst = hr->heir; + vcpu->arch.shregs.srr0 = hr->srr0; + vcpu->arch.shregs.srr1 = hr->srr1; + vcpu->arch.shregs.sprg0 = hr->sprg[0]; + vcpu->arch.shregs.sprg1 = hr->sprg[1]; + vcpu->arch.shregs.sprg2 = hr->sprg[2]; + vcpu->arch.shregs.sprg3 = hr->sprg[3]; + vcpu->arch.pid = hr->pidr; + vcpu->arch.cfar = hr->cfar; + vcpu->arch.ppr = hr->ppr; +} + +long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu) +{ + long int err, r; + struct kvm_nested_guest *l2; + struct pt_regs l2_regs, saved_l1_regs; + struct hv_guest_state l2_hv, saved_l1_hv; + struct kvmppc_vcore *vc = vcpu->arch.vcore; + u64 hv_ptr, regs_ptr; + u64 hdec_exp; + s64 delta_purr, delta_spurr, delta_ic, delta_vtb; + u64 mask; + unsigned long lpcr; + + if (vcpu->kvm->arch.l1_ptcr == 0) + return H_NOT_AVAILABLE; + + /* copy parameters in */ + hv_ptr = kvmppc_get_gpr(vcpu, 4); + err = kvm_vcpu_read_guest(vcpu, hv_ptr, &l2_hv, + sizeof(struct hv_guest_state)); + if (err) + return H_PARAMETER; + if (kvmppc_need_byteswap(vcpu)) + byteswap_hv_regs(&l2_hv); + if (l2_hv.version != HV_GUEST_STATE_VERSION) + return H_P2; + + regs_ptr = kvmppc_get_gpr(vcpu, 5); + err = kvm_vcpu_read_guest(vcpu, regs_ptr, &l2_regs, + sizeof(struct pt_regs)); + if (err) + return H_PARAMETER; + if (kvmppc_need_byteswap(vcpu)) + byteswap_pt_regs(&l2_regs); + if (l2_hv.vcpu_token >= NR_CPUS) + return H_PARAMETER; + + /* translate lpid */ + l2 = kvmhv_get_nested(vcpu->kvm, l2_hv.lpid, true); + if (!l2) + return H_PARAMETER; + if (!l2->l1_gr_to_hr) { + mutex_lock(&l2->tlb_lock); + kvmhv_update_ptbl_cache(l2); + mutex_unlock(&l2->tlb_lock); + } + + /* save l1 values of things */ + vcpu->arch.regs.msr = vcpu->arch.shregs.msr; + saved_l1_regs = vcpu->arch.regs; + kvmhv_save_hv_regs(vcpu, &saved_l1_hv); + + /* convert TB values/offsets to host (L0) values */ + hdec_exp = l2_hv.hdec_expiry - vc->tb_offset; + vc->tb_offset += l2_hv.tb_offset; + + /* set L1 state to L2 state */ + vcpu->arch.nested = l2; + vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token; + vcpu->arch.regs = l2_regs; + vcpu->arch.shregs.msr = vcpu->arch.regs.msr; + mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD | + LPCR_LPES | LPCR_MER; + lpcr = (vc->lpcr & ~mask) | (l2_hv.lpcr & mask); + sanitise_hv_regs(vcpu, &l2_hv); + restore_hv_regs(vcpu, &l2_hv); + + vcpu->arch.ret = RESUME_GUEST; + vcpu->arch.trap = 0; + do { + if (mftb() >= hdec_exp) { + vcpu->arch.trap = BOOK3S_INTERRUPT_HV_DECREMENTER; + r = RESUME_HOST; + break; + } + r = kvmhv_run_single_vcpu(vcpu->arch.kvm_run, vcpu, hdec_exp, + lpcr); + } while (is_kvmppc_resume_guest(r)); + + /* save L2 state for return */ + l2_regs = vcpu->arch.regs; + l2_regs.msr = vcpu->arch.shregs.msr; + delta_purr = vcpu->arch.purr - l2_hv.purr; + delta_spurr = vcpu->arch.spurr - l2_hv.spurr; + delta_ic = vcpu->arch.ic - l2_hv.ic; + delta_vtb = vc->vtb - l2_hv.vtb; + save_hv_return_state(vcpu, vcpu->arch.trap, &l2_hv); + + /* restore L1 state */ + vcpu->arch.nested = NULL; + vcpu->arch.regs = saved_l1_regs; + vcpu->arch.shregs.msr = saved_l1_regs.msr & ~MSR_TS_MASK; + /* set L1 MSR TS field according to L2 transaction state */ + if (l2_regs.msr & MSR_TS_MASK) + vcpu->arch.shregs.msr |= MSR_TS_S; + vc->tb_offset = saved_l1_hv.tb_offset; + restore_hv_regs(vcpu, &saved_l1_hv); + vcpu->arch.purr += delta_purr; + vcpu->arch.spurr += delta_spurr; + vcpu->arch.ic += delta_ic; + vc->vtb += delta_vtb; + + kvmhv_put_nested(l2); + + /* copy l2_hv_state and regs back to guest */ + if (kvmppc_need_byteswap(vcpu)) { + byteswap_hv_regs(&l2_hv); + byteswap_pt_regs(&l2_regs); + } + err = kvm_vcpu_write_guest(vcpu, hv_ptr, &l2_hv, + sizeof(struct hv_guest_state)); + if (err) + return H_AUTHORITY; + err = kvm_vcpu_write_guest(vcpu, regs_ptr, &l2_regs, + sizeof(struct pt_regs)); + if (err) + return H_AUTHORITY; + + if (r == -EINTR) + return H_INTERRUPT; + + return vcpu->arch.trap; +} + +long kvmhv_nested_init(void) +{ + long int ptb_order; + unsigned long ptcr; + long rc; + + if (!kvmhv_on_pseries()) + return 0; + if (!radix_enabled()) + return -ENODEV; + + /* find log base 2 of KVMPPC_NR_LPIDS, rounding up */ + ptb_order = __ilog2(KVMPPC_NR_LPIDS - 1) + 1; + if (ptb_order < 8) + ptb_order = 8; + pseries_partition_tb = kmalloc(sizeof(struct patb_entry) << ptb_order, + GFP_KERNEL); + if (!pseries_partition_tb) { + pr_err("kvm-hv: failed to allocated nested partition table\n"); + return -ENOMEM; + } + + ptcr = __pa(pseries_partition_tb) | (ptb_order - 8); + rc = plpar_hcall_norets(H_SET_PARTITION_TABLE, ptcr); + if (rc != H_SUCCESS) { + pr_err("kvm-hv: Parent hypervisor does not support nesting (rc=%ld)\n", + rc); + kfree(pseries_partition_tb); + pseries_partition_tb = NULL; + return -ENODEV; + } + + return 0; +} + +void kvmhv_nested_exit(void) +{ + /* + * N.B. the kvmhv_on_pseries() test is there because it enables + * the compiler to remove the call to plpar_hcall_norets() + * when CONFIG_PPC_PSERIES=n. + */ + if (kvmhv_on_pseries() && pseries_partition_tb) { + plpar_hcall_norets(H_SET_PARTITION_TABLE, 0); + kfree(pseries_partition_tb); + pseries_partition_tb = NULL; + } +} + +static void kvmhv_flush_lpid(unsigned int lpid) +{ + long rc; + + if (!kvmhv_on_pseries()) { + radix__flush_tlb_lpid(lpid); + return; + } + + rc = plpar_hcall_norets(H_TLB_INVALIDATE, H_TLBIE_P1_ENC(2, 0, 1), + lpid, TLBIEL_INVAL_SET_LPID); + if (rc) + pr_err("KVM: TLB LPID invalidation hcall failed, rc=%ld\n", rc); +} + +void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1) +{ + if (!kvmhv_on_pseries()) { + mmu_partition_table_set_entry(lpid, dw0, dw1); + return; + } + + pseries_partition_tb[lpid].patb0 = cpu_to_be64(dw0); + pseries_partition_tb[lpid].patb1 = cpu_to_be64(dw1); + /* L0 will do the necessary barriers */ + kvmhv_flush_lpid(lpid); +} + +static void kvmhv_set_nested_ptbl(struct kvm_nested_guest *gp) +{ + unsigned long dw0; + + dw0 = PATB_HR | radix__get_tree_size() | + __pa(gp->shadow_pgtable) | RADIX_PGD_INDEX_SIZE; + kvmhv_set_ptbl_entry(gp->shadow_lpid, dw0, gp->process_table); +} + +void kvmhv_vm_nested_init(struct kvm *kvm) +{ + kvm->arch.max_nested_lpid = -1; +} + +/* + * Handle the H_SET_PARTITION_TABLE hcall. + * r4 = guest real address of partition table + log_2(size) - 12 + * (formatted as for the PTCR). + */ +long kvmhv_set_partition_table(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + unsigned long ptcr = kvmppc_get_gpr(vcpu, 4); + int srcu_idx; + long ret = H_SUCCESS; + + srcu_idx = srcu_read_lock(&kvm->srcu); + /* + * Limit the partition table to 4096 entries (because that's what + * hardware supports), and check the base address. + */ + if ((ptcr & PRTS_MASK) > 12 - 8 || + !kvm_is_visible_gfn(vcpu->kvm, (ptcr & PRTB_MASK) >> PAGE_SHIFT)) + ret = H_PARAMETER; + srcu_read_unlock(&kvm->srcu, srcu_idx); + if (ret == H_SUCCESS) + kvm->arch.l1_ptcr = ptcr; + return ret; +} + +/* + * Reload the partition table entry for a guest. + * Caller must hold gp->tlb_lock. + */ +static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp) +{ + int ret; + struct patb_entry ptbl_entry; + unsigned long ptbl_addr; + struct kvm *kvm = gp->l1_host; + + ret = -EFAULT; + ptbl_addr = (kvm->arch.l1_ptcr & PRTB_MASK) + (gp->l1_lpid << 4); + if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 8))) + ret = kvm_read_guest(kvm, ptbl_addr, + &ptbl_entry, sizeof(ptbl_entry)); + if (ret) { + gp->l1_gr_to_hr = 0; + gp->process_table = 0; + } else { + gp->l1_gr_to_hr = be64_to_cpu(ptbl_entry.patb0); + gp->process_table = be64_to_cpu(ptbl_entry.patb1); + } + kvmhv_set_nested_ptbl(gp); +} + +struct kvm_nested_guest *kvmhv_alloc_nested(struct kvm *kvm, unsigned int lpid) +{ + struct kvm_nested_guest *gp; + long shadow_lpid; + + gp = kzalloc(sizeof(*gp), GFP_KERNEL); + if (!gp) + return NULL; + gp->l1_host = kvm; + gp->l1_lpid = lpid; + mutex_init(&gp->tlb_lock); + gp->shadow_pgtable = pgd_alloc(kvm->mm); + if (!gp->shadow_pgtable) + goto out_free; + shadow_lpid = kvmppc_alloc_lpid(); + if (shadow_lpid < 0) + goto out_free2; + gp->shadow_lpid = shadow_lpid; + + memset(gp->prev_cpu, -1, sizeof(gp->prev_cpu)); + + return gp; + + out_free2: + pgd_free(kvm->mm, gp->shadow_pgtable); + out_free: + kfree(gp); + return NULL; +} + +/* + * Free up any resources allocated for a nested guest. + */ +static void kvmhv_release_nested(struct kvm_nested_guest *gp) +{ + struct kvm *kvm = gp->l1_host; + + if (gp->shadow_pgtable) { + /* + * No vcpu is using this struct and no call to + * kvmhv_get_nested can find this struct, + * so we don't need to hold kvm->mmu_lock. + */ + kvmppc_free_pgtable_radix(kvm, gp->shadow_pgtable, + gp->shadow_lpid); + pgd_free(kvm->mm, gp->shadow_pgtable); + } + kvmhv_set_ptbl_entry(gp->shadow_lpid, 0, 0); + kvmppc_free_lpid(gp->shadow_lpid); + kfree(gp); +} + +static void kvmhv_remove_nested(struct kvm_nested_guest *gp) +{ + struct kvm *kvm = gp->l1_host; + int lpid = gp->l1_lpid; + long ref; + + spin_lock(&kvm->mmu_lock); + if (gp == kvm->arch.nested_guests[lpid]) { + kvm->arch.nested_guests[lpid] = NULL; + if (lpid == kvm->arch.max_nested_lpid) { + while (--lpid >= 0 && !kvm->arch.nested_guests[lpid]) + ; + kvm->arch.max_nested_lpid = lpid; + } + --gp->refcnt; + } + ref = gp->refcnt; + spin_unlock(&kvm->mmu_lock); + if (ref == 0) + kvmhv_release_nested(gp); +} + +/* + * Free up all nested resources allocated for this guest. + * This is called with no vcpus of the guest running, when + * switching the guest to HPT mode or when destroying the + * guest. + */ +void kvmhv_release_all_nested(struct kvm *kvm) +{ + int i; + struct kvm_nested_guest *gp; + struct kvm_nested_guest *freelist = NULL; + struct kvm_memory_slot *memslot; + int srcu_idx; + + spin_lock(&kvm->mmu_lock); + for (i = 0; i <= kvm->arch.max_nested_lpid; i++) { + gp = kvm->arch.nested_guests[i]; + if (!gp) + continue; + kvm->arch.nested_guests[i] = NULL; + if (--gp->refcnt == 0) { + gp->next = freelist; + freelist = gp; + } + } + kvm->arch.max_nested_lpid = -1; + spin_unlock(&kvm->mmu_lock); + while ((gp = freelist) != NULL) { + freelist = gp->next; + kvmhv_release_nested(gp); + } + + srcu_idx = srcu_read_lock(&kvm->srcu); + kvm_for_each_memslot(memslot, kvm_memslots(kvm)) + kvmhv_free_memslot_nest_rmap(memslot); + srcu_read_unlock(&kvm->srcu, srcu_idx); +} + +/* caller must hold gp->tlb_lock */ +static void kvmhv_flush_nested(struct kvm_nested_guest *gp) +{ + struct kvm *kvm = gp->l1_host; + + spin_lock(&kvm->mmu_lock); + kvmppc_free_pgtable_radix(kvm, gp->shadow_pgtable, gp->shadow_lpid); + spin_unlock(&kvm->mmu_lock); + kvmhv_flush_lpid(gp->shadow_lpid); + kvmhv_update_ptbl_cache(gp); + if (gp->l1_gr_to_hr == 0) + kvmhv_remove_nested(gp); +} + +struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid, + bool create) +{ + struct kvm_nested_guest *gp, *newgp; + + if (l1_lpid >= KVM_MAX_NESTED_GUESTS || + l1_lpid >= (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4))) + return NULL; + + spin_lock(&kvm->mmu_lock); + gp = kvm->arch.nested_guests[l1_lpid]; + if (gp) + ++gp->refcnt; + spin_unlock(&kvm->mmu_lock); + + if (gp || !create) + return gp; + + newgp = kvmhv_alloc_nested(kvm, l1_lpid); + if (!newgp) + return NULL; + spin_lock(&kvm->mmu_lock); + if (kvm->arch.nested_guests[l1_lpid]) { + /* someone else beat us to it */ + gp = kvm->arch.nested_guests[l1_lpid]; + } else { + kvm->arch.nested_guests[l1_lpid] = newgp; + ++newgp->refcnt; + gp = newgp; + newgp = NULL; + if (l1_lpid > kvm->arch.max_nested_lpid) + kvm->arch.max_nested_lpid = l1_lpid; + } + ++gp->refcnt; + spin_unlock(&kvm->mmu_lock); + + if (newgp) + kvmhv_release_nested(newgp); + + return gp; +} + +void kvmhv_put_nested(struct kvm_nested_guest *gp) +{ + struct kvm *kvm = gp->l1_host; + long ref; + + spin_lock(&kvm->mmu_lock); + ref = --gp->refcnt; + spin_unlock(&kvm->mmu_lock); + if (ref == 0) + kvmhv_release_nested(gp); +} + +static struct kvm_nested_guest *kvmhv_find_nested(struct kvm *kvm, int lpid) +{ + if (lpid > kvm->arch.max_nested_lpid) + return NULL; + return kvm->arch.nested_guests[lpid]; +} + +static inline bool kvmhv_n_rmap_is_equal(u64 rmap_1, u64 rmap_2) +{ + return !((rmap_1 ^ rmap_2) & (RMAP_NESTED_LPID_MASK | + RMAP_NESTED_GPA_MASK)); +} + +void kvmhv_insert_nest_rmap(struct kvm *kvm, unsigned long *rmapp, + struct rmap_nested **n_rmap) +{ + struct llist_node *entry = ((struct llist_head *) rmapp)->first; + struct rmap_nested *cursor; + u64 rmap, new_rmap = (*n_rmap)->rmap; + + /* Are there any existing entries? */ + if (!(*rmapp)) { + /* No -> use the rmap as a single entry */ + *rmapp = new_rmap | RMAP_NESTED_IS_SINGLE_ENTRY; + return; + } + + /* Do any entries match what we're trying to insert? */ + for_each_nest_rmap_safe(cursor, entry, &rmap) { + if (kvmhv_n_rmap_is_equal(rmap, new_rmap)) + return; + } + + /* Do we need to create a list or just add the new entry? */ + rmap = *rmapp; + if (rmap & RMAP_NESTED_IS_SINGLE_ENTRY) /* Not previously a list */ + *rmapp = 0UL; + llist_add(&((*n_rmap)->list), (struct llist_head *) rmapp); + if (rmap & RMAP_NESTED_IS_SINGLE_ENTRY) /* Not previously a list */ + (*n_rmap)->list.next = (struct llist_node *) rmap; + + /* Set NULL so not freed by caller */ + *n_rmap = NULL; +} + +static void kvmhv_remove_nest_rmap(struct kvm *kvm, u64 n_rmap, + unsigned long hpa, unsigned long mask) +{ + struct kvm_nested_guest *gp; + unsigned long gpa; + unsigned int shift, lpid; + pte_t *ptep; + + gpa = n_rmap & RMAP_NESTED_GPA_MASK; + lpid = (n_rmap & RMAP_NESTED_LPID_MASK) >> RMAP_NESTED_LPID_SHIFT; + gp = kvmhv_find_nested(kvm, lpid); + if (!gp) + return; + + /* Find and invalidate the pte */ + ptep = __find_linux_pte(gp->shadow_pgtable, gpa, NULL, &shift); + /* Don't spuriously invalidate ptes if the pfn has changed */ + if (ptep && pte_present(*ptep) && ((pte_val(*ptep) & mask) == hpa)) + kvmppc_unmap_pte(kvm, ptep, gpa, shift, NULL, gp->shadow_lpid); +} + +static void kvmhv_remove_nest_rmap_list(struct kvm *kvm, unsigned long *rmapp, + unsigned long hpa, unsigned long mask) +{ + struct llist_node *entry = llist_del_all((struct llist_head *) rmapp); + struct rmap_nested *cursor; + unsigned long rmap; + + for_each_nest_rmap_safe(cursor, entry, &rmap) { + kvmhv_remove_nest_rmap(kvm, rmap, hpa, mask); + kfree(cursor); + } +} + +/* called with kvm->mmu_lock held */ +void kvmhv_remove_nest_rmap_range(struct kvm *kvm, + struct kvm_memory_slot *memslot, + unsigned long gpa, unsigned long hpa, + unsigned long nbytes) +{ + unsigned long gfn, end_gfn; + unsigned long addr_mask; + + if (!memslot) + return; + gfn = (gpa >> PAGE_SHIFT) - memslot->base_gfn; + end_gfn = gfn + (nbytes >> PAGE_SHIFT); + + addr_mask = PTE_RPN_MASK & ~(nbytes - 1); + hpa &= addr_mask; + + for (; gfn < end_gfn; gfn++) { + unsigned long *rmap = &memslot->arch.rmap[gfn]; + kvmhv_remove_nest_rmap_list(kvm, rmap, hpa, addr_mask); + } +} + +static void kvmhv_free_memslot_nest_rmap(struct kvm_memory_slot *free) +{ + unsigned long page; + + for (page = 0; page < free->npages; page++) { + unsigned long rmap, *rmapp = &free->arch.rmap[page]; + struct rmap_nested *cursor; + struct llist_node *entry; + + entry = llist_del_all((struct llist_head *) rmapp); + for_each_nest_rmap_safe(cursor, entry, &rmap) + kfree(cursor); + } +} + +static bool kvmhv_invalidate_shadow_pte(struct kvm_vcpu *vcpu, + struct kvm_nested_guest *gp, + long gpa, int *shift_ret) +{ + struct kvm *kvm = vcpu->kvm; + bool ret = false; + pte_t *ptep; + int shift; + + spin_lock(&kvm->mmu_lock); + ptep = __find_linux_pte(gp->shadow_pgtable, gpa, NULL, &shift); + if (!shift) + shift = PAGE_SHIFT; + if (ptep && pte_present(*ptep)) { + kvmppc_unmap_pte(kvm, ptep, gpa, shift, NULL, gp->shadow_lpid); + ret = true; + } + spin_unlock(&kvm->mmu_lock); + + if (shift_ret) + *shift_ret = shift; + return ret; +} + +static inline int get_ric(unsigned int instr) +{ + return (instr >> 18) & 0x3; +} + +static inline int get_prs(unsigned int instr) +{ + return (instr >> 17) & 0x1; +} + +static inline int get_r(unsigned int instr) +{ + return (instr >> 16) & 0x1; +} + +static inline int get_lpid(unsigned long r_val) +{ + return r_val & 0xffffffff; +} + +static inline int get_is(unsigned long r_val) +{ + return (r_val >> 10) & 0x3; +} + +static inline int get_ap(unsigned long r_val) +{ + return (r_val >> 5) & 0x7; +} + +static inline long get_epn(unsigned long r_val) +{ + return r_val >> 12; +} + +static int kvmhv_emulate_tlbie_tlb_addr(struct kvm_vcpu *vcpu, int lpid, + int ap, long epn) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_nested_guest *gp; + long npages; + int shift, shadow_shift; + unsigned long addr; + + shift = ap_to_shift(ap); + addr = epn << 12; + if (shift < 0) + /* Invalid ap encoding */ + return -EINVAL; + + addr &= ~((1UL << shift) - 1); + npages = 1UL << (shift - PAGE_SHIFT); + + gp = kvmhv_get_nested(kvm, lpid, false); + if (!gp) /* No such guest -> nothing to do */ + return 0; + mutex_lock(&gp->tlb_lock); + + /* There may be more than one host page backing this single guest pte */ + do { + kvmhv_invalidate_shadow_pte(vcpu, gp, addr, &shadow_shift); + + npages -= 1UL << (shadow_shift - PAGE_SHIFT); + addr += 1UL << shadow_shift; + } while (npages > 0); + + mutex_unlock(&gp->tlb_lock); + kvmhv_put_nested(gp); + return 0; +} + +static void kvmhv_emulate_tlbie_lpid(struct kvm_vcpu *vcpu, + struct kvm_nested_guest *gp, int ric) +{ + struct kvm *kvm = vcpu->kvm; + + mutex_lock(&gp->tlb_lock); + switch (ric) { + case 0: + /* Invalidate TLB */ + spin_lock(&kvm->mmu_lock); + kvmppc_free_pgtable_radix(kvm, gp->shadow_pgtable, + gp->shadow_lpid); + kvmhv_flush_lpid(gp->shadow_lpid); + spin_unlock(&kvm->mmu_lock); + break; + case 1: + /* + * Invalidate PWC + * We don't cache this -> nothing to do + */ + break; + case 2: + /* Invalidate TLB, PWC and caching of partition table entries */ + kvmhv_flush_nested(gp); + break; + default: + break; + } + mutex_unlock(&gp->tlb_lock); +} + +static void kvmhv_emulate_tlbie_all_lpid(struct kvm_vcpu *vcpu, int ric) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_nested_guest *gp; + int i; + + spin_lock(&kvm->mmu_lock); + for (i = 0; i <= kvm->arch.max_nested_lpid; i++) { + gp = kvm->arch.nested_guests[i]; + if (gp) { + spin_unlock(&kvm->mmu_lock); + kvmhv_emulate_tlbie_lpid(vcpu, gp, ric); + spin_lock(&kvm->mmu_lock); + } + } + spin_unlock(&kvm->mmu_lock); +} + +static int kvmhv_emulate_priv_tlbie(struct kvm_vcpu *vcpu, unsigned int instr, + unsigned long rsval, unsigned long rbval) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_nested_guest *gp; + int r, ric, prs, is, ap; + int lpid; + long epn; + int ret = 0; + + ric = get_ric(instr); + prs = get_prs(instr); + r = get_r(instr); + lpid = get_lpid(rsval); + is = get_is(rbval); + + /* + * These cases are invalid and are not handled: + * r != 1 -> Only radix supported + * prs == 1 -> Not HV privileged + * ric == 3 -> No cluster bombs for radix + * is == 1 -> Partition scoped translations not associated with pid + * (!is) && (ric == 1 || ric == 2) -> Not supported by ISA + */ + if ((!r) || (prs) || (ric == 3) || (is == 1) || + ((!is) && (ric == 1 || ric == 2))) + return -EINVAL; + + switch (is) { + case 0: + /* + * We know ric == 0 + * Invalidate TLB for a given target address + */ + epn = get_epn(rbval); + ap = get_ap(rbval); + ret = kvmhv_emulate_tlbie_tlb_addr(vcpu, lpid, ap, epn); + break; + case 2: + /* Invalidate matching LPID */ + gp = kvmhv_get_nested(kvm, lpid, false); + if (gp) { + kvmhv_emulate_tlbie_lpid(vcpu, gp, ric); + kvmhv_put_nested(gp); + } + break; + case 3: + /* Invalidate ALL LPIDs */ + kvmhv_emulate_tlbie_all_lpid(vcpu, ric); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/* + * This handles the H_TLB_INVALIDATE hcall. + * Parameters are (r4) tlbie instruction code, (r5) rS contents, + * (r6) rB contents. + */ +long kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu) +{ + int ret; + + ret = kvmhv_emulate_priv_tlbie(vcpu, kvmppc_get_gpr(vcpu, 4), + kvmppc_get_gpr(vcpu, 5), kvmppc_get_gpr(vcpu, 6)); + if (ret) + return H_PARAMETER; + return H_SUCCESS; +} + +/* Used to convert a nested guest real address to a L1 guest real address */ +static int kvmhv_translate_addr_nested(struct kvm_vcpu *vcpu, + struct kvm_nested_guest *gp, + unsigned long n_gpa, unsigned long dsisr, + struct kvmppc_pte *gpte_p) +{ + u64 fault_addr, flags = dsisr & DSISR_ISSTORE; + int ret; + + ret = kvmppc_mmu_walk_radix_tree(vcpu, n_gpa, gpte_p, gp->l1_gr_to_hr, + &fault_addr); + + if (ret) { + /* We didn't find a pte */ + if (ret == -EINVAL) { + /* Unsupported mmu config */ + flags |= DSISR_UNSUPP_MMU; + } else if (ret == -ENOENT) { + /* No translation found */ + flags |= DSISR_NOHPTE; + } else if (ret == -EFAULT) { + /* Couldn't access L1 real address */ + flags |= DSISR_PRTABLE_FAULT; + vcpu->arch.fault_gpa = fault_addr; + } else { + /* Unknown error */ + return ret; + } + goto forward_to_l1; + } else { + /* We found a pte -> check permissions */ + if (dsisr & DSISR_ISSTORE) { + /* Can we write? */ + if (!gpte_p->may_write) { + flags |= DSISR_PROTFAULT; + goto forward_to_l1; + } + } else if (vcpu->arch.trap == BOOK3S_INTERRUPT_H_INST_STORAGE) { + /* Can we execute? */ + if (!gpte_p->may_execute) { + flags |= SRR1_ISI_N_OR_G; + goto forward_to_l1; + } + } else { + /* Can we read? */ + if (!gpte_p->may_read && !gpte_p->may_write) { + flags |= DSISR_PROTFAULT; + goto forward_to_l1; + } + } + } + + return 0; + +forward_to_l1: + vcpu->arch.fault_dsisr = flags; + if (vcpu->arch.trap == BOOK3S_INTERRUPT_H_INST_STORAGE) { + vcpu->arch.shregs.msr &= ~0x783f0000ul; + vcpu->arch.shregs.msr |= flags; + } + return RESUME_HOST; +} + +static long kvmhv_handle_nested_set_rc(struct kvm_vcpu *vcpu, + struct kvm_nested_guest *gp, + unsigned long n_gpa, + struct kvmppc_pte gpte, + unsigned long dsisr) +{ + struct kvm *kvm = vcpu->kvm; + bool writing = !!(dsisr & DSISR_ISSTORE); + u64 pgflags; + bool ret; + + /* Are the rc bits set in the L1 partition scoped pte? */ + pgflags = _PAGE_ACCESSED; + if (writing) + pgflags |= _PAGE_DIRTY; + if (pgflags & ~gpte.rc) + return RESUME_HOST; + + spin_lock(&kvm->mmu_lock); + /* Set the rc bit in the pte of our (L0) pgtable for the L1 guest */ + ret = kvmppc_hv_handle_set_rc(kvm, kvm->arch.pgtable, writing, + gpte.raddr, kvm->arch.lpid); + spin_unlock(&kvm->mmu_lock); + if (!ret) + return -EINVAL; + + /* Set the rc bit in the pte of the shadow_pgtable for the nest guest */ + ret = kvmppc_hv_handle_set_rc(kvm, gp->shadow_pgtable, writing, n_gpa, + gp->shadow_lpid); + if (!ret) + return -EINVAL; + return 0; +} + +static inline int kvmppc_radix_level_to_shift(int level) +{ + switch (level) { + case 2: + return PUD_SHIFT; + case 1: + return PMD_SHIFT; + default: + return PAGE_SHIFT; + } +} + +static inline int kvmppc_radix_shift_to_level(int shift) +{ + if (shift == PUD_SHIFT) + return 2; + if (shift == PMD_SHIFT) + return 1; + if (shift == PAGE_SHIFT) + return 0; + WARN_ON_ONCE(1); + return 0; +} + +/* called with gp->tlb_lock held */ +static long int __kvmhv_nested_page_fault(struct kvm_vcpu *vcpu, + struct kvm_nested_guest *gp) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_memory_slot *memslot; + struct rmap_nested *n_rmap; + struct kvmppc_pte gpte; + pte_t pte, *pte_p; + unsigned long mmu_seq; + unsigned long dsisr = vcpu->arch.fault_dsisr; + unsigned long ea = vcpu->arch.fault_dar; + unsigned long *rmapp; + unsigned long n_gpa, gpa, gfn, perm = 0UL; + unsigned int shift, l1_shift, level; + bool writing = !!(dsisr & DSISR_ISSTORE); + bool kvm_ro = false; + long int ret; + + if (!gp->l1_gr_to_hr) { + kvmhv_update_ptbl_cache(gp); + if (!gp->l1_gr_to_hr) + return RESUME_HOST; + } + + /* Convert the nested guest real address into a L1 guest real address */ + + n_gpa = vcpu->arch.fault_gpa & ~0xF000000000000FFFULL; + if (!(dsisr & DSISR_PRTABLE_FAULT)) + n_gpa |= ea & 0xFFF; + ret = kvmhv_translate_addr_nested(vcpu, gp, n_gpa, dsisr, &gpte); + + /* + * If the hardware found a translation but we don't now have a usable + * translation in the l1 partition-scoped tree, remove the shadow pte + * and let the guest retry. + */ + if (ret == RESUME_HOST && + (dsisr & (DSISR_PROTFAULT | DSISR_BADACCESS | DSISR_NOEXEC_OR_G | + DSISR_BAD_COPYPASTE))) + goto inval; + if (ret) + return ret; + + /* Failed to set the reference/change bits */ + if (dsisr & DSISR_SET_RC) { + ret = kvmhv_handle_nested_set_rc(vcpu, gp, n_gpa, gpte, dsisr); + if (ret == RESUME_HOST) + return ret; + if (ret) + goto inval; + dsisr &= ~DSISR_SET_RC; + if (!(dsisr & (DSISR_BAD_FAULT_64S | DSISR_NOHPTE | + DSISR_PROTFAULT))) + return RESUME_GUEST; + } + + /* + * We took an HISI or HDSI while we were running a nested guest which + * means we have no partition scoped translation for that. This means + * we need to insert a pte for the mapping into our shadow_pgtable. + */ + + l1_shift = gpte.page_shift; + if (l1_shift < PAGE_SHIFT) { + /* We don't support l1 using a page size smaller than our own */ + pr_err("KVM: L1 guest page shift (%d) less than our own (%d)\n", + l1_shift, PAGE_SHIFT); + return -EINVAL; + } + gpa = gpte.raddr; + gfn = gpa >> PAGE_SHIFT; + + /* 1. Get the corresponding host memslot */ + + memslot = gfn_to_memslot(kvm, gfn); + if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) { + if (dsisr & (DSISR_PRTABLE_FAULT | DSISR_BADACCESS)) { + /* unusual error -> reflect to the guest as a DSI */ + kvmppc_core_queue_data_storage(vcpu, ea, dsisr); + return RESUME_GUEST; + } + /* passthrough of emulated MMIO case... */ + pr_err("emulated MMIO passthrough?\n"); + return -EINVAL; + } + if (memslot->flags & KVM_MEM_READONLY) { + if (writing) { + /* Give the guest a DSI */ + kvmppc_core_queue_data_storage(vcpu, ea, + DSISR_ISSTORE | DSISR_PROTFAULT); + return RESUME_GUEST; + } + kvm_ro = true; + } + + /* 2. Find the host pte for this L1 guest real address */ + + /* Used to check for invalidations in progress */ + mmu_seq = kvm->mmu_notifier_seq; + smp_rmb(); + + /* See if can find translation in our partition scoped tables for L1 */ + pte = __pte(0); + spin_lock(&kvm->mmu_lock); + pte_p = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift); + if (!shift) + shift = PAGE_SHIFT; + if (pte_p) + pte = *pte_p; + spin_unlock(&kvm->mmu_lock); + + if (!pte_present(pte) || (writing && !(pte_val(pte) & _PAGE_WRITE))) { + /* No suitable pte found -> try to insert a mapping */ + ret = kvmppc_book3s_instantiate_page(vcpu, gpa, memslot, + writing, kvm_ro, &pte, &level); + if (ret == -EAGAIN) + return RESUME_GUEST; + else if (ret) + return ret; + shift = kvmppc_radix_level_to_shift(level); + } + + /* 3. Compute the pte we need to insert for nest_gpa -> host r_addr */ + + /* The permissions is the combination of the host and l1 guest ptes */ + perm |= gpte.may_read ? 0UL : _PAGE_READ; + perm |= gpte.may_write ? 0UL : _PAGE_WRITE; + perm |= gpte.may_execute ? 0UL : _PAGE_EXEC; + pte = __pte(pte_val(pte) & ~perm); + + /* What size pte can we insert? */ + if (shift > l1_shift) { + u64 mask; + unsigned int actual_shift = PAGE_SHIFT; + if (PMD_SHIFT < l1_shift) + actual_shift = PMD_SHIFT; + mask = (1UL << shift) - (1UL << actual_shift); + pte = __pte(pte_val(pte) | (gpa & mask)); + shift = actual_shift; + } + level = kvmppc_radix_shift_to_level(shift); + n_gpa &= ~((1UL << shift) - 1); + + /* 4. Insert the pte into our shadow_pgtable */ + + n_rmap = kzalloc(sizeof(*n_rmap), GFP_KERNEL); + if (!n_rmap) + return RESUME_GUEST; /* Let the guest try again */ + n_rmap->rmap = (n_gpa & RMAP_NESTED_GPA_MASK) | + (((unsigned long) gp->l1_lpid) << RMAP_NESTED_LPID_SHIFT); + rmapp = &memslot->arch.rmap[gfn - memslot->base_gfn]; + ret = kvmppc_create_pte(kvm, gp->shadow_pgtable, pte, n_gpa, level, + mmu_seq, gp->shadow_lpid, rmapp, &n_rmap); + if (n_rmap) + kfree(n_rmap); + if (ret == -EAGAIN) + ret = RESUME_GUEST; /* Let the guest try again */ + + return ret; + + inval: + kvmhv_invalidate_shadow_pte(vcpu, gp, n_gpa, NULL); + return RESUME_GUEST; +} + +long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu) +{ + struct kvm_nested_guest *gp = vcpu->arch.nested; + long int ret; + + mutex_lock(&gp->tlb_lock); + ret = __kvmhv_nested_page_fault(vcpu, gp); + mutex_unlock(&gp->tlb_lock); + return ret; +} + +int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid) +{ + int ret = -1; + + spin_lock(&kvm->mmu_lock); + while (++lpid <= kvm->arch.max_nested_lpid) { + if (kvm->arch.nested_guests[lpid]) { + ret = lpid; + break; + } + } + spin_unlock(&kvm->mmu_lock); + return ret; +} diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index b11043b23c18..0787f12c1a1b 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c @@ -177,6 +177,7 @@ void kvmppc_subcore_enter_guest(void) local_paca->sibling_subcore_state->in_guest[subcore_id] = 1; } +EXPORT_SYMBOL_GPL(kvmppc_subcore_enter_guest); void kvmppc_subcore_exit_guest(void) { @@ -187,6 +188,7 @@ void kvmppc_subcore_exit_guest(void) local_paca->sibling_subcore_state->in_guest[subcore_id] = 0; } +EXPORT_SYMBOL_GPL(kvmppc_subcore_exit_guest); static bool kvmppc_tb_resync_required(void) { @@ -331,5 +333,13 @@ long kvmppc_realmode_hmi_handler(void) } else { wait_for_tb_resync(); } + + /* + * Reset tb_offset_applied so the guest exit code won't try + * to subtract the previous timebase offset from the timebase. + */ + if (local_paca->kvm_hstate.kvm_vcore) + local_paca->kvm_hstate.kvm_vcore->tb_offset_applied = 0; + return 0; } diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index 758d1d23215e..b3f5786b20dc 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -136,7 +136,7 @@ static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu, /* Mark the target VCPU as having an interrupt pending */ vcpu->stat.queue_intr++; - set_bit(BOOK3S_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions); + set_bit(BOOK3S_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); /* Kick self ? Just set MER and return */ if (vcpu == this_vcpu) { @@ -170,8 +170,7 @@ static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu, static void icp_rm_clr_vcpu_irq(struct kvm_vcpu *vcpu) { /* Note: Only called on self ! */ - clear_bit(BOOK3S_IRQPRIO_EXTERNAL_LEVEL, - &vcpu->arch.pending_exceptions); + clear_bit(BOOK3S_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_MER); } @@ -768,6 +767,14 @@ static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again) void __iomem *xics_phys; int64_t rc; + if (kvmhv_on_pseries()) { + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + + iosync(); + plpar_hcall_raw(H_EOI, retbuf, hwirq); + return; + } + rc = pnv_opal_pci_msi_eoi(c, hwirq); if (rc) diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 1d14046124a0..9b8d50a7cbaf 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -28,6 +28,7 @@ #include <asm/exception-64s.h> #include <asm/kvm_book3s_asm.h> #include <asm/book3s/64/mmu-hash.h> +#include <asm/export.h> #include <asm/tm.h> #include <asm/opal.h> #include <asm/xive-regs.h> @@ -46,8 +47,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) #define NAPPING_NOVCPU 2 /* Stack frame offsets for kvmppc_hv_entry */ -#define SFS 160 +#define SFS 208 #define STACK_SLOT_TRAP (SFS-4) +#define STACK_SLOT_SHORT_PATH (SFS-8) #define STACK_SLOT_TID (SFS-16) #define STACK_SLOT_PSSCR (SFS-24) #define STACK_SLOT_PID (SFS-32) @@ -56,6 +58,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) #define STACK_SLOT_DAWR (SFS-56) #define STACK_SLOT_DAWRX (SFS-64) #define STACK_SLOT_HFSCR (SFS-72) +/* the following is used by the P9 short path */ +#define STACK_SLOT_NVGPRS (SFS-152) /* 18 gprs */ /* * Call kvmppc_hv_entry in real mode. @@ -113,45 +117,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) mtspr SPRN_SPRG_VDSO_WRITE,r3 /* Reload the host's PMU registers */ - lbz r4, PACA_PMCINUSE(r13) /* is the host using the PMU? */ - cmpwi r4, 0 - beq 23f /* skip if not */ -BEGIN_FTR_SECTION - ld r3, HSTATE_MMCR0(r13) - andi. r4, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO - cmpwi r4, MMCR0_PMAO - beql kvmppc_fix_pmao -END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG) - lwz r3, HSTATE_PMC1(r13) - lwz r4, HSTATE_PMC2(r13) - lwz r5, HSTATE_PMC3(r13) - lwz r6, HSTATE_PMC4(r13) - lwz r8, HSTATE_PMC5(r13) - lwz r9, HSTATE_PMC6(r13) - mtspr SPRN_PMC1, r3 - mtspr SPRN_PMC2, r4 - mtspr SPRN_PMC3, r5 - mtspr SPRN_PMC4, r6 - mtspr SPRN_PMC5, r8 - mtspr SPRN_PMC6, r9 - ld r3, HSTATE_MMCR0(r13) - ld r4, HSTATE_MMCR1(r13) - ld r5, HSTATE_MMCRA(r13) - ld r6, HSTATE_SIAR(r13) - ld r7, HSTATE_SDAR(r13) - mtspr SPRN_MMCR1, r4 - mtspr SPRN_MMCRA, r5 - mtspr SPRN_SIAR, r6 - mtspr SPRN_SDAR, r7 -BEGIN_FTR_SECTION - ld r8, HSTATE_MMCR2(r13) - ld r9, HSTATE_SIER(r13) - mtspr SPRN_MMCR2, r8 - mtspr SPRN_SIER, r9 -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - mtspr SPRN_MMCR0, r3 - isync -23: + bl kvmhv_load_host_pmu /* * Reload DEC. HDEC interrupts were disabled when @@ -796,66 +762,23 @@ BEGIN_FTR_SECTION b 91f END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) /* - * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR + * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR) */ mr r3, r4 ld r4, VCPU_MSR(r3) + li r5, 0 /* don't preserve non-vol regs */ bl kvmppc_restore_tm_hv + nop ld r4, HSTATE_KVM_VCPU(r13) 91: #endif - /* Load guest PMU registers */ - /* R4 is live here (vcpu pointer) */ - li r3, 1 - sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ - mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ - isync -BEGIN_FTR_SECTION - ld r3, VCPU_MMCR(r4) - andi. r5, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO - cmpwi r5, MMCR0_PMAO - beql kvmppc_fix_pmao -END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG) - lwz r3, VCPU_PMC(r4) /* always load up guest PMU registers */ - lwz r5, VCPU_PMC + 4(r4) /* to prevent information leak */ - lwz r6, VCPU_PMC + 8(r4) - lwz r7, VCPU_PMC + 12(r4) - lwz r8, VCPU_PMC + 16(r4) - lwz r9, VCPU_PMC + 20(r4) - mtspr SPRN_PMC1, r3 - mtspr SPRN_PMC2, r5 - mtspr SPRN_PMC3, r6 - mtspr SPRN_PMC4, r7 - mtspr SPRN_PMC5, r8 - mtspr SPRN_PMC6, r9 - ld r3, VCPU_MMCR(r4) - ld r5, VCPU_MMCR + 8(r4) - ld r6, VCPU_MMCR + 16(r4) - ld r7, VCPU_SIAR(r4) - ld r8, VCPU_SDAR(r4) - mtspr SPRN_MMCR1, r5 - mtspr SPRN_MMCRA, r6 - mtspr SPRN_SIAR, r7 - mtspr SPRN_SDAR, r8 -BEGIN_FTR_SECTION - ld r5, VCPU_MMCR + 24(r4) - ld r6, VCPU_SIER(r4) - mtspr SPRN_MMCR2, r5 - mtspr SPRN_SIER, r6 -BEGIN_FTR_SECTION_NESTED(96) - lwz r7, VCPU_PMC + 24(r4) - lwz r8, VCPU_PMC + 28(r4) - ld r9, VCPU_MMCR + 32(r4) - mtspr SPRN_SPMC1, r7 - mtspr SPRN_SPMC2, r8 - mtspr SPRN_MMCRS, r9 -END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96) -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - mtspr SPRN_MMCR0, r3 - isync + /* Load guest PMU registers; r4 = vcpu pointer here */ + mr r3, r4 + bl kvmhv_load_guest_pmu /* Load up FP, VMX and VSX registers */ + ld r4, HSTATE_KVM_VCPU(r13) bl kvmppc_load_fp ld r14, VCPU_GPR(R14)(r4) @@ -1100,73 +1023,40 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300) no_xive: #endif /* CONFIG_KVM_XICS */ -deliver_guest_interrupt: - ld r6, VCPU_CTR(r4) - ld r7, VCPU_XER(r4) - - mtctr r6 - mtxer r7 + li r0, 0 + stw r0, STACK_SLOT_SHORT_PATH(r1) -kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */ - ld r10, VCPU_PC(r4) - ld r11, VCPU_MSR(r4) +deliver_guest_interrupt: /* r4 = vcpu, r13 = paca */ + /* Check if we can deliver an external or decrementer interrupt now */ + ld r0, VCPU_PENDING_EXC(r4) +BEGIN_FTR_SECTION + /* On POWER9, also check for emulated doorbell interrupt */ + lbz r3, VCPU_DBELL_REQ(r4) + or r0, r0, r3 +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + cmpdi r0, 0 + beq 71f + mr r3, r4 + bl kvmppc_guest_entry_inject_int + ld r4, HSTATE_KVM_VCPU(r13) +71: ld r6, VCPU_SRR0(r4) ld r7, VCPU_SRR1(r4) mtspr SPRN_SRR0, r6 mtspr SPRN_SRR1, r7 +fast_guest_entry_c: + ld r10, VCPU_PC(r4) + ld r11, VCPU_MSR(r4) /* r11 = vcpu->arch.msr & ~MSR_HV */ rldicl r11, r11, 63 - MSR_HV_LG, 1 rotldi r11, r11, 1 + MSR_HV_LG ori r11, r11, MSR_ME - /* Check if we can deliver an external or decrementer interrupt now */ - ld r0, VCPU_PENDING_EXC(r4) - rldicl r0, r0, 64 - BOOK3S_IRQPRIO_EXTERNAL_LEVEL, 63 - cmpdi cr1, r0, 0 - andi. r8, r11, MSR_EE - mfspr r8, SPRN_LPCR - /* Insert EXTERNAL_LEVEL bit into LPCR at the MER bit position */ - rldimi r8, r0, LPCR_MER_SH, 63 - LPCR_MER_SH - mtspr SPRN_LPCR, r8 - isync - beq 5f - li r0, BOOK3S_INTERRUPT_EXTERNAL - bne cr1, 12f - mfspr r0, SPRN_DEC -BEGIN_FTR_SECTION - /* On POWER9 check whether the guest has large decrementer enabled */ - andis. r8, r8, LPCR_LD@h - bne 15f -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) - extsw r0, r0 -15: cmpdi r0, 0 - li r0, BOOK3S_INTERRUPT_DECREMENTER - bge 5f - -12: mtspr SPRN_SRR0, r10 - mr r10,r0 - mtspr SPRN_SRR1, r11 - mr r9, r4 - bl kvmppc_msr_interrupt -5: -BEGIN_FTR_SECTION - b fast_guest_return -END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) - /* On POWER9, check for pending doorbell requests */ - lbz r0, VCPU_DBELL_REQ(r4) - cmpwi r0, 0 - beq fast_guest_return - ld r5, HSTATE_KVM_VCORE(r13) - /* Set DPDES register so the CPU will take a doorbell interrupt */ - li r0, 1 - mtspr SPRN_DPDES, r0 - std r0, VCORE_DPDES(r5) - /* Make sure other cpus see vcore->dpdes set before dbell req clear */ - lwsync - /* Clear the pending doorbell request */ - li r0, 0 - stb r0, VCPU_DBELL_REQ(r4) + ld r6, VCPU_CTR(r4) + ld r7, VCPU_XER(r4) + mtctr r6 + mtxer r7 /* * Required state: @@ -1202,7 +1092,7 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) ld r5, VCPU_LR(r4) - lwz r6, VCPU_CR(r4) + ld r6, VCPU_CR(r4) mtlr r5 mtcr r6 @@ -1234,6 +1124,83 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) HRFI_TO_GUEST b . +/* + * Enter the guest on a P9 or later system where we have exactly + * one vcpu per vcore and we don't need to go to real mode + * (which implies that host and guest are both using radix MMU mode). + * r3 = vcpu pointer + * Most SPRs and all the VSRs have been loaded already. + */ +_GLOBAL(__kvmhv_vcpu_entry_p9) +EXPORT_SYMBOL_GPL(__kvmhv_vcpu_entry_p9) + mflr r0 + std r0, PPC_LR_STKOFF(r1) + stdu r1, -SFS(r1) + + li r0, 1 + stw r0, STACK_SLOT_SHORT_PATH(r1) + + std r3, HSTATE_KVM_VCPU(r13) + mfcr r4 + stw r4, SFS+8(r1) + + std r1, HSTATE_HOST_R1(r13) + + reg = 14 + .rept 18 + std reg, STACK_SLOT_NVGPRS + ((reg - 14) * 8)(r1) + reg = reg + 1 + .endr + + reg = 14 + .rept 18 + ld reg, __VCPU_GPR(reg)(r3) + reg = reg + 1 + .endr + + mfmsr r10 + std r10, HSTATE_HOST_MSR(r13) + + mr r4, r3 + b fast_guest_entry_c +guest_exit_short_path: + + li r0, KVM_GUEST_MODE_NONE + stb r0, HSTATE_IN_GUEST(r13) + + reg = 14 + .rept 18 + std reg, __VCPU_GPR(reg)(r9) + reg = reg + 1 + .endr + + reg = 14 + .rept 18 + ld reg, STACK_SLOT_NVGPRS + ((reg - 14) * 8)(r1) + reg = reg + 1 + .endr + + lwz r4, SFS+8(r1) + mtcr r4 + + mr r3, r12 /* trap number */ + + addi r1, r1, SFS + ld r0, PPC_LR_STKOFF(r1) + mtlr r0 + + /* If we are in real mode, do a rfid to get back to the caller */ + mfmsr r4 + andi. r5, r4, MSR_IR + bnelr + rldicl r5, r4, 64 - MSR_TS_S_LG, 62 /* extract TS field */ + mtspr SPRN_SRR0, r0 + ld r10, HSTATE_HOST_MSR(r13) + rldimi r10, r5, MSR_TS_S_LG, 63 - MSR_TS_T_LG + mtspr SPRN_SRR1, r10 + RFI_TO_KERNEL + b . + secondary_too_late: li r12, 0 stw r12, STACK_SLOT_TRAP(r1) @@ -1313,7 +1280,7 @@ kvmppc_interrupt_hv: std r3, VCPU_GPR(R12)(r9) /* CR is in the high half of r12 */ srdi r4, r12, 32 - stw r4, VCPU_CR(r9) + std r4, VCPU_CR(r9) BEGIN_FTR_SECTION ld r3, HSTATE_CFAR(r13) std r3, VCPU_CFAR(r9) @@ -1387,18 +1354,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) std r3, VCPU_CTR(r9) std r4, VCPU_XER(r9) -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM - /* For softpatch interrupt, go off and do TM instruction emulation */ - cmpwi r12, BOOK3S_INTERRUPT_HV_SOFTPATCH - beq kvmppc_tm_emul -#endif + /* Save more register state */ + mfdar r3 + mfdsisr r4 + std r3, VCPU_DAR(r9) + stw r4, VCPU_DSISR(r9) /* If this is a page table miss then see if it's theirs or ours */ cmpwi r12, BOOK3S_INTERRUPT_H_DATA_STORAGE beq kvmppc_hdsi + std r3, VCPU_FAULT_DAR(r9) + stw r4, VCPU_FAULT_DSISR(r9) cmpwi r12, BOOK3S_INTERRUPT_H_INST_STORAGE beq kvmppc_hisi +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM + /* For softpatch interrupt, go off and do TM instruction emulation */ + cmpwi r12, BOOK3S_INTERRUPT_HV_SOFTPATCH + beq kvmppc_tm_emul +#endif + /* See if this is a leftover HDEC interrupt */ cmpwi r12,BOOK3S_INTERRUPT_HV_DECREMENTER bne 2f @@ -1418,10 +1393,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) BEGIN_FTR_SECTION PPC_MSGSYNC lwsync + /* always exit if we're running a nested guest */ + ld r0, VCPU_NESTED(r9) + cmpdi r0, 0 + bne guest_exit_cont END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) lbz r0, HSTATE_HOST_IPI(r13) cmpwi r0, 0 - beq 4f + beq maybe_reenter_guest b guest_exit_cont 3: /* If it's a hypervisor facility unavailable interrupt, save HFSCR */ @@ -1433,82 +1412,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) 14: /* External interrupt ? */ cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL - bne+ guest_exit_cont - - /* External interrupt, first check for host_ipi. If this is - * set, we know the host wants us out so let's do it now - */ - bl kvmppc_read_intr - - /* - * Restore the active volatile registers after returning from - * a C function. - */ - ld r9, HSTATE_KVM_VCPU(r13) - li r12, BOOK3S_INTERRUPT_EXTERNAL - - /* - * kvmppc_read_intr return codes: - * - * Exit to host (r3 > 0) - * 1 An interrupt is pending that needs to be handled by the host - * Exit guest and return to host by branching to guest_exit_cont - * - * 2 Passthrough that needs completion in the host - * Exit guest and return to host by branching to guest_exit_cont - * However, we also set r12 to BOOK3S_INTERRUPT_HV_RM_HARD - * to indicate to the host to complete handling the interrupt - * - * Before returning to guest, we check if any CPU is heading out - * to the host and if so, we head out also. If no CPUs are heading - * check return values <= 0. - * - * Return to guest (r3 <= 0) - * 0 No external interrupt is pending - * -1 A guest wakeup IPI (which has now been cleared) - * In either case, we return to guest to deliver any pending - * guest interrupts. - * - * -2 A PCI passthrough external interrupt was handled - * (interrupt was delivered directly to guest) - * Return to guest to deliver any pending guest interrupts. - */ - - cmpdi r3, 1 - ble 1f - - /* Return code = 2 */ - li r12, BOOK3S_INTERRUPT_HV_RM_HARD - stw r12, VCPU_TRAP(r9) - b guest_exit_cont - -1: /* Return code <= 1 */ - cmpdi r3, 0 - bgt guest_exit_cont - - /* Return code <= 0 */ -4: ld r5, HSTATE_KVM_VCORE(r13) - lwz r0, VCORE_ENTRY_EXIT(r5) - cmpwi r0, 0x100 - mr r4, r9 - blt deliver_guest_interrupt - -guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ - /* Save more register state */ - mfdar r6 - mfdsisr r7 - std r6, VCPU_DAR(r9) - stw r7, VCPU_DSISR(r9) - /* don't overwrite fault_dar/fault_dsisr if HDSI */ - cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE - beq mc_cont - std r6, VCPU_FAULT_DAR(r9) - stw r7, VCPU_FAULT_DSISR(r9) - + beq kvmppc_guest_external /* See if it is a machine check */ cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK beq machine_check_realmode -mc_cont: + /* Or a hypervisor maintenance interrupt */ + cmpwi r12, BOOK3S_INTERRUPT_HMI + beq hmi_realmode + +guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ + #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING addi r3, r9, VCPU_TB_RMEXIT mr r4, r9 @@ -1552,6 +1465,11 @@ mc_cont: 1: #endif /* CONFIG_KVM_XICS */ + /* If we came in through the P9 short path, go back out to C now */ + lwz r0, STACK_SLOT_SHORT_PATH(r1) + cmpwi r0, 0 + bne guest_exit_short_path + /* For hash guest, read the guest SLB and save it away */ ld r5, VCPU_KVM(r9) lbz r0, KVM_RADIX(r5) @@ -1780,11 +1698,13 @@ BEGIN_FTR_SECTION b 91f END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) /* - * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR + * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR) */ mr r3, r9 ld r4, VCPU_MSR(r3) + li r5, 0 /* don't preserve non-vol regs */ bl kvmppc_save_tm_hv + nop ld r9, HSTATE_KVM_VCPU(r13) 91: #endif @@ -1802,83 +1722,12 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) 25: /* Save PMU registers if requested */ /* r8 and cr0.eq are live here */ -BEGIN_FTR_SECTION - /* - * POWER8 seems to have a hardware bug where setting - * MMCR0[PMAE] along with MMCR0[PMC1CE] and/or MMCR0[PMCjCE] - * when some counters are already negative doesn't seem - * to cause a performance monitor alert (and hence interrupt). - * The effect of this is that when saving the PMU state, - * if there is no PMU alert pending when we read MMCR0 - * before freezing the counters, but one becomes pending - * before we read the counters, we lose it. - * To work around this, we need a way to freeze the counters - * before reading MMCR0. Normally, freezing the counters - * is done by writing MMCR0 (to set MMCR0[FC]) which - * unavoidably writes MMCR0[PMA0] as well. On POWER8, - * we can also freeze the counters using MMCR2, by writing - * 1s to all the counter freeze condition bits (there are - * 9 bits each for 6 counters). - */ - li r3, -1 /* set all freeze bits */ - clrrdi r3, r3, 10 - mfspr r10, SPRN_MMCR2 - mtspr SPRN_MMCR2, r3 - isync -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - li r3, 1 - sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ - mfspr r4, SPRN_MMCR0 /* save MMCR0 */ - mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ - mfspr r6, SPRN_MMCRA - /* Clear MMCRA in order to disable SDAR updates */ - li r7, 0 - mtspr SPRN_MMCRA, r7 - isync + mr r3, r9 + li r4, 1 beq 21f /* if no VPA, save PMU stuff anyway */ - lbz r7, LPPACA_PMCINUSE(r8) - cmpwi r7, 0 /* did they ask for PMU stuff to be saved? */ - bne 21f - std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */ - b 22f -21: mfspr r5, SPRN_MMCR1 - mfspr r7, SPRN_SIAR - mfspr r8, SPRN_SDAR - std r4, VCPU_MMCR(r9) - std r5, VCPU_MMCR + 8(r9) - std r6, VCPU_MMCR + 16(r9) -BEGIN_FTR_SECTION - std r10, VCPU_MMCR + 24(r9) -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - std r7, VCPU_SIAR(r9) - std r8, VCPU_SDAR(r9) - mfspr r3, SPRN_PMC1 - mfspr r4, SPRN_PMC2 - mfspr r5, SPRN_PMC3 - mfspr r6, SPRN_PMC4 - mfspr r7, SPRN_PMC5 - mfspr r8, SPRN_PMC6 - stw r3, VCPU_PMC(r9) - stw r4, VCPU_PMC + 4(r9) - stw r5, VCPU_PMC + 8(r9) - stw r6, VCPU_PMC + 12(r9) - stw r7, VCPU_PMC + 16(r9) - stw r8, VCPU_PMC + 20(r9) -BEGIN_FTR_SECTION - mfspr r5, SPRN_SIER - std r5, VCPU_SIER(r9) -BEGIN_FTR_SECTION_NESTED(96) - mfspr r6, SPRN_SPMC1 - mfspr r7, SPRN_SPMC2 - mfspr r8, SPRN_MMCRS - stw r6, VCPU_PMC + 24(r9) - stw r7, VCPU_PMC + 28(r9) - std r8, VCPU_MMCR + 32(r9) - lis r4, 0x8000 - mtspr SPRN_MMCRS, r4 -END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96) -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) -22: + lbz r4, LPPACA_PMCINUSE(r8) +21: bl kvmhv_save_guest_pmu + ld r9, HSTATE_KVM_VCPU(r13) /* Restore host values of some registers */ BEGIN_FTR_SECTION @@ -2010,24 +1859,6 @@ BEGIN_FTR_SECTION mtspr SPRN_DPDES, r8 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - /* If HMI, call kvmppc_realmode_hmi_handler() */ - lwz r12, STACK_SLOT_TRAP(r1) - cmpwi r12, BOOK3S_INTERRUPT_HMI - bne 27f - bl kvmppc_realmode_hmi_handler - nop - cmpdi r3, 0 - /* - * At this point kvmppc_realmode_hmi_handler may have resync-ed - * the TB, and if it has, we must not subtract the guest timebase - * offset from the timebase. So, skip it. - * - * Also, do not call kvmppc_subcore_exit_guest() because it has - * been invoked as part of kvmppc_realmode_hmi_handler(). - */ - beq 30f - -27: /* Subtract timebase offset from timebase */ ld r8, VCORE_TB_OFFSET_APPL(r5) cmpdi r8,0 @@ -2045,7 +1876,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) addis r8,r8,0x100 /* if so, increment upper 40 bits */ mtspr SPRN_TBU40,r8 -17: bl kvmppc_subcore_exit_guest +17: + /* + * If this is an HMI, we called kvmppc_realmode_hmi_handler + * above, which may or may not have already called + * kvmppc_subcore_exit_guest. Fortunately, all that + * kvmppc_subcore_exit_guest does is clear a flag, so calling + * it again here is benign even if kvmppc_realmode_hmi_handler + * has already called it. + */ + bl kvmppc_subcore_exit_guest nop 30: ld r5,HSTATE_KVM_VCORE(r13) ld r4,VCORE_KVM(r5) /* pointer to struct kvm */ @@ -2099,6 +1939,67 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) mtlr r0 blr +kvmppc_guest_external: + /* External interrupt, first check for host_ipi. If this is + * set, we know the host wants us out so let's do it now + */ + bl kvmppc_read_intr + + /* + * Restore the active volatile registers after returning from + * a C function. + */ + ld r9, HSTATE_KVM_VCPU(r13) + li r12, BOOK3S_INTERRUPT_EXTERNAL + + /* + * kvmppc_read_intr return codes: + * + * Exit to host (r3 > 0) + * 1 An interrupt is pending that needs to be handled by the host + * Exit guest and return to host by branching to guest_exit_cont + * + * 2 Passthrough that needs completion in the host + * Exit guest and return to host by branching to guest_exit_cont + * However, we also set r12 to BOOK3S_INTERRUPT_HV_RM_HARD + * to indicate to the host to complete handling the interrupt + * + * Before returning to guest, we check if any CPU is heading out + * to the host and if so, we head out also. If no CPUs are heading + * check return values <= 0. + * + * Return to guest (r3 <= 0) + * 0 No external interrupt is pending + * -1 A guest wakeup IPI (which has now been cleared) + * In either case, we return to guest to deliver any pending + * guest interrupts. + * + * -2 A PCI passthrough external interrupt was handled + * (interrupt was delivered directly to guest) + * Return to guest to deliver any pending guest interrupts. + */ + + cmpdi r3, 1 + ble 1f + + /* Return code = 2 */ + li r12, BOOK3S_INTERRUPT_HV_RM_HARD + stw r12, VCPU_TRAP(r9) + b guest_exit_cont + +1: /* Return code <= 1 */ + cmpdi r3, 0 + bgt guest_exit_cont + + /* Return code <= 0 */ +maybe_reenter_guest: + ld r5, HSTATE_KVM_VCORE(r13) + lwz r0, VCORE_ENTRY_EXIT(r5) + cmpwi r0, 0x100 + mr r4, r9 + blt deliver_guest_interrupt + b guest_exit_cont + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM /* * Softpatch interrupt for transactional memory emulation cases @@ -2302,6 +2203,10 @@ hcall_try_real_mode: andi. r0,r11,MSR_PR /* sc 1 from userspace - reflect to guest syscall */ bne sc_1_fast_return + /* sc 1 from nested guest - give it to L1 to handle */ + ld r0, VCPU_NESTED(r9) + cmpdi r0, 0 + bne guest_exit_cont clrrdi r3,r3,2 cmpldi r3,hcall_real_table_end - hcall_real_table bge guest_exit_cont @@ -2561,6 +2466,7 @@ hcall_real_table: hcall_real_table_end: _GLOBAL(kvmppc_h_set_xdabr) +EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr) andi. r0, r5, DABRX_USER | DABRX_KERNEL beq 6f li r0, DABRX_USER | DABRX_KERNEL | DABRX_BTI @@ -2570,6 +2476,7 @@ _GLOBAL(kvmppc_h_set_xdabr) blr _GLOBAL(kvmppc_h_set_dabr) +EXPORT_SYMBOL_GPL(kvmppc_h_set_dabr) li r5, DABRX_USER | DABRX_KERNEL 3: BEGIN_FTR_SECTION @@ -2682,11 +2589,13 @@ BEGIN_FTR_SECTION b 91f END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) /* - * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR + * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR) */ ld r3, HSTATE_KVM_VCPU(r13) ld r4, VCPU_MSR(r3) + li r5, 0 /* don't preserve non-vol regs */ bl kvmppc_save_tm_hv + nop 91: #endif @@ -2802,11 +2711,13 @@ BEGIN_FTR_SECTION b 91f END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) /* - * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR + * NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS (but not CR) */ mr r3, r4 ld r4, VCPU_MSR(r3) + li r5, 0 /* don't preserve non-vol regs */ bl kvmppc_restore_tm_hv + nop ld r4, HSTATE_KVM_VCPU(r13) 91: #endif @@ -2874,13 +2785,7 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0) mr r9, r4 cmpdi r3, 0 bgt guest_exit_cont - - /* see if any other thread is already exiting */ - lwz r0,VCORE_ENTRY_EXIT(r5) - cmpwi r0,0x100 - bge guest_exit_cont - - b kvmppc_cede_reentry /* if not go back to guest */ + b maybe_reenter_guest /* cede when already previously prodded case */ kvm_cede_prodded: @@ -2947,12 +2852,12 @@ machine_check_realmode: */ ld r11, VCPU_MSR(r9) rldicl. r0, r11, 64-MSR_HV_LG, 63 /* check if it happened in HV mode */ - bne mc_cont /* if so, exit to host */ + bne guest_exit_cont /* if so, exit to host */ /* Check if guest is capable of handling NMI exit */ ld r10, VCPU_KVM(r9) lbz r10, KVM_FWNMI(r10) cmpdi r10, 1 /* FWNMI capable? */ - beq mc_cont /* if so, exit with KVM_EXIT_NMI. */ + beq guest_exit_cont /* if so, exit with KVM_EXIT_NMI. */ /* if not, fall through for backward compatibility. */ andi. r10, r11, MSR_RI /* check for unrecoverable exception */ @@ -2966,6 +2871,21 @@ machine_check_realmode: 2: b fast_interrupt_c_return /* + * Call C code to handle a HMI in real mode. + * Only the primary thread does the call, secondary threads are handled + * by calling hmi_exception_realmode() after kvmppc_hv_entry returns. + * r9 points to the vcpu on entry + */ +hmi_realmode: + lbz r0, HSTATE_PTID(r13) + cmpwi r0, 0 + bne guest_exit_cont + bl kvmppc_realmode_hmi_handler + ld r9, HSTATE_KVM_VCPU(r13) + li r12, BOOK3S_INTERRUPT_HMI + b guest_exit_cont + +/* * Check the reason we woke from nap, and take appropriate action. * Returns (in r3): * 0 if nothing needs to be done @@ -3130,10 +3050,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) * Save transactional state and TM-related registers. * Called with r3 pointing to the vcpu struct and r4 containing * the guest MSR value. - * This can modify all checkpointed registers, but + * r5 is non-zero iff non-volatile register state needs to be maintained. + * If r5 == 0, this can modify all checkpointed registers, but * restores r1 and r2 before exit. */ -kvmppc_save_tm_hv: +_GLOBAL_TOC(kvmppc_save_tm_hv) +EXPORT_SYMBOL_GPL(kvmppc_save_tm_hv) /* See if we need to handle fake suspend mode */ BEGIN_FTR_SECTION b __kvmppc_save_tm @@ -3161,12 +3083,6 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) nop - std r1, HSTATE_HOST_R1(r13) - - /* Clear the MSR RI since r1, r13 may be foobar. */ - li r5, 0 - mtmsrd r5, 1 - /* We have to treclaim here because that's the only way to do S->N */ li r3, TM_CAUSE_KVM_RESCHED TRECLAIM(R3) @@ -3175,22 +3091,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) * We were in fake suspend, so we are not going to save the * register state as the guest checkpointed state (since * we already have it), therefore we can now use any volatile GPR. + * In fact treclaim in fake suspend state doesn't modify + * any registers. */ - /* Reload PACA pointer, stack pointer and TOC. */ - GET_PACA(r13) - ld r1, HSTATE_HOST_R1(r13) - ld r2, PACATOC(r13) - /* Set MSR RI now we have r1 and r13 back. */ - li r5, MSR_RI - mtmsrd r5, 1 - - HMT_MEDIUM - ld r6, HSTATE_DSCR(r13) - mtspr SPRN_DSCR, r6 -BEGIN_FTR_SECTION_NESTED(96) +BEGIN_FTR_SECTION bl pnv_power9_force_smt4_release -END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96) +END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) nop 4: @@ -3216,10 +3123,12 @@ END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96) * Restore transactional state and TM-related registers. * Called with r3 pointing to the vcpu struct * and r4 containing the guest MSR value. + * r5 is non-zero iff non-volatile register state needs to be maintained. * This potentially modifies all checkpointed registers. * It restores r1 and r2 from the PACA. */ -kvmppc_restore_tm_hv: +_GLOBAL_TOC(kvmppc_restore_tm_hv) +EXPORT_SYMBOL_GPL(kvmppc_restore_tm_hv) /* * If we are doing TM emulation for the guest on a POWER9 DD2, * then we don't actually do a trechkpt -- we either set up @@ -3424,6 +3333,194 @@ kvmppc_msr_interrupt: blr /* + * Load up guest PMU state. R3 points to the vcpu struct. + */ +_GLOBAL(kvmhv_load_guest_pmu) +EXPORT_SYMBOL_GPL(kvmhv_load_guest_pmu) + mr r4, r3 + mflr r0 + li r3, 1 + sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ + mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ + isync +BEGIN_FTR_SECTION + ld r3, VCPU_MMCR(r4) + andi. r5, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO + cmpwi r5, MMCR0_PMAO + beql kvmppc_fix_pmao +END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG) + lwz r3, VCPU_PMC(r4) /* always load up guest PMU registers */ + lwz r5, VCPU_PMC + 4(r4) /* to prevent information leak */ + lwz r6, VCPU_PMC + 8(r4) + lwz r7, VCPU_PMC + 12(r4) + lwz r8, VCPU_PMC + 16(r4) + lwz r9, VCPU_PMC + 20(r4) + mtspr SPRN_PMC1, r3 + mtspr SPRN_PMC2, r5 + mtspr SPRN_PMC3, r6 + mtspr SPRN_PMC4, r7 + mtspr SPRN_PMC5, r8 + mtspr SPRN_PMC6, r9 + ld r3, VCPU_MMCR(r4) + ld r5, VCPU_MMCR + 8(r4) + ld r6, VCPU_MMCR + 16(r4) + ld r7, VCPU_SIAR(r4) + ld r8, VCPU_SDAR(r4) + mtspr SPRN_MMCR1, r5 + mtspr SPRN_MMCRA, r6 + mtspr SPRN_SIAR, r7 + mtspr SPRN_SDAR, r8 +BEGIN_FTR_SECTION + ld r5, VCPU_MMCR + 24(r4) + ld r6, VCPU_SIER(r4) + mtspr SPRN_MMCR2, r5 + mtspr SPRN_SIER, r6 +BEGIN_FTR_SECTION_NESTED(96) + lwz r7, VCPU_PMC + 24(r4) + lwz r8, VCPU_PMC + 28(r4) + ld r9, VCPU_MMCR + 32(r4) + mtspr SPRN_SPMC1, r7 + mtspr SPRN_SPMC2, r8 + mtspr SPRN_MMCRS, r9 +END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96) +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + mtspr SPRN_MMCR0, r3 + isync + mtlr r0 + blr + +/* + * Reload host PMU state saved in the PACA by kvmhv_save_host_pmu. + */ +_GLOBAL(kvmhv_load_host_pmu) +EXPORT_SYMBOL_GPL(kvmhv_load_host_pmu) + mflr r0 + lbz r4, PACA_PMCINUSE(r13) /* is the host using the PMU? */ + cmpwi r4, 0 + beq 23f /* skip if not */ +BEGIN_FTR_SECTION + ld r3, HSTATE_MMCR0(r13) + andi. r4, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO + cmpwi r4, MMCR0_PMAO + beql kvmppc_fix_pmao +END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG) + lwz r3, HSTATE_PMC1(r13) + lwz r4, HSTATE_PMC2(r13) + lwz r5, HSTATE_PMC3(r13) + lwz r6, HSTATE_PMC4(r13) + lwz r8, HSTATE_PMC5(r13) + lwz r9, HSTATE_PMC6(r13) + mtspr SPRN_PMC1, r3 + mtspr SPRN_PMC2, r4 + mtspr SPRN_PMC3, r5 + mtspr SPRN_PMC4, r6 + mtspr SPRN_PMC5, r8 + mtspr SPRN_PMC6, r9 + ld r3, HSTATE_MMCR0(r13) + ld r4, HSTATE_MMCR1(r13) + ld r5, HSTATE_MMCRA(r13) + ld r6, HSTATE_SIAR(r13) + ld r7, HSTATE_SDAR(r13) + mtspr SPRN_MMCR1, r4 + mtspr SPRN_MMCRA, r5 + mtspr SPRN_SIAR, r6 + mtspr SPRN_SDAR, r7 +BEGIN_FTR_SECTION + ld r8, HSTATE_MMCR2(r13) + ld r9, HSTATE_SIER(r13) + mtspr SPRN_MMCR2, r8 + mtspr SPRN_SIER, r9 +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + mtspr SPRN_MMCR0, r3 + isync + mtlr r0 +23: blr + +/* + * Save guest PMU state into the vcpu struct. + * r3 = vcpu, r4 = full save flag (PMU in use flag set in VPA) + */ +_GLOBAL(kvmhv_save_guest_pmu) +EXPORT_SYMBOL_GPL(kvmhv_save_guest_pmu) + mr r9, r3 + mr r8, r4 +BEGIN_FTR_SECTION + /* + * POWER8 seems to have a hardware bug where setting + * MMCR0[PMAE] along with MMCR0[PMC1CE] and/or MMCR0[PMCjCE] + * when some counters are already negative doesn't seem + * to cause a performance monitor alert (and hence interrupt). + * The effect of this is that when saving the PMU state, + * if there is no PMU alert pending when we read MMCR0 + * before freezing the counters, but one becomes pending + * before we read the counters, we lose it. + * To work around this, we need a way to freeze the counters + * before reading MMCR0. Normally, freezing the counters + * is done by writing MMCR0 (to set MMCR0[FC]) which + * unavoidably writes MMCR0[PMA0] as well. On POWER8, + * we can also freeze the counters using MMCR2, by writing + * 1s to all the counter freeze condition bits (there are + * 9 bits each for 6 counters). + */ + li r3, -1 /* set all freeze bits */ + clrrdi r3, r3, 10 + mfspr r10, SPRN_MMCR2 + mtspr SPRN_MMCR2, r3 + isync +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + li r3, 1 + sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ + mfspr r4, SPRN_MMCR0 /* save MMCR0 */ + mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ + mfspr r6, SPRN_MMCRA + /* Clear MMCRA in order to disable SDAR updates */ + li r7, 0 + mtspr SPRN_MMCRA, r7 + isync + cmpwi r8, 0 /* did they ask for PMU stuff to be saved? */ + bne 21f + std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */ + b 22f +21: mfspr r5, SPRN_MMCR1 + mfspr r7, SPRN_SIAR + mfspr r8, SPRN_SDAR + std r4, VCPU_MMCR(r9) + std r5, VCPU_MMCR + 8(r9) + std r6, VCPU_MMCR + 16(r9) +BEGIN_FTR_SECTION + std r10, VCPU_MMCR + 24(r9) +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) + std r7, VCPU_SIAR(r9) + std r8, VCPU_SDAR(r9) + mfspr r3, SPRN_PMC1 + mfspr r4, SPRN_PMC2 + mfspr r5, SPRN_PMC3 + mfspr r6, SPRN_PMC4 + mfspr r7, SPRN_PMC5 + mfspr r8, SPRN_PMC6 + stw r3, VCPU_PMC(r9) + stw r4, VCPU_PMC + 4(r9) + stw r5, VCPU_PMC + 8(r9) + stw r6, VCPU_PMC + 12(r9) + stw r7, VCPU_PMC + 16(r9) + stw r8, VCPU_PMC + 20(r9) +BEGIN_FTR_SECTION + mfspr r5, SPRN_SIER + std r5, VCPU_SIER(r9) +BEGIN_FTR_SECTION_NESTED(96) + mfspr r6, SPRN_SPMC1 + mfspr r7, SPRN_SPMC2 + mfspr r8, SPRN_MMCRS + stw r6, VCPU_PMC + 24(r9) + stw r7, VCPU_PMC + 28(r9) + std r8, VCPU_MMCR + 32(r9) + lis r4, 0x8000 + mtspr SPRN_MMCRS, r4 +END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96) +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) +22: blr + +/* * This works around a hardware bug on POWER8E processors, where * writing a 1 to the MMCR0[PMAO] bit doesn't generate a * performance monitor interrupt. Instead, when we need to have diff --git a/arch/powerpc/kvm/book3s_hv_tm.c b/arch/powerpc/kvm/book3s_hv_tm.c index 008285058f9b..888e2609e3f1 100644 --- a/arch/powerpc/kvm/book3s_hv_tm.c +++ b/arch/powerpc/kvm/book3s_hv_tm.c @@ -130,7 +130,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) return RESUME_GUEST; } /* Set CR0 to indicate previous transactional state */ - vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28); /* L=1 => tresume, L=0 => tsuspend */ if (instr & (1 << 21)) { @@ -174,7 +174,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) copy_from_checkpoint(vcpu); /* Set CR0 to indicate previous transactional state */ - vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28); vcpu->arch.shregs.msr &= ~MSR_TS_MASK; return RESUME_GUEST; @@ -204,7 +204,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) copy_to_checkpoint(vcpu); /* Set CR0 to indicate previous transactional state */ - vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 28); vcpu->arch.shregs.msr = msr | MSR_TS_S; return RESUME_GUEST; diff --git a/arch/powerpc/kvm/book3s_hv_tm_builtin.c b/arch/powerpc/kvm/book3s_hv_tm_builtin.c index b2c7c6fca4f9..3cf5863bc06e 100644 --- a/arch/powerpc/kvm/book3s_hv_tm_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_tm_builtin.c @@ -89,7 +89,8 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu) if (instr & (1 << 21)) vcpu->arch.shregs.msr = (msr & ~MSR_TS_MASK) | MSR_TS_T; /* Set CR0 to 0b0010 */ - vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | 0x20000000; + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | + 0x20000000; return 1; } @@ -105,5 +106,5 @@ void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu) vcpu->arch.shregs.msr &= ~MSR_TS_MASK; /* go to N state */ vcpu->arch.regs.nip = vcpu->arch.tfhar; copy_from_checkpoint(vcpu); - vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | 0xa0000000; + vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | 0xa0000000; } diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 614ebb4261f7..4efd65d9e828 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -167,7 +167,7 @@ void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu) svcpu->gpr[11] = vcpu->arch.regs.gpr[11]; svcpu->gpr[12] = vcpu->arch.regs.gpr[12]; svcpu->gpr[13] = vcpu->arch.regs.gpr[13]; - svcpu->cr = vcpu->arch.cr; + svcpu->cr = vcpu->arch.regs.ccr; svcpu->xer = vcpu->arch.regs.xer; svcpu->ctr = vcpu->arch.regs.ctr; svcpu->lr = vcpu->arch.regs.link; @@ -249,7 +249,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu) vcpu->arch.regs.gpr[11] = svcpu->gpr[11]; vcpu->arch.regs.gpr[12] = svcpu->gpr[12]; vcpu->arch.regs.gpr[13] = svcpu->gpr[13]; - vcpu->arch.cr = svcpu->cr; + vcpu->arch.regs.ccr = svcpu->cr; vcpu->arch.regs.xer = svcpu->xer; vcpu->arch.regs.ctr = svcpu->ctr; vcpu->arch.regs.link = svcpu->lr; @@ -1246,7 +1246,6 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_GUEST; break; case BOOK3S_INTERRUPT_EXTERNAL: - case BOOK3S_INTERRUPT_EXTERNAL_LEVEL: case BOOK3S_INTERRUPT_EXTERNAL_HV: case BOOK3S_INTERRUPT_H_VIRT: vcpu->stat.ext_intr_exits++; diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index b8356cdc0c04..b0b2bfc2ff51 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c @@ -310,7 +310,7 @@ static inline bool icp_try_update(struct kvmppc_icp *icp, */ if (new.out_ee) { kvmppc_book3s_queue_irqprio(icp->vcpu, - BOOK3S_INTERRUPT_EXTERNAL_LEVEL); + BOOK3S_INTERRUPT_EXTERNAL); if (!change_self) kvmppc_fast_vcpu_kick(icp->vcpu); } @@ -593,8 +593,7 @@ static noinline unsigned long kvmppc_h_xirr(struct kvm_vcpu *vcpu) u32 xirr; /* First, remove EE from the processor */ - kvmppc_book3s_dequeue_irqprio(icp->vcpu, - BOOK3S_INTERRUPT_EXTERNAL_LEVEL); + kvmppc_book3s_dequeue_irqprio(icp->vcpu, BOOK3S_INTERRUPT_EXTERNAL); /* * ICP State: Accept_Interrupt @@ -754,8 +753,7 @@ static noinline void kvmppc_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) * We can remove EE from the current processor, the update * transaction will set it again if needed */ - kvmppc_book3s_dequeue_irqprio(icp->vcpu, - BOOK3S_INTERRUPT_EXTERNAL_LEVEL); + kvmppc_book3s_dequeue_irqprio(icp->vcpu, BOOK3S_INTERRUPT_EXTERNAL); do { old_state = new_state = READ_ONCE(icp->state); @@ -1167,8 +1165,7 @@ int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval) * Deassert the CPU interrupt request. * icp_try_update will reassert it if necessary. */ - kvmppc_book3s_dequeue_irqprio(icp->vcpu, - BOOK3S_INTERRUPT_EXTERNAL_LEVEL); + kvmppc_book3s_dequeue_irqprio(icp->vcpu, BOOK3S_INTERRUPT_EXTERNAL); /* * Note that if we displace an interrupt from old_state.xisr, @@ -1393,7 +1390,8 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type) } #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE - if (cpu_has_feature(CPU_FTR_ARCH_206)) { + if (cpu_has_feature(CPU_FTR_ARCH_206) && + cpu_has_feature(CPU_FTR_HVMODE)) { /* Enable real mode support */ xics->real_mode = ENABLE_REALMODE; xics->real_mode_dbg = DEBUG_REALMODE; diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index 30c2eb766954..ad4a370703d3 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -62,6 +62,69 @@ #define XIVE_Q_GAP 2 /* + * Push a vcpu's context to the XIVE on guest entry. + * This assumes we are in virtual mode (MMU on) + */ +void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) +{ + void __iomem *tima = local_paca->kvm_hstate.xive_tima_virt; + u64 pq; + + if (!tima) + return; + eieio(); + __raw_writeq(vcpu->arch.xive_saved_state.w01, tima + TM_QW1_OS); + __raw_writel(vcpu->arch.xive_cam_word, tima + TM_QW1_OS + TM_WORD2); + vcpu->arch.xive_pushed = 1; + eieio(); + + /* + * We clear the irq_pending flag. There is a small chance of a + * race vs. the escalation interrupt happening on another + * processor setting it again, but the only consequence is to + * cause a spurious wakeup on the next H_CEDE, which is not an + * issue. + */ + vcpu->arch.irq_pending = 0; + + /* + * In single escalation mode, if the escalation interrupt is + * on, we mask it. + */ + if (vcpu->arch.xive_esc_on) { + pq = __raw_readq((void __iomem *)(vcpu->arch.xive_esc_vaddr + + XIVE_ESB_SET_PQ_01)); + mb(); + + /* + * We have a possible subtle race here: The escalation + * interrupt might have fired and be on its way to the + * host queue while we mask it, and if we unmask it + * early enough (re-cede right away), there is a + * theorical possibility that it fires again, thus + * landing in the target queue more than once which is + * a big no-no. + * + * Fortunately, solving this is rather easy. If the + * above load setting PQ to 01 returns a previous + * value where P is set, then we know the escalation + * interrupt is somewhere on its way to the host. In + * that case we simply don't clear the xive_esc_on + * flag below. It will be eventually cleared by the + * handler for the escalation interrupt. + * + * Then, when doing a cede, we check that flag again + * before re-enabling the escalation interrupt, and if + * set, we abort the cede. + */ + if (!(pq & XIVE_ESB_VAL_P)) + /* Now P is 0, we can clear the flag */ + vcpu->arch.xive_esc_on = 0; + } +} +EXPORT_SYMBOL_GPL(kvmppc_xive_push_vcpu); + +/* * This is a simple trigger for a generic XIVE IRQ. This must * only be called for interrupts that support a trigger page */ diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c index 4171ede8722b..033363d6e764 100644 --- a/arch/powerpc/kvm/book3s_xive_template.c +++ b/arch/powerpc/kvm/book3s_xive_template.c @@ -280,14 +280,6 @@ X_STATIC unsigned long GLUE(X_PFX,h_xirr)(struct kvm_vcpu *vcpu) /* First collect pending bits from HW */ GLUE(X_PFX,ack_pending)(xc); - /* - * Cleanup the old-style bits if needed (they may have been - * set by pull or an escalation interrupts). - */ - if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions)) - clear_bit(BOOK3S_IRQPRIO_EXTERNAL_LEVEL, - &vcpu->arch.pending_exceptions); - pr_devel(" new pending=0x%02x hw_cppr=%d cppr=%d\n", xc->pending, xc->hw_cppr, xc->cppr); diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S index 81bd8a07aa51..051af7d97327 100644 --- a/arch/powerpc/kvm/bookehv_interrupts.S +++ b/arch/powerpc/kvm/bookehv_interrupts.S @@ -182,7 +182,7 @@ */ PPC_LL r4, PACACURRENT(r13) PPC_LL r4, (THREAD + THREAD_KVM_VCPU)(r4) - stw r10, VCPU_CR(r4) + PPC_STL r10, VCPU_CR(r4) PPC_STL r11, VCPU_GPR(R4)(r4) PPC_STL r5, VCPU_GPR(R5)(r4) PPC_STL r6, VCPU_GPR(R6)(r4) @@ -292,7 +292,7 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1) PPC_STL r4, VCPU_GPR(R4)(r11) PPC_LL r4, THREAD_NORMSAVE(0)(r10) PPC_STL r5, VCPU_GPR(R5)(r11) - stw r13, VCPU_CR(r11) + PPC_STL r13, VCPU_CR(r11) mfspr r5, \srr0 PPC_STL r3, VCPU_GPR(R10)(r11) PPC_LL r3, THREAD_NORMSAVE(2)(r10) @@ -319,7 +319,7 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1) PPC_STL r4, VCPU_GPR(R4)(r11) PPC_LL r4, GPR9(r8) PPC_STL r5, VCPU_GPR(R5)(r11) - stw r9, VCPU_CR(r11) + PPC_STL r9, VCPU_CR(r11) mfspr r5, \srr0 PPC_STL r3, VCPU_GPR(R8)(r11) PPC_LL r3, GPR10(r8) @@ -643,7 +643,7 @@ lightweight_exit: PPC_LL r3, VCPU_LR(r4) PPC_LL r5, VCPU_XER(r4) PPC_LL r6, VCPU_CTR(r4) - lwz r7, VCPU_CR(r4) + PPC_LL r7, VCPU_CR(r4) PPC_LL r8, VCPU_PC(r4) PPC_LD(r9, VCPU_SHARED_MSR, r11) PPC_LL r0, VCPU_GPR(R0)(r4) diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c index 75dce1ef3bc8..f91b1309a0a8 100644 --- a/arch/powerpc/kvm/emulate_loadstore.c +++ b/arch/powerpc/kvm/emulate_loadstore.c @@ -117,7 +117,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) emulated = EMULATE_FAIL; vcpu->arch.regs.msr = vcpu->arch.shared->msr; - vcpu->arch.regs.ccr = vcpu->arch.cr; if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) { int type = op.type & INSTR_TYPE_MASK; int size = GETSIZE(op.type); diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index eba5756d5b41..2869a299c4ed 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -594,7 +594,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = !!(hv_enabled && radix_enabled()); break; case KVM_CAP_PPC_MMU_HASH_V3: - r = !!(hv_enabled && cpu_has_feature(CPU_FTR_ARCH_300)); + r = !!(hv_enabled && cpu_has_feature(CPU_FTR_ARCH_300) && + cpu_has_feature(CPU_FTR_HVMODE)); + break; + case KVM_CAP_PPC_NESTED_HV: + r = !!(hv_enabled && kvmppc_hv_ops->enable_nested && + !kvmppc_hv_ops->enable_nested(NULL)); break; #endif case KVM_CAP_SYNC_MMU: @@ -2114,6 +2119,14 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, r = kvm->arch.kvm_ops->set_smt_mode(kvm, mode, flags); break; } + + case KVM_CAP_PPC_NESTED_HV: + r = -EINVAL; + if (!is_kvmppc_hv_enabled(kvm) || + !kvm->arch.kvm_ops->enable_nested) + break; + r = kvm->arch.kvm_ops->enable_nested(kvm); + break; #endif default: r = -EINVAL; diff --git a/arch/powerpc/kvm/tm.S b/arch/powerpc/kvm/tm.S index 90e330f21356..0531a1492fdf 100644 --- a/arch/powerpc/kvm/tm.S +++ b/arch/powerpc/kvm/tm.S @@ -28,17 +28,25 @@ * Save transactional state and TM-related registers. * Called with: * - r3 pointing to the vcpu struct - * - r4 points to the MSR with current TS bits: + * - r4 containing the MSR with current TS bits: * (For HV KVM, it is VCPU_MSR ; For PR KVM, it is host MSR). - * This can modify all checkpointed registers, but - * restores r1, r2 before exit. + * - r5 containing a flag indicating that non-volatile registers + * must be preserved. + * If r5 == 0, this can modify all checkpointed registers, but + * restores r1, r2 before exit. If r5 != 0, this restores the + * MSR TM/FP/VEC/VSX bits to their state on entry. */ _GLOBAL(__kvmppc_save_tm) mflr r0 std r0, PPC_LR_STKOFF(r1) + stdu r1, -SWITCH_FRAME_SIZE(r1) + + mr r9, r3 + cmpdi cr7, r5, 0 /* Turn on TM. */ mfmsr r8 + mr r10, r8 li r0, 1 rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG ori r8, r8, MSR_FP @@ -51,6 +59,27 @@ _GLOBAL(__kvmppc_save_tm) std r1, HSTATE_SCRATCH2(r13) std r3, HSTATE_SCRATCH1(r13) + /* Save CR on the stack - even if r5 == 0 we need to get cr7 back. */ + mfcr r6 + SAVE_GPR(6, r1) + + /* Save DSCR so we can restore it to avoid running with user value */ + mfspr r7, SPRN_DSCR + SAVE_GPR(7, r1) + + /* + * We are going to do treclaim., which will modify all checkpointed + * registers. Save the non-volatile registers on the stack if + * preservation of non-volatile state has been requested. + */ + beq cr7, 3f + SAVE_NVGPRS(r1) + + /* MSR[TS] will be 0 (non-transactional) once we do treclaim. */ + li r0, 0 + rldimi r10, r0, MSR_TS_S_LG, 63 - MSR_TS_T_LG + SAVE_GPR(10, r1) /* final MSR value */ +3: #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE BEGIN_FTR_SECTION /* Emulation of the treclaim instruction needs TEXASR before treclaim */ @@ -74,22 +103,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST) std r9, PACATMSCRATCH(r13) ld r9, HSTATE_SCRATCH1(r13) - /* Get a few more GPRs free. */ - std r29, VCPU_GPRS_TM(29)(r9) - std r30, VCPU_GPRS_TM(30)(r9) - std r31, VCPU_GPRS_TM(31)(r9) - - /* Save away PPR and DSCR soon so don't run with user values. */ - mfspr r31, SPRN_PPR + /* Save away PPR soon so we don't run with user value. */ + std r0, VCPU_GPRS_TM(0)(r9) + mfspr r0, SPRN_PPR HMT_MEDIUM - mfspr r30, SPRN_DSCR -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE - ld r29, HSTATE_DSCR(r13) - mtspr SPRN_DSCR, r29 -#endif - /* Save all but r9, r13 & r29-r31 */ - reg = 0 + /* Reload stack pointer. */ + std r1, VCPU_GPRS_TM(1)(r9) + ld r1, HSTATE_SCRATCH2(r13) + + /* Set MSR RI now we have r1 and r13 back. */ + std r2, VCPU_GPRS_TM(2)(r9) + li r2, MSR_RI + mtmsrd r2, 1 + + /* Reload TOC pointer. */ + ld r2, PACATOC(r13) + + /* Save all but r0-r2, r9 & r13 */ + reg = 3 .rept 29 .if (reg != 9) && (reg != 13) std reg, VCPU_GPRS_TM(reg)(r9) @@ -103,33 +135,29 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST) ld r4, PACATMSCRATCH(r13) std r4, VCPU_GPRS_TM(9)(r9) - /* Reload stack pointer and TOC. */ - ld r1, HSTATE_SCRATCH2(r13) - ld r2, PACATOC(r13) - - /* Set MSR RI now we have r1 and r13 back. */ - li r5, MSR_RI - mtmsrd r5, 1 + /* Restore host DSCR and CR values, after saving guest values */ + mfcr r6 + mfspr r7, SPRN_DSCR + stw r6, VCPU_CR_TM(r9) + std r7, VCPU_DSCR_TM(r9) + REST_GPR(6, r1) + REST_GPR(7, r1) + mtcr r6 + mtspr SPRN_DSCR, r7 - /* Save away checkpinted SPRs. */ - std r31, VCPU_PPR_TM(r9) - std r30, VCPU_DSCR_TM(r9) + /* Save away checkpointed SPRs. */ + std r0, VCPU_PPR_TM(r9) mflr r5 - mfcr r6 mfctr r7 mfspr r8, SPRN_AMR mfspr r10, SPRN_TAR mfxer r11 std r5, VCPU_LR_TM(r9) - stw r6, VCPU_CR_TM(r9) std r7, VCPU_CTR_TM(r9) std r8, VCPU_AMR_TM(r9) std r10, VCPU_TAR_TM(r9) std r11, VCPU_XER_TM(r9) - /* Restore r12 as trap number. */ - lwz r12, VCPU_TRAP(r9) - /* Save FP/VSX. */ addi r3, r9, VCPU_FPRS_TM bl store_fp_state @@ -137,6 +165,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST) bl store_vr_state mfspr r6, SPRN_VRSAVE stw r6, VCPU_VRSAVE_TM(r9) + + /* Restore non-volatile registers if requested to */ + beq cr7, 1f + REST_NVGPRS(r1) + REST_GPR(10, r1) 1: /* * We need to save these SPRs after the treclaim so that the software @@ -146,12 +179,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST) */ mfspr r7, SPRN_TEXASR std r7, VCPU_TEXASR(r9) -11: mfspr r5, SPRN_TFHAR mfspr r6, SPRN_TFIAR std r5, VCPU_TFHAR(r9) std r6, VCPU_TFIAR(r9) + /* Restore MSR state if requested */ + beq cr7, 2f + mtmsrd r10, 0 +2: + addi r1, r1, SWITCH_FRAME_SIZE ld r0, PPC_LR_STKOFF(r1) mtlr r0 blr @@ -161,49 +198,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST) * be invoked from C function by PR KVM only. */ _GLOBAL(_kvmppc_save_tm_pr) - mflr r5 - std r5, PPC_LR_STKOFF(r1) - stdu r1, -SWITCH_FRAME_SIZE(r1) - SAVE_NVGPRS(r1) - - /* save MSR since TM/math bits might be impacted - * by __kvmppc_save_tm(). - */ - mfmsr r5 - SAVE_GPR(5, r1) - - /* also save DSCR/CR/TAR so that it can be recovered later */ - mfspr r6, SPRN_DSCR - SAVE_GPR(6, r1) - - mfcr r7 - stw r7, _CCR(r1) + mflr r0 + std r0, PPC_LR_STKOFF(r1) + stdu r1, -PPC_MIN_STKFRM(r1) mfspr r8, SPRN_TAR - SAVE_GPR(8, r1) + std r8, PPC_MIN_STKFRM-8(r1) + li r5, 1 /* preserve non-volatile registers */ bl __kvmppc_save_tm - REST_GPR(8, r1) + ld r8, PPC_MIN_STKFRM-8(r1) mtspr SPRN_TAR, r8 - ld r7, _CCR(r1) - mtcr r7 - - REST_GPR(6, r1) - mtspr SPRN_DSCR, r6 - - /* need preserve current MSR's MSR_TS bits */ - REST_GPR(5, r1) - mfmsr r6 - rldicl r6, r6, 64 - MSR_TS_S_LG, 62 - rldimi r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG - mtmsrd r5 - - REST_NVGPRS(r1) - addi r1, r1, SWITCH_FRAME_SIZE - ld r5, PPC_LR_STKOFF(r1) - mtlr r5 + addi r1, r1, PPC_MIN_STKFRM + ld r0, PPC_LR_STKOFF(r1) + mtlr r0 blr EXPORT_SYMBOL_GPL(_kvmppc_save_tm_pr); @@ -215,15 +225,21 @@ EXPORT_SYMBOL_GPL(_kvmppc_save_tm_pr); * - r4 is the guest MSR with desired TS bits: * For HV KVM, it is VCPU_MSR * For PR KVM, it is provided by caller - * This potentially modifies all checkpointed registers. - * It restores r1, r2 from the PACA. + * - r5 containing a flag indicating that non-volatile registers + * must be preserved. + * If r5 == 0, this potentially modifies all checkpointed registers, but + * restores r1, r2 from the PACA before exit. + * If r5 != 0, this restores the MSR TM/FP/VEC/VSX bits to their state on entry. */ _GLOBAL(__kvmppc_restore_tm) mflr r0 std r0, PPC_LR_STKOFF(r1) + cmpdi cr7, r5, 0 + /* Turn on TM/FP/VSX/VMX so we can restore them. */ mfmsr r5 + mr r10, r5 li r6, MSR_TM >> 32 sldi r6, r6, 32 or r5, r5, r6 @@ -244,8 +260,7 @@ _GLOBAL(__kvmppc_restore_tm) mr r5, r4 rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 - beqlr /* TM not active in guest */ - std r1, HSTATE_SCRATCH2(r13) + beq 9f /* TM not active in guest */ /* Make sure the failure summary is set, otherwise we'll program check * when we trechkpt. It's possible that this might have been not set @@ -256,6 +271,26 @@ _GLOBAL(__kvmppc_restore_tm) mtspr SPRN_TEXASR, r7 /* + * Make a stack frame and save non-volatile registers if requested. + */ + stdu r1, -SWITCH_FRAME_SIZE(r1) + std r1, HSTATE_SCRATCH2(r13) + + mfcr r6 + mfspr r7, SPRN_DSCR + SAVE_GPR(2, r1) + SAVE_GPR(6, r1) + SAVE_GPR(7, r1) + + beq cr7, 4f + SAVE_NVGPRS(r1) + + /* MSR[TS] will be 1 (suspended) once we do trechkpt */ + li r0, 1 + rldimi r10, r0, MSR_TS_S_LG, 63 - MSR_TS_T_LG + SAVE_GPR(10, r1) /* final MSR value */ +4: + /* * We need to load up the checkpointed state for the guest. * We need to do this early as it will blow away any GPRs, VSRs and * some SPRs. @@ -291,8 +326,6 @@ _GLOBAL(__kvmppc_restore_tm) ld r29, VCPU_DSCR_TM(r3) ld r30, VCPU_PPR_TM(r3) - std r2, PACATMSCRATCH(r13) /* Save TOC */ - /* Clear the MSR RI since r1, r13 are all going to be foobar. */ li r5, 0 mtmsrd r5, 1 @@ -318,18 +351,31 @@ _GLOBAL(__kvmppc_restore_tm) /* Now let's get back the state we need. */ HMT_MEDIUM GET_PACA(r13) -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE - ld r29, HSTATE_DSCR(r13) - mtspr SPRN_DSCR, r29 -#endif ld r1, HSTATE_SCRATCH2(r13) - ld r2, PACATMSCRATCH(r13) + REST_GPR(7, r1) + mtspr SPRN_DSCR, r7 /* Set the MSR RI since we have our registers back. */ li r5, MSR_RI mtmsrd r5, 1 + + /* Restore TOC pointer and CR */ + REST_GPR(2, r1) + REST_GPR(6, r1) + mtcr r6 + + /* Restore non-volatile registers if requested to. */ + beq cr7, 5f + REST_GPR(10, r1) + REST_NVGPRS(r1) + +5: addi r1, r1, SWITCH_FRAME_SIZE ld r0, PPC_LR_STKOFF(r1) mtlr r0 + +9: /* Restore MSR bits if requested */ + beqlr cr7 + mtmsrd r10, 0 blr /* @@ -337,47 +383,23 @@ _GLOBAL(__kvmppc_restore_tm) * can be invoked from C function by PR KVM only. */ _GLOBAL(_kvmppc_restore_tm_pr) - mflr r5 - std r5, PPC_LR_STKOFF(r1) - stdu r1, -SWITCH_FRAME_SIZE(r1) - SAVE_NVGPRS(r1) - - /* save MSR to avoid TM/math bits change */ - mfmsr r5 - SAVE_GPR(5, r1) - - /* also save DSCR/CR/TAR so that it can be recovered later */ - mfspr r6, SPRN_DSCR - SAVE_GPR(6, r1) - - mfcr r7 - stw r7, _CCR(r1) + mflr r0 + std r0, PPC_LR_STKOFF(r1) + stdu r1, -PPC_MIN_STKFRM(r1) + /* save TAR so that it can be recovered later */ mfspr r8, SPRN_TAR - SAVE_GPR(8, r1) + std r8, PPC_MIN_STKFRM-8(r1) + li r5, 1 bl __kvmppc_restore_tm - REST_GPR(8, r1) + ld r8, PPC_MIN_STKFRM-8(r1) mtspr SPRN_TAR, r8 - ld r7, _CCR(r1) - mtcr r7 - - REST_GPR(6, r1) - mtspr SPRN_DSCR, r6 - - /* need preserve current MSR's MSR_TS bits */ - REST_GPR(5, r1) - mfmsr r6 - rldicl r6, r6, 64 - MSR_TS_S_LG, 62 - rldimi r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG - mtmsrd r5 - - REST_NVGPRS(r1) - addi r1, r1, SWITCH_FRAME_SIZE - ld r5, PPC_LR_STKOFF(r1) - mtlr r5 + addi r1, r1, PPC_MIN_STKFRM + ld r0, PPC_LR_STKOFF(r1) + mtlr r0 blr EXPORT_SYMBOL_GPL(_kvmppc_restore_tm_pr); diff --git a/arch/powerpc/kvm/trace_book3s.h b/arch/powerpc/kvm/trace_book3s.h index f3b23759e017..372a82fa2de3 100644 --- a/arch/powerpc/kvm/trace_book3s.h +++ b/arch/powerpc/kvm/trace_book3s.h @@ -14,7 +14,6 @@ {0x400, "INST_STORAGE"}, \ {0x480, "INST_SEGMENT"}, \ {0x500, "EXTERNAL"}, \ - {0x501, "EXTERNAL_LEVEL"}, \ {0x502, "EXTERNAL_HV"}, \ {0x600, "ALIGNMENT"}, \ {0x700, "PROGRAM"}, \ diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 670286808928..3bf9fc6fd36c 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -3,8 +3,6 @@ # Makefile for ppc-specific library files.. # -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE) @@ -14,6 +12,8 @@ obj-y += string.o alloc.o code-patching.o feature-fixups.o obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o strlen_32.o +obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o + # See corresponding test in arch/powerpc/Makefile # 64-bit linker creates .sfpr on demand for final link (vmlinux), # so it is only needed for modules, and only for older linkers which diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index 5ffee298745f..89502cbccb1b 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -98,8 +98,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr) else pfn = __pa_symbol(addr) >> PAGE_SHIFT; - err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), - pgprot_val(PAGE_KERNEL)); + err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL); pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err); if (err) diff --git a/arch/powerpc/lib/error-inject.c b/arch/powerpc/lib/error-inject.c new file mode 100644 index 000000000000..407b992fb02f --- /dev/null +++ b/arch/powerpc/lib/error-inject.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/error-injection.h> +#include <linux/kprobes.h> +#include <linux/uaccess.h> + +void override_function_with_return(struct pt_regs *regs) +{ + /* + * Emulate 'blr'. 'regs' represents the state on entry of a predefined + * function in the kernel/module, captured on a kprobe. We don't need + * to worry about 32-bit userspace on a 64-bit kernel. + */ + regs->nip = regs->link; +} +NOKPROBE_SYMBOL(override_function_with_return); diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index ec531de99996..3c3be02f33b7 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S @@ -40,7 +40,7 @@ _GLOBAL(memset) .Lms: PPC_MTOCRF(1,r0) mr r6,r3 blt cr1,8f - beq+ 3f /* if already 8-byte aligned */ + beq 3f /* if already 8-byte aligned */ subf r5,r0,r5 bf 31,1f stb r4,0(r6) @@ -85,7 +85,7 @@ _GLOBAL(memset) addi r6,r6,8 8: cmpwi r5,0 PPC_MTOCRF(1,r5) - beqlr+ + beqlr bf 29,9f stw r4,0(r6) addi r6,r6,4 diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c index cf77d755246d..36484a2ef915 100644 --- a/arch/powerpc/mm/8xx_mmu.c +++ b/arch/powerpc/mm/8xx_mmu.c @@ -67,7 +67,7 @@ void __init MMU_init_hw(void) /* PIN up to the 3 first 8Mb after IMMR in DTLB table */ #ifdef CONFIG_PIN_TLB_DATA unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000; - unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY; + unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY; #ifdef CONFIG_PIN_TLB_IMMR int i = 29; #else @@ -91,11 +91,10 @@ static void __init mmu_mapin_immr(void) { unsigned long p = PHYS_IMMR_BASE; unsigned long v = VIRT_IMMR_BASE; - unsigned long f = pgprot_val(PAGE_KERNEL_NCG); int offset; for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE) - map_kernel_page(v + offset, p + offset, f); + map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG); } /* Address of instructions to patch */ diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index cdf6a9960046..ca96e7be4d0e 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -3,10 +3,10 @@ # Makefile for the linux ppc-specific parts of the memory manager. # -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) +CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE) + obj-y := fault.o mem.o pgtable.o mmap.o \ init_$(BITS).o pgtable_$(BITS).o \ init-common.o mmu_context.o drmem.o @@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o -obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o +obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o @@ -43,5 +43,12 @@ obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o obj-$(CONFIG_SPAPR_TCE_IOMMU) += mmu_context_iommu.o obj-$(CONFIG_PPC_PTDUMP) += dump_linuxpagetables.o +ifdef CONFIG_PPC_PTDUMP +obj-$(CONFIG_4xx) += dump_linuxpagetables-generic.o +obj-$(CONFIG_PPC_8xx) += dump_linuxpagetables-8xx.o +obj-$(CONFIG_PPC_BOOK3E_MMU) += dump_linuxpagetables-generic.o +obj-$(CONFIG_PPC_BOOK3S_32) += dump_linuxpagetables-generic.o +obj-$(CONFIG_PPC_BOOK3S_64) += dump_linuxpagetables-book3s64.o +endif obj-$(CONFIG_PPC_HTDUMP) += dump_hashpagetable.o obj-$(CONFIG_PPC_MEM_KEYS) += pkeys.o diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index 382528475433..b6e7b5952ab5 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c @@ -228,7 +228,7 @@ __dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t do { SetPageReserved(page); map_kernel_page(vaddr, page_to_phys(page), - pgprot_val(pgprot_noncached(PAGE_KERNEL))); + pgprot_noncached(PAGE_KERNEL)); page++; vaddr += PAGE_SIZE; } while (size -= PAGE_SIZE); diff --git a/arch/powerpc/mm/dump_linuxpagetables-8xx.c b/arch/powerpc/mm/dump_linuxpagetables-8xx.c new file mode 100644 index 000000000000..ab9e3f24db2f --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-8xx.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * From split of dump_linuxpagetables.c + * Copyright 2016, Rashmica Gupta, IBM Corp. + * + */ +#include <linux/kernel.h> +#include <asm/pgtable.h> + +#include "dump_linuxpagetables.h" + +static const struct flag_info flag_array[] = { + { + .mask = _PAGE_SH, + .val = 0, + .set = "user", + .clear = " ", + }, { + .mask = _PAGE_RO | _PAGE_NA, + .val = 0, + .set = "rw", + }, { + .mask = _PAGE_RO | _PAGE_NA, + .val = _PAGE_RO, + .set = "r ", + }, { + .mask = _PAGE_RO | _PAGE_NA, + .val = _PAGE_NA, + .set = " ", + }, { + .mask = _PAGE_EXEC, + .val = _PAGE_EXEC, + .set = " X ", + .clear = " ", + }, { + .mask = _PAGE_PRESENT, + .val = _PAGE_PRESENT, + .set = "present", + .clear = " ", + }, { + .mask = _PAGE_GUARDED, + .val = _PAGE_GUARDED, + .set = "guarded", + .clear = " ", + }, { + .mask = _PAGE_DIRTY, + .val = _PAGE_DIRTY, + .set = "dirty", + .clear = " ", + }, { + .mask = _PAGE_ACCESSED, + .val = _PAGE_ACCESSED, + .set = "accessed", + .clear = " ", + }, { + .mask = _PAGE_NO_CACHE, + .val = _PAGE_NO_CACHE, + .set = "no cache", + .clear = " ", + }, { + .mask = _PAGE_SPECIAL, + .val = _PAGE_SPECIAL, + .set = "special", + } +}; + +struct pgtable_level pg_level[5] = { + { + }, { /* pgd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pud */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pmd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pte */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, +}; diff --git a/arch/powerpc/mm/dump_linuxpagetables-book3s64.c b/arch/powerpc/mm/dump_linuxpagetables-book3s64.c new file mode 100644 index 000000000000..ed6fcf78256e --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-book3s64.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * From split of dump_linuxpagetables.c + * Copyright 2016, Rashmica Gupta, IBM Corp. + * + */ +#include <linux/kernel.h> +#include <asm/pgtable.h> + +#include "dump_linuxpagetables.h" + +static const struct flag_info flag_array[] = { + { + .mask = _PAGE_PRIVILEGED, + .val = 0, + .set = "user", + .clear = " ", + }, { + .mask = _PAGE_READ, + .val = _PAGE_READ, + .set = "r", + .clear = " ", + }, { + .mask = _PAGE_WRITE, + .val = _PAGE_WRITE, + .set = "w", + .clear = " ", + }, { + .mask = _PAGE_EXEC, + .val = _PAGE_EXEC, + .set = " X ", + .clear = " ", + }, { + .mask = _PAGE_PTE, + .val = _PAGE_PTE, + .set = "pte", + .clear = " ", + }, { + .mask = _PAGE_PRESENT, + .val = _PAGE_PRESENT, + .set = "valid", + .clear = " ", + }, { + .mask = _PAGE_PRESENT | _PAGE_INVALID, + .val = 0, + .set = " ", + .clear = "present", + }, { + .mask = H_PAGE_HASHPTE, + .val = H_PAGE_HASHPTE, + .set = "hpte", + .clear = " ", + }, { + .mask = _PAGE_DIRTY, + .val = _PAGE_DIRTY, + .set = "dirty", + .clear = " ", + }, { + .mask = _PAGE_ACCESSED, + .val = _PAGE_ACCESSED, + .set = "accessed", + .clear = " ", + }, { + .mask = _PAGE_NON_IDEMPOTENT, + .val = _PAGE_NON_IDEMPOTENT, + .set = "non-idempotent", + .clear = " ", + }, { + .mask = _PAGE_TOLERANT, + .val = _PAGE_TOLERANT, + .set = "tolerant", + .clear = " ", + }, { + .mask = H_PAGE_BUSY, + .val = H_PAGE_BUSY, + .set = "busy", + }, { +#ifdef CONFIG_PPC_64K_PAGES + .mask = H_PAGE_COMBO, + .val = H_PAGE_COMBO, + .set = "combo", + }, { + .mask = H_PAGE_4K_PFN, + .val = H_PAGE_4K_PFN, + .set = "4K_pfn", + }, { +#else /* CONFIG_PPC_64K_PAGES */ + .mask = H_PAGE_F_GIX, + .val = H_PAGE_F_GIX, + .set = "f_gix", + .is_val = true, + .shift = H_PAGE_F_GIX_SHIFT, + }, { + .mask = H_PAGE_F_SECOND, + .val = H_PAGE_F_SECOND, + .set = "f_second", + }, { +#endif /* CONFIG_PPC_64K_PAGES */ + .mask = _PAGE_SPECIAL, + .val = _PAGE_SPECIAL, + .set = "special", + } +}; + +struct pgtable_level pg_level[5] = { + { + }, { /* pgd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pud */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pmd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pte */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, +}; diff --git a/arch/powerpc/mm/dump_linuxpagetables-generic.c b/arch/powerpc/mm/dump_linuxpagetables-generic.c new file mode 100644 index 000000000000..1e3829ec1348 --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-generic.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * From split of dump_linuxpagetables.c + * Copyright 2016, Rashmica Gupta, IBM Corp. + * + */ +#include <linux/kernel.h> +#include <asm/pgtable.h> + +#include "dump_linuxpagetables.h" + +static const struct flag_info flag_array[] = { + { + .mask = _PAGE_USER, + .val = _PAGE_USER, + .set = "user", + .clear = " ", + }, { + .mask = _PAGE_RW, + .val = _PAGE_RW, + .set = "rw", + .clear = "r ", + }, { +#ifndef CONFIG_PPC_BOOK3S_32 + .mask = _PAGE_EXEC, + .val = _PAGE_EXEC, + .set = " X ", + .clear = " ", + }, { +#endif + .mask = _PAGE_PRESENT, + .val = _PAGE_PRESENT, + .set = "present", + .clear = " ", + }, { + .mask = _PAGE_GUARDED, + .val = _PAGE_GUARDED, + .set = "guarded", + .clear = " ", + }, { + .mask = _PAGE_DIRTY, + .val = _PAGE_DIRTY, + .set = "dirty", + .clear = " ", + }, { + .mask = _PAGE_ACCESSED, + .val = _PAGE_ACCESSED, + .set = "accessed", + .clear = " ", + }, { + .mask = _PAGE_WRITETHRU, + .val = _PAGE_WRITETHRU, + .set = "write through", + .clear = " ", + }, { + .mask = _PAGE_NO_CACHE, + .val = _PAGE_NO_CACHE, + .set = "no cache", + .clear = " ", + }, { + .mask = _PAGE_SPECIAL, + .val = _PAGE_SPECIAL, + .set = "special", + } +}; + +struct pgtable_level pg_level[5] = { + { + }, { /* pgd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pud */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pmd */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, { /* pte */ + .flag = flag_array, + .num = ARRAY_SIZE(flag_array), + }, +}; diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c index 876e2a3c79f2..2b74f8adf4d0 100644 --- a/arch/powerpc/mm/dump_linuxpagetables.c +++ b/arch/powerpc/mm/dump_linuxpagetables.c @@ -27,6 +27,8 @@ #include <asm/page.h> #include <asm/pgalloc.h> +#include "dump_linuxpagetables.h" + #ifdef CONFIG_PPC32 #define KERN_VIRT_START 0 #endif @@ -101,159 +103,6 @@ static struct addr_marker address_markers[] = { { -1, NULL }, }; -struct flag_info { - u64 mask; - u64 val; - const char *set; - const char *clear; - bool is_val; - int shift; -}; - -static const struct flag_info flag_array[] = { - { - .mask = _PAGE_USER | _PAGE_PRIVILEGED, - .val = _PAGE_USER, - .set = "user", - .clear = " ", - }, { - .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, - .val = _PAGE_RW, - .set = "rw", - }, { - .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, - .val = _PAGE_RO, - .set = "ro", - }, { -#if _PAGE_NA != 0 - .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, - .val = _PAGE_RO, - .set = "na", - }, { -#endif - .mask = _PAGE_EXEC, - .val = _PAGE_EXEC, - .set = " X ", - .clear = " ", - }, { - .mask = _PAGE_PTE, - .val = _PAGE_PTE, - .set = "pte", - .clear = " ", - }, { - .mask = _PAGE_PRESENT, - .val = _PAGE_PRESENT, - .set = "present", - .clear = " ", - }, { -#ifdef CONFIG_PPC_BOOK3S_64 - .mask = H_PAGE_HASHPTE, - .val = H_PAGE_HASHPTE, -#else - .mask = _PAGE_HASHPTE, - .val = _PAGE_HASHPTE, -#endif - .set = "hpte", - .clear = " ", - }, { -#ifndef CONFIG_PPC_BOOK3S_64 - .mask = _PAGE_GUARDED, - .val = _PAGE_GUARDED, - .set = "guarded", - .clear = " ", - }, { -#endif - .mask = _PAGE_DIRTY, - .val = _PAGE_DIRTY, - .set = "dirty", - .clear = " ", - }, { - .mask = _PAGE_ACCESSED, - .val = _PAGE_ACCESSED, - .set = "accessed", - .clear = " ", - }, { -#ifndef CONFIG_PPC_BOOK3S_64 - .mask = _PAGE_WRITETHRU, - .val = _PAGE_WRITETHRU, - .set = "write through", - .clear = " ", - }, { -#endif -#ifndef CONFIG_PPC_BOOK3S_64 - .mask = _PAGE_NO_CACHE, - .val = _PAGE_NO_CACHE, - .set = "no cache", - .clear = " ", - }, { -#else - .mask = _PAGE_NON_IDEMPOTENT, - .val = _PAGE_NON_IDEMPOTENT, - .set = "non-idempotent", - .clear = " ", - }, { - .mask = _PAGE_TOLERANT, - .val = _PAGE_TOLERANT, - .set = "tolerant", - .clear = " ", - }, { -#endif -#ifdef CONFIG_PPC_BOOK3S_64 - .mask = H_PAGE_BUSY, - .val = H_PAGE_BUSY, - .set = "busy", - }, { -#ifdef CONFIG_PPC_64K_PAGES - .mask = H_PAGE_COMBO, - .val = H_PAGE_COMBO, - .set = "combo", - }, { - .mask = H_PAGE_4K_PFN, - .val = H_PAGE_4K_PFN, - .set = "4K_pfn", - }, { -#else /* CONFIG_PPC_64K_PAGES */ - .mask = H_PAGE_F_GIX, - .val = H_PAGE_F_GIX, - .set = "f_gix", - .is_val = true, - .shift = H_PAGE_F_GIX_SHIFT, - }, { - .mask = H_PAGE_F_SECOND, - .val = H_PAGE_F_SECOND, - .set = "f_second", - }, { -#endif /* CONFIG_PPC_64K_PAGES */ -#endif - .mask = _PAGE_SPECIAL, - .val = _PAGE_SPECIAL, - .set = "special", - } -}; - -struct pgtable_level { - const struct flag_info *flag; - size_t num; - u64 mask; -}; - -static struct pgtable_level pg_level[] = { - { - }, { /* pgd */ - .flag = flag_array, - .num = ARRAY_SIZE(flag_array), - }, { /* pud */ - .flag = flag_array, - .num = ARRAY_SIZE(flag_array), - }, { /* pmd */ - .flag = flag_array, - .num = ARRAY_SIZE(flag_array), - }, { /* pte */ - .flag = flag_array, - .num = ARRAY_SIZE(flag_array), - }, -}; - static void dump_flag_info(struct pg_state *st, const struct flag_info *flag, u64 pte, int num) { @@ -418,12 +267,13 @@ static void walk_pagetables(struct pg_state *st) unsigned int i; unsigned long addr; + addr = st->start_address; + /* * Traverse the linux pagetable structure and dump pages that are in * the hash pagetable. */ - for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { - addr = KERN_VIRT_START + i * PGDIR_SIZE; + for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) { if (!pgd_none(*pgd) && !pgd_huge(*pgd)) /* pgd exists */ walk_pud(st, pgd, addr); @@ -472,9 +322,14 @@ static int ptdump_show(struct seq_file *m, void *v) { struct pg_state st = { .seq = m, - .start_address = KERN_VIRT_START, .marker = address_markers, }; + + if (radix_enabled()) + st.start_address = PAGE_OFFSET; + else + st.start_address = KERN_VIRT_START; + /* Traverse kernel page tables */ walk_pagetables(&st); note_page(&st, 0, 0, 0); diff --git a/arch/powerpc/mm/dump_linuxpagetables.h b/arch/powerpc/mm/dump_linuxpagetables.h new file mode 100644 index 000000000000..5d513636de73 --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/types.h> + +struct flag_info { + u64 mask; + u64 val; + const char *set; + const char *clear; + bool is_val; + int shift; +}; + +struct pgtable_level { + const struct flag_info *flag; + size_t num; + u64 mask; +}; + +extern struct pgtable_level pg_level[5]; diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index d51cf5f4e45e..1697e903bbf2 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -103,8 +103,7 @@ static bool store_updates_sp(unsigned int inst) */ static int -__bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code, - int pkey) +__bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code) { /* * If we are in kernel mode, bail out with a SEGV, this will @@ -114,18 +113,17 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code, if (!user_mode(regs)) return SIGSEGV; - _exception_pkey(SIGSEGV, regs, si_code, address, pkey); + _exception(SIGSEGV, regs, si_code, address); return 0; } static noinline int bad_area_nosemaphore(struct pt_regs *regs, unsigned long address) { - return __bad_area_nosemaphore(regs, address, SEGV_MAPERR, 0); + return __bad_area_nosemaphore(regs, address, SEGV_MAPERR); } -static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code, - int pkey) +static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code) { struct mm_struct *mm = current->mm; @@ -135,54 +133,61 @@ static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code, */ up_read(&mm->mmap_sem); - return __bad_area_nosemaphore(regs, address, si_code, pkey); + return __bad_area_nosemaphore(regs, address, si_code); } static noinline int bad_area(struct pt_regs *regs, unsigned long address) { - return __bad_area(regs, address, SEGV_MAPERR, 0); + return __bad_area(regs, address, SEGV_MAPERR); } static int bad_key_fault_exception(struct pt_regs *regs, unsigned long address, int pkey) { - return __bad_area_nosemaphore(regs, address, SEGV_PKUERR, pkey); + /* + * If we are in kernel mode, bail out with a SEGV, this will + * be caught by the assembly which will restore the non-volatile + * registers before calling bad_page_fault() + */ + if (!user_mode(regs)) + return SIGSEGV; + + _exception_pkey(regs, address, pkey); + + return 0; } static noinline int bad_access(struct pt_regs *regs, unsigned long address) { - return __bad_area(regs, address, SEGV_ACCERR, 0); + return __bad_area(regs, address, SEGV_ACCERR); } static int do_sigbus(struct pt_regs *regs, unsigned long address, vm_fault_t fault) { - siginfo_t info; - unsigned int lsb = 0; - if (!user_mode(regs)) return SIGBUS; current->thread.trap_nr = BUS_ADRERR; - clear_siginfo(&info); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void __user *)address; #ifdef CONFIG_MEMORY_FAILURE if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { + unsigned int lsb = 0; /* shutup gcc */ + pr_err("MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", current->comm, current->pid, address); - info.si_code = BUS_MCEERR_AR; + + if (fault & VM_FAULT_HWPOISON_LARGE) + lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); + if (fault & VM_FAULT_HWPOISON) + lsb = PAGE_SHIFT; + + force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, + current); + return 0; } - if (fault & VM_FAULT_HWPOISON_LARGE) - lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); - if (fault & VM_FAULT_HWPOISON) - lsb = PAGE_SHIFT; #endif - info.si_addr_lsb = lsb; - force_sig_info(SIGBUS, &info, current); + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, current); return 0; } diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 729f02df8290..aaa28fd918fe 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -115,6 +115,8 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is) tlbiel_hash_set_isa300(0, is, 0, 2, 1); asm volatile("ptesync": : :"memory"); + + asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); } void hash__tlbiel_all(unsigned int action) @@ -140,8 +142,6 @@ void hash__tlbiel_all(unsigned int action) tlbiel_all_isa206(POWER7_TLB_SETS, is); else WARN(1, "%s called on pre-POWER7 CPU\n", __func__); - - asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); } static inline unsigned long ___tlbie(unsigned long vpn, int psize, diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index f23a89d8e4ce..0cc7fbc3bd1c 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -1001,9 +1001,9 @@ void __init hash__early_init_mmu(void) * 4k use hugepd format, so for hash set then to * zero */ - __pmd_val_bits = 0; - __pud_val_bits = 0; - __pgd_val_bits = 0; + __pmd_val_bits = HASH_PMD_VAL_BITS; + __pud_val_bits = HASH_PUD_VAL_BITS; + __pgd_val_bits = HASH_PGD_VAL_BITS; __kernel_virt_start = H_KERN_VIRT_START; __kernel_virt_size = H_KERN_VIRT_SIZE; @@ -1125,7 +1125,7 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) { copy_mm_to_paca(mm); - slb_flush_and_rebolt(); + slb_flush_and_restore_bolted(); } } #endif /* CONFIG_PPC_64K_PAGES */ @@ -1197,7 +1197,7 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm, if (user_region) { if (psize != get_paca_psize(ea)) { copy_mm_to_paca(mm); - slb_flush_and_rebolt(); + slb_flush_and_restore_bolted(); } } else if (get_paca()->vmalloc_sllp != mmu_psize_defs[mmu_vmalloc_psize].sllp) { @@ -1482,7 +1482,7 @@ static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) #endif void hash_preload(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap) + bool is_exec, unsigned long trap) { int hugepage_shift; unsigned long vsid; @@ -1490,6 +1490,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, pte_t *ptep; unsigned long flags; int rc, ssize, update_flags = 0; + unsigned long access = _PAGE_PRESENT | _PAGE_READ | (is_exec ? _PAGE_EXEC : 0); BUG_ON(REGION_ID(ea) != USER_REGION_ID); diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 01f213d2bcb9..dfbc3b32f09b 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c @@ -51,6 +51,12 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, new_pmd |= _PAGE_DIRTY; } while (!pmd_xchg(pmdp, __pmd(old_pmd), __pmd(new_pmd))); + /* + * Make sure this is thp or devmap entry + */ + if (!(old_pmd & (H_PAGE_THP_HUGE | _PAGE_DEVMAP))) + return 0; + rflags = htab_convert_pte_flags(new_pmd); #if 0 diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index b320f5097a06..2e6a8f9345d3 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c @@ -62,6 +62,10 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, new_pte |= _PAGE_DIRTY; } while(!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); + /* Make sure this is a hugetlb entry */ + if (old_pte & (H_PAGE_THP_HUGE | _PAGE_DEVMAP)) + return 0; + rflags = htab_convert_pte_flags(new_pte); if (unlikely(mmu_psize == MMU_PAGE_16G)) offset = PTRS_PER_PUD; diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index e87f9ef9115b..a7226ed9cae6 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -19,6 +19,7 @@ #include <linux/moduleparam.h> #include <linux/swap.h> #include <linux/swapops.h> +#include <linux/kmemleak.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/tlb.h> @@ -95,7 +96,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, break; else { #ifdef CONFIG_PPC_BOOK3S_64 - *hpdp = __hugepd(__pa(new) | + *hpdp = __hugepd(__pa(new) | HUGEPD_VAL_BITS | (shift_to_mmu_psize(pshift) << 2)); #elif defined(CONFIG_PPC_8xx) *hpdp = __hugepd(__pa(new) | _PMD_USER | @@ -112,6 +113,8 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, for (i = i - 1 ; i >= 0; i--, hpdp--) *hpdp = __hugepd(0); kmem_cache_free(cachep, new); + } else { + kmemleak_ignore(new); } spin_unlock(ptl); return 0; @@ -837,8 +840,12 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea, ret_pte = (pte_t *) pmdp; goto out; } - - if (pmd_huge(pmd)) { + /* + * pmd_large check below will handle the swap pmd pte + * we need to do both the check because they are config + * dependent. + */ + if (pmd_huge(pmd) || pmd_large(pmd)) { ret_pte = (pte_t *) pmdp; goto out; } else if (is_hugepd(__hugepd(pmd_val(pmd)))) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 04ccb274a620..dd949d6649a2 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -309,11 +309,11 @@ void __init paging_init(void) unsigned long end = __fix_to_virt(FIX_HOLE); for (; v < end; v += PAGE_SIZE) - map_kernel_page(v, 0, 0); /* XXX gross */ + map_kernel_page(v, 0, __pgprot(0)); /* XXX gross */ #endif #ifdef CONFIG_HIGHMEM - map_kernel_page(PKMAP_BASE, 0, 0); /* XXX gross */ + map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */ pkmap_page_table = virt_to_kpte(PKMAP_BASE); kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); @@ -509,7 +509,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, * We don't need to worry about _PAGE_PRESENT here because we are * called with either mm->page_table_lock held or ptl lock held */ - unsigned long access, trap; + unsigned long trap; + bool is_exec; if (radix_enabled()) { prefetch((void *)address); @@ -531,16 +532,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, trap = current->thread.regs ? TRAP(current->thread.regs) : 0UL; switch (trap) { case 0x300: - access = 0UL; + is_exec = false; break; case 0x400: - access = _PAGE_EXEC; + is_exec = true; break; default: return; } - hash_preload(vma->vm_mm, address, access, trap); + hash_preload(vma->vm_mm, address, is_exec, trap); #endif /* CONFIG_PPC_STD_MMU */ #if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \ && defined(CONFIG_HUGETLB_PAGE) diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index dbd8f762140b..510f103d7813 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c @@ -53,6 +53,8 @@ int hash__alloc_context_id(void) } EXPORT_SYMBOL_GPL(hash__alloc_context_id); +void slb_setup_new_exec(void); + static int hash__init_new_context(struct mm_struct *mm) { int index; @@ -84,6 +86,13 @@ static int hash__init_new_context(struct mm_struct *mm) return index; } +void hash__setup_new_exec(void) +{ + slice_setup_new_exec(); + + slb_setup_new_exec(); +} + static int radix__init_new_context(struct mm_struct *mm) { unsigned long rts_field; diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index e5d779eed181..8574fbbc45e0 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -22,6 +22,7 @@ #include <asm/mmu.h> #ifdef CONFIG_PPC_MMU_NOHASH +#include <asm/trace.h> /* * On 40x and 8xx, we directly inline tlbia and tlbivax @@ -30,10 +31,12 @@ static inline void _tlbil_all(void) { asm volatile ("sync; tlbia; isync" : : : "memory"); + trace_tlbia(MMU_NO_CONTEXT); } static inline void _tlbil_pid(unsigned int pid) { asm volatile ("sync; tlbia; isync" : : : "memory"); + trace_tlbia(pid); } #define _tlbil_pid_noind(pid) _tlbil_pid(pid) @@ -55,6 +58,7 @@ static inline void _tlbil_va(unsigned long address, unsigned int pid, unsigned int tsize, unsigned int ind) { asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); + trace_tlbie(0, 0, address, pid, 0, 0, 0); } #elif defined(CONFIG_PPC_BOOK3E) extern void _tlbil_va(unsigned long address, unsigned int pid, @@ -82,7 +86,7 @@ static inline void _tlbivax_bcast(unsigned long address, unsigned int pid, #else /* CONFIG_PPC_MMU_NOHASH */ extern void hash_preload(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap); + bool is_exec, unsigned long trap); extern void _tlbie(unsigned long address); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 055b211b7126..693ae1c1acba 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1521,6 +1521,10 @@ int start_topology_update(void) } } + pr_info("Starting topology update%s%s\n", + (prrn_enabled ? " prrn_enabled" : ""), + (vphn_enabled ? " vphn_enabled" : "")); + return rc; } @@ -1542,6 +1546,8 @@ int stop_topology_update(void) rc = del_timer_sync(&topology_timer); } + pr_info("Stopping topology update\n"); + return rc; } diff --git a/arch/powerpc/mm/pgtable-book3e.c b/arch/powerpc/mm/pgtable-book3e.c index a2298930f990..e0ccf36714b2 100644 --- a/arch/powerpc/mm/pgtable-book3e.c +++ b/arch/powerpc/mm/pgtable-book3e.c @@ -42,7 +42,7 @@ int __meminit vmemmap_create_mapping(unsigned long start, * thus must have the low bits clear */ for (i = 0; i < page_size; i += PAGE_SIZE) - BUG_ON(map_kernel_page(start + i, phys, flags)); + BUG_ON(map_kernel_page(start + i, phys, __pgprot(flags))); return 0; } @@ -70,7 +70,7 @@ static __ref void *early_alloc_pgtable(unsigned long size) * map_kernel_page adds an entry to the ioremap page table * and adds an entry to the HPT, possibly bolting it */ -int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) +int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) { pgd_t *pgdp; pud_t *pudp; @@ -89,8 +89,6 @@ int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) ptep = pte_alloc_kernel(pmdp, ea); if (!ptep) return -ENOMEM; - set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, - __pgprot(flags))); } else { pgdp = pgd_offset_k(ea); #ifndef __PAGETABLE_PUD_FOLDED @@ -113,9 +111,8 @@ int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) pmd_populate_kernel(&init_mm, pmdp, ptep); } ptep = pte_offset_kernel(pmdp, ea); - set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, - __pgprot(flags))); } + set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot)); smp_wmb(); return 0; diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c index 01d7c0f7c4f0..9f93c9f985c5 100644 --- a/arch/powerpc/mm/pgtable-book3s64.c +++ b/arch/powerpc/mm/pgtable-book3s64.c @@ -69,9 +69,14 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd) { #ifdef CONFIG_DEBUG_VM - WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); + /* + * Make sure hardware valid bit is not set. We don't do + * tlb flush for this update. + */ + + WARN_ON(pte_hw_valid(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); assert_spin_locked(pmd_lockptr(mm, pmdp)); - WARN_ON(!(pmd_trans_huge(pmd) || pmd_devmap(pmd))); + WARN_ON(!(pmd_large(pmd) || pmd_devmap(pmd))); #endif trace_hugepage_set_pmd(addr, pmd_val(pmd)); return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); @@ -106,7 +111,7 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, { unsigned long old_pmd; - old_pmd = pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0); + old_pmd = pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, _PAGE_INVALID); flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); /* * This ensures that generic code that rely on IRQ disabling diff --git a/arch/powerpc/mm/pgtable-hash64.c b/arch/powerpc/mm/pgtable-hash64.c index 692bfc9e372c..c08d49046a96 100644 --- a/arch/powerpc/mm/pgtable-hash64.c +++ b/arch/powerpc/mm/pgtable-hash64.c @@ -142,7 +142,7 @@ void hash__vmemmap_remove_mapping(unsigned long start, * map_kernel_page adds an entry to the ioremap page table * and adds an entry to the HPT, possibly bolting it */ -int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) +int hash__map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) { pgd_t *pgdp; pud_t *pudp; @@ -161,8 +161,7 @@ int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flag ptep = pte_alloc_kernel(pmdp, ea); if (!ptep) return -ENOMEM; - set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, - __pgprot(flags))); + set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot)); } else { /* * If the mm subsystem is not fully up, we cannot create a @@ -170,7 +169,7 @@ int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flag * entry in the hardware page table. * */ - if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, + if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, pgprot_val(prot), mmu_io_psize, mmu_kernel_ssize)) { printk(KERN_ERR "Failed to do bolted mapping IO " "memory at %016lx !\n", pa); diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index c879979faa73..931156069a81 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c @@ -241,9 +241,8 @@ void radix__mark_initmem_nx(void) } #endif /* CONFIG_STRICT_KERNEL_RWX */ -static inline void __meminit print_mapping(unsigned long start, - unsigned long end, - unsigned long size) +static inline void __meminit +print_mapping(unsigned long start, unsigned long end, unsigned long size, bool exec) { char buf[10]; @@ -252,7 +251,17 @@ static inline void __meminit print_mapping(unsigned long start, string_get_size(size, 1, STRING_UNITS_2, buf, sizeof(buf)); - pr_info("Mapped 0x%016lx-0x%016lx with %s pages\n", start, end, buf); + pr_info("Mapped 0x%016lx-0x%016lx with %s pages%s\n", start, end, buf, + exec ? " (exec)" : ""); +} + +static unsigned long next_boundary(unsigned long addr, unsigned long end) +{ +#ifdef CONFIG_STRICT_KERNEL_RWX + if (addr < __pa_symbol(__init_begin)) + return __pa_symbol(__init_begin); +#endif + return end; } static int __meminit create_physical_mapping(unsigned long start, @@ -260,13 +269,8 @@ static int __meminit create_physical_mapping(unsigned long start, int nid) { unsigned long vaddr, addr, mapping_size = 0; + bool prev_exec, exec = false; pgprot_t prot; - unsigned long max_mapping_size; -#ifdef CONFIG_STRICT_KERNEL_RWX - int split_text_mapping = 1; -#else - int split_text_mapping = 0; -#endif int psize; start = _ALIGN_UP(start, PAGE_SIZE); @@ -274,14 +278,12 @@ static int __meminit create_physical_mapping(unsigned long start, unsigned long gap, previous_size; int rc; - gap = end - addr; + gap = next_boundary(addr, end) - addr; previous_size = mapping_size; - max_mapping_size = PUD_SIZE; + prev_exec = exec; -retry: if (IS_ALIGNED(addr, PUD_SIZE) && gap >= PUD_SIZE && - mmu_psize_defs[MMU_PAGE_1G].shift && - PUD_SIZE <= max_mapping_size) { + mmu_psize_defs[MMU_PAGE_1G].shift) { mapping_size = PUD_SIZE; psize = MMU_PAGE_1G; } else if (IS_ALIGNED(addr, PMD_SIZE) && gap >= PMD_SIZE && @@ -293,32 +295,21 @@ retry: psize = mmu_virtual_psize; } - if (split_text_mapping && (mapping_size == PUD_SIZE) && - (addr <= __pa_symbol(__init_begin)) && - (addr + mapping_size) >= __pa_symbol(_stext)) { - max_mapping_size = PMD_SIZE; - goto retry; - } - - if (split_text_mapping && (mapping_size == PMD_SIZE) && - (addr <= __pa_symbol(__init_begin)) && - (addr + mapping_size) >= __pa_symbol(_stext)) { - mapping_size = PAGE_SIZE; - psize = mmu_virtual_psize; - } - - if (mapping_size != previous_size) { - print_mapping(start, addr, previous_size); - start = addr; - } - vaddr = (unsigned long)__va(addr); if (overlaps_kernel_text(vaddr, vaddr + mapping_size) || - overlaps_interrupt_vector_text(vaddr, vaddr + mapping_size)) + overlaps_interrupt_vector_text(vaddr, vaddr + mapping_size)) { prot = PAGE_KERNEL_X; - else + exec = true; + } else { prot = PAGE_KERNEL; + exec = false; + } + + if (mapping_size != previous_size || exec != prev_exec) { + print_mapping(start, addr, previous_size, prev_exec); + start = addr; + } rc = __map_kernel_page(vaddr, addr, prot, mapping_size, nid, start, end); if (rc) @@ -327,7 +318,7 @@ retry: update_page_count(psize, 1); } - print_mapping(start, addr, mapping_size); + print_mapping(start, addr, mapping_size, exec); return 0; } diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index d71c7777669c..010e1c616cb2 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -44,20 +44,13 @@ static inline int is_exec_fault(void) static inline int pte_looks_normal(pte_t pte) { -#if defined(CONFIG_PPC_BOOK3S_64) - if ((pte_val(pte) & (_PAGE_PRESENT | _PAGE_SPECIAL)) == _PAGE_PRESENT) { + if (pte_present(pte) && !pte_special(pte)) { if (pte_ci(pte)) return 0; if (pte_user(pte)) return 1; } return 0; -#else - return (pte_val(pte) & - (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER | - _PAGE_PRIVILEGED)) == - (_PAGE_PRESENT | _PAGE_USER); -#endif } static struct page *maybe_pte_to_page(pte_t pte) @@ -73,7 +66,7 @@ static struct page *maybe_pte_to_page(pte_t pte) return page; } -#if defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 +#ifdef CONFIG_PPC_BOOK3S /* Server-style MMU handles coherency when hashing if HW exec permission * is supposed per page (currently 64-bit only). If not, then, we always @@ -106,7 +99,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, return pte; } -#else /* defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 */ +#else /* CONFIG_PPC_BOOK3S */ /* Embedded type MMU with HW exec support. This is a bit more complicated * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so @@ -117,7 +110,7 @@ static pte_t set_pte_filter(pte_t pte) struct page *pg; /* No exec permission in the first place, move on */ - if (!(pte_val(pte) & _PAGE_EXEC) || !pte_looks_normal(pte)) + if (!pte_exec(pte) || !pte_looks_normal(pte)) return pte; /* If you set _PAGE_EXEC on weird pages you're on your own */ @@ -137,7 +130,7 @@ static pte_t set_pte_filter(pte_t pte) } /* Else, we filter out _PAGE_EXEC */ - return __pte(pte_val(pte) & ~_PAGE_EXEC); + return pte_exprotect(pte); } static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, @@ -150,7 +143,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, * if necessary. Also if _PAGE_EXEC is already set, same deal, * we just bail out */ - if (dirty || (pte_val(pte) & _PAGE_EXEC) || !is_exec_fault()) + if (dirty || pte_exec(pte) || !is_exec_fault()) return pte; #ifdef CONFIG_DEBUG_VM @@ -176,10 +169,10 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, set_bit(PG_arch_1, &pg->flags); bail: - return __pte(pte_val(pte) | _PAGE_EXEC); + return pte_mkexec(pte); } -#endif /* !(defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0) */ +#endif /* CONFIG_PPC_BOOK3S */ /* * set_pte stores a linux PTE into the linux page table. @@ -188,14 +181,13 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { /* - * When handling numa faults, we already have the pte marked - * _PAGE_PRESENT, but we can be sure that it is not in hpte. - * Hence we can use set_pte_at for them. + * Make sure hardware valid bit is not set. We don't do + * tlb flush for this update. */ - VM_WARN_ON(pte_present(*ptep) && !pte_protnone(*ptep)); + VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep)); /* Add the pte bit when trying to set a pte */ - pte = __pte(pte_val(pte) | _PAGE_PTE); + pte = pte_mkpte(pte); /* Note: mm->context.id might not yet have been assigned as * this context might not have been activated yet when this diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 120a49bfb9c6..5877f5aa8f5d 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -76,56 +76,69 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) void __iomem * ioremap(phys_addr_t addr, unsigned long size) { - return __ioremap_caller(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED, - __builtin_return_address(0)); + pgprot_t prot = pgprot_noncached(PAGE_KERNEL); + + return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); } EXPORT_SYMBOL(ioremap); void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size) { - return __ioremap_caller(addr, size, _PAGE_NO_CACHE, - __builtin_return_address(0)); + pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL); + + return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); } EXPORT_SYMBOL(ioremap_wc); void __iomem * +ioremap_wt(phys_addr_t addr, unsigned long size) +{ + pgprot_t prot = pgprot_cached_wthru(PAGE_KERNEL); + + return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_wt); + +void __iomem * +ioremap_coherent(phys_addr_t addr, unsigned long size) +{ + pgprot_t prot = pgprot_cached(PAGE_KERNEL); + + return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_coherent); + +void __iomem * ioremap_prot(phys_addr_t addr, unsigned long size, unsigned long flags) { + pte_t pte = __pte(flags); + /* writeable implies dirty for kernel addresses */ - if ((flags & (_PAGE_RW | _PAGE_RO)) != _PAGE_RO) - flags |= _PAGE_DIRTY | _PAGE_HWWRITE; + if (pte_write(pte)) + pte = pte_mkdirty(pte); /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ - flags &= ~(_PAGE_USER | _PAGE_EXEC); - flags |= _PAGE_PRIVILEGED; + pte = pte_exprotect(pte); + pte = pte_mkprivileged(pte); - return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); + return __ioremap_caller(addr, size, pte_pgprot(pte), __builtin_return_address(0)); } EXPORT_SYMBOL(ioremap_prot); void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { - return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); + return __ioremap_caller(addr, size, __pgprot(flags), __builtin_return_address(0)); } void __iomem * -__ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, - void *caller) +__ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *caller) { unsigned long v, i; phys_addr_t p; int err; - /* Make sure we have the base flags */ - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - - /* Non-cacheable page cannot be coherent */ - if (flags & _PAGE_NO_CACHE) - flags &= ~_PAGE_COHERENT; - /* * Choose an address to map it to. * Once the vmalloc system is running, we use it. @@ -183,7 +196,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, err = 0; for (i = 0; i < size && err == 0; i += PAGE_SIZE) - err = map_kernel_page(v+i, p+i, flags); + err = map_kernel_page(v + i, p + i, prot); if (err) { if (slab_is_available()) vunmap((void *)v); @@ -209,7 +222,7 @@ void iounmap(volatile void __iomem *addr) } EXPORT_SYMBOL(iounmap); -int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) +int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot) { pmd_t *pd; pte_t *pg; @@ -224,10 +237,8 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) /* The PTE should never be already set nor present in the * hash table */ - BUG_ON((pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)) && - flags); - set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, - __pgprot(flags))); + BUG_ON((pte_present(*pg) | pte_hashpte(*pg)) && pgprot_val(prot)); + set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, prot)); } smp_wmb(); return err; @@ -238,7 +249,7 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) */ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) { - unsigned long v, s, f; + unsigned long v, s; phys_addr_t p; int ktext; @@ -248,11 +259,10 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) for (; s < top; s += PAGE_SIZE) { ktext = ((char *)v >= _stext && (char *)v < etext) || ((char *)v >= _sinittext && (char *)v < _einittext); - f = ktext ? pgprot_val(PAGE_KERNEL_TEXT) : pgprot_val(PAGE_KERNEL); - map_kernel_page(v, p, f); + map_kernel_page(v, p, ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL); #ifdef CONFIG_PPC_STD_MMU_32 if (ktext) - hash_preload(&init_mm, v, 0, 0x300); + hash_preload(&init_mm, v, false, 0x300); #endif v += PAGE_SIZE; p += PAGE_SIZE; diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 53e9eeecd5d4..fb1375c07e8c 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -113,17 +113,12 @@ unsigned long ioremap_bot = IOREMAP_BASE; * __ioremap_at - Low level function to establish the page tables * for an IO mapping */ -void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, - unsigned long flags) +void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_t prot) { unsigned long i; - /* Make sure we have the base flags */ - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - /* We don't support the 4K PFN hack with ioremap */ - if (flags & H_PAGE_4K_PFN) + if (pgprot_val(prot) & H_PAGE_4K_PFN) return NULL; WARN_ON(pa & ~PAGE_MASK); @@ -131,7 +126,7 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, WARN_ON(size & ~PAGE_MASK); for (i = 0; i < size; i += PAGE_SIZE) - if (map_kernel_page((unsigned long)ea+i, pa+i, flags)) + if (map_kernel_page((unsigned long)ea + i, pa + i, prot)) return NULL; return (void __iomem *)ea; @@ -152,7 +147,7 @@ void __iounmap_at(void *ea, unsigned long size) } void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, - unsigned long flags, void *caller) + pgprot_t prot, void *caller) { phys_addr_t paligned; void __iomem *ret; @@ -182,11 +177,11 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, return NULL; area->phys_addr = paligned; - ret = __ioremap_at(paligned, area->addr, size, flags); + ret = __ioremap_at(paligned, area->addr, size, prot); if (!ret) vunmap(area->addr); } else { - ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); + ret = __ioremap_at(paligned, (void *)ioremap_bot, size, prot); if (ret) ioremap_bot += size; } @@ -199,49 +194,59 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { - return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); + return __ioremap_caller(addr, size, __pgprot(flags), __builtin_return_address(0)); } void __iomem * ioremap(phys_addr_t addr, unsigned long size) { - unsigned long flags = pgprot_val(pgprot_noncached(__pgprot(0))); + pgprot_t prot = pgprot_noncached(PAGE_KERNEL); void *caller = __builtin_return_address(0); if (ppc_md.ioremap) - return ppc_md.ioremap(addr, size, flags, caller); - return __ioremap_caller(addr, size, flags, caller); + return ppc_md.ioremap(addr, size, prot, caller); + return __ioremap_caller(addr, size, prot, caller); } void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size) { - unsigned long flags = pgprot_val(pgprot_noncached_wc(__pgprot(0))); + pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL); + void *caller = __builtin_return_address(0); + + if (ppc_md.ioremap) + return ppc_md.ioremap(addr, size, prot, caller); + return __ioremap_caller(addr, size, prot, caller); +} + +void __iomem *ioremap_coherent(phys_addr_t addr, unsigned long size) +{ + pgprot_t prot = pgprot_cached(PAGE_KERNEL); void *caller = __builtin_return_address(0); if (ppc_md.ioremap) - return ppc_md.ioremap(addr, size, flags, caller); - return __ioremap_caller(addr, size, flags, caller); + return ppc_md.ioremap(addr, size, prot, caller); + return __ioremap_caller(addr, size, prot, caller); } void __iomem * ioremap_prot(phys_addr_t addr, unsigned long size, unsigned long flags) { + pte_t pte = __pte(flags); void *caller = __builtin_return_address(0); /* writeable implies dirty for kernel addresses */ - if (flags & _PAGE_WRITE) - flags |= _PAGE_DIRTY; + if (pte_write(pte)) + pte = pte_mkdirty(pte); /* we don't want to let _PAGE_EXEC leak out */ - flags &= ~_PAGE_EXEC; + pte = pte_exprotect(pte); /* * Force kernel mapping. */ - flags &= ~_PAGE_USER; - flags |= _PAGE_PRIVILEGED; + pte = pte_mkprivileged(pte); if (ppc_md.ioremap) - return ppc_md.ioremap(addr, size, flags, caller); - return __ioremap_caller(addr, size, flags, caller); + return ppc_md.ioremap(addr, size, pte_pgprot(pte), caller); + return __ioremap_caller(addr, size, pte_pgprot(pte), caller); } @@ -306,7 +311,7 @@ struct page *pud_page(pud_t pud) */ struct page *pmd_page(pmd_t pmd) { - if (pmd_trans_huge(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)) + if (pmd_large(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)) return pte_page(pmd_pte(pmd)); return virt_to_page(pmd_page_vaddr(pmd)); } diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index bea6c544e38f..38a793bfca37 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -163,7 +163,7 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys, * Preload a translation in the hash table */ void hash_preload(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap) + bool is_exec, unsigned long trap) { pmd_t *pmd; diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 9f574e59d178..c3fdf2969d9f 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include <asm/asm-prototypes.h> #include <asm/pgtable.h> #include <asm/mmu.h> #include <asm/mmu_context.h> @@ -30,11 +31,10 @@ enum slb_index { LINEAR_INDEX = 0, /* Kernel linear map (0xc000000000000000) */ - VMALLOC_INDEX = 1, /* Kernel virtual map (0xd000000000000000) */ - KSTACK_INDEX = 2, /* Kernel stack map */ + KSTACK_INDEX = 1, /* Kernel stack map */ }; -extern void slb_allocate(unsigned long ea); +static long slb_allocate_user(struct mm_struct *mm, unsigned long ea); #define slb_esid_mask(ssize) \ (((ssize) == MMU_SEGSIZE_256M)? ESID_MASK: ESID_MASK_1T) @@ -45,13 +45,43 @@ static inline unsigned long mk_esid_data(unsigned long ea, int ssize, return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | index; } -static inline unsigned long mk_vsid_data(unsigned long ea, int ssize, +static inline unsigned long __mk_vsid_data(unsigned long vsid, int ssize, unsigned long flags) { - return (get_kernel_vsid(ea, ssize) << slb_vsid_shift(ssize)) | flags | + return (vsid << slb_vsid_shift(ssize)) | flags | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); } +static inline unsigned long mk_vsid_data(unsigned long ea, int ssize, + unsigned long flags) +{ + return __mk_vsid_data(get_kernel_vsid(ea, ssize), ssize, flags); +} + +static void assert_slb_exists(unsigned long ea) +{ +#ifdef CONFIG_DEBUG_VM + unsigned long tmp; + + WARN_ON_ONCE(mfmsr() & MSR_EE); + + asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0"); + WARN_ON(tmp == 0); +#endif +} + +static void assert_slb_notexists(unsigned long ea) +{ +#ifdef CONFIG_DEBUG_VM + unsigned long tmp; + + WARN_ON_ONCE(mfmsr() & MSR_EE); + + asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0"); + WARN_ON(tmp != 0); +#endif +} + static inline void slb_shadow_update(unsigned long ea, int ssize, unsigned long flags, enum slb_index index) @@ -84,6 +114,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize, */ slb_shadow_update(ea, ssize, flags, index); + assert_slb_notexists(ea); asm volatile("slbmte %0,%1" : : "r" (mk_vsid_data(ea, ssize, flags)), "r" (mk_esid_data(ea, ssize, index)) @@ -105,17 +136,20 @@ void __slb_restore_bolted_realmode(void) : "r" (be64_to_cpu(p->save_area[index].vsid)), "r" (be64_to_cpu(p->save_area[index].esid))); } + + assert_slb_exists(local_paca->kstack); } /* * Insert the bolted entries into an empty SLB. - * This is not the same as rebolt because the bolted segments are not - * changed, just loaded from the shadow area. */ void slb_restore_bolted_realmode(void) { __slb_restore_bolted_realmode(); get_paca()->slb_cache_ptr = 0; + + get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; + get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; } /* @@ -123,113 +157,262 @@ void slb_restore_bolted_realmode(void) */ void slb_flush_all_realmode(void) { - /* - * This flushes all SLB entries including 0, so it must be realmode. - */ asm volatile("slbmte %0,%0; slbia" : : "r" (0)); } -static void __slb_flush_and_rebolt(void) +/* + * This flushes non-bolted entries, it can be run in virtual mode. Must + * be called with interrupts disabled. + */ +void slb_flush_and_restore_bolted(void) { - /* If you change this make sure you change SLB_NUM_BOLTED - * and PR KVM appropriately too. */ - unsigned long linear_llp, vmalloc_llp, lflags, vflags; - unsigned long ksp_esid_data, ksp_vsid_data; + struct slb_shadow *p = get_slb_shadow(); - linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; - vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; - lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | vmalloc_llp; + BUILD_BUG_ON(SLB_NUM_BOLTED != 2); - ksp_esid_data = mk_esid_data(get_paca()->kstack, mmu_kernel_ssize, KSTACK_INDEX); - if ((ksp_esid_data & ~0xfffffffUL) <= PAGE_OFFSET) { - ksp_esid_data &= ~SLB_ESID_V; - ksp_vsid_data = 0; - slb_shadow_clear(KSTACK_INDEX); - } else { - /* Update stack entry; others don't change */ - slb_shadow_update(get_paca()->kstack, mmu_kernel_ssize, lflags, KSTACK_INDEX); - ksp_vsid_data = - be64_to_cpu(get_slb_shadow()->save_area[KSTACK_INDEX].vsid); - } + WARN_ON(!irqs_disabled()); + + /* + * We can't take a PMU exception in the following code, so hard + * disable interrupts. + */ + hard_irq_disable(); - /* We need to do this all in asm, so we're sure we don't touch - * the stack between the slbia and rebolting it. */ asm volatile("isync\n" "slbia\n" - /* Slot 1 - first VMALLOC segment */ - "slbmte %0,%1\n" - /* Slot 2 - kernel stack */ - "slbmte %2,%3\n" - "isync" - :: "r"(mk_vsid_data(VMALLOC_START, mmu_kernel_ssize, vflags)), - "r"(mk_esid_data(VMALLOC_START, mmu_kernel_ssize, VMALLOC_INDEX)), - "r"(ksp_vsid_data), - "r"(ksp_esid_data) + "slbmte %0, %1\n" + "isync\n" + :: "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].vsid)), + "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].esid)) : "memory"); + assert_slb_exists(get_paca()->kstack); + + get_paca()->slb_cache_ptr = 0; + + get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; + get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; } -void slb_flush_and_rebolt(void) +void slb_save_contents(struct slb_entry *slb_ptr) { + int i; + unsigned long e, v; - WARN_ON(!irqs_disabled()); + /* Save slb_cache_ptr value. */ + get_paca()->slb_save_cache_ptr = get_paca()->slb_cache_ptr; + + if (!slb_ptr) + return; + + for (i = 0; i < mmu_slb_size; i++) { + asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); + asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); + slb_ptr->esid = e; + slb_ptr->vsid = v; + slb_ptr++; + } +} + +void slb_dump_contents(struct slb_entry *slb_ptr) +{ + int i, n; + unsigned long e, v; + unsigned long llp; + + if (!slb_ptr) + return; + + pr_err("SLB contents of cpu 0x%x\n", smp_processor_id()); + pr_err("Last SLB entry inserted at slot %d\n", get_paca()->stab_rr); + + for (i = 0; i < mmu_slb_size; i++) { + e = slb_ptr->esid; + v = slb_ptr->vsid; + slb_ptr++; + + if (!e && !v) + continue; + + pr_err("%02d %016lx %016lx\n", i, e, v); + + if (!(e & SLB_ESID_V)) { + pr_err("\n"); + continue; + } + llp = v & SLB_VSID_LLP; + if (v & SLB_VSID_B_1T) { + pr_err(" 1T ESID=%9lx VSID=%13lx LLP:%3lx\n", + GET_ESID_1T(e), + (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, llp); + } else { + pr_err(" 256M ESID=%9lx VSID=%13lx LLP:%3lx\n", + GET_ESID(e), + (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT, llp); + } + } + pr_err("----------------------------------\n"); + + /* Dump slb cache entires as well. */ + pr_err("SLB cache ptr value = %d\n", get_paca()->slb_save_cache_ptr); + pr_err("Valid SLB cache entries:\n"); + n = min_t(int, get_paca()->slb_save_cache_ptr, SLB_CACHE_ENTRIES); + for (i = 0; i < n; i++) + pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]); + pr_err("Rest of SLB cache entries:\n"); + for (i = n; i < SLB_CACHE_ENTRIES; i++) + pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]); +} +void slb_vmalloc_update(void) +{ /* - * We can't take a PMU exception in the following code, so hard - * disable interrupts. + * vmalloc is not bolted, so just have to flush non-bolted. */ - hard_irq_disable(); + slb_flush_and_restore_bolted(); +} - __slb_flush_and_rebolt(); - get_paca()->slb_cache_ptr = 0; +static bool preload_hit(struct thread_info *ti, unsigned long esid) +{ + unsigned char i; + + for (i = 0; i < ti->slb_preload_nr; i++) { + unsigned char idx; + + idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR; + if (esid == ti->slb_preload_esid[idx]) + return true; + } + return false; } -void slb_vmalloc_update(void) +static bool preload_add(struct thread_info *ti, unsigned long ea) { - unsigned long vflags; + unsigned char idx; + unsigned long esid; + + if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) { + /* EAs are stored >> 28 so 256MB segments don't need clearing */ + if (ea & ESID_MASK_1T) + ea &= ESID_MASK_1T; + } + + esid = ea >> SID_SHIFT; - vflags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmalloc_psize].sllp; - slb_shadow_update(VMALLOC_START, mmu_kernel_ssize, vflags, VMALLOC_INDEX); - slb_flush_and_rebolt(); + if (preload_hit(ti, esid)) + return false; + + idx = (ti->slb_preload_tail + ti->slb_preload_nr) % SLB_PRELOAD_NR; + ti->slb_preload_esid[idx] = esid; + if (ti->slb_preload_nr == SLB_PRELOAD_NR) + ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR; + else + ti->slb_preload_nr++; + + return true; } -/* Helper function to compare esids. There are four cases to handle. - * 1. The system is not 1T segment size capable. Use the GET_ESID compare. - * 2. The system is 1T capable, both addresses are < 1T, use the GET_ESID compare. - * 3. The system is 1T capable, only one of the two addresses is > 1T. This is not a match. - * 4. The system is 1T capable, both addresses are > 1T, use the GET_ESID_1T macro to compare. - */ -static inline int esids_match(unsigned long addr1, unsigned long addr2) +static void preload_age(struct thread_info *ti) { - int esid_1t_count; + if (!ti->slb_preload_nr) + return; + ti->slb_preload_nr--; + ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR; +} - /* System is not 1T segment size capable. */ - if (!mmu_has_feature(MMU_FTR_1T_SEGMENT)) - return (GET_ESID(addr1) == GET_ESID(addr2)); +void slb_setup_new_exec(void) +{ + struct thread_info *ti = current_thread_info(); + struct mm_struct *mm = current->mm; + unsigned long exec = 0x10000000; - esid_1t_count = (((addr1 >> SID_SHIFT_1T) != 0) + - ((addr2 >> SID_SHIFT_1T) != 0)); + WARN_ON(irqs_disabled()); - /* both addresses are < 1T */ - if (esid_1t_count == 0) - return (GET_ESID(addr1) == GET_ESID(addr2)); + /* + * preload cache can only be used to determine whether a SLB + * entry exists if it does not start to overflow. + */ + if (ti->slb_preload_nr + 2 > SLB_PRELOAD_NR) + return; - /* One address < 1T, the other > 1T. Not a match */ - if (esid_1t_count == 1) - return 0; + hard_irq_disable(); - /* Both addresses are > 1T. */ - return (GET_ESID_1T(addr1) == GET_ESID_1T(addr2)); + /* + * We have no good place to clear the slb preload cache on exec, + * flush_thread is about the earliest arch hook but that happens + * after we switch to the mm and have aleady preloaded the SLBEs. + * + * For the most part that's probably okay to use entries from the + * previous exec, they will age out if unused. It may turn out to + * be an advantage to clear the cache before switching to it, + * however. + */ + + /* + * preload some userspace segments into the SLB. + * Almost all 32 and 64bit PowerPC executables are linked at + * 0x10000000 so it makes sense to preload this segment. + */ + if (!is_kernel_addr(exec)) { + if (preload_add(ti, exec)) + slb_allocate_user(mm, exec); + } + + /* Libraries and mmaps. */ + if (!is_kernel_addr(mm->mmap_base)) { + if (preload_add(ti, mm->mmap_base)) + slb_allocate_user(mm, mm->mmap_base); + } + + /* see switch_slb */ + asm volatile("isync" : : : "memory"); + + local_irq_enable(); } +void preload_new_slb_context(unsigned long start, unsigned long sp) +{ + struct thread_info *ti = current_thread_info(); + struct mm_struct *mm = current->mm; + unsigned long heap = mm->start_brk; + + WARN_ON(irqs_disabled()); + + /* see above */ + if (ti->slb_preload_nr + 3 > SLB_PRELOAD_NR) + return; + + hard_irq_disable(); + + /* Userspace entry address. */ + if (!is_kernel_addr(start)) { + if (preload_add(ti, start)) + slb_allocate_user(mm, start); + } + + /* Top of stack, grows down. */ + if (!is_kernel_addr(sp)) { + if (preload_add(ti, sp)) + slb_allocate_user(mm, sp); + } + + /* Bottom of heap, grows up. */ + if (heap && !is_kernel_addr(heap)) { + if (preload_add(ti, heap)) + slb_allocate_user(mm, heap); + } + + /* see switch_slb */ + asm volatile("isync" : : : "memory"); + + local_irq_enable(); +} + + /* Flush all user entries from the segment table of the current processor. */ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) { - unsigned long offset; - unsigned long slbie_data = 0; - unsigned long pc = KSTK_EIP(tsk); - unsigned long stack = KSTK_ESP(tsk); - unsigned long exec_base; + struct thread_info *ti = task_thread_info(tsk); + unsigned char i; /* * We need interrupts hard-disabled here, not just soft-disabled, @@ -238,91 +421,107 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) * which would update the slb_cache/slb_cache_ptr fields in the PACA. */ hard_irq_disable(); - offset = get_paca()->slb_cache_ptr; - if (!mmu_has_feature(MMU_FTR_NO_SLBIE_B) && - offset <= SLB_CACHE_ENTRIES) { - int i; - asm volatile("isync" : : : "memory"); - for (i = 0; i < offset; i++) { - slbie_data = (unsigned long)get_paca()->slb_cache[i] - << SID_SHIFT; /* EA */ - slbie_data |= user_segment_size(slbie_data) - << SLBIE_SSIZE_SHIFT; - slbie_data |= SLBIE_C; /* C set for user addresses */ - asm volatile("slbie %0" : : "r" (slbie_data)); - } - asm volatile("isync" : : : "memory"); + asm volatile("isync" : : : "memory"); + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + /* + * SLBIA IH=3 invalidates all Class=1 SLBEs and their + * associated lookaside structures, which matches what + * switch_slb wants. So ARCH_300 does not use the slb + * cache. + */ + asm volatile(PPC_SLBIA(3)); } else { - __slb_flush_and_rebolt(); - } + unsigned long offset = get_paca()->slb_cache_ptr; + + if (!mmu_has_feature(MMU_FTR_NO_SLBIE_B) && + offset <= SLB_CACHE_ENTRIES) { + unsigned long slbie_data = 0; + + for (i = 0; i < offset; i++) { + unsigned long ea; + + ea = (unsigned long) + get_paca()->slb_cache[i] << SID_SHIFT; + /* + * Could assert_slb_exists here, but hypervisor + * or machine check could have come in and + * removed the entry at this point. + */ + + slbie_data = ea; + slbie_data |= user_segment_size(slbie_data) + << SLBIE_SSIZE_SHIFT; + slbie_data |= SLBIE_C; /* user slbs have C=1 */ + asm volatile("slbie %0" : : "r" (slbie_data)); + } + + /* Workaround POWER5 < DD2.1 issue */ + if (!cpu_has_feature(CPU_FTR_ARCH_207S) && offset == 1) + asm volatile("slbie %0" : : "r" (slbie_data)); + + } else { + struct slb_shadow *p = get_slb_shadow(); + unsigned long ksp_esid_data = + be64_to_cpu(p->save_area[KSTACK_INDEX].esid); + unsigned long ksp_vsid_data = + be64_to_cpu(p->save_area[KSTACK_INDEX].vsid); + + asm volatile(PPC_SLBIA(1) "\n" + "slbmte %0,%1\n" + "isync" + :: "r"(ksp_vsid_data), + "r"(ksp_esid_data)); + + get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; + } - /* Workaround POWER5 < DD2.1 issue */ - if (offset == 1 || offset > SLB_CACHE_ENTRIES) - asm volatile("slbie %0" : : "r" (slbie_data)); + get_paca()->slb_cache_ptr = 0; + } + get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; - get_paca()->slb_cache_ptr = 0; copy_mm_to_paca(mm); /* - * preload some userspace segments into the SLB. - * Almost all 32 and 64bit PowerPC executables are linked at - * 0x10000000 so it makes sense to preload this segment. + * We gradually age out SLBs after a number of context switches to + * reduce reload overhead of unused entries (like we do with FP/VEC + * reload). Each time we wrap 256 switches, take an entry out of the + * SLB preload cache. */ - exec_base = 0x10000000; - - if (is_kernel_addr(pc) || is_kernel_addr(stack) || - is_kernel_addr(exec_base)) - return; + tsk->thread.load_slb++; + if (!tsk->thread.load_slb) { + unsigned long pc = KSTK_EIP(tsk); - slb_allocate(pc); + preload_age(ti); + preload_add(ti, pc); + } - if (!esids_match(pc, stack)) - slb_allocate(stack); + for (i = 0; i < ti->slb_preload_nr; i++) { + unsigned char idx; + unsigned long ea; - if (!esids_match(pc, exec_base) && - !esids_match(stack, exec_base)) - slb_allocate(exec_base); -} + idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR; + ea = (unsigned long)ti->slb_preload_esid[idx] << SID_SHIFT; -static inline void patch_slb_encoding(unsigned int *insn_addr, - unsigned int immed) -{ + slb_allocate_user(mm, ea); + } /* - * This function patches either an li or a cmpldi instruction with - * a new immediate value. This relies on the fact that both li - * (which is actually addi) and cmpldi both take a 16-bit immediate - * value, and it is situated in the same location in the instruction, - * ie. bits 16-31 (Big endian bit order) or the lower 16 bits. - * The signedness of the immediate operand differs between the two - * instructions however this code is only ever patching a small value, - * much less than 1 << 15, so we can get away with it. - * To patch the value we read the existing instruction, clear the - * immediate value, and or in our new value, then write the instruction - * back. + * Synchronize slbmte preloads with possible subsequent user memory + * address accesses by the kernel (user mode won't happen until + * rfid, which is safe). */ - unsigned int insn = (*insn_addr & 0xffff0000) | immed; - patch_instruction(insn_addr, insn); + asm volatile("isync" : : : "memory"); } -extern u32 slb_miss_kernel_load_linear[]; -extern u32 slb_miss_kernel_load_io[]; -extern u32 slb_compare_rr_to_size[]; -extern u32 slb_miss_kernel_load_vmemmap[]; - void slb_set_size(u16 size) { - if (mmu_slb_size == size) - return; - mmu_slb_size = size; - patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size); } void slb_initialize(void) { unsigned long linear_llp, vmalloc_llp, io_llp; - unsigned long lflags, vflags; + unsigned long lflags; static int slb_encoding_inited; #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long vmemmap_llp; @@ -338,34 +537,24 @@ void slb_initialize(void) #endif if (!slb_encoding_inited) { slb_encoding_inited = 1; - patch_slb_encoding(slb_miss_kernel_load_linear, - SLB_VSID_KERNEL | linear_llp); - patch_slb_encoding(slb_miss_kernel_load_io, - SLB_VSID_KERNEL | io_llp); - patch_slb_encoding(slb_compare_rr_to_size, - mmu_slb_size); - pr_devel("SLB: linear LLP = %04lx\n", linear_llp); pr_devel("SLB: io LLP = %04lx\n", io_llp); - #ifdef CONFIG_SPARSEMEM_VMEMMAP - patch_slb_encoding(slb_miss_kernel_load_vmemmap, - SLB_VSID_KERNEL | vmemmap_llp); pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); #endif } - get_paca()->stab_rr = SLB_NUM_BOLTED; + get_paca()->stab_rr = SLB_NUM_BOLTED - 1; + get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; + get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | vmalloc_llp; /* Invalidate the entire SLB (even entry 0) & all the ERATS */ asm volatile("isync":::"memory"); asm volatile("slbmte %0,%0"::"r" (0) : "memory"); asm volatile("isync; slbia; isync":::"memory"); create_shadowed_slbe(PAGE_OFFSET, mmu_kernel_ssize, lflags, LINEAR_INDEX); - create_shadowed_slbe(VMALLOC_START, mmu_kernel_ssize, vflags, VMALLOC_INDEX); /* For the boot cpu, we're running on the stack in init_thread_union, * which is in the first segment of the linear mapping, and also @@ -381,122 +570,259 @@ void slb_initialize(void) asm volatile("isync":::"memory"); } -static void insert_slb_entry(unsigned long vsid, unsigned long ea, - int bpsize, int ssize) +static void slb_cache_update(unsigned long esid_data) { - unsigned long flags, vsid_data, esid_data; - enum slb_index index; int slb_cache_index; - /* - * We are irq disabled, hence should be safe to access PACA. - */ - VM_WARN_ON(!irqs_disabled()); - - /* - * We can't take a PMU exception in the following code, so hard - * disable interrupts. - */ - hard_irq_disable(); - - index = get_paca()->stab_rr; - - /* - * simple round-robin replacement of slb starting at SLB_NUM_BOLTED. - */ - if (index < (mmu_slb_size - 1)) - index++; - else - index = SLB_NUM_BOLTED; - - get_paca()->stab_rr = index; - - flags = SLB_VSID_USER | mmu_psize_defs[bpsize].sllp; - vsid_data = (vsid << slb_vsid_shift(ssize)) | flags | - ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); - esid_data = mk_esid_data(ea, ssize, index); - - /* - * No need for an isync before or after this slbmte. The exception - * we enter with and the rfid we exit with are context synchronizing. - * Also we only handle user segments here. - */ - asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data) - : "memory"); + if (cpu_has_feature(CPU_FTR_ARCH_300)) + return; /* ISAv3.0B and later does not use slb_cache */ /* * Now update slb cache entries */ - slb_cache_index = get_paca()->slb_cache_ptr; + slb_cache_index = local_paca->slb_cache_ptr; if (slb_cache_index < SLB_CACHE_ENTRIES) { /* * We have space in slb cache for optimized switch_slb(). * Top 36 bits from esid_data as per ISA */ - get_paca()->slb_cache[slb_cache_index++] = esid_data >> 28; - get_paca()->slb_cache_ptr++; + local_paca->slb_cache[slb_cache_index++] = esid_data >> 28; + local_paca->slb_cache_ptr++; } else { /* * Our cache is full and the current cache content strictly * doesn't indicate the active SLB conents. Bump the ptr * so that switch_slb() will ignore the cache. */ - get_paca()->slb_cache_ptr = SLB_CACHE_ENTRIES + 1; + local_paca->slb_cache_ptr = SLB_CACHE_ENTRIES + 1; } } -static void handle_multi_context_slb_miss(int context_id, unsigned long ea) +static enum slb_index alloc_slb_index(bool kernel) { - struct mm_struct *mm = current->mm; - unsigned long vsid; - int bpsize; + enum slb_index index; /* - * We are always above 1TB, hence use high user segment size. + * The allocation bitmaps can become out of synch with the SLB + * when the _switch code does slbie when bolting a new stack + * segment and it must not be anywhere else in the SLB. This leaves + * a kernel allocated entry that is unused in the SLB. With very + * large systems or small segment sizes, the bitmaps could slowly + * fill with these entries. They will eventually be cleared out + * by the round robin allocator in that case, so it's probably not + * worth accounting for. */ - vsid = get_vsid(context_id, ea, mmu_highuser_ssize); - bpsize = get_slice_psize(mm, ea); - insert_slb_entry(vsid, ea, bpsize, mmu_highuser_ssize); + + /* + * SLBs beyond 32 entries are allocated with stab_rr only + * POWER7/8/9 have 32 SLB entries, this could be expanded if a + * future CPU has more. + */ + if (local_paca->slb_used_bitmap != U32_MAX) { + index = ffz(local_paca->slb_used_bitmap); + local_paca->slb_used_bitmap |= 1U << index; + if (kernel) + local_paca->slb_kern_bitmap |= 1U << index; + } else { + /* round-robin replacement of slb starting at SLB_NUM_BOLTED. */ + index = local_paca->stab_rr; + if (index < (mmu_slb_size - 1)) + index++; + else + index = SLB_NUM_BOLTED; + local_paca->stab_rr = index; + if (index < 32) { + if (kernel) + local_paca->slb_kern_bitmap |= 1U << index; + else + local_paca->slb_kern_bitmap &= ~(1U << index); + } + } + BUG_ON(index < SLB_NUM_BOLTED); + + return index; } -void slb_miss_large_addr(struct pt_regs *regs) +static long slb_insert_entry(unsigned long ea, unsigned long context, + unsigned long flags, int ssize, bool kernel) { - enum ctx_state prev_state = exception_enter(); - unsigned long ea = regs->dar; - int context; + unsigned long vsid; + unsigned long vsid_data, esid_data; + enum slb_index index; - if (REGION_ID(ea) != USER_REGION_ID) - goto slb_bad_addr; + vsid = get_vsid(context, ea, ssize); + if (!vsid) + return -EFAULT; /* - * Are we beyound what the page table layout supports ? + * There must not be a kernel SLB fault in alloc_slb_index or before + * slbmte here or the allocation bitmaps could get out of whack with + * the SLB. + * + * User SLB faults or preloads take this path which might get inlined + * into the caller, so add compiler barriers here to ensure unsafe + * memory accesses do not come between. */ - if ((ea & ~REGION_MASK) >= H_PGTABLE_RANGE) - goto slb_bad_addr; + barrier(); - /* Lower address should have been handled by asm code */ - if (ea < (1UL << MAX_EA_BITS_PER_CONTEXT)) - goto slb_bad_addr; + index = alloc_slb_index(kernel); + + vsid_data = __mk_vsid_data(vsid, ssize, flags); + esid_data = mk_esid_data(ea, ssize, index); + + /* + * No need for an isync before or after this slbmte. The exception + * we enter with and the rfid we exit with are context synchronizing. + * User preloads should add isync afterwards in case the kernel + * accesses user memory before it returns to userspace with rfid. + */ + assert_slb_notexists(ea); + asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data)); + + barrier(); + + if (!kernel) + slb_cache_update(esid_data); + + return 0; +} + +static long slb_allocate_kernel(unsigned long ea, unsigned long id) +{ + unsigned long context; + unsigned long flags; + int ssize; + + if (id == KERNEL_REGION_ID) { + + /* We only support upto MAX_PHYSMEM_BITS */ + if ((ea & ~REGION_MASK) > (1UL << MAX_PHYSMEM_BITS)) + return -EFAULT; + + flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_linear_psize].sllp; + +#ifdef CONFIG_SPARSEMEM_VMEMMAP + } else if (id == VMEMMAP_REGION_ID) { + + if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT)) + return -EFAULT; + + flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmemmap_psize].sllp; +#endif + } else if (id == VMALLOC_REGION_ID) { + + if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT)) + return -EFAULT; + + if (ea < H_VMALLOC_END) + flags = get_paca()->vmalloc_sllp; + else + flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp; + } else { + return -EFAULT; + } + + ssize = MMU_SEGSIZE_1T; + if (!mmu_has_feature(MMU_FTR_1T_SEGMENT)) + ssize = MMU_SEGSIZE_256M; + + context = get_kernel_context(ea); + return slb_insert_entry(ea, context, flags, ssize, true); +} + +static long slb_allocate_user(struct mm_struct *mm, unsigned long ea) +{ + unsigned long context; + unsigned long flags; + int bpsize; + int ssize; /* * consider this as bad access if we take a SLB miss * on an address above addr limit. */ - if (ea >= current->mm->context.slb_addr_limit) - goto slb_bad_addr; + if (ea >= mm->context.slb_addr_limit) + return -EFAULT; - context = get_ea_context(¤t->mm->context, ea); + context = get_user_context(&mm->context, ea); if (!context) - goto slb_bad_addr; + return -EFAULT; + + if (unlikely(ea >= H_PGTABLE_RANGE)) { + WARN_ON(1); + return -EFAULT; + } - handle_multi_context_slb_miss(context, ea); - exception_exit(prev_state); - return; + ssize = user_segment_size(ea); -slb_bad_addr: - if (user_mode(regs)) - _exception(SIGSEGV, regs, SEGV_BNDERR, ea); - else - bad_page_fault(regs, ea, SIGSEGV); - exception_exit(prev_state); + bpsize = get_slice_psize(mm, ea); + flags = SLB_VSID_USER | mmu_psize_defs[bpsize].sllp; + + return slb_insert_entry(ea, context, flags, ssize, false); +} + +long do_slb_fault(struct pt_regs *regs, unsigned long ea) +{ + unsigned long id = REGION_ID(ea); + + /* IRQs are not reconciled here, so can't check irqs_disabled */ + VM_WARN_ON(mfmsr() & MSR_EE); + + if (unlikely(!(regs->msr & MSR_RI))) + return -EINVAL; + + /* + * SLB kernel faults must be very careful not to touch anything + * that is not bolted. E.g., PACA and global variables are okay, + * mm->context stuff is not. + * + * SLB user faults can access all of kernel memory, but must be + * careful not to touch things like IRQ state because it is not + * "reconciled" here. The difficulty is that we must use + * fast_exception_return to return from kernel SLB faults without + * looking at possible non-bolted memory. We could test user vs + * kernel faults in the interrupt handler asm and do a full fault, + * reconcile, ret_from_except for user faults which would make them + * first class kernel code. But for performance it's probably nicer + * if they go via fast_exception_return too. + */ + if (id >= KERNEL_REGION_ID) { + long err; +#ifdef CONFIG_DEBUG_VM + /* Catch recursive kernel SLB faults. */ + BUG_ON(local_paca->in_kernel_slb_handler); + local_paca->in_kernel_slb_handler = 1; +#endif + err = slb_allocate_kernel(ea, id); +#ifdef CONFIG_DEBUG_VM + local_paca->in_kernel_slb_handler = 0; +#endif + return err; + } else { + struct mm_struct *mm = current->mm; + long err; + + if (unlikely(!mm)) + return -EFAULT; + + err = slb_allocate_user(mm, ea); + if (!err) + preload_add(current_thread_info(), ea); + + return err; + } +} + +void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err) +{ + if (err == -EFAULT) { + if (user_mode(regs)) + _exception(SIGSEGV, regs, SEGV_BNDERR, ea); + else + bad_page_fault(regs, ea, SIGSEGV); + } else if (err == -EINVAL) { + unrecoverable_exception(regs); + } else { + BUG(); + } } diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S deleted file mode 100644 index 4ac5057ad439..000000000000 --- a/arch/powerpc/mm/slb_low.S +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Low-level SLB routines - * - * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM - * - * Based on earlier C version: - * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com - * Copyright (c) 2001 Dave Engebretsen - * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <asm/processor.h> -#include <asm/ppc_asm.h> -#include <asm/asm-offsets.h> -#include <asm/cputable.h> -#include <asm/page.h> -#include <asm/mmu.h> -#include <asm/pgtable.h> -#include <asm/firmware.h> -#include <asm/feature-fixups.h> - -/* - * This macro generates asm code to compute the VSID scramble - * function. Used in slb_allocate() and do_stab_bolted. The function - * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS - * - * rt = register containing the proto-VSID and into which the - * VSID will be stored - * rx = scratch register (clobbered) - * rf = flags - * - * - rt and rx must be different registers - * - The answer will end up in the low VSID_BITS bits of rt. The higher - * bits may contain other garbage, so you may need to mask the - * result. - */ -#define ASM_VSID_SCRAMBLE(rt, rx, rf, size) \ - lis rx,VSID_MULTIPLIER_##size@h; \ - ori rx,rx,VSID_MULTIPLIER_##size@l; \ - mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \ -/* \ - * powermac get slb fault before feature fixup, so make 65 bit part \ - * the default part of feature fixup \ - */ \ -BEGIN_MMU_FTR_SECTION \ - srdi rx,rt,VSID_BITS_65_##size; \ - clrldi rt,rt,(64-VSID_BITS_65_##size); \ - add rt,rt,rx; \ - addi rx,rt,1; \ - srdi rx,rx,VSID_BITS_65_##size; \ - add rt,rt,rx; \ - rldimi rf,rt,SLB_VSID_SHIFT_##size,(64 - (SLB_VSID_SHIFT_##size + VSID_BITS_65_##size)); \ -MMU_FTR_SECTION_ELSE \ - srdi rx,rt,VSID_BITS_##size; \ - clrldi rt,rt,(64-VSID_BITS_##size); \ - add rt,rt,rx; /* add high and low bits */ \ - addi rx,rt,1; \ - srdi rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */ \ - add rt,rt,rx; \ - rldimi rf,rt,SLB_VSID_SHIFT_##size,(64 - (SLB_VSID_SHIFT_##size + VSID_BITS_##size)); \ -ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_68_BIT_VA) - - -/* void slb_allocate(unsigned long ea); - * - * Create an SLB entry for the given EA (user or kernel). - * r3 = faulting address, r13 = PACA - * r9, r10, r11 are clobbered by this function - * r3 is preserved. - * No other registers are examined or changed. - */ -_GLOBAL(slb_allocate) - /* - * Check if the address falls within the range of the first context, or - * if we may need to handle multi context. For the first context we - * allocate the slb entry via the fast path below. For large address we - * branch out to C-code and see if additional contexts have been - * allocated. - * The test here is: - * (ea & ~REGION_MASK) >= (1ull << MAX_EA_BITS_PER_CONTEXT) - */ - rldicr. r9,r3,4,(63 - MAX_EA_BITS_PER_CONTEXT - 4) - bne- 8f - - srdi r9,r3,60 /* get region */ - srdi r10,r3,SID_SHIFT /* get esid */ - cmpldi cr7,r9,0xc /* cmp PAGE_OFFSET for later use */ - - /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */ - blt cr7,0f /* user or kernel? */ - - /* Check if hitting the linear mapping or some other kernel space - */ - bne cr7,1f - - /* Linear mapping encoding bits, the "li" instruction below will - * be patched by the kernel at boot - */ -.globl slb_miss_kernel_load_linear -slb_miss_kernel_load_linear: - li r11,0 - /* - * context = (ea >> 60) - (0xc - 1) - * r9 = region id. - */ - subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET - -BEGIN_FTR_SECTION - b .Lslb_finish_load -END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) - b .Lslb_finish_load_1T - -1: -#ifdef CONFIG_SPARSEMEM_VMEMMAP - cmpldi cr0,r9,0xf - bne 1f -/* Check virtual memmap region. To be patched at kernel boot */ -.globl slb_miss_kernel_load_vmemmap -slb_miss_kernel_load_vmemmap: - li r11,0 - b 6f -1: -#endif /* CONFIG_SPARSEMEM_VMEMMAP */ - - /* - * r10 contains the ESID, which is the original faulting EA shifted - * right by 28 bits. We need to compare that with (H_VMALLOC_END >> 28) - * which is 0xd00038000. That can't be used as an immediate, even if we - * ignored the 0xd, so we have to load it into a register, and we only - * have one register free. So we must load all of (H_VMALLOC_END >> 28) - * into a register and compare ESID against that. - */ - lis r11,(H_VMALLOC_END >> 32)@h // r11 = 0xffffffffd0000000 - ori r11,r11,(H_VMALLOC_END >> 32)@l // r11 = 0xffffffffd0003800 - // Rotate left 4, then mask with 0xffffffff0 - rldic r11,r11,4,28 // r11 = 0xd00038000 - cmpld r10,r11 // if r10 >= r11 - bge 5f // goto io_mapping - - /* - * vmalloc mapping gets the encoding from the PACA as the mapping - * can be demoted from 64K -> 4K dynamically on some machines. - */ - lhz r11,PACAVMALLOCSLLP(r13) - b 6f -5: - /* IO mapping */ -.globl slb_miss_kernel_load_io -slb_miss_kernel_load_io: - li r11,0 -6: - /* - * context = (ea >> 60) - (0xc - 1) - * r9 = region id. - */ - subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET - -BEGIN_FTR_SECTION - b .Lslb_finish_load -END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) - b .Lslb_finish_load_1T - -0: /* - * For userspace addresses, make sure this is region 0. - */ - cmpdi r9, 0 - bne- 8f - /* - * user space make sure we are within the allowed limit - */ - ld r11,PACA_SLB_ADDR_LIMIT(r13) - cmpld r3,r11 - bge- 8f - - /* when using slices, we extract the psize off the slice bitmaps - * and then we need to get the sllp encoding off the mmu_psize_defs - * array. - * - * XXX This is a bit inefficient especially for the normal case, - * so we should try to implement a fast path for the standard page - * size using the old sllp value so we avoid the array. We cannot - * really do dynamic patching unfortunately as processes might flip - * between 4k and 64k standard page size - */ -#ifdef CONFIG_PPC_MM_SLICES - /* r10 have esid */ - cmpldi r10,16 - /* below SLICE_LOW_TOP */ - blt 5f - /* - * Handle hpsizes, - * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index - */ - srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */ - addi r9,r11,PACAHIGHSLICEPSIZE - lbzx r9,r13,r9 /* r9 is hpsizes[r11] */ - /* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */ - rldicl r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63 - b 6f - -5: - /* - * Handle lpsizes - * r9 is get_paca()->context.low_slices_psize[index], r11 is mask_index - */ - srdi r11,r10,1 /* index */ - addi r9,r11,PACALOWSLICESPSIZE - lbzx r9,r13,r9 /* r9 is lpsizes[r11] */ - rldicl r11,r10,0,63 /* r11 = r10 & 0x1 */ -6: - sldi r11,r11,2 /* index * 4 */ - /* Extract the psize and multiply to get an array offset */ - srd r9,r9,r11 - andi. r9,r9,0xf - mulli r9,r9,MMUPSIZEDEFSIZE - - /* Now get to the array and obtain the sllp - */ - ld r11,PACATOC(r13) - ld r11,mmu_psize_defs@got(r11) - add r11,r11,r9 - ld r11,MMUPSIZESLLP(r11) - ori r11,r11,SLB_VSID_USER -#else - /* paca context sllp already contains the SLB_VSID_USER bits */ - lhz r11,PACACONTEXTSLLP(r13) -#endif /* CONFIG_PPC_MM_SLICES */ - - ld r9,PACACONTEXTID(r13) -BEGIN_FTR_SECTION - cmpldi r10,0x1000 - bge .Lslb_finish_load_1T -END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) - b .Lslb_finish_load - -8: /* invalid EA - return an error indication */ - crset 4*cr0+eq /* indicate failure */ - blr - -/* - * Finish loading of an SLB entry and return - * - * r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET - */ -.Lslb_finish_load: - rldimi r10,r9,ESID_BITS,0 - ASM_VSID_SCRAMBLE(r10,r9,r11,256M) - /* r3 = EA, r11 = VSID data */ - /* - * Find a slot, round robin. Previously we tried to find a - * free slot first but that took too long. Unfortunately we - * dont have any LRU information to help us choose a slot. - */ - - mr r9,r3 - - /* slb_finish_load_1T continues here. r9=EA with non-ESID bits clear */ -7: ld r10,PACASTABRR(r13) - addi r10,r10,1 - /* This gets soft patched on boot. */ -.globl slb_compare_rr_to_size -slb_compare_rr_to_size: - cmpldi r10,0 - - blt+ 4f - li r10,SLB_NUM_BOLTED - -4: - std r10,PACASTABRR(r13) - -3: - rldimi r9,r10,0,36 /* r9 = EA[0:35] | entry */ - oris r10,r9,SLB_ESID_V@h /* r10 = r9 | SLB_ESID_V */ - - /* r9 = ESID data, r11 = VSID data */ - - /* - * No need for an isync before or after this slbmte. The exception - * we enter with and the rfid we exit with are context synchronizing. - */ - slbmte r11,r10 - - /* we're done for kernel addresses */ - crclr 4*cr0+eq /* set result to "success" */ - bgelr cr7 - - /* Update the slb cache */ - lhz r9,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */ - cmpldi r9,SLB_CACHE_ENTRIES - bge 1f - - /* still room in the slb cache */ - sldi r11,r9,2 /* r11 = offset * sizeof(u32) */ - srdi r10,r10,28 /* get the 36 bits of the ESID */ - add r11,r11,r13 /* r11 = (u32 *)paca + offset */ - stw r10,PACASLBCACHE(r11) /* paca->slb_cache[offset] = esid */ - addi r9,r9,1 /* offset++ */ - b 2f -1: /* offset >= SLB_CACHE_ENTRIES */ - li r9,SLB_CACHE_ENTRIES+1 -2: - sth r9,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */ - crclr 4*cr0+eq /* set result to "success" */ - blr - -/* - * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return. - * - * r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9 - */ -.Lslb_finish_load_1T: - srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */ - rldimi r10,r9,ESID_BITS_1T,0 - ASM_VSID_SCRAMBLE(r10,r9,r11,1T) - - li r10,MMU_SEGSIZE_1T - rldimi r11,r10,SLB_VSID_SSIZE_SHIFT,0 /* insert segment size */ - - /* r3 = EA, r11 = VSID data */ - clrrdi r9,r3,SID_SHIFT_1T /* clear out non-ESID bits */ - b 7b - - -_ASM_NOKPROBE_SYMBOL(slb_allocate) -_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_linear) -_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_io) -_ASM_NOKPROBE_SYMBOL(slb_compare_rr_to_size) -#ifdef CONFIG_SPARSEMEM_VMEMMAP -_ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_vmemmap) -#endif diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 205fe557ca10..06898c13901d 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -31,6 +31,7 @@ #include <linux/spinlock.h> #include <linux/export.h> #include <linux/hugetlb.h> +#include <linux/sched/mm.h> #include <asm/mman.h> #include <asm/mmu.h> #include <asm/copro.h> @@ -61,6 +62,13 @@ static void slice_print_mask(const char *label, const struct slice_mask *mask) { #endif +static inline bool slice_addr_is_low(unsigned long addr) +{ + u64 tmp = (u64)addr; + + return tmp < SLICE_LOW_TOP; +} + static void slice_range_to_mask(unsigned long start, unsigned long len, struct slice_mask *ret) { @@ -70,7 +78,7 @@ static void slice_range_to_mask(unsigned long start, unsigned long len, if (SLICE_NUM_HIGH) bitmap_zero(ret->high_slices, SLICE_NUM_HIGH); - if (start < SLICE_LOW_TOP) { + if (slice_addr_is_low(start)) { unsigned long mend = min(end, (unsigned long)(SLICE_LOW_TOP - 1)); @@ -78,7 +86,7 @@ static void slice_range_to_mask(unsigned long start, unsigned long len, - (1u << GET_LOW_SLICE_INDEX(start)); } - if ((start + len) > SLICE_LOW_TOP) { + if (SLICE_NUM_HIGH && !slice_addr_is_low(end)) { unsigned long start_index = GET_HIGH_SLICE_INDEX(start); unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; @@ -133,7 +141,7 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret, if (!slice_low_has_vma(mm, i)) ret->low_slices |= 1u << i; - if (high_limit <= SLICE_LOW_TOP) + if (slice_addr_is_low(high_limit - 1)) return; for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) @@ -182,7 +190,7 @@ static bool slice_check_range_fits(struct mm_struct *mm, unsigned long end = start + len - 1; u64 low_slices = 0; - if (start < SLICE_LOW_TOP) { + if (slice_addr_is_low(start)) { unsigned long mend = min(end, (unsigned long)(SLICE_LOW_TOP - 1)); @@ -192,7 +200,7 @@ static bool slice_check_range_fits(struct mm_struct *mm, if ((low_slices & available->low_slices) != low_slices) return false; - if (SLICE_NUM_HIGH && ((start + len) > SLICE_LOW_TOP)) { + if (SLICE_NUM_HIGH && !slice_addr_is_low(end)) { unsigned long start_index = GET_HIGH_SLICE_INDEX(start); unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; @@ -219,7 +227,7 @@ static void slice_flush_segments(void *parm) copy_mm_to_paca(current->active_mm); local_irq_save(flags); - slb_flush_and_rebolt(); + slb_flush_and_restore_bolted(); local_irq_restore(flags); #endif } @@ -303,7 +311,7 @@ static bool slice_scan_available(unsigned long addr, int end, unsigned long *boundary_addr) { unsigned long slice; - if (addr < SLICE_LOW_TOP) { + if (slice_addr_is_low(addr)) { slice = GET_LOW_SLICE_INDEX(addr); *boundary_addr = (slice + end) << SLICE_LOW_SHIFT; return !!(available->low_slices & (1u << slice)); @@ -706,7 +714,7 @@ unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) VM_BUG_ON(radix_enabled()); - if (addr < SLICE_LOW_TOP) { + if (slice_addr_is_low(addr)) { psizes = mm->context.low_slices_psize; index = GET_LOW_SLICE_INDEX(addr); } else { @@ -757,6 +765,20 @@ void slice_init_new_context_exec(struct mm_struct *mm) bitmap_fill(mask->high_slices, SLICE_NUM_HIGH); } +#ifdef CONFIG_PPC_BOOK3S_64 +void slice_setup_new_exec(void) +{ + struct mm_struct *mm = current->mm; + + slice_dbg("slice_setup_new_exec(mm=%p)\n", mm); + + if (!is_32bit_task()) + return; + + mm->context.slb_addr_limit = DEFAULT_MAP_WINDOW; +} +#endif + void slice_set_range_psize(struct mm_struct *mm, unsigned long start, unsigned long len, unsigned int psize) { diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index fef3e1eb3a19..6a23b9ebd2a1 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c @@ -366,6 +366,7 @@ static inline void _tlbiel_lpid_guest(unsigned long lpid, unsigned long ric) __tlbiel_lpid_guest(lpid, set, RIC_FLUSH_TLB); asm volatile("ptesync": : :"memory"); + asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); } @@ -833,6 +834,15 @@ EXPORT_SYMBOL_GPL(radix__flush_pwc_lpid); /* * Flush partition scoped translations from LPID (=LPIDR) */ +void radix__flush_tlb_lpid(unsigned int lpid) +{ + _tlbie_lpid(lpid, RIC_FLUSH_ALL); +} +EXPORT_SYMBOL_GPL(radix__flush_tlb_lpid); + +/* + * Flush partition scoped translations from LPID (=LPIDR) + */ void radix__local_flush_tlb_lpid(unsigned int lpid) { _tlbiel_lpid(lpid, RIC_FLUSH_ALL); @@ -1007,7 +1017,6 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) goto local; } _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); - goto local; } else { local: _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 15fe5f0c8665..ae5d568e267f 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -503,6 +503,9 @@ static void setup_page_sizes(void) for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { struct mmu_psize_def *def = &mmu_psize_defs[psize]; + if (!def->shift) + continue; + if (tlb1ps & (1U << (def->shift - 10))) { def->flags |= MMU_PAGE_SIZE_DIRECT; diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 7a7834c39f64..8d26d7416481 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c index ad054dd0d666..5df6290d1ccc 100644 --- a/arch/powerpc/oprofile/backtrace.c +++ b/arch/powerpc/oprofile/backtrace.c @@ -7,7 +7,7 @@ * 2 of the License, or (at your option) any later version. **/ -#include <linux/compat_time.h> +#include <linux/time.h> #include <linux/oprofile.h> #include <linux/sched.h> #include <asm/processor.h> diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index 82986d2acd9b..ab26df5bacb9 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index 1fafc32b12a0..6954636b16d1 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c @@ -1392,7 +1392,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id if (ret) goto err_free_cpuhp_mem; - pr_info("%s performance monitor hardware support registered\n", + pr_debug("%s performance monitor hardware support registered\n", pmu_ptr->pmu.name); return 0; diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 7963658dbc22..6dbae9884ec4 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c @@ -238,6 +238,7 @@ static int power7_marked_instr_event(u64 event) case 6: if (psel == 0x64) return pmc >= 3; + break; case 8: return unit == 0xd; } diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 60254a321a91..2a9d66254ffc 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig @@ -2,7 +2,6 @@ config ACADIA bool "Acadia" depends on 40x - default n select PPC40x_SIMPLE select 405EZ help @@ -11,7 +10,6 @@ config ACADIA config EP405 bool "EP405/EP405PC" depends on 40x - default n select 405GP select PCI help @@ -20,7 +18,6 @@ config EP405 config HOTFOOT bool "Hotfoot" depends on 40x - default n select PPC40x_SIMPLE select PCI help @@ -29,7 +26,6 @@ config HOTFOOT config KILAUEA bool "Kilauea" depends on 40x - default n select 405EX select PPC40x_SIMPLE select PPC4xx_PCI_EXPRESS @@ -41,7 +37,6 @@ config KILAUEA config MAKALU bool "Makalu" depends on 40x - default n select 405EX select PCI select PPC4xx_PCI_EXPRESS @@ -62,7 +57,6 @@ config WALNUT config XILINX_VIRTEX_GENERIC_BOARD bool "Generic Xilinx Virtex board" depends on 40x - default n select XILINX_VIRTEX_II_PRO select XILINX_VIRTEX_4_FX select XILINX_INTC @@ -80,7 +74,6 @@ config XILINX_VIRTEX_GENERIC_BOARD config OBS600 bool "OpenBlockS 600" depends on 40x - default n select 405EX select PPC40x_SIMPLE help @@ -90,7 +83,6 @@ config OBS600 config PPC40x_SIMPLE bool "Simple PowerPC 40x board support" depends on 40x - default n help This option enables the simple PowerPC 40x platform support. @@ -156,7 +148,6 @@ config IBM405_ERR51 config APM8018X bool "APM8018X" depends on 40x - default n select PPC40x_SIMPLE help This option enables support for the AppliedMicro APM8018X evaluation diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index a6011422b861..f024efd5a4c2 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -2,7 +2,6 @@ config PPC_47x bool "Support for 47x variant" depends on 44x - default n select MPIC help This option enables support for the 47x family of processors and is @@ -11,7 +10,6 @@ config PPC_47x config BAMBOO bool "Bamboo" depends on 44x - default n select PPC44x_SIMPLE select 440EP select PCI @@ -21,7 +19,6 @@ config BAMBOO config BLUESTONE bool "Bluestone" depends on 44x - default n select PPC44x_SIMPLE select APM821xx select PCI_MSI @@ -44,7 +41,6 @@ config EBONY config SAM440EP bool "Sam440ep" depends on 44x - default n select 440EP select PCI help @@ -53,7 +49,6 @@ config SAM440EP config SEQUOIA bool "Sequoia" depends on 44x - default n select PPC44x_SIMPLE select 440EPX help @@ -62,7 +57,6 @@ config SEQUOIA config TAISHAN bool "Taishan" depends on 44x - default n select PPC44x_SIMPLE select 440GX select PCI @@ -73,7 +67,6 @@ config TAISHAN config KATMAI bool "Katmai" depends on 44x - default n select PPC44x_SIMPLE select 440SPe select PCI @@ -86,7 +79,6 @@ config KATMAI config RAINIER bool "Rainier" depends on 44x - default n select PPC44x_SIMPLE select 440GRX select PCI @@ -96,7 +88,6 @@ config RAINIER config WARP bool "PIKA Warp" depends on 44x - default n select 440EP help This option enables support for the PIKA Warp(tm) Appliance. The Warp @@ -109,7 +100,6 @@ config WARP config ARCHES bool "Arches" depends on 44x - default n select PPC44x_SIMPLE select 460EX # Odd since it uses 460GT but the effects are the same select PCI @@ -120,7 +110,6 @@ config ARCHES config CANYONLANDS bool "Canyonlands" depends on 44x - default n select 460EX select PCI select PPC4xx_PCI_EXPRESS @@ -134,7 +123,6 @@ config CANYONLANDS config GLACIER bool "Glacier" depends on 44x - default n select PPC44x_SIMPLE select 460EX # Odd since it uses 460GT but the effects are the same select PCI @@ -147,7 +135,6 @@ config GLACIER config REDWOOD bool "Redwood" depends on 44x - default n select PPC44x_SIMPLE select 460SX select PCI @@ -160,7 +147,6 @@ config REDWOOD config EIGER bool "Eiger" depends on 44x - default n select PPC44x_SIMPLE select 460SX select PCI @@ -172,7 +158,6 @@ config EIGER config YOSEMITE bool "Yosemite" depends on 44x - default n select PPC44x_SIMPLE select 440EP select PCI @@ -182,7 +167,6 @@ config YOSEMITE config ISS4xx bool "ISS 4xx Simulator" depends on (44x || 40x) - default n select 405GP if 40x select 440GP if 44x && !PPC_47x select PPC_FPU @@ -193,7 +177,6 @@ config ISS4xx config CURRITUCK bool "IBM Currituck (476fpe) Support" depends on PPC_47x - default n select SWIOTLB select 476FPE select PPC4xx_PCI_EXPRESS @@ -203,7 +186,6 @@ config CURRITUCK config FSP2 bool "IBM FSP2 (476fpe) Support" depends on PPC_47x - default n select 476FPE select IBM_EMAC_EMAC4 if IBM_EMAC select IBM_EMAC_RGMII if IBM_EMAC @@ -215,7 +197,6 @@ config FSP2 config AKEBONO bool "IBM Akebono (476gtr) Support" depends on PPC_47x - default n select SWIOTLB select 476FPE select PPC4xx_PCI_EXPRESS @@ -241,7 +222,6 @@ config AKEBONO config ICON bool "Icon" depends on 44x - default n select PPC44x_SIMPLE select 440SPe select PCI @@ -252,7 +232,6 @@ config ICON config XILINX_VIRTEX440_GENERIC_BOARD bool "Generic Xilinx Virtex 5 FXT board support" depends on 44x - default n select XILINX_VIRTEX_5_FXT select XILINX_INTC help @@ -280,7 +259,6 @@ config XILINX_ML510 config PPC44x_SIMPLE bool "Simple PowerPC 44x board support" depends on 44x - default n help This option enables the simple PowerPC 44x platform support. diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c index 04f0c73a9b4f..7a507f775308 100644 --- a/arch/powerpc/platforms/44x/fsp2.c +++ b/arch/powerpc/platforms/44x/fsp2.c @@ -210,15 +210,15 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) for_each_compatible_node(np, NULL, compat) { irq = irq_of_parse_and_map(np, 0); if (irq == NO_IRQ) { - pr_err("device tree node %s is missing a interrupt", - np->name); + pr_err("device tree node %pOFn is missing a interrupt", + np); return; } rc = request_irq(irq, errirq_handler, 0, np->name, np); if (rc) { - pr_err("fsp_of_probe: request_irq failed: np=%s rc=%d", - np->full_name, rc); + pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d", + np, rc); return; } } diff --git a/arch/powerpc/platforms/4xx/ocm.c b/arch/powerpc/platforms/4xx/ocm.c index 69d9f60d9fe5..f5bbd4563342 100644 --- a/arch/powerpc/platforms/4xx/ocm.c +++ b/arch/powerpc/platforms/4xx/ocm.c @@ -113,7 +113,6 @@ static void __init ocm_init_node(int count, struct device_node *node) int len; struct resource rsrc; - int ioflags; ocm = ocm_get_node(count); @@ -179,9 +178,8 @@ static void __init ocm_init_node(int count, struct device_node *node) /* ioremap the non-cached region */ if (ocm->nc.memtotal) { - ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC; ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal, - ioflags); + _PAGE_EXEC | PAGE_KERNEL_NCG); if (!ocm->nc.virt) { printk(KERN_ERR @@ -195,9 +193,8 @@ static void __init ocm_init_node(int count, struct device_node *node) /* ioremap the cached region */ if (ocm->c.memtotal) { - ioflags = _PAGE_EXEC; ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal, - ioflags); + _PAGE_EXEC | PAGE_KERNEL); if (!ocm->c.virt) { printk(KERN_ERR diff --git a/arch/powerpc/platforms/4xx/soc.c b/arch/powerpc/platforms/4xx/soc.c index 5e36508b2a70..1844bf502fcf 100644 --- a/arch/powerpc/platforms/4xx/soc.c +++ b/arch/powerpc/platforms/4xx/soc.c @@ -200,7 +200,7 @@ void ppc4xx_reset_system(char *cmd) u32 reset_type = DBCR0_RST_SYSTEM; const u32 *prop; - np = of_find_node_by_type(NULL, "cpu"); + np = of_get_cpu_node(0, NULL); if (np) { prop = of_get_property(np, "reset-type", NULL); diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 6e04099361b9..1947a88bc69f 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig @@ -51,7 +51,6 @@ endif config PQ2ADS bool - default n config 8260 bool diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 7e966f4cf19a..fff72425727a 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -216,8 +216,8 @@ static int smp_85xx_start_cpu(int cpu) /* Map the spin table */ if (ioremappable) - spin_table = ioremap_prot(*cpu_rel_addr, - sizeof(struct epapr_spin_table), _PAGE_COHERENT); + spin_table = ioremap_coherent(*cpu_rel_addr, + sizeof(struct epapr_spin_table)); else spin_table = phys_to_virt(*cpu_rel_addr); diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 027c42d8966c..f1c805c8adbc 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -66,7 +66,7 @@ static int __init get_freq(char *name, unsigned long *val) int found = 0; /* The cpu node should have timebase and clock frequency properties */ - cpu = of_find_node_by_type(NULL, "cpu"); + cpu = of_get_cpu_node(0, NULL); if (cpu) { fp = of_get_property(cpu, name, NULL); @@ -147,8 +147,9 @@ void __init mpc8xx_calibrate_decr(void) * we have to enable the timebase). The decrementer interrupt * is wired into the vector table, nothing to do here for that. */ - cpu = of_find_node_by_type(NULL, "cpu"); + cpu = of_get_cpu_node(0, NULL); virq= irq_of_parse_and_map(cpu, 0); + of_node_put(cpu); irq = virq_to_hw(virq); sys_tmr2 = immr_map(im_sit); diff --git a/arch/powerpc/platforms/8xx/machine_check.c b/arch/powerpc/platforms/8xx/machine_check.c index 402016705a39..9944fc303df0 100644 --- a/arch/powerpc/platforms/8xx/machine_check.c +++ b/arch/powerpc/platforms/8xx/machine_check.c @@ -18,9 +18,9 @@ int machine_check_8xx(struct pt_regs *regs) pr_err("Machine check in kernel mode.\n"); pr_err("Caused by (from SRR1=%lx): ", reason); if (reason & 0x40000000) - pr_err("Fetch error at address %lx\n", regs->nip); + pr_cont("Fetch error at address %lx\n", regs->nip); else - pr_err("Data access error at address %lx\n", regs->dar); + pr_cont("Data access error at address %lx\n", regs->dar); #ifdef CONFIG_PCI /* the qspan pci read routines can cause machine checks -- Cort diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 14ef17e10ec9..260a56b7602d 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -23,7 +23,6 @@ source "arch/powerpc/platforms/amigaone/Kconfig" config KVM_GUEST bool "KVM Guest support" - default n select EPAPR_PARAVIRT ---help--- This option enables various optimizations for running under the KVM @@ -34,7 +33,6 @@ config KVM_GUEST config EPAPR_PARAVIRT bool "ePAPR para-virtualization support" - default n help Enables ePAPR para-virtualization support for guests. @@ -74,7 +72,6 @@ config PPC_DT_CPU_FTRS config UDBG_RTAS_CONSOLE bool "RTAS based debug console" depends on PPC_RTAS - default n config PPC_SMP_MUXED_IPI bool @@ -86,16 +83,13 @@ config PPC_SMP_MUXED_IPI config IPIC bool - default n config MPIC bool - default n config MPIC_TIMER bool "MPIC Global Timer" depends on MPIC && FSL_SOC - default n help The MPIC global timer is a hardware timer inside the Freescale PIC complying with OpenPIC standard. When the @@ -107,7 +101,6 @@ config MPIC_TIMER config FSL_MPIC_TIMER_WAKEUP tristate "Freescale MPIC global timer wakeup driver" depends on FSL_SOC && MPIC_TIMER && PM - default n help The driver provides a way to wake up the system by MPIC timer. @@ -115,43 +108,35 @@ config FSL_MPIC_TIMER_WAKEUP config PPC_EPAPR_HV_PIC bool - default n select EPAPR_PARAVIRT config MPIC_WEIRD bool - default n config MPIC_MSGR bool "MPIC message register support" depends on MPIC - default n help Enables support for the MPIC message registers. These registers are used for inter-processor communication. config PPC_I8259 bool - default n config U3_DART bool depends on PPC64 - default n config PPC_RTAS bool - default n config RTAS_ERROR_LOGGING bool depends on PPC_RTAS - default n config PPC_RTAS_DAEMON bool depends on PPC_RTAS - default n config RTAS_PROC bool "Proc interface to RTAS" @@ -164,11 +149,9 @@ config RTAS_FLASH config MMIO_NVRAM bool - default n config MPIC_U3_HT_IRQS bool - default n config MPIC_BROKEN_REGREAD bool @@ -187,15 +170,12 @@ config EEH config PPC_MPC106 bool - default n config PPC_970_NAP bool - default n config PPC_P7_NAP bool - default n config PPC_INDIRECT_PIO bool @@ -295,7 +275,6 @@ config CPM2 config FSL_ULI1575 bool - default n select GENERIC_ISA_DMA help Supports for the ULI1575 PCIe south bridge that exists on some diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 6c6a7c72cae4..f4e2c5729374 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 config PPC64 bool "64-bit kernel" - default n select ZLIB_DEFLATE help This option selects whether a 32-bit or a 64-bit kernel @@ -72,6 +71,7 @@ config PPC_BOOK3S_64 select PPC_HAVE_PMU_SUPPORT select SYS_SUPPORTS_HUGETLBFS select HAVE_ARCH_TRANSPARENT_HUGEPAGE + select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE select ARCH_SUPPORTS_NUMA_BALANCING select IRQ_WORK @@ -368,7 +368,6 @@ config PPC_MM_SLICES bool default y if PPC_BOOK3S_64 default y if PPC_8xx && HUGETLB_PAGE - default n config PPC_HAVE_PMU_SUPPORT bool @@ -382,7 +381,6 @@ config PPC_PERF_CTRS config FORCE_SMP # Allow platforms to force SMP=y by selecting this bool - default n select SMP config SMP @@ -423,7 +421,6 @@ config CHECK_CACHE_COHERENCY config PPC_DOORBELL bool - default n endmenu diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index e46bb7ea710f..143d4417f6cc 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - obj-$(CONFIG_FSL_ULI1575) += fsl_uli1575.o obj-$(CONFIG_PPC_PMAC) += powermac/ diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 9f5958f16923..4b2f114f3116 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 config PPC_CELL bool - default n config PPC_CELL_COMMON bool @@ -22,7 +21,6 @@ config PPC_CELL_NATIVE select IBM_EMAC_RGMII if IBM_EMAC select IBM_EMAC_ZMII if IBM_EMAC #test only select IBM_EMAC_TAH if IBM_EMAC #test only - default n config PPC_IBM_CELL_BLADE bool "IBM Cell Blade" @@ -54,7 +52,6 @@ config SPU_FS config SPU_BASE bool - default n select PPC_COPRO_BASE config CBE_RAS diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c index 882944c36ef5..5d8e8b6bb1cc 100644 --- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c +++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c @@ -49,7 +49,7 @@ static int calc_freq(struct spu_gov_info_struct *info) cpu = info->policy->cpu; busy_spus = atomic_read(&cbe_spu_info[cpu_to_node(cpu)].busy_spus); - CALC_LOAD(info->busy_spus, EXP, busy_spus * FIXED_1); + info->busy_spus = calc_load(info->busy_spus, EXP, busy_spus * FIXED_1); pr_debug("cpu %d: busy_spus=%d, info->busy_spus=%ld\n", cpu, busy_spus, info->busy_spus); diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 0c45cdbac4cf..7f12c7b78c0f 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -50,11 +50,11 @@ struct cbe_spu_info cbe_spu_info[MAX_NUMNODES]; EXPORT_SYMBOL_GPL(cbe_spu_info); /* - * The spufs fault-handling code needs to call force_sig_info to raise signals + * The spufs fault-handling code needs to call force_sig_fault to raise signals * on DMA errors. Export it here to avoid general kernel-wide access to this * function */ -EXPORT_SYMBOL_GPL(force_sig_info); +EXPORT_SYMBOL_GPL(force_sig_fault); /* * Protects cbe_spu_info and spu->number. diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 5c409c98cca8..f7e36373f6e0 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -180,35 +180,22 @@ out: static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) { - struct of_phandle_args oirq; - int ret; int i; for (i=0; i < 3; i++) { - ret = of_irq_parse_one(np, i, &oirq); - if (ret) { - pr_debug("spu_new: failed to get irq %d\n", i); - goto err; - } - ret = -EINVAL; - pr_debug(" irq %d no 0x%x on %pOF\n", i, oirq.args[0], - oirq.np); - spu->irqs[i] = irq_create_of_mapping(&oirq); - if (!spu->irqs[i]) { - pr_debug("spu_new: failed to map it !\n"); + spu->irqs[i] = irq_of_parse_and_map(np, i); + if (!spu->irqs[i]) goto err; - } } return 0; err: - pr_debug("failed to map irq %x for spu %s\n", *oirq.args, - spu->name); + pr_debug("failed to map irq %x for spu %s\n", i, spu->name); for (; i >= 0; i--) { if (spu->irqs[i]) irq_dispose_mapping(spu->irqs[i]); } - return ret; + return -EINVAL; } static int spu_map_resource(struct spu *spu, int nr, @@ -295,8 +282,8 @@ static int __init of_enumerate_spus(int (*fn)(void *data)) for_each_node_by_type(node, "spe") { ret = fn(node); if (ret) { - printk(KERN_WARNING "%s: Error initializing %s\n", - __func__, node->name); + printk(KERN_WARNING "%s: Error initializing %pOFn\n", + __func__, node); of_node_put(node); break; } diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index 83cf58daaa79..971ac43b5d60 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -36,42 +36,32 @@ static void spufs_handle_event(struct spu_context *ctx, unsigned long ea, int type) { - siginfo_t info; - if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { ctx->event_return |= type; wake_up_all(&ctx->stop_wq); return; } - clear_siginfo(&info); - switch (type) { case SPE_EVENT_INVALID_DMA: - info.si_signo = SIGBUS; - info.si_code = BUS_OBJERR; + force_sig_fault(SIGBUS, BUS_OBJERR, NULL, current); break; case SPE_EVENT_SPE_DATA_STORAGE: - info.si_signo = SIGSEGV; - info.si_addr = (void __user *)ea; - info.si_code = SEGV_ACCERR; ctx->ops->restart_dma(ctx); + force_sig_fault(SIGSEGV, SEGV_ACCERR, (void __user *)ea, + current); break; case SPE_EVENT_DMA_ALIGNMENT: - info.si_signo = SIGBUS; /* DAR isn't set for an alignment fault :( */ - info.si_code = BUS_ADRALN; + force_sig_fault(SIGBUS, BUS_ADRALN, NULL, current); break; case SPE_EVENT_SPE_ERROR: - info.si_signo = SIGILL; - info.si_addr = (void __user *)(unsigned long) - ctx->ops->npc_read(ctx) - 4; - info.si_code = ILL_ILLOPC; + force_sig_fault( + SIGILL, ILL_ILLOPC, + (void __user *)(unsigned long) + ctx->ops->npc_read(ctx) - 4, current); break; } - - if (info.si_signo) - force_sig_info(info.si_signo, &info, current); } int spufs_handle_class0(struct spu_context *ctx) diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index c9ef3c532169..9fcccb4490b9 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -987,9 +987,9 @@ static void spu_calc_load(void) unsigned long active_tasks; /* fixed-point */ active_tasks = count_active_contexts() * FIXED_1; - CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks); - CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks); - CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks); + spu_avenrun[0] = calc_load(spu_avenrun[0], EXP_1, active_tasks); + spu_avenrun[1] = calc_load(spu_avenrun[1], EXP_5, active_tasks); + spu_avenrun[2] = calc_load(spu_avenrun[2], EXP_15, active_tasks); } static void spusched_wake(struct timer_list *unused) @@ -1071,9 +1071,6 @@ void spuctx_switch_state(struct spu_context *ctx, } } -#define LOAD_INT(x) ((x) >> FSHIFT) -#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) - static int show_spu_loadavg(struct seq_file *s, void *private) { int a, b, c; diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 403523c061ba..ecf703ee3a76 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -112,7 +112,7 @@ static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible) } error = of_address_to_resource(np, 0, &res); if (error) { - pr_err("no valid reg found for %s\n", np->name); + pr_err("no valid reg found for %pOFn\n", np); goto out_put; } diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig index 376d0be36b66..2601fac50354 100644 --- a/arch/powerpc/platforms/maple/Kconfig +++ b/arch/powerpc/platforms/maple/Kconfig @@ -13,7 +13,6 @@ config PPC_MAPLE select PPC_RTAS select MMIO_NVRAM select ATA_NONSTANDARD if ATA - default n help This option enables support for the Maple 970FX Evaluation Board. For more information, refer to <http://www.970eval.com> diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index d458a791d35b..98e3bc22bebc 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig @@ -2,7 +2,6 @@ config PPC_PASEMI depends on PPC64 && PPC_BOOK3S && CPU_BIG_ENDIAN bool "PA Semi SoC-based platforms" - default n select MPIC select PCI select PPC_UDBG_16550 diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index c80f72c370ae..53384eb42a76 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c @@ -576,7 +576,7 @@ int pasemi_dma_init(void) res.start = 0xfd800000; res.end = res.start + 0x1000; } - dma_status = __ioremap(res.start, resource_size(&res), 0); + dma_status = ioremap_cache(res.start, resource_size(&res)); pci_dev_put(iob_pdev); for (i = 0; i < MAX_TXCH; i++) diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index f2839eed0f89..923bfb340433 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -1,9 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 CFLAGS_bootx_init.o += -fPIC +CFLAGS_bootx_init.o += $(call cc-option, -fno-stack-protector) ifdef CONFIG_FUNCTION_TRACER # Do not trace early boot code -CFLAGS_REMOVE_bootx_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_bootx_init.o = $(CC_FLAGS_FTRACE) endif obj-y += pic.o setup.o time.o feature.o pci.o \ diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 4eb8cb38fc69..ed2f54b3f173 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1049,7 +1049,6 @@ core99_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; - struct device_node *cpus; const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, @@ -1059,10 +1058,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) if (macio->type != macio_keylargo) return -ENODEV; - cpus = of_find_node_by_path("/cpus"); - if (cpus == NULL) - return -ENODEV; - for (np = cpus->child; np != NULL; np = np->sibling) { + for_each_of_cpu_node(np) { const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) @@ -1072,7 +1068,6 @@ core99_reset_cpu(struct device_node *node, long param, long value) break; } } - of_node_put(cpus); if (np == NULL || reset_io == 0) reset_io = dflt_reset_lines[param]; @@ -1504,16 +1499,12 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; - struct device_node *cpus; macio = &macio_chips[0]; if (macio->type != macio_keylargo2 && macio->type != macio_shasta) return -ENODEV; - cpus = of_find_node_by_path("/cpus"); - if (cpus == NULL) - return -ENODEV; - for (np = cpus->child; np != NULL; np = np->sibling) { + for_each_of_cpu_node(np) { const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) @@ -1523,7 +1514,6 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) break; } } - of_node_put(cpus); if (np == NULL || reset_io == 0) return -ENODEV; @@ -2515,31 +2505,26 @@ found: * supposed to be set when not supported, but I'm not very confident * that all Apple OF revs did it properly, I do it the paranoid way. */ - while (uninorth_base && uninorth_rev > 3) { - struct device_node *cpus = of_find_node_by_path("/cpus"); + if (uninorth_base && uninorth_rev > 3) { struct device_node *np; - if (!cpus || !cpus->child) { - printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); - of_node_put(cpus); - break; - } - np = cpus->child; - /* Nap mode not supported on SMP */ - if (np->sibling) { - of_node_put(cpus); - break; - } - /* Nap mode not supported if flush-on-lock property is present */ - if (of_get_property(np, "flush-on-lock", NULL)) { - of_node_put(cpus); - break; + for_each_of_cpu_node(np) { + int cpu_count = 1; + + /* Nap mode not supported on SMP */ + if (of_get_property(np, "flush-on-lock", NULL) || + (cpu_count > 1)) { + powersave_nap = 0; + of_node_put(np); + break; + } + + cpu_count++; + powersave_nap = 1; } - of_node_put(cpus); - powersave_nap = 1; - printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); - break; } + if (powersave_nap) + printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); /* On CPUs that support it (750FX), lowspeed by default during * NAP mode diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 3a529fcdae97..2f00e3daafb0 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -243,10 +243,9 @@ static void __init l2cr_init(void) { /* Checks "l2cr-value" property in the registry */ if (cpu_has_feature(CPU_FTR_L2CR)) { - struct device_node *np = of_find_node_by_name(NULL, "cpus"); - if (!np) - np = of_find_node_by_type(NULL, "cpu"); - if (np) { + struct device_node *np; + + for_each_of_cpu_node(np) { const unsigned int *l2cr = of_get_property(np, "l2cr-value", NULL); if (l2cr) { @@ -256,6 +255,7 @@ static void __init l2cr_init(void) _set_L2CR(ppc_override_l2cr_value); } of_node_put(np); + break; } } @@ -279,8 +279,8 @@ static void __init pmac_setup_arch(void) /* Set loops_per_jiffy to a half-way reasonable value, for use until calibrate_delay gets called. */ loops_per_jiffy = 50000000 / HZ; - cpu = of_find_node_by_type(NULL, "cpu"); - if (cpu != NULL) { + + for_each_of_cpu_node(cpu) { fp = of_get_property(cpu, "clock-frequency", NULL); if (fp != NULL) { if (pvr >= 0x30 && pvr < 0x80) @@ -292,8 +292,9 @@ static void __init pmac_setup_arch(void) else /* 601, 603, etc. */ loops_per_jiffy = *fp / (2 * HZ); + of_node_put(cpu); + break; } - of_node_put(cpu); } /* See if newworld or oldworld */ diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index f92c1918fb56..f157e3d071f2 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -45,13 +45,6 @@ #endif /* - * Offset between Unix time (1970-based) and Mac time (1904-based). Cuda and PMU - * times wrap in 2040. If we need to handle later times, the read_time functions - * need to be changed to interpret wrapped times as post-2040. - */ -#define RTC_OFFSET 2082844800 - -/* * Calibrate the decrementer frequency with the VIA timer 1. */ #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ @@ -90,98 +83,6 @@ long __init pmac_time_init(void) return delta; } -#ifdef CONFIG_ADB_CUDA -static time64_t cuda_get_time(void) -{ - struct adb_request req; - time64_t now; - - if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) - return 0; - while (!req.complete) - cuda_poll(); - if (req.reply_len != 7) - printk(KERN_ERR "cuda_get_time: got %d byte reply\n", - req.reply_len); - now = (u32)((req.reply[3] << 24) + (req.reply[4] << 16) + - (req.reply[5] << 8) + req.reply[6]); - /* it's either after year 2040, or the RTC has gone backwards */ - WARN_ON(now < RTC_OFFSET); - - return now - RTC_OFFSET; -} - -#define cuda_get_rtc_time(tm) rtc_time64_to_tm(cuda_get_time(), (tm)) - -static int cuda_set_rtc_time(struct rtc_time *tm) -{ - u32 nowtime; - struct adb_request req; - - nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); - if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, - nowtime >> 24, nowtime >> 16, nowtime >> 8, - nowtime) < 0) - return -ENXIO; - while (!req.complete) - cuda_poll(); - if ((req.reply_len != 3) && (req.reply_len != 7)) - printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n", - req.reply_len); - return 0; -} - -#else -#define cuda_get_time() 0 -#define cuda_get_rtc_time(tm) -#define cuda_set_rtc_time(tm) 0 -#endif - -#ifdef CONFIG_ADB_PMU -static time64_t pmu_get_time(void) -{ - struct adb_request req; - time64_t now; - - if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) - return 0; - pmu_wait_complete(&req); - if (req.reply_len != 4) - printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n", - req.reply_len); - now = (u32)((req.reply[0] << 24) + (req.reply[1] << 16) + - (req.reply[2] << 8) + req.reply[3]); - - /* it's either after year 2040, or the RTC has gone backwards */ - WARN_ON(now < RTC_OFFSET); - - return now - RTC_OFFSET; -} - -#define pmu_get_rtc_time(tm) rtc_time64_to_tm(pmu_get_time(), (tm)) - -static int pmu_set_rtc_time(struct rtc_time *tm) -{ - u32 nowtime; - struct adb_request req; - - nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); - if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24, - nowtime >> 16, nowtime >> 8, nowtime) < 0) - return -ENXIO; - pmu_wait_complete(&req); - if (req.reply_len != 0) - printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n", - req.reply_len); - return 0; -} - -#else -#define pmu_get_time() 0 -#define pmu_get_rtc_time(tm) -#define pmu_set_rtc_time(tm) 0 -#endif - #ifdef CONFIG_PMAC_SMU static time64_t smu_get_time(void) { @@ -191,11 +92,6 @@ static time64_t smu_get_time(void) return 0; return rtc_tm_to_time64(&tm); } - -#else -#define smu_get_time() 0 -#define smu_get_rtc_time(tm, spin) -#define smu_set_rtc_time(tm, spin) 0 #endif /* Can't be __init, it's called when suspending and resuming */ @@ -203,12 +99,18 @@ time64_t pmac_get_boot_time(void) { /* Get the time from the RTC, used only at boot time */ switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA case SYS_CTRLER_CUDA: return cuda_get_time(); +#endif +#ifdef CONFIG_ADB_PMU case SYS_CTRLER_PMU: return pmu_get_time(); +#endif +#ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: return smu_get_time(); +#endif default: return 0; } @@ -218,15 +120,21 @@ void pmac_get_rtc_time(struct rtc_time *tm) { /* Get the time from the RTC, used only at boot time */ switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA case SYS_CTRLER_CUDA: - cuda_get_rtc_time(tm); + rtc_time64_to_tm(cuda_get_time(), tm); break; +#endif +#ifdef CONFIG_ADB_PMU case SYS_CTRLER_PMU: - pmu_get_rtc_time(tm); + rtc_time64_to_tm(pmu_get_time(), tm); break; +#endif +#ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: smu_get_rtc_time(tm, 1); break; +#endif default: ; } @@ -235,12 +143,18 @@ void pmac_get_rtc_time(struct rtc_time *tm) int pmac_set_rtc_time(struct rtc_time *tm) { switch (sys_ctrler) { +#ifdef CONFIG_ADB_CUDA case SYS_CTRLER_CUDA: return cuda_set_rtc_time(tm); +#endif +#ifdef CONFIG_ADB_PMU case SYS_CTRLER_PMU: return pmu_set_rtc_time(tm); +#endif +#ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: return smu_set_rtc_time(tm, 1); +#endif default: return -ENODEV; } diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig index f8dc98d3dc01..99083fe992d5 100644 --- a/arch/powerpc/platforms/powernv/Kconfig +++ b/arch/powerpc/platforms/powernv/Kconfig @@ -15,11 +15,6 @@ config PPC_POWERNV select PPC_SCOM select ARCH_RANDOM select CPU_FREQ - select CPU_FREQ_GOV_PERFORMANCE - select CPU_FREQ_GOV_POWERSAVE - select CPU_FREQ_GOV_USERSPACE - select CPU_FREQ_GOV_ONDEMAND - select CPU_FREQ_GOV_CONSERVATIVE select PPC_DOORBELL select MMU_NOTIFIER select FORCE_SMP @@ -35,7 +30,6 @@ config OPAL_PRD config PPC_MEMTRACE bool "Enable removal of RAM from kernel mappings for tracing" depends on PPC_POWERNV && MEMORY_HOTREMOVE - default n help Enabling this option allows for the removal of memory (RAM) from the kernel mappings to be used for hardware tracing. diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 3c1beae29f2d..abc0be7507c8 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -223,14 +223,6 @@ int pnv_eeh_post_init(void) eeh_probe_devices(); eeh_addr_cache_build(); - if (eeh_has_flag(EEH_POSTPONED_PROBE)) { - eeh_clear_flag(EEH_POSTPONED_PROBE); - if (eeh_enabled()) - pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); - else - pr_info("EEH: No capable adapters found\n"); - } - /* Register OPAL event notifier */ eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR)); if (eeh_event_irq < 0) { @@ -391,12 +383,6 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) return NULL; - /* Skip if we haven't probed yet */ - if (phb->ioda.pe_rmap[config_addr] == IODA_INVALID_PE) { - eeh_add_flag(EEH_POSTPONED_PROBE); - return NULL; - } - /* Initialize eeh device */ edev->class_code = pdn->class_code; edev->mode &= 0xFFFFFF00; @@ -604,7 +590,7 @@ static int pnv_eeh_get_phb_state(struct eeh_pe *pe) EEH_STATE_MMIO_ENABLED | EEH_STATE_DMA_ENABLED); } else if (!(pe->state & EEH_PE_ISOLATED)) { - eeh_pe_state_mark(pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(pe); pnv_eeh_get_phb_diag(pe); if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) @@ -706,7 +692,7 @@ static int pnv_eeh_get_pe_state(struct eeh_pe *pe) if (phb->freeze_pe) phb->freeze_pe(phb, pe->addr); - eeh_pe_state_mark(pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(pe); pnv_eeh_get_phb_diag(pe); if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) @@ -1054,7 +1040,7 @@ static int pnv_eeh_reset_vf_pe(struct eeh_pe *pe, int option) int ret; /* The VF PE should have only one child device */ - edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list); + edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); pdn = eeh_dev_to_pdn(edev); if (!pdn) return -ENXIO; @@ -1148,43 +1134,6 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option) } /** - * pnv_eeh_wait_state - Wait for PE state - * @pe: EEH PE - * @max_wait: maximal period in millisecond - * - * Wait for the state of associated PE. It might take some time - * to retrieve the PE's state. - */ -static int pnv_eeh_wait_state(struct eeh_pe *pe, int max_wait) -{ - int ret; - int mwait; - - while (1) { - ret = pnv_eeh_get_state(pe, &mwait); - - /* - * If the PE's state is temporarily unavailable, - * we have to wait for the specified time. Otherwise, - * the PE's state will be returned immediately. - */ - if (ret != EEH_STATE_UNAVAILABLE) - return ret; - - if (max_wait <= 0) { - pr_warn("%s: Timeout getting PE#%x's state (%d)\n", - __func__, pe->addr, max_wait); - return EEH_STATE_NOT_SUPPORT; - } - - max_wait -= mwait; - msleep(mwait); - } - - return EEH_STATE_NOT_SUPPORT; -} - -/** * pnv_eeh_get_log - Retrieve error log * @pe: EEH PE * @severity: temporary or permanent error log @@ -1611,7 +1560,7 @@ static int pnv_eeh_next_error(struct eeh_pe **pe) if ((ret == EEH_NEXT_ERR_FROZEN_PE || ret == EEH_NEXT_ERR_FENCED_PHB) && !((*pe)->state & EEH_PE_ISOLATED)) { - eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(*pe); pnv_eeh_get_phb_diag(*pe); if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) @@ -1640,7 +1589,7 @@ static int pnv_eeh_next_error(struct eeh_pe **pe) } /* We possibly migrate to another PE */ - eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); + eeh_pe_mark_isolated(*pe); } /* @@ -1702,7 +1651,6 @@ static struct eeh_ops pnv_eeh_ops = { .get_pe_addr = pnv_eeh_get_pe_addr, .get_state = pnv_eeh_get_state, .reset = pnv_eeh_reset, - .wait_state = pnv_eeh_wait_state, .get_log = pnv_eeh_get_log, .configure_bridge = pnv_eeh_configure_bridge, .err_inject = pnv_eeh_err_inject, diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 51dc398ae3f7..a29fdf8a2e56 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -90,17 +90,15 @@ static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages) walk_memory_range(start_pfn, end_pfn, (void *)MEM_OFFLINE, change_memblock_state); - lock_device_hotplug(); - remove_memory(nid, start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); - unlock_device_hotplug(); return true; } static u64 memtrace_alloc_node(u32 nid, u64 size) { - u64 start_pfn, end_pfn, nr_pages; + u64 start_pfn, end_pfn, nr_pages, pfn; u64 base_pfn; + u64 bytes = memory_block_size_bytes(); if (!node_spanned_pages(nid)) return 0; @@ -113,8 +111,21 @@ static u64 memtrace_alloc_node(u32 nid, u64 size) end_pfn = round_down(end_pfn - nr_pages, nr_pages); for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) { - if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) + if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) { + /* + * Remove memory in memory block size chunks so that + * iomem resources are always split to the same size and + * we never try to remove memory that spans two iomem + * resources. + */ + lock_device_hotplug(); + end_pfn = base_pfn + nr_pages; + for (pfn = base_pfn; pfn < end_pfn; pfn += bytes>> PAGE_SHIFT) { + remove_memory(nid, pfn << PAGE_SHIFT, bytes); + } + unlock_device_hotplug(); return base_pfn << PAGE_SHIFT; + } } return 0; diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 8006c54a91e3..6f60e0931922 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c @@ -17,7 +17,7 @@ #include <linux/pci.h> #include <linux/memblock.h> #include <linux/iommu.h> -#include <linux/debugfs.h> +#include <linux/sizes.h> #include <asm/debugfs.h> #include <asm/tlb.h> @@ -42,14 +42,6 @@ static DEFINE_SPINLOCK(npu_context_lock); /* - * When an address shootdown range exceeds this threshold we invalidate the - * entire TLB on the GPU for the given PID rather than each specific address in - * the range. - */ -static uint64_t atsd_threshold = 2 * 1024 * 1024; -static struct dentry *atsd_threshold_dentry; - -/* * Other types of TCE cache invalidation are not functional in the * hardware. */ @@ -454,79 +446,73 @@ static void put_mmio_atsd_reg(struct npu *npu, int reg) } /* MMIO ATSD register offsets */ -#define XTS_ATSD_AVA 1 -#define XTS_ATSD_STAT 2 - -static void mmio_launch_invalidate(struct mmio_atsd_reg *mmio_atsd_reg, - unsigned long launch, unsigned long va) -{ - struct npu *npu = mmio_atsd_reg->npu; - int reg = mmio_atsd_reg->reg; - - __raw_writeq_be(va, npu->mmio_atsd_regs[reg] + XTS_ATSD_AVA); - eieio(); - __raw_writeq_be(launch, npu->mmio_atsd_regs[reg]); -} +#define XTS_ATSD_LAUNCH 0 +#define XTS_ATSD_AVA 1 +#define XTS_ATSD_STAT 2 -static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], - unsigned long pid, bool flush) +static unsigned long get_atsd_launch_val(unsigned long pid, unsigned long psize) { - int i; - unsigned long launch; - - for (i = 0; i <= max_npu2_index; i++) { - if (mmio_atsd_reg[i].reg < 0) - continue; + unsigned long launch = 0; - /* IS set to invalidate matching PID */ - launch = PPC_BIT(12); - - /* PRS set to process-scoped */ - launch |= PPC_BIT(13); + if (psize == MMU_PAGE_COUNT) { + /* IS set to invalidate entire matching PID */ + launch |= PPC_BIT(12); + } else { + /* AP set to invalidate region of psize */ + launch |= (u64)mmu_get_ap(psize) << PPC_BITLSHIFT(17); + } - /* AP */ - launch |= (u64) - mmu_get_ap(mmu_virtual_psize) << PPC_BITLSHIFT(17); + /* PRS set to process-scoped */ + launch |= PPC_BIT(13); - /* PID */ - launch |= pid << PPC_BITLSHIFT(38); + /* PID */ + launch |= pid << PPC_BITLSHIFT(38); - /* No flush */ - launch |= !flush << PPC_BITLSHIFT(39); + /* Leave "No flush" (bit 39) 0 so every ATSD performs a flush */ - /* Invalidating the entire process doesn't use a va */ - mmio_launch_invalidate(&mmio_atsd_reg[i], launch, 0); - } + return launch; } -static void mmio_invalidate_va(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], - unsigned long va, unsigned long pid, bool flush) +static void mmio_atsd_regs_write(struct mmio_atsd_reg + mmio_atsd_reg[NV_MAX_NPUS], unsigned long offset, + unsigned long val) { - int i; - unsigned long launch; + struct npu *npu; + int i, reg; for (i = 0; i <= max_npu2_index; i++) { - if (mmio_atsd_reg[i].reg < 0) + reg = mmio_atsd_reg[i].reg; + if (reg < 0) continue; - /* IS set to invalidate target VA */ - launch = 0; + npu = mmio_atsd_reg[i].npu; + __raw_writeq_be(val, npu->mmio_atsd_regs[reg] + offset); + } +} + +static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], + unsigned long pid) +{ + unsigned long launch = get_atsd_launch_val(pid, MMU_PAGE_COUNT); - /* PRS set to process scoped */ - launch |= PPC_BIT(13); + /* Invalidating the entire process doesn't use a va */ + mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_LAUNCH, launch); +} - /* AP */ - launch |= (u64) - mmu_get_ap(mmu_virtual_psize) << PPC_BITLSHIFT(17); +static void mmio_invalidate_range(struct mmio_atsd_reg + mmio_atsd_reg[NV_MAX_NPUS], unsigned long pid, + unsigned long start, unsigned long psize) +{ + unsigned long launch = get_atsd_launch_val(pid, psize); - /* PID */ - launch |= pid << PPC_BITLSHIFT(38); + /* Write all VAs first */ + mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_AVA, start); - /* No flush */ - launch |= !flush << PPC_BITLSHIFT(39); + /* Issue one barrier for all address writes */ + eieio(); - mmio_launch_invalidate(&mmio_atsd_reg[i], launch, va); - } + /* Launch */ + mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_LAUNCH, launch); } #define mn_to_npu_context(x) container_of(x, struct npu_context, mn) @@ -612,14 +598,36 @@ static void release_atsd_reg(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]) } /* - * Invalidate either a single address or an entire PID depending on - * the value of va. + * Invalidate a virtual address range */ -static void mmio_invalidate(struct npu_context *npu_context, int va, - unsigned long address, bool flush) +static void mmio_invalidate(struct npu_context *npu_context, + unsigned long start, unsigned long size) { struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]; unsigned long pid = npu_context->mm->context.id; + unsigned long atsd_start = 0; + unsigned long end = start + size - 1; + int atsd_psize = MMU_PAGE_COUNT; + + /* + * Convert the input range into one of the supported sizes. If the range + * doesn't fit, use the next larger supported size. Invalidation latency + * is high, so over-invalidation is preferred to issuing multiple + * invalidates. + * + * A 4K page size isn't supported by NPU/GPU ATS, so that case is + * ignored. + */ + if (size == SZ_64K) { + atsd_start = start; + atsd_psize = MMU_PAGE_64K; + } else if (ALIGN_DOWN(start, SZ_2M) == ALIGN_DOWN(end, SZ_2M)) { + atsd_start = ALIGN_DOWN(start, SZ_2M); + atsd_psize = MMU_PAGE_2M; + } else if (ALIGN_DOWN(start, SZ_1G) == ALIGN_DOWN(end, SZ_1G)) { + atsd_start = ALIGN_DOWN(start, SZ_1G); + atsd_psize = MMU_PAGE_1G; + } if (npu_context->nmmu_flush) /* @@ -634,23 +642,25 @@ static void mmio_invalidate(struct npu_context *npu_context, int va, * an invalidate. */ acquire_atsd_reg(npu_context, mmio_atsd_reg); - if (va) - mmio_invalidate_va(mmio_atsd_reg, address, pid, flush); + + if (atsd_psize == MMU_PAGE_COUNT) + mmio_invalidate_pid(mmio_atsd_reg, pid); else - mmio_invalidate_pid(mmio_atsd_reg, pid, flush); + mmio_invalidate_range(mmio_atsd_reg, pid, atsd_start, + atsd_psize); mmio_invalidate_wait(mmio_atsd_reg); - if (flush) { - /* - * The GPU requires two flush ATSDs to ensure all entries have - * been flushed. We use PID 0 as it will never be used for a - * process on the GPU. - */ - mmio_invalidate_pid(mmio_atsd_reg, 0, true); - mmio_invalidate_wait(mmio_atsd_reg); - mmio_invalidate_pid(mmio_atsd_reg, 0, true); - mmio_invalidate_wait(mmio_atsd_reg); - } + + /* + * The GPU requires two flush ATSDs to ensure all entries have been + * flushed. We use PID 0 as it will never be used for a process on the + * GPU. + */ + mmio_invalidate_pid(mmio_atsd_reg, 0); + mmio_invalidate_wait(mmio_atsd_reg); + mmio_invalidate_pid(mmio_atsd_reg, 0); + mmio_invalidate_wait(mmio_atsd_reg); + release_atsd_reg(mmio_atsd_reg); } @@ -667,7 +677,7 @@ static void pnv_npu2_mn_release(struct mmu_notifier *mn, * There should be no more translation requests for this PID, but we * need to ensure any entries for it are removed from the TLB. */ - mmio_invalidate(npu_context, 0, 0, true); + mmio_invalidate(npu_context, 0, ~0UL); } static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn, @@ -676,8 +686,7 @@ static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn, pte_t pte) { struct npu_context *npu_context = mn_to_npu_context(mn); - - mmio_invalidate(npu_context, 1, address, true); + mmio_invalidate(npu_context, address, PAGE_SIZE); } static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn, @@ -685,21 +694,7 @@ static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn, unsigned long start, unsigned long end) { struct npu_context *npu_context = mn_to_npu_context(mn); - unsigned long address; - - if (end - start > atsd_threshold) { - /* - * Just invalidate the entire PID if the address range is too - * large. - */ - mmio_invalidate(npu_context, 0, 0, true); - } else { - for (address = start; address < end; address += PAGE_SIZE) - mmio_invalidate(npu_context, 1, address, false); - - /* Do the flush only on the final addess == end */ - mmio_invalidate(npu_context, 1, address, true); - } + mmio_invalidate(npu_context, start, end - start); } static const struct mmu_notifier_ops nv_nmmu_notifier_ops = { @@ -962,11 +957,6 @@ int pnv_npu2_init(struct pnv_phb *phb) static int npu_index; uint64_t rc = 0; - if (!atsd_threshold_dentry) { - atsd_threshold_dentry = debugfs_create_x64("atsd_threshold", - 0600, powerpc_debugfs_root, &atsd_threshold); - } - phb->npu.nmmu_flush = of_property_read_bool(phb->hose->dn, "ibm,nmmu-flush"); for_each_child_of_node(phb->hose->dn, dn) { diff --git a/arch/powerpc/platforms/powernv/opal-powercap.c b/arch/powerpc/platforms/powernv/opal-powercap.c index badb29bde93f..d90ee4fc2c6a 100644 --- a/arch/powerpc/platforms/powernv/opal-powercap.c +++ b/arch/powerpc/platforms/powernv/opal-powercap.c @@ -199,7 +199,7 @@ void __init opal_powercap_init(void) } j = 0; - pcaps[i].pg.name = node->name; + pcaps[i].pg.name = kasprintf(GFP_KERNEL, "%pOFn", node); if (has_min) { powercap_add_attr(min, "powercap-min", &pcaps[i].pattrs[j]); @@ -237,6 +237,7 @@ out_pcaps_pattrs: while (--i >= 0) { kfree(pcaps[i].pattrs); kfree(pcaps[i].pg.attrs); + kfree(pcaps[i].pg.name); } kobject_put(powercap_kobj); out_pcaps: diff --git a/arch/powerpc/platforms/powernv/opal-sensor-groups.c b/arch/powerpc/platforms/powernv/opal-sensor-groups.c index f7d04b6a2d7a..179609220e6f 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor-groups.c +++ b/arch/powerpc/platforms/powernv/opal-sensor-groups.c @@ -214,9 +214,9 @@ void __init opal_sensor_groups_init(void) } if (!of_property_read_u32(node, "ibm,chip-id", &chipid)) - sprintf(sgs[i].name, "%s%d", node->name, chipid); + sprintf(sgs[i].name, "%pOFn%d", node, chipid); else - sprintf(sgs[i].name, "%s", node->name); + sprintf(sgs[i].name, "%pOFn", node); sgs[i].sg.name = sgs[i].name; if (add_attr_group(ops, len, &sgs[i], sgid)) { diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c index 9aa87df114fd..916a4b7b1bb5 100644 --- a/arch/powerpc/platforms/powernv/opal-sysparam.c +++ b/arch/powerpc/platforms/powernv/opal-sysparam.c @@ -194,7 +194,7 @@ void __init opal_sys_param_init(void) count = of_property_count_strings(sysparam, "param-name"); if (count < 0) { pr_err("SYSPARAM: No string found of property param-name in " - "the node %s\n", sysparam->name); + "the node %pOFn\n", sysparam); goto out_param_buf; } diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 38fe4087484a..a4641515956f 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -535,7 +535,7 @@ static int opal_recover_mce(struct pt_regs *regs, return recovered; } -void pnv_platform_error_reboot(struct pt_regs *regs, const char *msg) +void __noreturn pnv_platform_error_reboot(struct pt_regs *regs, const char *msg) { panic_flush_kmsg_start(); diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index adddde023622..14befee4b3f1 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -219,17 +219,41 @@ static void pnv_prepare_going_down(void) static void __noreturn pnv_restart(char *cmd) { - long rc = OPAL_BUSY; + long rc; pnv_prepare_going_down(); - while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { - rc = opal_cec_reboot(); - if (rc == OPAL_BUSY_EVENT) - opal_poll_events(NULL); + do { + if (!cmd) + rc = opal_cec_reboot(); + else if (strcmp(cmd, "full") == 0) + rc = opal_cec_reboot2(OPAL_REBOOT_FULL_IPL, NULL); else + rc = OPAL_UNSUPPORTED; + + if (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { + /* Opal is busy wait for some time and retry */ + opal_poll_events(NULL); mdelay(10); - } + + } else if (cmd && rc) { + /* Unknown error while issuing reboot */ + if (rc == OPAL_UNSUPPORTED) + pr_err("Unsupported '%s' reboot.\n", cmd); + else + pr_err("Unable to issue '%s' reboot. Err=%ld\n", + cmd, rc); + pr_info("Forcing a cec-reboot\n"); + cmd = NULL; + rc = OPAL_BUSY; + + } else if (rc != OPAL_SUCCESS) { + /* Unknown error while issuing cec-reboot */ + pr_err("Unable to reboot. Err=%ld\n", rc); + } + + } while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT); + for (;;) opal_poll_events(NULL); } @@ -437,6 +461,16 @@ static unsigned long pnv_get_proc_freq(unsigned int cpu) return ret_freq; } +static long pnv_machine_check_early(struct pt_regs *regs) +{ + long handled = 0; + + if (cur_cpu_spec && cur_cpu_spec->machine_check_early) + handled = cur_cpu_spec->machine_check_early(regs); + + return handled; +} + define_machine(powernv) { .name = "PowerNV", .probe = pnv_probe, @@ -448,6 +482,7 @@ define_machine(powernv) { .machine_shutdown = pnv_shutdown, .power_save = NULL, .calibrate_decr = generic_calibrate_decr, + .machine_check_early = pnv_machine_check_early, #ifdef CONFIG_KEXEC_CORE .kexec_cpu_down = pnv_kexec_cpu_down, #endif diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 6f7525555b19..24864b8aaf5d 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -49,7 +49,6 @@ config PS3_HTAB_SIZE config PS3_DYNAMIC_DMA depends on PPC_PS3 bool "PS3 Platform dynamic DMA page table management" - default n help This option will enable kernel support to take advantage of the per device dynamic DMA page table management provided by the Cell @@ -89,7 +88,6 @@ config PS3_SYS_MANAGER config PS3_REPOSITORY_WRITE bool "PS3 Repository write support" if PS3_ADVANCED depends on PPC_PS3 - default n help Enables support for writing to the PS3 System Repository. diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index cdbfc5cfd6f3..f5387ad82279 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c @@ -664,7 +664,7 @@ static int update_flash_db(void) db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff); count = os_area_flash_write(db, sizeof(struct os_area_db), pos); - if (count < sizeof(struct os_area_db)) { + if (count < 0 || count < sizeof(struct os_area_db)) { pr_debug("%s: os_area_flash_write failed %zd\n", __func__, count); error = count < 0 ? count : -EIO; diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index b54850845466..7746c2a3c509 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c @@ -215,8 +215,7 @@ static int __init setup_areas(struct spu *spu) goto fail_ioremap; } - spu->local_store = (__force void *)ioremap_prot(spu->local_store_phys, - LS_SIZE, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); + spu->local_store = (__force void *)ioremap_wc(spu->local_store_phys, LS_SIZE); if (!spu->local_store) { pr_debug("%s:%d: ioremap local_store failed\n", diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 0c698fd6d491..2e4bd32154b5 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -28,7 +28,6 @@ config PPC_PSERIES config PPC_SPLPAR depends on PPC_PSERIES bool "Support for shared-processor logical partitions" - default n help Enabling this option will make the kernel run more efficiently on logically-partitioned pSeries systems which use shared @@ -99,7 +98,6 @@ config PPC_SMLPAR bool "Support for shared-memory logical partitions" depends on PPC_PSERIES select LPARCFG - default n help Select this option to enable shared memory partition support. With this option a system running in an LPAR can be given more @@ -140,3 +138,10 @@ config IBMEBUS bool "Support for GX bus based adapters" help Bus device driver for GX bus based adapters. + +config PAPR_SCM + depends on PPC_PSERIES && MEMORY_HOTPLUG + select LIBNVDIMM + tristate "Support for the PAPR Storage Class Memory interface" + help + Enable access to hypervisor provided storage class memory. diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 7e89d5c47068..a43ec843c8e2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_KEXEC_CORE) += kexec.o obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o -obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o +obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o pmem.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVCS) += hvcserver.o @@ -24,6 +24,7 @@ obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMEBUS) += ibmebus.o +obj-$(CONFIG_PAPR_SCM) += papr_scm.o ifdef CONFIG_PPC_PSERIES obj-$(CONFIG_SUSPEND) += suspend.o diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index a0b20c03f078..7625546caefd 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -32,8 +32,6 @@ static struct workqueue_struct *pseries_hp_wq; struct pseries_hp_work { struct work_struct work; struct pseries_hp_errorlog *errlog; - struct completion *hp_completion; - int *rc; }; struct cc_workarea { @@ -329,7 +327,7 @@ int dlpar_release_drc(u32 drc_index) return 0; } -static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) +int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) { int rc; @@ -357,6 +355,10 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) case PSERIES_HP_ELOG_RESOURCE_CPU: rc = dlpar_cpu(hp_elog); break; + case PSERIES_HP_ELOG_RESOURCE_PMEM: + rc = dlpar_hp_pmem(hp_elog); + break; + default: pr_warn_ratelimited("Invalid resource (%d) specified\n", hp_elog->resource); @@ -371,20 +373,13 @@ static void pseries_hp_work_fn(struct work_struct *work) struct pseries_hp_work *hp_work = container_of(work, struct pseries_hp_work, work); - if (hp_work->rc) - *(hp_work->rc) = handle_dlpar_errorlog(hp_work->errlog); - else - handle_dlpar_errorlog(hp_work->errlog); - - if (hp_work->hp_completion) - complete(hp_work->hp_completion); + handle_dlpar_errorlog(hp_work->errlog); kfree(hp_work->errlog); kfree((void *)work); } -void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, - struct completion *hotplug_done, int *rc) +void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog) { struct pseries_hp_work *work; struct pseries_hp_errorlog *hp_errlog_copy; @@ -397,13 +392,9 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, if (work) { INIT_WORK((struct work_struct *)work, pseries_hp_work_fn); work->errlog = hp_errlog_copy; - work->hp_completion = hotplug_done; - work->rc = rc; queue_work(pseries_hp_wq, (struct work_struct *)work); } else { - *rc = -ENOMEM; kfree(hp_errlog_copy); - complete(hotplug_done); } } @@ -521,18 +512,15 @@ static int dlpar_parse_id_type(char **cmd, struct pseries_hp_errorlog *hp_elog) static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { - struct pseries_hp_errorlog *hp_elog; - struct completion hotplug_done; + struct pseries_hp_errorlog hp_elog; char *argbuf; char *args; int rc; args = argbuf = kstrdup(buf, GFP_KERNEL); - hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL); - if (!hp_elog || !argbuf) { + if (!argbuf) { pr_info("Could not allocate resources for DLPAR operation\n"); kfree(argbuf); - kfree(hp_elog); return -ENOMEM; } @@ -540,25 +528,22 @@ static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, * Parse out the request from the user, this will be in the form: * <resource> <action> <id_type> <id> */ - rc = dlpar_parse_resource(&args, hp_elog); + rc = dlpar_parse_resource(&args, &hp_elog); if (rc) goto dlpar_store_out; - rc = dlpar_parse_action(&args, hp_elog); + rc = dlpar_parse_action(&args, &hp_elog); if (rc) goto dlpar_store_out; - rc = dlpar_parse_id_type(&args, hp_elog); + rc = dlpar_parse_id_type(&args, &hp_elog); if (rc) goto dlpar_store_out; - init_completion(&hotplug_done); - queue_hotplug_event(hp_elog, &hotplug_done, &rc); - wait_for_completion(&hotplug_done); + rc = handle_dlpar_errorlog(&hp_elog); dlpar_store_out: kfree(argbuf); - kfree(hp_elog); if (rc) pr_err("Could not handle DLPAR request \"%s\"\n", buf); diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 18014cdeb590..ef6595153642 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c @@ -149,7 +149,7 @@ static int dtl_start(struct dtl *dtl) /* Register our dtl buffer with the hypervisor. The HV expects the * buffer size to be passed in the second word of the buffer */ - ((u32 *)dtl->buf)[1] = DISPATCH_LOG_BYTES; + ((u32 *)dtl->buf)[1] = cpu_to_be32(DISPATCH_LOG_BYTES); hwcpu = get_hard_smp_processor_id(dtl->cpu); addr = __pa(dtl->buf); @@ -184,7 +184,7 @@ static void dtl_stop(struct dtl *dtl) static u64 dtl_current_index(struct dtl *dtl) { - return lppaca_of(dtl->cpu).dtl_idx; + return be64_to_cpu(lppaca_of(dtl->cpu).dtl_idx); } #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 823cb27efa8b..c9e5ca4afb26 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -438,7 +438,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) /** * pseries_eeh_get_state - Retrieve PE state * @pe: EEH PE - * @state: return value + * @delay: suggested time to wait if state is unavailable * * Retrieve the state of the specified PE. On RTAS compliant * pseries platform, there already has one dedicated RTAS function @@ -448,7 +448,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) * RTAS calls for the purpose, we need to try the new one and back * to the old one if the new one couldn't work properly. */ -static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) +static int pseries_eeh_get_state(struct eeh_pe *pe, int *delay) { int config_addr; int ret; @@ -499,7 +499,8 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) break; case 5: if (rets[2]) { - if (state) *state = rets[2]; + if (delay) + *delay = rets[2]; result = EEH_STATE_UNAVAILABLE; } else { result = EEH_STATE_NOT_SUPPORT; @@ -554,64 +555,6 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option) } /** - * pseries_eeh_wait_state - Wait for PE state - * @pe: EEH PE - * @max_wait: maximal period in millisecond - * - * Wait for the state of associated PE. It might take some time - * to retrieve the PE's state. - */ -static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait) -{ - int ret; - int mwait; - - /* - * According to PAPR, the state of PE might be temporarily - * unavailable. Under the circumstance, we have to wait - * for indicated time determined by firmware. The maximal - * wait time is 5 minutes, which is acquired from the original - * EEH implementation. Also, the original implementation - * also defined the minimal wait time as 1 second. - */ -#define EEH_STATE_MIN_WAIT_TIME (1000) -#define EEH_STATE_MAX_WAIT_TIME (300 * 1000) - - while (1) { - ret = pseries_eeh_get_state(pe, &mwait); - - /* - * If the PE's state is temporarily unavailable, - * we have to wait for the specified time. Otherwise, - * the PE's state will be returned immediately. - */ - if (ret != EEH_STATE_UNAVAILABLE) - return ret; - - if (max_wait <= 0) { - pr_warn("%s: Timeout when getting PE's state (%d)\n", - __func__, max_wait); - return EEH_STATE_NOT_SUPPORT; - } - - if (mwait <= 0) { - pr_warn("%s: Firmware returned bad wait value %d\n", - __func__, mwait); - mwait = EEH_STATE_MIN_WAIT_TIME; - } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { - pr_warn("%s: Firmware returned too long wait value %d\n", - __func__, mwait); - mwait = EEH_STATE_MAX_WAIT_TIME; - } - - max_wait -= mwait; - msleep(mwait); - } - - return EEH_STATE_NOT_SUPPORT; -} - -/** * pseries_eeh_get_log - Retrieve error log * @pe: EEH PE * @severity: temporary or permanent error log @@ -849,7 +792,6 @@ static struct eeh_ops pseries_eeh_ops = { .get_pe_addr = pseries_eeh_get_pe_addr, .get_state = pseries_eeh_get_state, .reset = pseries_eeh_reset, - .wait_state = pseries_eeh_wait_state, .get_log = pseries_eeh_get_log, .configure_bridge = pseries_eeh_configure_bridge, .err_inject = NULL, diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c index 6eeb0d4bab61..446ef104fb3a 100644 --- a/arch/powerpc/platforms/pseries/event_sources.c +++ b/arch/powerpc/platforms/pseries/event_sources.c @@ -16,7 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <asm/prom.h> +#include <linux/interrupt.h> +#include <linux/of_irq.h> #include "pseries.h" @@ -24,34 +25,19 @@ void request_event_sources_irqs(struct device_node *np, irq_handler_t handler, const char *name) { - int i, index, count = 0; - struct of_phandle_args oirq; - unsigned int virqs[16]; + int i, virq, rc; - /* First try to do a proper OF tree parsing */ - for (index = 0; of_irq_parse_one(np, index, &oirq) == 0; - index++) { - if (count > 15) - break; - virqs[count] = irq_create_of_mapping(&oirq); - if (!virqs[count]) { - pr_err("event-sources: Unable to allocate " - "interrupt number for %pOF\n", - np); - WARN_ON(1); - } else { - count++; - } - } + for (i = 0; i < 16; i++) { + virq = of_irq_get(np, i); + if (virq < 0) + return; + if (WARN(!virq, "event-sources: Unable to allocate " + "interrupt number for %pOF\n", np)) + continue; - /* Now request them */ - for (i = 0; i < count; i++) { - if (request_irq(virqs[i], handler, 0, name, NULL)) { - pr_err("event-sources: Unable to request interrupt " - "%d for %pOF\n", virqs[i], np); - WARN_ON(1); + rc = request_irq(virq, handler, 0, name, NULL); + if (WARN(rc, "event-sources: Unable to request interrupt %d for %pOF\n", + virq, np)) return; - } } } - diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index a3bbeb43689e..608ecad0178f 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -65,6 +65,8 @@ hypertas_fw_features_table[] = { {FW_FEATURE_SET_MODE, "hcall-set-mode"}, {FW_FEATURE_BEST_ENERGY, "hcall-best-energy-1*"}, {FW_FEATURE_HPT_RESIZE, "hcall-hpt-resize"}, + {FW_FEATURE_BLOCK_REMOVE, "hcall-block-remove"}, + {FW_FEATURE_PAPR_SCM, "hcall-scm"}, }; /* Build up the firmware features bitmask using the contents of diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 6ef77caf7bcf..2f8e62163602 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -287,7 +287,7 @@ static int pseries_add_processor(struct device_node *np) if (cpumask_empty(tmp)) { printk(KERN_ERR "Unable to find space in cpu_present_mask for" - " processor %s with %d thread(s)\n", np->name, + " processor %pOFn with %d thread(s)\n", np, nthreads); goto out_unlock; } @@ -481,8 +481,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index) if (rc) { saved_rc = rc; - pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n", - dn->name, rc, drc_index); + pr_warn("Failed to attach node %pOFn, rc: %d, drc index: %x\n", + dn, rc, drc_index); rc = dlpar_release_drc(drc_index); if (!rc) @@ -494,8 +494,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index) rc = dlpar_online_cpu(dn); if (rc) { saved_rc = rc; - pr_warn("Failed to online cpu %s, rc: %d, drc index: %x\n", - dn->name, rc, drc_index); + pr_warn("Failed to online cpu %pOFn, rc: %d, drc index: %x\n", + dn, rc, drc_index); rc = dlpar_detach_node(dn); if (!rc) @@ -504,7 +504,7 @@ static ssize_t dlpar_cpu_add(u32 drc_index) return saved_rc; } - pr_debug("Successfully added CPU %s, drc index: %x\n", dn->name, + pr_debug("Successfully added CPU %pOFn, drc index: %x\n", dn, drc_index); return rc; } @@ -570,19 +570,19 @@ static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index) { int rc; - pr_debug("Attempting to remove CPU %s, drc index: %x\n", - dn->name, drc_index); + pr_debug("Attempting to remove CPU %pOFn, drc index: %x\n", + dn, drc_index); rc = dlpar_offline_cpu(dn); if (rc) { - pr_warn("Failed to offline CPU %s, rc: %d\n", dn->name, rc); + pr_warn("Failed to offline CPU %pOFn, rc: %d\n", dn, rc); return -EINVAL; } rc = dlpar_release_drc(drc_index); if (rc) { - pr_warn("Failed to release drc (%x) for CPU %s, rc: %d\n", - drc_index, dn->name, rc); + pr_warn("Failed to release drc (%x) for CPU %pOFn, rc: %d\n", + drc_index, dn, rc); dlpar_online_cpu(dn); return rc; } @@ -591,7 +591,7 @@ static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index) if (rc) { int saved_rc = rc; - pr_warn("Failed to detach CPU %s, rc: %d", dn->name, rc); + pr_warn("Failed to detach CPU %pOFn, rc: %d", dn, rc); rc = dlpar_acquire_drc(drc_index); if (!rc) @@ -662,8 +662,8 @@ static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove) rc = of_property_read_u32(dn, "ibm,my-drc-index", &cpu_drcs[cpus_found - 1]); if (rc) { - pr_warn("Error occurred getting drc-index for %s\n", - dn->name); + pr_warn("Error occurred getting drc-index for %pOFn\n", + dn); of_node_put(dn); return -1; } diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index c1578f54c626..2b796da822c2 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -101,11 +101,12 @@ static struct property *dlpar_clone_property(struct property *prop, return new_prop; } -static u32 find_aa_index(struct device_node *dr_node, - struct property *ala_prop, const u32 *lmb_assoc) +static bool find_aa_index(struct device_node *dr_node, + struct property *ala_prop, + const u32 *lmb_assoc, u32 *aa_index) { - u32 *assoc_arrays; - u32 aa_index; + u32 *assoc_arrays, new_prop_size; + struct property *new_prop; int aa_arrays, aa_array_entries, aa_array_sz; int i, index; @@ -121,54 +122,48 @@ static u32 find_aa_index(struct device_node *dr_node, aa_array_entries = be32_to_cpu(assoc_arrays[1]); aa_array_sz = aa_array_entries * sizeof(u32); - aa_index = -1; for (i = 0; i < aa_arrays; i++) { index = (i * aa_array_entries) + 2; if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz)) continue; - aa_index = i; - break; + *aa_index = i; + return true; } - if (aa_index == -1) { - struct property *new_prop; - u32 new_prop_size; - - new_prop_size = ala_prop->length + aa_array_sz; - new_prop = dlpar_clone_property(ala_prop, new_prop_size); - if (!new_prop) - return -1; - - assoc_arrays = new_prop->value; + new_prop_size = ala_prop->length + aa_array_sz; + new_prop = dlpar_clone_property(ala_prop, new_prop_size); + if (!new_prop) + return false; - /* increment the number of entries in the lookup array */ - assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); + assoc_arrays = new_prop->value; - /* copy the new associativity into the lookup array */ - index = aa_arrays * aa_array_entries + 2; - memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); + /* increment the number of entries in the lookup array */ + assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); - of_update_property(dr_node, new_prop); + /* copy the new associativity into the lookup array */ + index = aa_arrays * aa_array_entries + 2; + memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); - /* - * The associativity lookup array index for this lmb is - * number of entries - 1 since we added its associativity - * to the end of the lookup array. - */ - aa_index = be32_to_cpu(assoc_arrays[0]) - 1; - } + of_update_property(dr_node, new_prop); - return aa_index; + /* + * The associativity lookup array index for this lmb is + * number of entries - 1 since we added its associativity + * to the end of the lookup array. + */ + *aa_index = be32_to_cpu(assoc_arrays[0]) - 1; + return true; } -static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) +static int update_lmb_associativity_index(struct drmem_lmb *lmb) { struct device_node *parent, *lmb_node, *dr_node; struct property *ala_prop; const u32 *lmb_assoc; u32 aa_index; + bool found; parent = of_find_node_by_path("/"); if (!parent) @@ -200,46 +195,17 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) return -ENODEV; } - aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); + found = find_aa_index(dr_node, ala_prop, lmb_assoc, &aa_index); dlpar_free_cc_nodes(lmb_node); - return aa_index; -} -static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb) -{ - int rc, aa_index; - - lmb->flags |= DRCONF_MEM_ASSIGNED; - - aa_index = lookup_lmb_associativity_index(lmb); - if (aa_index < 0) { - pr_err("Couldn't find associativity index for drc index %x\n", - lmb->drc_index); - return aa_index; + if (!found) { + pr_err("Could not find LMB associativity\n"); + return -1; } lmb->aa_index = aa_index; - - rtas_hp_event = true; - rc = drmem_update_dt(); - rtas_hp_event = false; - - return rc; -} - -static int dlpar_remove_device_tree_lmb(struct drmem_lmb *lmb) -{ - int rc; - - lmb->flags &= ~DRCONF_MEM_ASSIGNED; - lmb->aa_index = 0xffffffff; - - rtas_hp_event = true; - rc = drmem_update_dt(); - rtas_hp_event = false; - - return rc; + return 0; } static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) @@ -428,7 +394,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) /* Update memory regions for memory remove */ memblock_remove(lmb->base_addr, block_sz); - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); + lmb->flags &= ~DRCONF_MEM_ASSIGNED; + return 0; } @@ -688,10 +656,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) if (lmb->flags & DRCONF_MEM_ASSIGNED) return -EINVAL; - rc = dlpar_add_device_tree_lmb(lmb); + rc = update_lmb_associativity_index(lmb); if (rc) { - pr_err("Couldn't update device tree for drc index %x\n", - lmb->drc_index); dlpar_release_drc(lmb->drc_index); return rc; } @@ -704,14 +670,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) /* Add the memory */ rc = add_memory(nid, lmb->base_addr, block_sz); if (rc) { - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); return rc; } rc = dlpar_online_lmb(lmb); if (rc) { remove_memory(nid, lmb->base_addr, block_sz); - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); } else { lmb->flags |= DRCONF_MEM_ASSIGNED; } @@ -958,6 +924,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) break; } + if (!rc) { + rtas_hp_event = true; + rc = drmem_update_dt(); + rtas_hp_event = false; + } + unlock_device_hotplug(); return rc; } diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c index c7c1140c13b6..5b4a56131904 100644 --- a/arch/powerpc/platforms/pseries/ibmebus.c +++ b/arch/powerpc/platforms/pseries/ibmebus.c @@ -404,7 +404,7 @@ static ssize_t name_show(struct device *dev, struct platform_device *ofdev; ofdev = to_platform_device(dev); - return sprintf(buf, "%s\n", ofdev->dev.of_node->name); + return sprintf(buf, "%pOFn\n", ofdev->dev.of_node); } static DEVICE_ATTR_RO(name); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index d3992ced0782..32d4452973e7 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -48,6 +48,7 @@ #include <asm/kexec.h> #include <asm/fadump.h> #include <asm/asm-prototypes.h> +#include <asm/debugfs.h> #include "pseries.h" @@ -417,6 +418,79 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn, BUG_ON(lpar_rc != H_SUCCESS); } + +/* + * As defined in the PAPR's section 14.5.4.1.8 + * The control mask doesn't include the returned reference and change bit from + * the processed PTE. + */ +#define HBLKR_AVPN 0x0100000000000000UL +#define HBLKR_CTRL_MASK 0xf800000000000000UL +#define HBLKR_CTRL_SUCCESS 0x8000000000000000UL +#define HBLKR_CTRL_ERRNOTFOUND 0x8800000000000000UL +#define HBLKR_CTRL_ERRBUSY 0xa000000000000000UL + +/** + * H_BLOCK_REMOVE caller. + * @idx should point to the latest @param entry set with a PTEX. + * If PTE cannot be processed because another CPUs has already locked that + * group, those entries are put back in @param starting at index 1. + * If entries has to be retried and @retry_busy is set to true, these entries + * are retried until success. If @retry_busy is set to false, the returned + * is the number of entries yet to process. + */ +static unsigned long call_block_remove(unsigned long idx, unsigned long *param, + bool retry_busy) +{ + unsigned long i, rc, new_idx; + unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; + + if (idx < 2) { + pr_warn("Unexpected empty call to H_BLOCK_REMOVE"); + return 0; + } +again: + new_idx = 0; + if (idx > PLPAR_HCALL9_BUFSIZE) { + pr_err("Too many PTEs (%lu) for H_BLOCK_REMOVE", idx); + idx = PLPAR_HCALL9_BUFSIZE; + } else if (idx < PLPAR_HCALL9_BUFSIZE) + param[idx] = HBR_END; + + rc = plpar_hcall9(H_BLOCK_REMOVE, retbuf, + param[0], /* AVA */ + param[1], param[2], param[3], param[4], /* TS0-7 */ + param[5], param[6], param[7], param[8]); + if (rc == H_SUCCESS) + return 0; + + BUG_ON(rc != H_PARTIAL); + + /* Check that the unprocessed entries were 'not found' or 'busy' */ + for (i = 0; i < idx-1; i++) { + unsigned long ctrl = retbuf[i] & HBLKR_CTRL_MASK; + + if (ctrl == HBLKR_CTRL_ERRBUSY) { + param[++new_idx] = param[i+1]; + continue; + } + + BUG_ON(ctrl != HBLKR_CTRL_SUCCESS + && ctrl != HBLKR_CTRL_ERRNOTFOUND); + } + + /* + * If there were entries found busy, retry these entries if requested, + * of if all the entries have to be retried. + */ + if (new_idx && (retry_busy || new_idx == (PLPAR_HCALL9_BUFSIZE-1))) { + idx = new_idx + 1; + goto again; + } + + return new_idx; +} + #ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need @@ -424,17 +498,57 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn, */ #define PPC64_HUGE_HPTE_BATCH 12 -static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, - unsigned long *vpn, int count, - int psize, int ssize) +static void hugepage_block_invalidate(unsigned long *slot, unsigned long *vpn, + int count, int psize, int ssize) { unsigned long param[PLPAR_HCALL9_BUFSIZE]; - int i = 0, pix = 0, rc; - unsigned long flags = 0; - int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); + unsigned long shift, current_vpgb, vpgb; + int i, pix = 0; - if (lock_tlbie) - spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); + shift = mmu_psize_defs[psize].shift; + + for (i = 0; i < count; i++) { + /* + * Shifting 3 bits more on the right to get a + * 8 pages aligned virtual addresse. + */ + vpgb = (vpn[i] >> (shift - VPN_SHIFT + 3)); + if (!pix || vpgb != current_vpgb) { + /* + * Need to start a new 8 pages block, flush + * the current one if needed. + */ + if (pix) + (void)call_block_remove(pix, param, true); + current_vpgb = vpgb; + param[0] = hpte_encode_avpn(vpn[i], psize, ssize); + pix = 1; + } + + param[pix++] = HBR_REQUEST | HBLKR_AVPN | slot[i]; + if (pix == PLPAR_HCALL9_BUFSIZE) { + pix = call_block_remove(pix, param, false); + /* + * pix = 0 means that all the entries were + * removed, we can start a new block. + * Otherwise, this means that there are entries + * to retry, and pix points to latest one, so + * we should increment it and try to continue + * the same block. + */ + if (pix) + pix++; + } + } + if (pix) + (void)call_block_remove(pix, param, true); +} + +static void hugepage_bulk_invalidate(unsigned long *slot, unsigned long *vpn, + int count, int psize, int ssize) +{ + unsigned long param[PLPAR_HCALL9_BUFSIZE]; + int i = 0, pix = 0, rc; for (i = 0; i < count; i++) { @@ -462,6 +576,23 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, param[6], param[7]); BUG_ON(rc != H_SUCCESS); } +} + +static inline void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, + unsigned long *vpn, + int count, int psize, + int ssize) +{ + unsigned long flags = 0; + int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); + + if (lock_tlbie) + spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); + + if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) + hugepage_block_invalidate(slot, vpn, count, psize, ssize); + else + hugepage_bulk_invalidate(slot, vpn, count, psize, ssize); if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); @@ -546,6 +677,86 @@ static int pSeries_lpar_hpte_removebolted(unsigned long ea, return 0; } + +static inline unsigned long compute_slot(real_pte_t pte, + unsigned long vpn, + unsigned long index, + unsigned long shift, + int ssize) +{ + unsigned long slot, hash, hidx; + + hash = hpt_hash(vpn, shift, ssize); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + return slot; +} + +/** + * The hcall H_BLOCK_REMOVE implies that the virtual pages to processed are + * "all within the same naturally aligned 8 page virtual address block". + */ +static void do_block_remove(unsigned long number, struct ppc64_tlb_batch *batch, + unsigned long *param) +{ + unsigned long vpn; + unsigned long i, pix = 0; + unsigned long index, shift, slot, current_vpgb, vpgb; + real_pte_t pte; + int psize, ssize; + + psize = batch->psize; + ssize = batch->ssize; + + for (i = 0; i < number; i++) { + vpn = batch->vpn[i]; + pte = batch->pte[i]; + pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { + /* + * Shifting 3 bits more on the right to get a + * 8 pages aligned virtual addresse. + */ + vpgb = (vpn >> (shift - VPN_SHIFT + 3)); + if (!pix || vpgb != current_vpgb) { + /* + * Need to start a new 8 pages block, flush + * the current one if needed. + */ + if (pix) + (void)call_block_remove(pix, param, + true); + current_vpgb = vpgb; + param[0] = hpte_encode_avpn(vpn, psize, + ssize); + pix = 1; + } + + slot = compute_slot(pte, vpn, index, shift, ssize); + param[pix++] = HBR_REQUEST | HBLKR_AVPN | slot; + + if (pix == PLPAR_HCALL9_BUFSIZE) { + pix = call_block_remove(pix, param, false); + /* + * pix = 0 means that all the entries were + * removed, we can start a new block. + * Otherwise, this means that there are entries + * to retry, and pix points to latest one, so + * we should increment it and try to continue + * the same block. + */ + if (pix) + pix++; + } + } pte_iterate_hashed_end(); + } + + if (pix) + (void)call_block_remove(pix, param, true); +} + /* * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. @@ -558,13 +769,18 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); unsigned long param[PLPAR_HCALL9_BUFSIZE]; - unsigned long hash, index, shift, hidx, slot; + unsigned long index, shift, slot; real_pte_t pte; int psize, ssize; if (lock_tlbie) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); + if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) { + do_block_remove(number, batch, param); + goto out; + } + psize = batch->psize; ssize = batch->ssize; pix = 0; @@ -572,12 +788,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) vpn = batch->vpn[i]; pte = batch->pte[i]; pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { - hash = hpt_hash(vpn, shift, ssize); - hidx = __rpte_to_hidx(pte, index); - if (hidx & _PTEIDX_SECONDARY) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += hidx & _PTEIDX_GROUP_IX; + slot = compute_slot(pte, vpn, index, shift, ssize); if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { /* * lpar doesn't use the passed actual page size @@ -608,6 +819,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) BUG_ON(rc != H_SUCCESS); } +out: if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); } @@ -1028,3 +1240,56 @@ static int __init reserve_vrma_context_id(void) return 0; } machine_device_initcall(pseries, reserve_vrma_context_id); + +#ifdef CONFIG_DEBUG_FS +/* debugfs file interface for vpa data */ +static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len, + loff_t *pos) +{ + int cpu = (long)filp->private_data; + struct lppaca *lppaca = &lppaca_of(cpu); + + return simple_read_from_buffer(buf, len, pos, lppaca, + sizeof(struct lppaca)); +} + +static const struct file_operations vpa_fops = { + .open = simple_open, + .read = vpa_file_read, + .llseek = default_llseek, +}; + +static int __init vpa_debugfs_init(void) +{ + char name[16]; + long i; + static struct dentry *vpa_dir; + + if (!firmware_has_feature(FW_FEATURE_SPLPAR)) + return 0; + + vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root); + if (!vpa_dir) { + pr_warn("%s: can't create vpa root dir\n", __func__); + return -ENOMEM; + } + + /* set up the per-cpu vpa file*/ + for_each_possible_cpu(i) { + struct dentry *d; + + sprintf(name, "cpu-%ld", i); + + d = debugfs_create_file(name, 0400, vpa_dir, (void *)i, + &vpa_fops); + if (!d) { + pr_warn("%s: can't create per-cpu vpa file\n", + __func__); + return -ENOMEM; + } + } + + return 0; +} +machine_arch_initcall(pseries, vpa_debugfs_init); +#endif /* CONFIG_DEBUG_FS */ diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 7c872dc01bdb..8bd590af488a 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c @@ -585,8 +585,7 @@ static ssize_t update_mpp(u64 *entitlement, u8 *weight) static ssize_t lparcfg_write(struct file *file, const char __user * buf, size_t count, loff_t * off) { - int kbuf_sz = 64; - char kbuf[kbuf_sz]; + char kbuf[64]; char *tmp; u64 new_entitled, *new_entitled_ptr = &new_entitled; u8 new_weight, *new_weight_ptr = &new_weight; @@ -595,7 +594,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, if (!firmware_has_feature(FW_FEATURE_SPLPAR)) return -EINVAL; - if (count > kbuf_sz) + if (count > sizeof(kbuf)) return -EINVAL; if (copy_from_user(kbuf, buf, count)) diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index f0e30dc94988..88925f8ca8a0 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -242,7 +242,7 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) static void prrn_update_node(__be32 phandle) { - struct pseries_hp_errorlog *hp_elog; + struct pseries_hp_errorlog hp_elog; struct device_node *dn; /* @@ -255,18 +255,12 @@ static void prrn_update_node(__be32 phandle) return; } - hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL); - if(!hp_elog) - return; - - hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM; - hp_elog->action = PSERIES_HP_ELOG_ACTION_READD; - hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; - hp_elog->_drc_u.drc_index = phandle; - - queue_hotplug_event(hp_elog, NULL, NULL); + hp_elog.resource = PSERIES_HP_ELOG_RESOURCE_MEM; + hp_elog.action = PSERIES_HP_ELOG_ACTION_READD; + hp_elog.id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; + hp_elog._drc_u.drc_index = phandle; - kfree(hp_elog); + handle_dlpar_errorlog(&hp_elog); } int pseries_devicetree_update(s32 scope) @@ -366,6 +360,8 @@ static ssize_t migration_store(struct class *class, if (rc) return rc; + stop_topology_update(); + do { rc = rtas_ibm_suspend_me(streamid); if (rc == -EAGAIN) @@ -376,6 +372,9 @@ static ssize_t migration_store(struct class *class, return rc; post_mobility_fixup(); + + start_topology_update(); + return count; } diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index b7496948129e..8011b4129e3a 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -203,7 +203,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) /* Get the top level device in the PE */ edev = pdn_to_eeh_dev(PCI_DN(dn)); if (edev->pe) - edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); + edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, + entry); dn = pci_device_to_OF_node(edev->pdev); if (!dn) return NULL; diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c new file mode 100644 index 000000000000..ee9372b65ca5 --- /dev/null +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define pr_fmt(fmt) "papr-scm: " fmt + +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/ndctl.h> +#include <linux/sched.h> +#include <linux/libnvdimm.h> +#include <linux/platform_device.h> + +#include <asm/plpar_wrappers.h> + +#define BIND_ANY_ADDR (~0ul) + +#define PAPR_SCM_DIMM_CMD_MASK \ + ((1ul << ND_CMD_GET_CONFIG_SIZE) | \ + (1ul << ND_CMD_GET_CONFIG_DATA) | \ + (1ul << ND_CMD_SET_CONFIG_DATA)) + +struct papr_scm_priv { + struct platform_device *pdev; + struct device_node *dn; + uint32_t drc_index; + uint64_t blocks; + uint64_t block_size; + int metadata_size; + + uint64_t bound_addr; + + struct nvdimm_bus_descriptor bus_desc; + struct nvdimm_bus *bus; + struct nvdimm *nvdimm; + struct resource res; + struct nd_region *region; + struct nd_interleave_set nd_set; +}; + +static int drc_pmem_bind(struct papr_scm_priv *p) +{ + unsigned long ret[PLPAR_HCALL_BUFSIZE]; + uint64_t rc, token; + + /* + * When the hypervisor cannot map all the requested memory in a single + * hcall it returns H_BUSY and we call again with the token until + * we get H_SUCCESS. Aborting the retry loop before getting H_SUCCESS + * leave the system in an undefined state, so we wait. + */ + token = 0; + + do { + rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0, + p->blocks, BIND_ANY_ADDR, token); + token = be64_to_cpu(ret[0]); + cond_resched(); + } while (rc == H_BUSY); + + if (rc) { + dev_err(&p->pdev->dev, "bind err: %lld\n", rc); + return -ENXIO; + } + + p->bound_addr = be64_to_cpu(ret[1]); + + dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res); + + return 0; +} + +static int drc_pmem_unbind(struct papr_scm_priv *p) +{ + unsigned long ret[PLPAR_HCALL_BUFSIZE]; + uint64_t rc, token; + + token = 0; + + /* NB: unbind has the same retry requirements mentioned above */ + do { + rc = plpar_hcall(H_SCM_UNBIND_MEM, ret, p->drc_index, + p->bound_addr, p->blocks, token); + token = be64_to_cpu(ret); + cond_resched(); + } while (rc == H_BUSY); + + if (rc) + dev_err(&p->pdev->dev, "unbind error: %lld\n", rc); + + return !!rc; +} + +static int papr_scm_meta_get(struct papr_scm_priv *p, + struct nd_cmd_get_config_data_hdr *hdr) +{ + unsigned long data[PLPAR_HCALL_BUFSIZE]; + int64_t ret; + + if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1) + return -EINVAL; + + ret = plpar_hcall(H_SCM_READ_METADATA, data, p->drc_index, + hdr->in_offset, 1); + + if (ret == H_PARAMETER) /* bad DRC index */ + return -ENODEV; + if (ret) + return -EINVAL; /* other invalid parameter */ + + hdr->out_buf[0] = data[0] & 0xff; + + return 0; +} + +static int papr_scm_meta_set(struct papr_scm_priv *p, + struct nd_cmd_set_config_hdr *hdr) +{ + int64_t ret; + + if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1) + return -EINVAL; + + ret = plpar_hcall_norets(H_SCM_WRITE_METADATA, + p->drc_index, hdr->in_offset, hdr->in_buf[0], 1); + + if (ret == H_PARAMETER) /* bad DRC index */ + return -ENODEV; + if (ret) + return -EINVAL; /* other invalid parameter */ + + return 0; +} + +int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) +{ + struct nd_cmd_get_config_size *get_size_hdr; + struct papr_scm_priv *p; + + /* Only dimm-specific calls are supported atm */ + if (!nvdimm) + return -EINVAL; + + p = nvdimm_provider_data(nvdimm); + + switch (cmd) { + case ND_CMD_GET_CONFIG_SIZE: + get_size_hdr = buf; + + get_size_hdr->status = 0; + get_size_hdr->max_xfer = 1; + get_size_hdr->config_size = p->metadata_size; + *cmd_rc = 0; + break; + + case ND_CMD_GET_CONFIG_DATA: + *cmd_rc = papr_scm_meta_get(p, buf); + break; + + case ND_CMD_SET_CONFIG_DATA: + *cmd_rc = papr_scm_meta_set(p, buf); + break; + + default: + return -EINVAL; + } + + dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc); + + return 0; +} + +static const struct attribute_group *region_attr_groups[] = { + &nd_region_attribute_group, + &nd_device_attribute_group, + &nd_mapping_attribute_group, + &nd_numa_attribute_group, + NULL, +}; + +static const struct attribute_group *bus_attr_groups[] = { + &nvdimm_bus_attribute_group, + NULL, +}; + +static const struct attribute_group *papr_scm_dimm_groups[] = { + &nvdimm_attribute_group, + &nd_device_attribute_group, + NULL, +}; + +static int papr_scm_nvdimm_init(struct papr_scm_priv *p) +{ + struct device *dev = &p->pdev->dev; + struct nd_mapping_desc mapping; + struct nd_region_desc ndr_desc; + unsigned long dimm_flags; + + p->bus_desc.ndctl = papr_scm_ndctl; + p->bus_desc.module = THIS_MODULE; + p->bus_desc.of_node = p->pdev->dev.of_node; + p->bus_desc.attr_groups = bus_attr_groups; + p->bus_desc.provider_name = kstrdup(p->pdev->name, GFP_KERNEL); + + if (!p->bus_desc.provider_name) + return -ENOMEM; + + p->bus = nvdimm_bus_register(NULL, &p->bus_desc); + if (!p->bus) { + dev_err(dev, "Error creating nvdimm bus %pOF\n", p->dn); + return -ENXIO; + } + + dimm_flags = 0; + set_bit(NDD_ALIASING, &dimm_flags); + + p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_groups, + dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL); + if (!p->nvdimm) { + dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn); + goto err; + } + + /* now add the region */ + + memset(&mapping, 0, sizeof(mapping)); + mapping.nvdimm = p->nvdimm; + mapping.start = 0; + mapping.size = p->blocks * p->block_size; // XXX: potential overflow? + + memset(&ndr_desc, 0, sizeof(ndr_desc)); + ndr_desc.attr_groups = region_attr_groups; + ndr_desc.numa_node = dev_to_node(&p->pdev->dev); + ndr_desc.res = &p->res; + ndr_desc.of_node = p->dn; + ndr_desc.provider_data = p; + ndr_desc.mapping = &mapping; + ndr_desc.num_mappings = 1; + ndr_desc.nd_set = &p->nd_set; + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags); + + p->region = nvdimm_pmem_region_create(p->bus, &ndr_desc); + if (!p->region) { + dev_err(dev, "Error registering region %pR from %pOF\n", + ndr_desc.res, p->dn); + goto err; + } + + return 0; + +err: nvdimm_bus_unregister(p->bus); + kfree(p->bus_desc.provider_name); + return -ENXIO; +} + +static int papr_scm_probe(struct platform_device *pdev) +{ + uint32_t drc_index, metadata_size, unit_cap[2]; + struct device_node *dn = pdev->dev.of_node; + struct papr_scm_priv *p; + int rc; + + /* check we have all the required DT properties */ + if (of_property_read_u32(dn, "ibm,my-drc-index", &drc_index)) { + dev_err(&pdev->dev, "%pOF: missing drc-index!\n", dn); + return -ENODEV; + } + + if (of_property_read_u32_array(dn, "ibm,unit-capacity", unit_cap, 2)) { + dev_err(&pdev->dev, "%pOF: missing unit-capacity!\n", dn); + return -ENODEV; + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + /* optional DT properties */ + of_property_read_u32(dn, "ibm,metadata-size", &metadata_size); + + p->dn = dn; + p->drc_index = drc_index; + p->block_size = unit_cap[0]; + p->blocks = unit_cap[1]; + + /* might be zero */ + p->metadata_size = metadata_size; + p->pdev = pdev; + + /* request the hypervisor to bind this region to somewhere in memory */ + rc = drc_pmem_bind(p); + if (rc) + goto err; + + /* setup the resource for the newly bound range */ + p->res.start = p->bound_addr; + p->res.end = p->bound_addr + p->blocks * p->block_size; + p->res.name = pdev->name; + p->res.flags = IORESOURCE_MEM; + + rc = papr_scm_nvdimm_init(p); + if (rc) + goto err2; + + platform_set_drvdata(pdev, p); + + return 0; + +err2: drc_pmem_unbind(p); +err: kfree(p); + return rc; +} + +static int papr_scm_remove(struct platform_device *pdev) +{ + struct papr_scm_priv *p = platform_get_drvdata(pdev); + + nvdimm_bus_unregister(p->bus); + drc_pmem_unbind(p); + kfree(p); + + return 0; +} + +static const struct of_device_id papr_scm_match[] = { + { .compatible = "ibm,pmemory" }, + { }, +}; + +static struct platform_driver papr_scm_driver = { + .probe = papr_scm_probe, + .remove = papr_scm_remove, + .driver = { + .name = "papr_scm", + .owner = THIS_MODULE, + .of_match_table = papr_scm_match, + }, +}; + +module_platform_driver(papr_scm_driver); +MODULE_DEVICE_TABLE(of, papr_scm_match); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("IBM Corporation"); diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index eab96637d6cf..41d8a4d1d02e 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -239,6 +239,7 @@ void __init pSeries_final_fixup(void) { pSeries_request_regions(); + eeh_probe_devices(); eeh_addr_cache_build(); #ifdef CONFIG_PCI_IOV diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c new file mode 100644 index 000000000000..a27f40eb57b1 --- /dev/null +++ b/arch/powerpc/platforms/pseries/pmem.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Handles hot and cold plug of persistent memory regions on pseries. + */ + +#define pr_fmt(fmt) "pseries-pmem: " fmt + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/sched.h> /* for idle_task_exit */ +#include <linux/sched/hotplug.h> +#include <linux/cpu.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/slab.h> +#include <asm/prom.h> +#include <asm/rtas.h> +#include <asm/firmware.h> +#include <asm/machdep.h> +#include <asm/vdso_datapage.h> +#include <asm/plpar_wrappers.h> +#include <asm/topology.h> + +#include "pseries.h" +#include "offline_states.h" + +static struct device_node *pmem_node; + +static ssize_t pmem_drc_add_node(u32 drc_index) +{ + struct device_node *dn; + int rc; + + pr_debug("Attempting to add pmem node, drc index: %x\n", drc_index); + + rc = dlpar_acquire_drc(drc_index); + if (rc) { + pr_err("Failed to acquire DRC, rc: %d, drc index: %x\n", + rc, drc_index); + return -EINVAL; + } + + dn = dlpar_configure_connector(cpu_to_be32(drc_index), pmem_node); + if (!dn) { + pr_err("configure-connector failed for drc %x\n", drc_index); + dlpar_release_drc(drc_index); + return -EINVAL; + } + + /* NB: The of reconfig notifier creates platform device from the node */ + rc = dlpar_attach_node(dn, pmem_node); + if (rc) { + pr_err("Failed to attach node %s, rc: %d, drc index: %x\n", + dn->name, rc, drc_index); + + if (dlpar_release_drc(drc_index)) + dlpar_free_cc_nodes(dn); + + return rc; + } + + pr_info("Successfully added %pOF, drc index: %x\n", dn, drc_index); + + return 0; +} + +static ssize_t pmem_drc_remove_node(u32 drc_index) +{ + struct device_node *dn; + uint32_t index; + int rc; + + for_each_child_of_node(pmem_node, dn) { + if (of_property_read_u32(dn, "ibm,my-drc-index", &index)) + continue; + if (index == drc_index) + break; + } + + if (!dn) { + pr_err("Attempting to remove unused DRC index %x\n", drc_index); + return -ENODEV; + } + + pr_debug("Attempting to remove %pOF, drc index: %x\n", dn, drc_index); + + /* * NB: tears down the ibm,pmemory device as a side-effect */ + rc = dlpar_detach_node(dn); + if (rc) + return rc; + + rc = dlpar_release_drc(drc_index); + if (rc) { + pr_err("Failed to release drc (%x) for CPU %s, rc: %d\n", + drc_index, dn->name, rc); + dlpar_attach_node(dn, pmem_node); + return rc; + } + + pr_info("Successfully removed PMEM with drc index: %x\n", drc_index); + + return 0; +} + +int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog) +{ + u32 count, drc_index; + int rc; + + /* slim chance, but we might get a hotplug event while booting */ + if (!pmem_node) + pmem_node = of_find_node_by_type(NULL, "ibm,persistent-memory"); + if (!pmem_node) { + pr_err("Hotplug event for a pmem device, but none exists\n"); + return -ENODEV; + } + + if (hp_elog->id_type != PSERIES_HP_ELOG_ID_DRC_INDEX) { + pr_err("Unsupported hotplug event type %d\n", + hp_elog->id_type); + return -EINVAL; + } + + count = hp_elog->_drc_u.drc_count; + drc_index = hp_elog->_drc_u.drc_index; + + lock_device_hotplug(); + + if (hp_elog->action == PSERIES_HP_ELOG_ACTION_ADD) { + rc = pmem_drc_add_node(drc_index); + } else if (hp_elog->action == PSERIES_HP_ELOG_ACTION_REMOVE) { + rc = pmem_drc_remove_node(drc_index); + } else { + pr_err("Unsupported hotplug action (%d)\n", hp_elog->action); + rc = -EINVAL; + } + + unlock_device_hotplug(); + return rc; +} + +const struct of_device_id drc_pmem_match[] = { + { .type = "ibm,persistent-memory", }, + {} +}; + +static int pseries_pmem_init(void) +{ + pmem_node = of_find_node_by_type(NULL, "ibm,persistent-memory"); + if (!pmem_node) + return 0; + + /* + * The generic OF bus probe/populate handles creating platform devices + * from the child (ibm,pmemory) nodes. The generic code registers an of + * reconfig notifier to handle the hot-add/remove cases too. + */ + of_platform_bus_probe(pmem_node, drc_pmem_match, NULL); + + return 0; +} +machine_arch_initcall(pseries, pseries_pmem_init); diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 60db2ee511fb..7dee8c5d3363 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -24,6 +24,7 @@ struct pt_regs; extern int pSeries_system_reset_exception(struct pt_regs *regs); extern int pSeries_machine_check_exception(struct pt_regs *regs); +extern long pseries_machine_check_realmode(struct pt_regs *regs); #ifdef CONFIG_SMP extern void smp_init_pseries(void); @@ -59,15 +60,21 @@ extern int dlpar_detach_node(struct device_node *); extern int dlpar_acquire_drc(u32 drc_index); extern int dlpar_release_drc(u32 drc_index); -void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, - struct completion *hotplug_done, int *rc); +void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog); +int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_errlog); + #ifdef CONFIG_MEMORY_HOTPLUG int dlpar_memory(struct pseries_hp_errorlog *hp_elog); +int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog); #else static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog) { return -EOPNOTSUPP; } +static inline int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog) +{ + return -EOPNOTSUPP; +} #endif #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 851ce326874a..d97d52772789 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -27,6 +27,7 @@ #include <asm/machdep.h> #include <asm/rtas.h> #include <asm/firmware.h> +#include <asm/mce.h> #include "pseries.h" @@ -50,6 +51,101 @@ static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id); static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); static irqreturn_t ras_error_interrupt(int irq, void *dev_id); +/* RTAS pseries MCE errorlog section. */ +struct pseries_mc_errorlog { + __be32 fru_id; + __be32 proc_id; + u8 error_type; + /* + * sub_err_type (1 byte). Bit fields depends on error_type + * + * MSB0 + * | + * V + * 01234567 + * XXXXXXXX + * + * For error_type == MC_ERROR_TYPE_UE + * XXXXXXXX + * X 1: Permanent or Transient UE. + * X 1: Effective address provided. + * X 1: Logical address provided. + * XX 2: Reserved. + * XXX 3: Type of UE error. + * + * For error_type != MC_ERROR_TYPE_UE + * XXXXXXXX + * X 1: Effective address provided. + * XXXXX 5: Reserved. + * XX 2: Type of SLB/ERAT/TLB error. + */ + u8 sub_err_type; + u8 reserved_1[6]; + __be64 effective_address; + __be64 logical_address; +} __packed; + +/* RTAS pseries MCE error types */ +#define MC_ERROR_TYPE_UE 0x00 +#define MC_ERROR_TYPE_SLB 0x01 +#define MC_ERROR_TYPE_ERAT 0x02 +#define MC_ERROR_TYPE_TLB 0x04 +#define MC_ERROR_TYPE_D_CACHE 0x05 +#define MC_ERROR_TYPE_I_CACHE 0x07 + +/* RTAS pseries MCE error sub types */ +#define MC_ERROR_UE_INDETERMINATE 0 +#define MC_ERROR_UE_IFETCH 1 +#define MC_ERROR_UE_PAGE_TABLE_WALK_IFETCH 2 +#define MC_ERROR_UE_LOAD_STORE 3 +#define MC_ERROR_UE_PAGE_TABLE_WALK_LOAD_STORE 4 + +#define MC_ERROR_SLB_PARITY 0 +#define MC_ERROR_SLB_MULTIHIT 1 +#define MC_ERROR_SLB_INDETERMINATE 2 + +#define MC_ERROR_ERAT_PARITY 1 +#define MC_ERROR_ERAT_MULTIHIT 2 +#define MC_ERROR_ERAT_INDETERMINATE 3 + +#define MC_ERROR_TLB_PARITY 1 +#define MC_ERROR_TLB_MULTIHIT 2 +#define MC_ERROR_TLB_INDETERMINATE 3 + +static inline u8 rtas_mc_error_sub_type(const struct pseries_mc_errorlog *mlog) +{ + switch (mlog->error_type) { + case MC_ERROR_TYPE_UE: + return (mlog->sub_err_type & 0x07); + case MC_ERROR_TYPE_SLB: + case MC_ERROR_TYPE_ERAT: + case MC_ERROR_TYPE_TLB: + return (mlog->sub_err_type & 0x03); + default: + return 0; + } +} + +static +inline u64 rtas_mc_get_effective_addr(const struct pseries_mc_errorlog *mlog) +{ + __be64 addr = 0; + + switch (mlog->error_type) { + case MC_ERROR_TYPE_UE: + if (mlog->sub_err_type & 0x40) + addr = mlog->effective_address; + break; + case MC_ERROR_TYPE_SLB: + case MC_ERROR_TYPE_ERAT: + case MC_ERROR_TYPE_TLB: + if (mlog->sub_err_type & 0x80) + addr = mlog->effective_address; + default: + break; + } + return be64_to_cpu(addr); +} /* * Enable the hotplug interrupt late because processing them may touch other @@ -237,8 +333,9 @@ static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id) * hotplug events on the ras_log_buf to be handled by rtas_errd. */ if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM || - hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU) - queue_hotplug_event(hp_elog, NULL, NULL); + hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU || + hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_PMEM) + queue_hotplug_event(hp_elog); else log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0); @@ -427,6 +524,188 @@ int pSeries_system_reset_exception(struct pt_regs *regs) return 0; /* need to perform reset */ } +#define VAL_TO_STRING(ar, val) \ + (((val) < ARRAY_SIZE(ar)) ? ar[(val)] : "Unknown") + +static void pseries_print_mce_info(struct pt_regs *regs, + struct rtas_error_log *errp) +{ + const char *level, *sevstr; + struct pseries_errorlog *pseries_log; + struct pseries_mc_errorlog *mce_log; + u8 error_type, err_sub_type; + u64 addr; + u8 initiator = rtas_error_initiator(errp); + int disposition = rtas_error_disposition(errp); + + static const char * const initiators[] = { + "Unknown", + "CPU", + "PCI", + "ISA", + "Memory", + "Power Mgmt", + }; + static const char * const mc_err_types[] = { + "UE", + "SLB", + "ERAT", + "TLB", + "D-Cache", + "Unknown", + "I-Cache", + }; + static const char * const mc_ue_types[] = { + "Indeterminate", + "Instruction fetch", + "Page table walk ifetch", + "Load/Store", + "Page table walk Load/Store", + }; + + /* SLB sub errors valid values are 0x0, 0x1, 0x2 */ + static const char * const mc_slb_types[] = { + "Parity", + "Multihit", + "Indeterminate", + }; + + /* TLB and ERAT sub errors valid values are 0x1, 0x2, 0x3 */ + static const char * const mc_soft_types[] = { + "Unknown", + "Parity", + "Multihit", + "Indeterminate", + }; + + if (!rtas_error_extended(errp)) { + pr_err("Machine check interrupt: Missing extended error log\n"); + return; + } + + pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); + if (pseries_log == NULL) + return; + + mce_log = (struct pseries_mc_errorlog *)pseries_log->data; + + error_type = mce_log->error_type; + err_sub_type = rtas_mc_error_sub_type(mce_log); + + switch (rtas_error_severity(errp)) { + case RTAS_SEVERITY_NO_ERROR: + level = KERN_INFO; + sevstr = "Harmless"; + break; + case RTAS_SEVERITY_WARNING: + level = KERN_WARNING; + sevstr = ""; + break; + case RTAS_SEVERITY_ERROR: + case RTAS_SEVERITY_ERROR_SYNC: + level = KERN_ERR; + sevstr = "Severe"; + break; + case RTAS_SEVERITY_FATAL: + default: + level = KERN_ERR; + sevstr = "Fatal"; + break; + } + +#ifdef CONFIG_PPC_BOOK3S_64 + /* Display faulty slb contents for SLB errors. */ + if (error_type == MC_ERROR_TYPE_SLB) + slb_dump_contents(local_paca->mce_faulty_slbs); +#endif + + printk("%s%s Machine check interrupt [%s]\n", level, sevstr, + disposition == RTAS_DISP_FULLY_RECOVERED ? + "Recovered" : "Not recovered"); + if (user_mode(regs)) { + printk("%s NIP: [%016lx] PID: %d Comm: %s\n", level, + regs->nip, current->pid, current->comm); + } else { + printk("%s NIP [%016lx]: %pS\n", level, regs->nip, + (void *)regs->nip); + } + printk("%s Initiator: %s\n", level, + VAL_TO_STRING(initiators, initiator)); + + switch (error_type) { + case MC_ERROR_TYPE_UE: + printk("%s Error type: %s [%s]\n", level, + VAL_TO_STRING(mc_err_types, error_type), + VAL_TO_STRING(mc_ue_types, err_sub_type)); + break; + case MC_ERROR_TYPE_SLB: + printk("%s Error type: %s [%s]\n", level, + VAL_TO_STRING(mc_err_types, error_type), + VAL_TO_STRING(mc_slb_types, err_sub_type)); + break; + case MC_ERROR_TYPE_ERAT: + case MC_ERROR_TYPE_TLB: + printk("%s Error type: %s [%s]\n", level, + VAL_TO_STRING(mc_err_types, error_type), + VAL_TO_STRING(mc_soft_types, err_sub_type)); + break; + default: + printk("%s Error type: %s\n", level, + VAL_TO_STRING(mc_err_types, error_type)); + break; + } + + addr = rtas_mc_get_effective_addr(mce_log); + if (addr) + printk("%s Effective address: %016llx\n", level, addr); +} + +static int mce_handle_error(struct rtas_error_log *errp) +{ + struct pseries_errorlog *pseries_log; + struct pseries_mc_errorlog *mce_log; + int disposition = rtas_error_disposition(errp); + u8 error_type; + + if (!rtas_error_extended(errp)) + goto out; + + pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); + if (pseries_log == NULL) + goto out; + + mce_log = (struct pseries_mc_errorlog *)pseries_log->data; + error_type = mce_log->error_type; + +#ifdef CONFIG_PPC_BOOK3S_64 + if (disposition == RTAS_DISP_NOT_RECOVERED) { + switch (error_type) { + case MC_ERROR_TYPE_SLB: + case MC_ERROR_TYPE_ERAT: + /* + * Store the old slb content in paca before flushing. + * Print this when we go to virtual mode. + * There are chances that we may hit MCE again if there + * is a parity error on the SLB entry we trying to read + * for saving. Hence limit the slb saving to single + * level of recursion. + */ + if (local_paca->in_mce == 1) + slb_save_contents(local_paca->mce_faulty_slbs); + flush_and_reload_slb(); + disposition = RTAS_DISP_FULLY_RECOVERED; + rtas_set_disposition_recovered(errp); + break; + default: + break; + } + } +#endif + +out: + return disposition; +} + /* * Process MCE rtas errlog event. */ @@ -452,8 +731,11 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err) int recovered = 0; int disposition = rtas_error_disposition(err); + pseries_print_mce_info(regs, err); + if (!(regs->msr & MSR_RI)) { /* If MSR_RI isn't set, we cannot recover */ + pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n"); recovered = 0; } else if (disposition == RTAS_DISP_FULLY_RECOVERED) { @@ -503,11 +785,31 @@ int pSeries_machine_check_exception(struct pt_regs *regs) struct rtas_error_log *errp; if (fwnmi_active) { - errp = fwnmi_get_errinfo(regs); fwnmi_release_errinfo(); + errp = fwnmi_get_errlog(); if (errp && recover_mce(regs, errp)) return 1; } return 0; } + +long pseries_machine_check_realmode(struct pt_regs *regs) +{ + struct rtas_error_log *errp; + int disposition; + + if (fwnmi_active) { + errp = fwnmi_get_errinfo(regs); + /* + * Call to fwnmi_release_errinfo() in real mode causes kernel + * to panic. Hence we will call it as soon as we go into + * virtual mode. + */ + disposition = mce_handle_error(errp); + if (disposition == RTAS_DISP_FULLY_RECOVERED) + return 1; + } + + return 0; +} diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ba1791fd3234..0f553dcfa548 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -107,6 +107,10 @@ static void __init fwnmi_init(void) u8 *mce_data_buf; unsigned int i; int nr_cpus = num_possible_cpus(); +#ifdef CONFIG_PPC_BOOK3S_64 + struct slb_entry *slb_ptr; + size_t size; +#endif int ibm_nmi_register = rtas_token("ibm,nmi-register"); if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE) @@ -132,6 +136,15 @@ static void __init fwnmi_init(void) paca_ptrs[i]->mce_data_buf = mce_data_buf + (RTAS_ERROR_LOG_MAX * i); } + +#ifdef CONFIG_PPC_BOOK3S_64 + /* Allocate per cpu slb area to save old slb contents during MCE */ + size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus; + slb_ptr = __va(memblock_alloc_base(size, sizeof(struct slb_entry), + ppc64_rma_size)); + for_each_possible_cpu(i) + paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i); +#endif } static void pseries_8259_cascade(struct irq_desc *desc) @@ -1017,6 +1030,7 @@ define_machine(pseries) { .calibrate_decr = generic_calibrate_decr, .progress = rtas_progress, .system_reset_exception = pSeries_system_reset_exception, + .machine_check_early = pseries_machine_check_realmode, .machine_check_exception = pSeries_machine_check_exception, #ifdef CONFIG_KEXEC_CORE .machine_kexec = pSeries_machine_kexec, diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 49e04ec19238..88f1ad1d6309 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -1349,7 +1349,6 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) struct device_node *parent_node; const __be32 *prop; enum vio_dev_family family; - const char *of_node_name = of_node->name ? of_node->name : "<unknown>"; /* * Determine if this node is a under the /vdevice node or under the @@ -1362,24 +1361,24 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) else if (!strcmp(parent_node->type, "vdevice")) family = VDEVICE; else { - pr_warn("%s: parent(%pOF) of %s not recognized.\n", + pr_warn("%s: parent(%pOF) of %pOFn not recognized.\n", __func__, parent_node, - of_node_name); + of_node); of_node_put(parent_node); return NULL; } of_node_put(parent_node); } else { - pr_warn("%s: could not determine the parent of node %s.\n", - __func__, of_node_name); + pr_warn("%s: could not determine the parent of node %pOFn.\n", + __func__, of_node); return NULL; } if (family == PFO) { if (of_get_property(of_node, "interrupt-controller", NULL)) { - pr_debug("%s: Skipping the interrupt controller %s.\n", - __func__, of_node_name); + pr_debug("%s: Skipping the interrupt controller %pOFn.\n", + __func__, of_node); return NULL; } } @@ -1399,15 +1398,15 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) if (of_node->type != NULL) viodev->type = of_node->type; else { - pr_warn("%s: node %s is missing the 'device_type' " - "property.\n", __func__, of_node_name); + pr_warn("%s: node %pOFn is missing the 'device_type' " + "property.\n", __func__, of_node); goto out; } prop = of_get_property(of_node, "reg", NULL); if (prop == NULL) { - pr_warn("%s: node %s missing 'reg'\n", - __func__, of_node_name); + pr_warn("%s: node %pOFn missing 'reg'\n", + __func__, of_node); goto out; } unit_address = of_read_number(prop, 1); @@ -1422,8 +1421,8 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) if (prop != NULL) viodev->resource_id = of_read_number(prop, 1); - dev_set_name(&viodev->dev, "%s", of_node_name); - viodev->type = of_node_name; + dev_set_name(&viodev->dev, "%pOFn", of_node); + viodev->type = dev_name(&viodev->dev); viodev->irq = 0; } @@ -1694,7 +1693,7 @@ struct vio_dev *vio_find_node(struct device_node *vnode) snprintf(kobj_name, sizeof(kobj_name), "%x", (uint32_t)of_read_number(prop, 1)); } else if (!strcmp(dev_type, "ibm,platform-facilities")) - snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name); + snprintf(kobj_name, sizeof(kobj_name), "%pOFn", vnode); else return NULL; diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index bcef2ac56479..e0dbec780fe9 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig @@ -6,19 +6,16 @@ config PPC4xx_PCI_EXPRESS bool depends on PCI && 4xx - default n config PPC4xx_HSTA_MSI bool depends on PCI_MSI depends on PCI && 4xx - default n config PPC4xx_MSI bool depends on PCI_MSI depends on PCI && 4xx - default n config PPC_MSI_BITMAP bool @@ -37,11 +34,9 @@ config PPC_SCOM config SCOM_DEBUGFS bool "Expose SCOM controllers via debugfs" depends on PPC_SCOM && DEBUG_FS - default n config GE_FPGA bool - default n config FSL_CORENET_RCPM bool diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index f730539074c4..2caa4defdfb6 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) @@ -56,8 +55,6 @@ obj-$(CONFIG_PPC_SCOM) += scom.o obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS) += udbg_memcons.o -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror - obj-$(CONFIG_PPC_XICS) += xics/ obj-$(CONFIG_PPC_XIVE) += xive/ diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c index 00ccf3e4fcb4..15cbdd4fde06 100644 --- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c +++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c @@ -107,11 +107,11 @@ int __init instantiate_cache_sram(struct platform_device *dev, goto out_free; } - cache_sram->base_virt = ioremap_prot(cache_sram->base_phys, - cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL); + cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys, + cache_sram->size); if (!cache_sram->base_virt) { - dev_err(&dev->dev, "%pOF: ioremap_prot failed\n", - dev->dev.of_node); + dev_err(&dev->dev, "%pOF: ioremap_coherent failed\n", + dev->dev.of_node); ret = -ENOMEM; goto out_release; } diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 535cf1f6941c..6300123ce965 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -846,7 +846,7 @@ void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) u32 ipic_get_mcp_status(void) { - return ipic_read(primary_ipic->regs, IPIC_SERSR); + return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0; } void ipic_clear_mcp_status(u32 mask) diff --git a/arch/powerpc/sysdev/xics/Makefile b/arch/powerpc/sysdev/xics/Makefile index 5d438d92472b..ba1e3117b1c0 100644 --- a/arch/powerpc/sysdev/xics/Makefile +++ b/arch/powerpc/sysdev/xics/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror obj-y += xics-common.o obj-$(CONFIG_PPC_ICP_NATIVE) += icp-native.o diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig index 70ee976e1de0..785c292d104b 100644 --- a/arch/powerpc/sysdev/xive/Kconfig +++ b/arch/powerpc/sysdev/xive/Kconfig @@ -1,17 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 config PPC_XIVE bool - default n select PPC_SMP_MUXED_IPI select HARDIRQS_SW_RESEND config PPC_XIVE_NATIVE bool - default n select PPC_XIVE depends on PPC_POWERNV config PPC_XIVE_SPAPR bool - default n select PPC_XIVE diff --git a/arch/powerpc/sysdev/xive/Makefile b/arch/powerpc/sysdev/xive/Makefile index 536d6e5706e3..dea2abc23f4d 100644 --- a/arch/powerpc/sysdev/xive/Makefile +++ b/arch/powerpc/sysdev/xive/Makefile @@ -1,4 +1,3 @@ -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror obj-y += common.o obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index 959a2a62f233..9824074ec1b5 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -1010,12 +1010,13 @@ static void xive_ipi_eoi(struct irq_data *d) { struct xive_cpu *xc = __this_cpu_read(xive_cpu); - DBG_VERBOSE("IPI eoi: irq=%d [0x%lx] (HW IRQ 0x%x) pending=%02x\n", - d->irq, irqd_to_hwirq(d), xc->hw_ipi, xc->pending_prio); - /* Handle possible race with unplug and drop stale IPIs */ if (!xc) return; + + DBG_VERBOSE("IPI eoi: irq=%d [0x%lx] (HW IRQ 0x%x) pending=%02x\n", + d->irq, irqd_to_hwirq(d), xc->hw_ipi, xc->pending_prio); + xive_do_source_eoi(xc->hw_ipi, &xc->ipi_data); xive_do_queue_eoi(xc); } diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 5b20a678d755..1ca127d052a6 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -238,20 +238,11 @@ static bool xive_native_match(struct device_node *node) #ifdef CONFIG_SMP static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) { - struct device_node *np; - unsigned int chip_id; s64 irq; - /* Find the chip ID */ - np = of_get_cpu_node(cpu, NULL); - if (np) { - if (of_property_read_u32(np, "ibm,chip-id", &chip_id) < 0) - chip_id = 0; - } - /* Allocate an IPI and populate info about it */ for (;;) { - irq = opal_xive_allocate_irq(chip_id); + irq = opal_xive_allocate_irq(xc->chip_id); if (irq == OPAL_BUSY) { msleep(OPAL_BUSY_DELAY_MS); continue; diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 1bc3abb237cd..69e7fb47bcaa 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile @@ -1,14 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for xmon -subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror +# Disable clang warning for using setjmp without setjmp.h header +subdir-ccflags-y := $(call cc-disable-warning, builtin-requires-header) GCOV_PROFILE := n UBSAN_SANITIZE := n # Disable ftrace for the entire directory ORIG_CFLAGS := $(KBUILD_CFLAGS) -KBUILD_CFLAGS = $(subst -mno-sched-epilog,,$(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS))) +KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS)) ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 4264aedc7775..36b8dc47a3c3 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2378,25 +2378,33 @@ static void dump_one_paca(int cpu) DUMP(p, cpu_start, "%#-*x"); DUMP(p, kexec_state, "%#-*x"); #ifdef CONFIG_PPC_BOOK3S_64 - for (i = 0; i < SLB_NUM_BOLTED; i++) { - u64 esid, vsid; + if (!early_radix_enabled()) { + for (i = 0; i < SLB_NUM_BOLTED; i++) { + u64 esid, vsid; - if (!p->slb_shadow_ptr) - continue; + if (!p->slb_shadow_ptr) + continue; + + esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid); + vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); - esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid); - vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); + if (esid || vsid) { + printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", + 22, "slb_shadow", i, esid, vsid); + } + } + DUMP(p, vmalloc_sllp, "%#-*x"); + DUMP(p, stab_rr, "%#-*x"); + DUMP(p, slb_used_bitmap, "%#-*x"); + DUMP(p, slb_kern_bitmap, "%#-*x"); - if (esid || vsid) { - printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", - 22, "slb_shadow", i, esid, vsid); + if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { + DUMP(p, slb_cache_ptr, "%#-*x"); + for (i = 0; i < SLB_CACHE_ENTRIES; i++) + printf(" %-*s[%d] = 0x%016x\n", + 22, "slb_cache", i, p->slb_cache[i]); } } - DUMP(p, vmalloc_sllp, "%#-*x"); - DUMP(p, slb_cache_ptr, "%#-*x"); - for (i = 0; i < SLB_CACHE_ENTRIES; i++) - printf(" %-*s[%d] = 0x%016x\n", - 22, "slb_cache", i, p->slb_cache[i]); DUMP(p, rfi_flush_fallback_area, "%-*px"); #endif @@ -2412,7 +2420,9 @@ static void dump_one_paca(int cpu) DUMP(p, __current, "%-*px"); DUMP(p, kstack, "%#-*llx"); printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1)); - DUMP(p, stab_rr, "%#-*llx"); +#ifdef CONFIG_STACKPROTECTOR + DUMP(p, canary, "%#-*lx"); +#endif DUMP(p, saved_r1, "%#-*llx"); DUMP(p, trap_save, "%#-*x"); DUMP(p, irq_soft_mask, "%#-*x"); @@ -2444,11 +2454,15 @@ static void dump_one_paca(int cpu) DUMP(p, accounting.utime, "%#-*lx"); DUMP(p, accounting.stime, "%#-*lx"); +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME DUMP(p, accounting.utime_scaled, "%#-*lx"); +#endif DUMP(p, accounting.starttime, "%#-*lx"); DUMP(p, accounting.starttime_user, "%#-*lx"); +#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME DUMP(p, accounting.startspurr, "%#-*lx"); DUMP(p, accounting.utime_sspurr, "%#-*lx"); +#endif DUMP(p, accounting.steal_time, "%#-*lx"); #undef DUMP @@ -2988,15 +3002,17 @@ static void show_task(struct task_struct *tsk) #ifdef CONFIG_PPC_BOOK3S_64 void format_pte(void *ptep, unsigned long pte) { + pte_t entry = __pte(pte); + printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte); printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); printf("Flags = %s%s%s%s%s\n", - (pte & _PAGE_ACCESSED) ? "Accessed " : "", - (pte & _PAGE_DIRTY) ? "Dirty " : "", - (pte & _PAGE_READ) ? "Read " : "", - (pte & _PAGE_WRITE) ? "Write " : "", - (pte & _PAGE_EXEC) ? "Exec " : ""); + pte_young(entry) ? "Accessed " : "", + pte_dirty(entry) ? "Dirty " : "", + pte_read(entry) ? "Read " : "", + pte_write(entry) ? "Write " : "", + pte_exec(entry) ? "Exec " : ""); } static void show_pte(unsigned long addr) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index a344980287a5..fe451348ae57 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -31,6 +31,7 @@ config RISCV select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select HAVE_DMA_CONTIGUOUS + select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_GENERIC_DMA_COHERENT select HAVE_PERF_EVENTS select IRQ_DOMAIN @@ -108,10 +109,12 @@ config ARCH_RV32I select GENERIC_LIB_ASHRDI3 select GENERIC_LIB_LSHRDI3 select GENERIC_LIB_UCMPDI2 + select GENERIC_LIB_UMODDI3 config ARCH_RV64I bool "RV64I" select 64BIT + select ARCH_SUPPORTS_INT128 if GCC_VERSION >= 50000 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FTRACE_MCOUNT_RECORD @@ -208,14 +211,61 @@ config RISCV_BASE_PMU endmenu +config FPU + bool "FPU support" + default y + help + Say N here if you want to disable all floating-point related procedure + in the kernel. + + If you don't know what to do here, say Y. + endmenu -menu "Kernel type" +menu "Kernel features" source "kernel/Kconfig.hz" endmenu +menu "Boot options" + +config CMDLINE_BOOL + bool "Built-in kernel command line" + help + For most platforms, it is firmware or second stage bootloader + that by default specifies the kernel command line options. + However, it might be necessary or advantageous to either override + the default kernel command line or add a few extra options to it. + For such cases, this option allows hardcoding command line options + directly into the kernel. + + For that, choose 'Y' here and fill in the extra boot parameters + in CONFIG_CMDLINE. + + The built-in options will be concatenated to the default command + line if CMDLINE_FORCE is set to 'N'. Otherwise, the default + command line will be ignored and replaced by the built-in string. + +config CMDLINE + string "Built-in kernel command string" + depends on CMDLINE_BOOL + default "" + help + Supply command-line options at build time by entering them here. + +config CMDLINE_FORCE + bool "Built-in command line overrides bootloader arguments" + depends on CMDLINE_BOOL + help + Set this option to 'Y' to have the kernel ignore the bootloader + or firmware command line. Instead, the built-in command line + will be used exclusively. + + If you don't know what to do here, say N. + +endmenu + menu "Bus support" config PCI diff --git a/arch/riscv/Kconfig.debug b/arch/riscv/Kconfig.debug index 3224ff6ecf6e..c5a72f17c469 100644 --- a/arch/riscv/Kconfig.debug +++ b/arch/riscv/Kconfig.debug @@ -1,37 +1,2 @@ - -config CMDLINE_BOOL - bool "Built-in kernel command line" - help - For most platforms, it is firmware or second stage bootloader - that by default specifies the kernel command line options. - However, it might be necessary or advantageous to either override - the default kernel command line or add a few extra options to it. - For such cases, this option allows hardcoding command line options - directly into the kernel. - - For that, choose 'Y' here and fill in the extra boot parameters - in CONFIG_CMDLINE. - - The built-in options will be concatenated to the default command - line if CMDLINE_FORCE is set to 'N'. Otherwise, the default - command line will be ignored and replaced by the built-in string. - -config CMDLINE - string "Built-in kernel command string" - depends on CMDLINE_BOOL - default "" - help - Supply command-line options at build time by entering them here. - -config CMDLINE_FORCE - bool "Built-in command line overrides bootloader arguments" - depends on CMDLINE_BOOL - help - Set this option to 'Y' to have the kernel ignore the bootloader - or firmware command line. Instead, the built-in command line - will be used exclusively. - - If you don't know what to do here, say N. - config EARLY_PRINTK def_bool y diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 61ec42405ec9..d10146197533 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -25,10 +25,7 @@ ifeq ($(CONFIG_ARCH_RV64I),y) KBUILD_CFLAGS += -mabi=lp64 KBUILD_AFLAGS += -mabi=lp64 - - KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128) - KBUILD_MARCH = rv64im KBUILD_LDFLAGS += -melf64lriscv else BITS := 32 @@ -36,22 +33,20 @@ else KBUILD_CFLAGS += -mabi=ilp32 KBUILD_AFLAGS += -mabi=ilp32 - KBUILD_MARCH = rv32im KBUILD_LDFLAGS += -melf32lriscv endif KBUILD_CFLAGS += -Wall -ifeq ($(CONFIG_RISCV_ISA_A),y) - KBUILD_ARCH_A = a -endif -ifeq ($(CONFIG_RISCV_ISA_C),y) - KBUILD_ARCH_C = c -endif - -KBUILD_AFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)fd$(KBUILD_ARCH_C) +# ISA string setting +riscv-march-$(CONFIG_ARCH_RV32I) := rv32im +riscv-march-$(CONFIG_ARCH_RV64I) := rv64im +riscv-march-$(CONFIG_RISCV_ISA_A) := $(riscv-march-y)a +riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd +riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c +KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) +KBUILD_AFLAGS += -march=$(riscv-march-y) -KBUILD_CFLAGS += -march=$(KBUILD_MARCH)$(KBUILD_ARCH_A)$(KBUILD_ARCH_C) KBUILD_CFLAGS += -mno-save-restore KBUILD_CFLAGS += -DCONFIG_PAGE_OFFSET=$(CONFIG_PAGE_OFFSET) diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index efdbe311e936..6a646d9ea780 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -13,7 +13,6 @@ generic-y += errno.h generic-y += exec.h generic-y += fb.h generic-y += fcntl.h -generic-y += futex.h generic-y += hardirq.h generic-y += hash.h generic-y += hw_irq.h diff --git a/arch/riscv/include/asm/futex.h b/arch/riscv/include/asm/futex.h new file mode 100644 index 000000000000..3b19eba1bc8e --- /dev/null +++ b/arch/riscv/include/asm/futex.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2006 Ralf Baechle (ralf@linux-mips.org) + * Copyright (c) 2018 Jim Wilson (jimw@sifive.com) + */ + +#ifndef _ASM_FUTEX_H +#define _ASM_FUTEX_H + +#ifndef CONFIG_RISCV_ISA_A +/* + * Use the generic interrupt disabling versions if the A extension + * is not supported. + */ +#ifdef CONFIG_SMP +#error "Can't support generic futex calls without A extension on SMP" +#endif +#include <asm-generic/futex.h> + +#else /* CONFIG_RISCV_ISA_A */ + +#include <linux/futex.h> +#include <linux/uaccess.h> +#include <linux/errno.h> +#include <asm/asm.h> + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ +{ \ + uintptr_t tmp; \ + __enable_user_access(); \ + __asm__ __volatile__ ( \ + "1: " insn " \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + " .balign 4 \n" \ + "3: li %[r],%[e] \n" \ + " jump 2b,%[t] \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " .balign " RISCV_SZPTR " \n" \ + " " RISCV_PTR " 1b, 3b \n" \ + " .previous \n" \ + : [r] "+r" (ret), [ov] "=&r" (oldval), \ + [u] "+m" (*uaddr), [t] "=&r" (tmp) \ + : [op] "Jr" (oparg), [e] "i" (-EFAULT) \ + : "memory"); \ + __disable_user_access(); \ +} + +static inline int +arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) +{ + int oldval = 0, ret = 0; + + pagefault_disable(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("amoswap.w.aqrl %[ov],%z[op],%[u]", + ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("amoadd.w.aqrl %[ov],%z[op],%[u]", + ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("amoor.w.aqrl %[ov],%z[op],%[u]", + ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("amoand.w.aqrl %[ov],%z[op],%[u]", + ret, oldval, uaddr, ~oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("amoxor.w.aqrl %[ov],%z[op],%[u]", + ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + pagefault_enable(); + + if (!ret) + *oval = oldval; + + return ret; +} + +static inline int +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) +{ + int ret = 0; + u32 val; + uintptr_t tmp; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + + __enable_user_access(); + __asm__ __volatile__ ( + "1: lr.w.aqrl %[v],%[u] \n" + " bne %[v],%z[ov],3f \n" + "2: sc.w.aqrl %[t],%z[nv],%[u] \n" + " bnez %[t],1b \n" + "3: \n" + " .section .fixup,\"ax\" \n" + " .balign 4 \n" + "4: li %[r],%[e] \n" + " jump 3b,%[t] \n" + " .previous \n" + " .section __ex_table,\"a\" \n" + " .balign " RISCV_SZPTR " \n" + " " RISCV_PTR " 1b, 4b \n" + " " RISCV_PTR " 2b, 4b \n" + " .previous \n" + : [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp) + : [ov] "Jr" (oldval), [nv] "Jr" (newval), [e] "i" (-EFAULT) + : "memory"); + __disable_user_access(); + + *uval = val; + return ret; +} + +#endif /* CONFIG_RISCV_ISA_A */ +#endif /* _ASM_FUTEX_H */ diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 3fe4af8147d2..50de774d827a 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -88,7 +88,7 @@ static inline void wait_for_interrupt(void) } struct device_node; -extern int riscv_of_processor_hart(struct device_node *node); +int riscv_of_processor_hartid(struct device_node *node); extern void riscv_fill_hwcap(void); diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index 36016845461d..41aa73b476f4 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -14,16 +14,24 @@ #ifndef _ASM_RISCV_SMP_H #define _ASM_RISCV_SMP_H -/* This both needs asm-offsets.h and is used when generating it. */ -#ifndef GENERATING_ASM_OFFSETS -#include <asm/asm-offsets.h> -#endif - #include <linux/cpumask.h> #include <linux/irqreturn.h> +#include <linux/thread_info.h> + +#define INVALID_HARTID ULONG_MAX +/* + * Mapping between linux logical cpu index and hartid. + */ +extern unsigned long __cpuid_to_hartid_map[NR_CPUS]; +#define cpuid_to_hartid_map(cpu) __cpuid_to_hartid_map[cpu] + +struct seq_file; #ifdef CONFIG_SMP +/* print IPI stats */ +void show_ipi_stats(struct seq_file *p, int prec); + /* SMP initialization hook for setup_arch */ void __init setup_smp(void); @@ -33,14 +41,31 @@ void arch_send_call_function_ipi_mask(struct cpumask *mask); /* Hook for the generic smp_call_function_single() routine. */ void arch_send_call_function_single_ipi(int cpu); +int riscv_hartid_to_cpuid(int hartid); +void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out); + /* - * This is particularly ugly: it appears we can't actually get the definition - * of task_struct here, but we need access to the CPU this task is running on. - * Instead of using C we're using asm-offsets.h to get the current processor - * ID. + * Obtains the hart ID of the currently executing task. This relies on + * THREAD_INFO_IN_TASK, but we define that unconditionally. */ -#define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU))) +#define raw_smp_processor_id() (current_thread_info()->cpu) -#endif /* CONFIG_SMP */ +#else + +static inline void show_ipi_stats(struct seq_file *p, int prec) +{ +} +static inline int riscv_hartid_to_cpuid(int hartid) +{ + return 0; +} + +static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in, + struct cpumask *out) +{ + cpumask_set_cpu(cpuid_to_hartid_map(0), out); +} + +#endif /* CONFIG_SMP */ #endif /* _ASM_RISCV_SMP_H */ diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index dd6b05bff75b..733559083f24 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -18,6 +18,7 @@ #include <asm/ptrace.h> #include <asm/csr.h> +#ifdef CONFIG_FPU extern void __fstate_save(struct task_struct *save_to); extern void __fstate_restore(struct task_struct *restore_from); @@ -55,6 +56,14 @@ static inline void __switch_to_aux(struct task_struct *prev, fstate_restore(next, task_pt_regs(next)); } +extern bool has_fpu; +#else +#define has_fpu false +#define fstate_save(task, regs) do { } while (0) +#define fstate_restore(task, regs) do { } while (0) +#define __switch_to_aux(__prev, __next) do { } while (0) +#endif + extern struct task_struct *__switch_to(struct task_struct *, struct task_struct *); @@ -62,7 +71,8 @@ extern struct task_struct *__switch_to(struct task_struct *, do { \ struct task_struct *__prev = (prev); \ struct task_struct *__next = (next); \ - __switch_to_aux(__prev, __next); \ + if (has_fpu) \ + __switch_to_aux(__prev, __next); \ ((last) = __switch_to(__prev, __next)); \ } while (0) diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index 85c2d8bae957..54fee0cadb1e 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -16,6 +16,7 @@ #define _ASM_RISCV_TLBFLUSH_H #include <linux/mm_types.h> +#include <asm/smp.h> /* * Flush entire local TLB. 'sfence.vma' implicitly fences with the instruction @@ -49,13 +50,22 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, #include <asm/sbi.h> +static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start, + unsigned long size) +{ + struct cpumask hmask; + + cpumask_clear(&hmask); + riscv_cpuid_to_hartid_mask(cmask, &hmask); + sbi_remote_sfence_vma(hmask.bits, start, size); +} + #define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1) #define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0) #define flush_tlb_range(vma, start, end) \ - sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \ - start, (end) - (start)) + remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start)) #define flush_tlb_mm(mm) \ - sbi_remote_sfence_vma(mm_cpumask(mm)->bits, 0, -1) + remote_sfence_vma(mm_cpumask(mm), 0, -1) #endif /* CONFIG_SMP */ diff --git a/arch/riscv/include/asm/unistd.h b/arch/riscv/include/asm/unistd.h index 0caea01d5cca..eff7aa9aa163 100644 --- a/arch/riscv/include/asm/unistd.h +++ b/arch/riscv/include/asm/unistd.h @@ -16,6 +16,7 @@ * be included multiple times. See uapi/asm/syscalls.h for more info. */ +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SYS_CLONE #include <uapi/asm/unistd.h> #include <uapi/asm/syscalls.h> diff --git a/arch/riscv/include/uapi/asm/Kbuild b/arch/riscv/include/uapi/asm/Kbuild index 7e91f4850475..5511b9918131 100644 --- a/arch/riscv/include/uapi/asm/Kbuild +++ b/arch/riscv/include/uapi/asm/Kbuild @@ -26,3 +26,4 @@ generic-y += swab.h generic-y += termbits.h generic-y += termios.h generic-y += types.h +generic-y += siginfo.h diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h index 1e0dfc36aab9..644a00ce6e2e 100644 --- a/arch/riscv/include/uapi/asm/elf.h +++ b/arch/riscv/include/uapi/asm/elf.h @@ -19,7 +19,10 @@ typedef unsigned long elf_greg_t; typedef struct user_regs_struct elf_gregset_t; #define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t)) +/* We don't support f without d, or q. */ +typedef __u64 elf_fpreg_t; typedef union __riscv_fp_state elf_fpregset_t; +#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t)) #if __riscv_xlen == 64 #define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info) diff --git a/arch/riscv/include/uapi/asm/siginfo.h b/arch/riscv/include/uapi/asm/siginfo.h deleted file mode 100644 index f96849aac662..000000000000 --- a/arch/riscv/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 ARM Ltd. - * Copyright (C) 2016 SiFive, Inc. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef __ASM_SIGINFO_H -#define __ASM_SIGINFO_H - -#define __ARCH_SI_PREAMBLE_SIZE (__SIZEOF_POINTER__ == 4 ? 12 : 16) - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index e1274fc03af4..f13f7f276639 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -31,6 +31,7 @@ obj-y += vdso/ CFLAGS_setup.o := -mcmodel=medany +obj-$(CONFIG_FPU) += fpu.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 0bc86e5f8f3f..cb35ffd8ec6b 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -22,13 +22,6 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, { this_leaf->level = level; this_leaf->type = type; - /* not a sector cache */ - this_leaf->physical_line_partition = 1; - /* TODO: Add to DTS */ - this_leaf->attributes = - CACHE_WRITE_BACK - | CACHE_READ_ALLOCATE - | CACHE_WRITE_ALLOCATE; } static int __init_cache_level(unsigned int cpu) diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index ca6c81e54e37..3a5a2ee31547 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -14,9 +14,13 @@ #include <linux/init.h> #include <linux/seq_file.h> #include <linux/of.h> +#include <asm/smp.h> -/* Return -1 if not a valid hart */ -int riscv_of_processor_hart(struct device_node *node) +/* + * Returns the hart ID of the given device tree node, or -1 if the device tree + * node isn't a RISC-V hart. + */ +int riscv_of_processor_hartid(struct device_node *node) { const char *isa, *status; u32 hart; @@ -58,6 +62,64 @@ int riscv_of_processor_hart(struct device_node *node) #ifdef CONFIG_PROC_FS +static void print_isa(struct seq_file *f, const char *orig_isa) +{ + static const char *ext = "mafdc"; + const char *isa = orig_isa; + const char *e; + + /* + * Linux doesn't support rv32e or rv128i, and we only support booting + * kernels on harts with the same ISA that the kernel is compiled for. + */ +#if defined(CONFIG_32BIT) + if (strncmp(isa, "rv32i", 5) != 0) + return; +#elif defined(CONFIG_64BIT) + if (strncmp(isa, "rv64i", 5) != 0) + return; +#endif + + /* Print the base ISA, as we already know it's legal. */ + seq_puts(f, "isa\t\t: "); + seq_write(f, isa, 5); + isa += 5; + + /* + * Check the rest of the ISA string for valid extensions, printing those + * we find. RISC-V ISA strings define an order, so we only print the + * extension bits when they're in order. + */ + for (e = ext; *e != '\0'; ++e) { + if (isa[0] == e[0]) { + seq_write(f, isa, 1); + isa++; + } + } + seq_puts(f, "\n"); + + /* + * If we were given an unsupported ISA in the device tree then print + * a bit of info describing what went wrong. + */ + if (isa[0] != '\0') + pr_info("unsupported ISA \"%s\" in device tree", orig_isa); +} + +static void print_mmu(struct seq_file *f, const char *mmu_type) +{ +#if defined(CONFIG_32BIT) + if (strcmp(mmu_type, "riscv,sv32") != 0) + return; +#elif defined(CONFIG_64BIT) + if (strcmp(mmu_type, "riscv,sv39") != 0 && + strcmp(mmu_type, "riscv,sv48") != 0) + return; +#endif + + seq_printf(f, "mmu\t\t: %s\n", mmu_type+6); +} + static void *c_start(struct seq_file *m, loff_t *pos) { *pos = cpumask_next(*pos - 1, cpu_online_mask); @@ -78,21 +140,20 @@ static void c_stop(struct seq_file *m, void *v) static int c_show(struct seq_file *m, void *v) { - unsigned long hart_id = (unsigned long)v - 1; - struct device_node *node = of_get_cpu_node(hart_id, NULL); + unsigned long cpu_id = (unsigned long)v - 1; + struct device_node *node = of_get_cpu_node(cpuid_to_hartid_map(cpu_id), + NULL); const char *compat, *isa, *mmu; - seq_printf(m, "hart\t: %lu\n", hart_id); - if (!of_property_read_string(node, "riscv,isa", &isa) - && isa[0] == 'r' - && isa[1] == 'v') - seq_printf(m, "isa\t: %s\n", isa); - if (!of_property_read_string(node, "mmu-type", &mmu) - && !strncmp(mmu, "riscv,", 6)) - seq_printf(m, "mmu\t: %s\n", mmu+6); + seq_printf(m, "processor\t: %lu\n", cpu_id); + seq_printf(m, "hart\t\t: %lu\n", cpuid_to_hartid_map(cpu_id)); + if (!of_property_read_string(node, "riscv,isa", &isa)) + print_isa(m, isa); + if (!of_property_read_string(node, "mmu-type", &mmu)) + print_mmu(m, mmu); if (!of_property_read_string(node, "compatible", &compat) && strcmp(compat, "riscv")) - seq_printf(m, "uarch\t: %s\n", compat); + seq_printf(m, "uarch\t\t: %s\n", compat); seq_puts(m, "\n"); return 0; diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 17011a870044..5493f3228704 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -22,6 +22,9 @@ #include <asm/hwcap.h> unsigned long elf_hwcap __read_mostly; +#ifdef CONFIG_FPU +bool has_fpu __read_mostly; +#endif void riscv_fill_hwcap(void) { @@ -57,5 +60,17 @@ void riscv_fill_hwcap(void) for (i = 0; i < strlen(isa); ++i) elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])]; + /* We don't support systems with F but without D, so mask those out + * here. */ + if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & COMPAT_HWCAP_ISA_D)) { + pr_info("This kernel does not support systems with F but not D"); + elf_hwcap &= ~COMPAT_HWCAP_ISA_F; + } + pr_info("elf_hwcap is 0x%lx", elf_hwcap); + +#ifdef CONFIG_FPU + if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)) + has_fpu = true; +#endif } diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index fa2c08e3c05e..13d4826ab2a1 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -168,7 +168,6 @@ ENTRY(handle_exception) /* Handle interrupts */ move a0, sp /* pt_regs */ - move a1, s4 /* scause */ tail do_IRQ 1: /* Exceptions run with interrupts enabled */ @@ -357,93 +356,6 @@ ENTRY(__switch_to) ret ENDPROC(__switch_to) -ENTRY(__fstate_save) - li a2, TASK_THREAD_F0 - add a0, a0, a2 - li t1, SR_FS - csrs sstatus, t1 - frcsr t0 - fsd f0, TASK_THREAD_F0_F0(a0) - fsd f1, TASK_THREAD_F1_F0(a0) - fsd f2, TASK_THREAD_F2_F0(a0) - fsd f3, TASK_THREAD_F3_F0(a0) - fsd f4, TASK_THREAD_F4_F0(a0) - fsd f5, TASK_THREAD_F5_F0(a0) - fsd f6, TASK_THREAD_F6_F0(a0) - fsd f7, TASK_THREAD_F7_F0(a0) - fsd f8, TASK_THREAD_F8_F0(a0) - fsd f9, TASK_THREAD_F9_F0(a0) - fsd f10, TASK_THREAD_F10_F0(a0) - fsd f11, TASK_THREAD_F11_F0(a0) - fsd f12, TASK_THREAD_F12_F0(a0) - fsd f13, TASK_THREAD_F13_F0(a0) - fsd f14, TASK_THREAD_F14_F0(a0) - fsd f15, TASK_THREAD_F15_F0(a0) - fsd f16, TASK_THREAD_F16_F0(a0) - fsd f17, TASK_THREAD_F17_F0(a0) - fsd f18, TASK_THREAD_F18_F0(a0) - fsd f19, TASK_THREAD_F19_F0(a0) - fsd f20, TASK_THREAD_F20_F0(a0) - fsd f21, TASK_THREAD_F21_F0(a0) - fsd f22, TASK_THREAD_F22_F0(a0) - fsd f23, TASK_THREAD_F23_F0(a0) - fsd f24, TASK_THREAD_F24_F0(a0) - fsd f25, TASK_THREAD_F25_F0(a0) - fsd f26, TASK_THREAD_F26_F0(a0) - fsd f27, TASK_THREAD_F27_F0(a0) - fsd f28, TASK_THREAD_F28_F0(a0) - fsd f29, TASK_THREAD_F29_F0(a0) - fsd f30, TASK_THREAD_F30_F0(a0) - fsd f31, TASK_THREAD_F31_F0(a0) - sw t0, TASK_THREAD_FCSR_F0(a0) - csrc sstatus, t1 - ret -ENDPROC(__fstate_save) - -ENTRY(__fstate_restore) - li a2, TASK_THREAD_F0 - add a0, a0, a2 - li t1, SR_FS - lw t0, TASK_THREAD_FCSR_F0(a0) - csrs sstatus, t1 - fld f0, TASK_THREAD_F0_F0(a0) - fld f1, TASK_THREAD_F1_F0(a0) - fld f2, TASK_THREAD_F2_F0(a0) - fld f3, TASK_THREAD_F3_F0(a0) - fld f4, TASK_THREAD_F4_F0(a0) - fld f5, TASK_THREAD_F5_F0(a0) - fld f6, TASK_THREAD_F6_F0(a0) - fld f7, TASK_THREAD_F7_F0(a0) - fld f8, TASK_THREAD_F8_F0(a0) - fld f9, TASK_THREAD_F9_F0(a0) - fld f10, TASK_THREAD_F10_F0(a0) - fld f11, TASK_THREAD_F11_F0(a0) - fld f12, TASK_THREAD_F12_F0(a0) - fld f13, TASK_THREAD_F13_F0(a0) - fld f14, TASK_THREAD_F14_F0(a0) - fld f15, TASK_THREAD_F15_F0(a0) - fld f16, TASK_THREAD_F16_F0(a0) - fld f17, TASK_THREAD_F17_F0(a0) - fld f18, TASK_THREAD_F18_F0(a0) - fld f19, TASK_THREAD_F19_F0(a0) - fld f20, TASK_THREAD_F20_F0(a0) - fld f21, TASK_THREAD_F21_F0(a0) - fld f22, TASK_THREAD_F22_F0(a0) - fld f23, TASK_THREAD_F23_F0(a0) - fld f24, TASK_THREAD_F24_F0(a0) - fld f25, TASK_THREAD_F25_F0(a0) - fld f26, TASK_THREAD_F26_F0(a0) - fld f27, TASK_THREAD_F27_F0(a0) - fld f28, TASK_THREAD_F28_F0(a0) - fld f29, TASK_THREAD_F29_F0(a0) - fld f30, TASK_THREAD_F30_F0(a0) - fld f31, TASK_THREAD_F31_F0(a0) - fscsr t0 - csrc sstatus, t1 - ret -ENDPROC(__fstate_restore) - - .section ".rodata" /* Exception vector table */ ENTRY(excp_vect_table) diff --git a/arch/riscv/kernel/fpu.S b/arch/riscv/kernel/fpu.S new file mode 100644 index 000000000000..1defb0618aff --- /dev/null +++ b/arch/riscv/kernel/fpu.S @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/linkage.h> + +#include <asm/asm.h> +#include <asm/csr.h> +#include <asm/asm-offsets.h> + +ENTRY(__fstate_save) + li a2, TASK_THREAD_F0 + add a0, a0, a2 + li t1, SR_FS + csrs sstatus, t1 + frcsr t0 + fsd f0, TASK_THREAD_F0_F0(a0) + fsd f1, TASK_THREAD_F1_F0(a0) + fsd f2, TASK_THREAD_F2_F0(a0) + fsd f3, TASK_THREAD_F3_F0(a0) + fsd f4, TASK_THREAD_F4_F0(a0) + fsd f5, TASK_THREAD_F5_F0(a0) + fsd f6, TASK_THREAD_F6_F0(a0) + fsd f7, TASK_THREAD_F7_F0(a0) + fsd f8, TASK_THREAD_F8_F0(a0) + fsd f9, TASK_THREAD_F9_F0(a0) + fsd f10, TASK_THREAD_F10_F0(a0) + fsd f11, TASK_THREAD_F11_F0(a0) + fsd f12, TASK_THREAD_F12_F0(a0) + fsd f13, TASK_THREAD_F13_F0(a0) + fsd f14, TASK_THREAD_F14_F0(a0) + fsd f15, TASK_THREAD_F15_F0(a0) + fsd f16, TASK_THREAD_F16_F0(a0) + fsd f17, TASK_THREAD_F17_F0(a0) + fsd f18, TASK_THREAD_F18_F0(a0) + fsd f19, TASK_THREAD_F19_F0(a0) + fsd f20, TASK_THREAD_F20_F0(a0) + fsd f21, TASK_THREAD_F21_F0(a0) + fsd f22, TASK_THREAD_F22_F0(a0) + fsd f23, TASK_THREAD_F23_F0(a0) + fsd f24, TASK_THREAD_F24_F0(a0) + fsd f25, TASK_THREAD_F25_F0(a0) + fsd f26, TASK_THREAD_F26_F0(a0) + fsd f27, TASK_THREAD_F27_F0(a0) + fsd f28, TASK_THREAD_F28_F0(a0) + fsd f29, TASK_THREAD_F29_F0(a0) + fsd f30, TASK_THREAD_F30_F0(a0) + fsd f31, TASK_THREAD_F31_F0(a0) + sw t0, TASK_THREAD_FCSR_F0(a0) + csrc sstatus, t1 + ret +ENDPROC(__fstate_save) + +ENTRY(__fstate_restore) + li a2, TASK_THREAD_F0 + add a0, a0, a2 + li t1, SR_FS + lw t0, TASK_THREAD_FCSR_F0(a0) + csrs sstatus, t1 + fld f0, TASK_THREAD_F0_F0(a0) + fld f1, TASK_THREAD_F1_F0(a0) + fld f2, TASK_THREAD_F2_F0(a0) + fld f3, TASK_THREAD_F3_F0(a0) + fld f4, TASK_THREAD_F4_F0(a0) + fld f5, TASK_THREAD_F5_F0(a0) + fld f6, TASK_THREAD_F6_F0(a0) + fld f7, TASK_THREAD_F7_F0(a0) + fld f8, TASK_THREAD_F8_F0(a0) + fld f9, TASK_THREAD_F9_F0(a0) + fld f10, TASK_THREAD_F10_F0(a0) + fld f11, TASK_THREAD_F11_F0(a0) + fld f12, TASK_THREAD_F12_F0(a0) + fld f13, TASK_THREAD_F13_F0(a0) + fld f14, TASK_THREAD_F14_F0(a0) + fld f15, TASK_THREAD_F15_F0(a0) + fld f16, TASK_THREAD_F16_F0(a0) + fld f17, TASK_THREAD_F17_F0(a0) + fld f18, TASK_THREAD_F18_F0(a0) + fld f19, TASK_THREAD_F19_F0(a0) + fld f20, TASK_THREAD_F20_F0(a0) + fld f21, TASK_THREAD_F21_F0(a0) + fld f22, TASK_THREAD_F22_F0(a0) + fld f23, TASK_THREAD_F23_F0(a0) + fld f24, TASK_THREAD_F24_F0(a0) + fld f25, TASK_THREAD_F25_F0(a0) + fld f26, TASK_THREAD_F26_F0(a0) + fld f27, TASK_THREAD_F27_F0(a0) + fld f28, TASK_THREAD_F28_F0(a0) + fld f29, TASK_THREAD_F29_F0(a0) + fld f30, TASK_THREAD_F30_F0(a0) + fld f31, TASK_THREAD_F31_F0(a0) + fscsr t0 + csrc sstatus, t1 + ret +ENDPROC(__fstate_restore) diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index c4d2c63f9a29..711190d473d4 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -47,6 +47,8 @@ ENTRY(_start) /* Save hart ID and DTB physical address */ mv s0, a0 mv s1, a1 + la a2, boot_cpu_hartid + REG_S a0, (a2) /* Initialize page tables and relocate to virtual addresses */ la sp, init_thread_union + THREAD_SIZE @@ -55,7 +57,7 @@ ENTRY(_start) /* Restore C environment */ la tp, init_task - sw s0, TASK_TI_CPU(tp) + sw zero, TASK_TI_CPU(tp) la sp, init_thread_union li a0, ASM_THREAD_SIZE diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c index 0cfac48a1272..48e6b7db83a1 100644 --- a/arch/riscv/kernel/irq.c +++ b/arch/riscv/kernel/irq.c @@ -8,6 +8,8 @@ #include <linux/interrupt.h> #include <linux/irqchip.h> #include <linux/irqdomain.h> +#include <linux/seq_file.h> +#include <asm/smp.h> /* * Possible interrupt causes: @@ -24,12 +26,18 @@ */ #define INTERRUPT_CAUSE_FLAG (1UL << (__riscv_xlen - 1)) -asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs, unsigned long cause) +int arch_show_interrupts(struct seq_file *p, int prec) +{ + show_ipi_stats(p, prec); + return 0; +} + +asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); - switch (cause & ~INTERRUPT_CAUSE_FLAG) { + switch (regs->scause & ~INTERRUPT_CAUSE_FLAG) { case INTERRUPT_CAUSE_TIMER: riscv_timer_interrupt(); break; diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S index 5721624886a1..8a5593ff9ff3 100644 --- a/arch/riscv/kernel/mcount.S +++ b/arch/riscv/kernel/mcount.S @@ -75,7 +75,6 @@ ENTRY(return_to_handler) RESTORE_RET_ABI_STATE jalr a1 ENDPROC(return_to_handler) -EXPORT_SYMBOL(return_to_handler) #endif #ifndef CONFIG_DYNAMIC_FTRACE diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index d7c6ca7c95ae..bef19993ea92 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -76,7 +76,9 @@ void show_regs(struct pt_regs *regs) void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL; + regs->sstatus = SR_SPIE; + if (has_fpu) + regs->sstatus |= SR_FS_INITIAL; regs->sepc = pc; regs->sp = sp; set_fs(USER_DS); @@ -84,12 +86,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc, void flush_thread(void) { +#ifdef CONFIG_FPU /* * Reset FPU context * frm: round to nearest, ties to even (IEEE default) * fflags: accrued exceptions cleared */ memset(¤t->thread.fstate, 0, sizeof(current->thread.fstate)); +#endif } int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 9f82a7e34c64..60f1e02eed36 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -28,6 +28,9 @@ enum riscv_regset { REGSET_X, +#ifdef CONFIG_FPU + REGSET_F, +#endif }; static int riscv_gpr_get(struct task_struct *target, @@ -54,6 +57,45 @@ static int riscv_gpr_set(struct task_struct *target, return ret; } +#ifdef CONFIG_FPU +static int riscv_fpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + int ret; + struct __riscv_d_ext_state *fstate = &target->thread.fstate; + + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0, + offsetof(struct __riscv_d_ext_state, fcsr)); + if (!ret) { + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0, + offsetof(struct __riscv_d_ext_state, fcsr) + + sizeof(fstate->fcsr)); + } + + return ret; +} + +static int riscv_fpr_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 __riscv_d_ext_state *fstate = &target->thread.fstate; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, + offsetof(struct __riscv_d_ext_state, fcsr)); + if (!ret) { + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0, + offsetof(struct __riscv_d_ext_state, fcsr) + + sizeof(fstate->fcsr)); + } + + return ret; +} +#endif static const struct user_regset riscv_user_regset[] = { [REGSET_X] = { @@ -64,6 +106,16 @@ static const struct user_regset riscv_user_regset[] = { .get = &riscv_gpr_get, .set = &riscv_gpr_set, }, +#ifdef CONFIG_FPU + [REGSET_F] = { + .core_note_type = NT_PRFPREG, + .n = ELF_NFPREG, + .size = sizeof(elf_fpreg_t), + .align = sizeof(elf_fpreg_t), + .get = &riscv_fpr_get, + .set = &riscv_fpr_set, + }, +#endif }; static const struct user_regset_view riscv_user_native_view = { diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index b2d26d9d8489..2c290e6aaa6e 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -81,6 +81,16 @@ EXPORT_SYMBOL(empty_zero_page); /* The lucky hart to first increment this variable will boot the other cores */ atomic_t hart_lottery; +unsigned long boot_cpu_hartid; + +unsigned long __cpuid_to_hartid_map[NR_CPUS] = { + [0 ... NR_CPUS-1] = INVALID_HARTID +}; + +void __init smp_setup_processor_id(void) +{ + cpuid_to_hartid_map(0) = boot_cpu_hartid; +} #ifdef CONFIG_BLK_DEV_INITRD static void __init setup_initrd(void) @@ -227,7 +237,10 @@ void __init setup_arch(char **cmdline_p) setup_bootmem(); paging_init(); unflatten_device_tree(); + +#ifdef CONFIG_SWIOTLB swiotlb_init(1); +#endif #ifdef CONFIG_SMP setup_smp(); diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 718d0c984ef0..f9b5e7e352ef 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -37,45 +37,69 @@ struct rt_sigframe { struct ucontext uc; }; -static long restore_d_state(struct pt_regs *regs, - struct __riscv_d_ext_state __user *state) +#ifdef CONFIG_FPU +static long restore_fp_state(struct pt_regs *regs, + union __riscv_fp_state *sc_fpregs) { long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; + size_t i; + err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); - if (likely(!err)) - fstate_restore(current, regs); + if (unlikely(err)) + return err; + + fstate_restore(current, regs); + + /* We support no other extension state at this time. */ + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { + u32 value; + + err = __get_user(value, &sc_fpregs->q.reserved[i]); + if (unlikely(err)) + break; + if (value != 0) + return -EINVAL; + } + return err; } -static long save_d_state(struct pt_regs *regs, - struct __riscv_d_ext_state __user *state) +static long save_fp_state(struct pt_regs *regs, + union __riscv_fp_state *sc_fpregs) { + long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; + size_t i; + fstate_save(current, regs); - return __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); + err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); + if (unlikely(err)) + return err; + + /* We support no other extension state at this time. */ + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { + err = __put_user(0, &sc_fpregs->q.reserved[i]); + if (unlikely(err)) + break; + } + + return err; } +#else +#define save_fp_state(task, regs) (0) +#define restore_fp_state(task, regs) (0) +#endif static long restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { long err; - size_t i; /* sc_regs is structured the same as the start of pt_regs */ err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); - if (unlikely(err)) - return err; /* Restore the floating-point state. */ - err = restore_d_state(regs, &sc->sc_fpregs.d); - if (unlikely(err)) - return err; - /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) { - u32 value; - err = __get_user(value, &sc->sc_fpregs.q.reserved[i]); - if (unlikely(err)) - break; - if (value != 0) - return -EINVAL; - } + if (has_fpu) + err |= restore_fp_state(regs, &sc->sc_fpregs); return err; } @@ -124,14 +148,11 @@ static long setup_sigcontext(struct rt_sigframe __user *frame, { struct sigcontext __user *sc = &frame->uc.uc_mcontext; long err; - size_t i; /* sc_regs is structured the same as the start of pt_regs */ err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); /* Save the floating-point state. */ - err |= save_d_state(regs, &sc->sc_fpregs.d); - /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) - err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]); + if (has_fpu) + err |= save_fp_state(regs, &sc->sc_fpregs); return err; } diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 906fe21ea21b..57b1383e5ef7 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -22,23 +22,44 @@ #include <linux/interrupt.h> #include <linux/smp.h> #include <linux/sched.h> +#include <linux/seq_file.h> #include <asm/sbi.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> -/* A collection of single bit ipi messages. */ -static struct { - unsigned long bits ____cacheline_aligned; -} ipi_data[NR_CPUS] __cacheline_aligned; - enum ipi_message_type { IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_MAX }; +/* A collection of single bit ipi messages. */ +static struct { + unsigned long stats[IPI_MAX] ____cacheline_aligned; + unsigned long bits ____cacheline_aligned; +} ipi_data[NR_CPUS] __cacheline_aligned; + +int riscv_hartid_to_cpuid(int hartid) +{ + int i = -1; + + for (i = 0; i < NR_CPUS; i++) + if (cpuid_to_hartid_map(i) == hartid) + return i; + pr_err("Couldn't find cpu id for hartid [%d]\n", hartid); + BUG(); + return i; +} + +void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out) +{ + int cpu; + + for_each_cpu(cpu, in) + cpumask_set_cpu(cpuid_to_hartid_map(cpu), out); +} /* Unsupported */ int setup_profiling_timer(unsigned int multiplier) { @@ -48,6 +69,7 @@ int setup_profiling_timer(unsigned int multiplier) void riscv_software_interrupt(void) { unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; + unsigned long *stats = ipi_data[smp_processor_id()].stats; /* Clear pending IPI */ csr_clear(sip, SIE_SSIE); @@ -62,11 +84,15 @@ void riscv_software_interrupt(void) if (ops == 0) return; - if (ops & (1 << IPI_RESCHEDULE)) + if (ops & (1 << IPI_RESCHEDULE)) { + stats[IPI_RESCHEDULE]++; scheduler_ipi(); + } - if (ops & (1 << IPI_CALL_FUNC)) + if (ops & (1 << IPI_CALL_FUNC)) { + stats[IPI_CALL_FUNC]++; generic_smp_call_function_interrupt(); + } BUG_ON((ops >> IPI_MAX) != 0); @@ -78,14 +104,36 @@ void riscv_software_interrupt(void) static void send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) { - int i; + int cpuid, hartid; + struct cpumask hartid_mask; + cpumask_clear(&hartid_mask); mb(); - for_each_cpu(i, to_whom) - set_bit(operation, &ipi_data[i].bits); - + for_each_cpu(cpuid, to_whom) { + set_bit(operation, &ipi_data[cpuid].bits); + hartid = cpuid_to_hartid_map(cpuid); + cpumask_set_cpu(hartid, &hartid_mask); + } mb(); - sbi_send_ipi(cpumask_bits(to_whom)); + sbi_send_ipi(cpumask_bits(&hartid_mask)); +} + +static const char * const ipi_names[] = { + [IPI_RESCHEDULE] = "Rescheduling interrupts", + [IPI_CALL_FUNC] = "Function call interrupts", +}; + +void show_ipi_stats(struct seq_file *p, int prec) +{ + unsigned int cpu, i; + + for (i = 0; i < IPI_MAX; i++) { + seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, + prec >= 4 ? " " : ""); + for_each_online_cpu(cpu) + seq_printf(p, "%10lu ", ipi_data[cpu].stats[i]); + seq_printf(p, " %s\n", ipi_names[i]); + } } void arch_send_call_function_ipi_mask(struct cpumask *mask) @@ -127,7 +175,7 @@ void smp_send_reschedule(int cpu) void flush_icache_mm(struct mm_struct *mm, bool local) { unsigned int cpu; - cpumask_t others, *mask; + cpumask_t others, hmask, *mask; preempt_disable(); @@ -145,9 +193,11 @@ void flush_icache_mm(struct mm_struct *mm, bool local) */ cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu)); local |= cpumask_empty(&others); - if (mm != current->active_mm || !local) - sbi_remote_fence_i(others.bits); - else { + if (mm != current->active_mm || !local) { + cpumask_clear(&hmask); + riscv_cpuid_to_hartid_mask(&others, &hmask); + sbi_remote_fence_i(hmask.bits); + } else { /* * It's assumed that at least one strongly ordered operation is * performed on this hart between setting a hart's cpumask bit diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 56abab6a9812..18cda0e8cf94 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -30,6 +30,7 @@ #include <linux/irq.h> #include <linux/of.h> #include <linux/sched/task_stack.h> +#include <linux/sched/mm.h> #include <asm/irq.h> #include <asm/mmu_context.h> #include <asm/tlbflush.h> @@ -50,25 +51,33 @@ void __init smp_prepare_cpus(unsigned int max_cpus) void __init setup_smp(void) { struct device_node *dn = NULL; - int hart, im_okay_therefore_i_am = 0; + int hart; + bool found_boot_cpu = false; + int cpuid = 1; while ((dn = of_find_node_by_type(dn, "cpu"))) { - hart = riscv_of_processor_hart(dn); - if (hart >= 0) { - set_cpu_possible(hart, true); - set_cpu_present(hart, true); - if (hart == smp_processor_id()) { - BUG_ON(im_okay_therefore_i_am); - im_okay_therefore_i_am = 1; - } + hart = riscv_of_processor_hartid(dn); + if (hart < 0) + continue; + + if (hart == cpuid_to_hartid_map(0)) { + BUG_ON(found_boot_cpu); + found_boot_cpu = 1; + continue; } + + cpuid_to_hartid_map(cpuid) = hart; + set_cpu_possible(cpuid, true); + set_cpu_present(cpuid, true); + cpuid++; } - BUG_ON(!im_okay_therefore_i_am); + BUG_ON(!found_boot_cpu); } int __cpu_up(unsigned int cpu, struct task_struct *tidle) { + int hartid = cpuid_to_hartid_map(cpu); tidle->thread_info.cpu = cpu; /* @@ -79,8 +88,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) * the spinning harts that they can continue the boot process. */ smp_mb(); - __cpu_up_stack_pointer[cpu] = task_stack_page(tidle) + THREAD_SIZE; - __cpu_up_task_pointer[cpu] = tidle; + WRITE_ONCE(__cpu_up_stack_pointer[hartid], + task_stack_page(tidle) + THREAD_SIZE); + WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle); while (!cpu_online(cpu)) cpu_relax(); @@ -100,14 +110,22 @@ asmlinkage void __init smp_callin(void) struct mm_struct *mm = &init_mm; /* All kernel threads share the same mm context. */ - atomic_inc(&mm->mm_count); + mmgrab(mm); current->active_mm = mm; trap_init(); notify_cpu_starting(smp_processor_id()); set_cpu_online(smp_processor_id(), 1); + /* + * Remote TLB flushes are ignored while the CPU is offline, so emit + * a local TLB flush right now just in case. + */ local_flush_tlb_all(); - local_irq_enable(); + /* + * Disable preemption before enabling interrupts, so we don't try to + * schedule a CPU that hasn't actually started yet. + */ preempt_disable(); + local_irq_enable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 445ec84f9a47..5739bd05d289 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -2,6 +2,7 @@ lib-y += delay.o lib-y += memcpy.o lib-y += memset.o lib-y += uaccess.o -lib-y += tishift.o + +lib-(CONFIG_64BIT) += tishift.o lib-$(CONFIG_32BIT) += udivdi3.o diff --git a/arch/riscv/mm/ioremap.c b/arch/riscv/mm/ioremap.c index 70ef2724cdf6..bd2f2db557cc 100644 --- a/arch/riscv/mm/ioremap.c +++ b/arch/riscv/mm/ioremap.c @@ -42,7 +42,7 @@ static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size, /* Page-align mappings */ offset = addr & (~PAGE_MASK); - addr &= PAGE_MASK; + addr -= offset; size = PAGE_ALIGN(size + offset); area = get_vm_area_caller(size, VM_IOREMAP, caller); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 039a3417dfc4..8b25e1f45b27 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -783,6 +783,17 @@ config VFIO_CCW To compile this driver as a module, choose M here: the module will be called vfio_ccw. +config VFIO_AP + def_tristate n + prompt "VFIO support for AP devices" + depends on S390_AP_IOMMU && VFIO_MDEV_DEVICE && KVM + help + This driver grants access to Adjunct Processor (AP) devices + via the VFIO mediated device interface. + + To compile this driver as a module, choose M here: the module + will be called vfio_ap. + endmenu menu "Dump support" diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 433a994b1a89..54f375627532 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -25,10 +25,6 @@ #include "appldata.h" - -#define LOAD_INT(x) ((x) >> FSHIFT) -#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) - /* * OS data * diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 941d8cc6c9f5..259d1698ac50 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -668,7 +668,6 @@ CONFIG_CRYPTO_USER=m # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index eb6f75f24208..37fd60c20e22 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig @@ -610,7 +610,6 @@ CONFIG_CRYPTO_USER=m # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_PCRYPT=m CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_MCRYPTD=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_LRW=m diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index c54cb26eb7f5..812d9498d97b 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -44,7 +44,7 @@ struct s390_aes_ctx { int key_len; unsigned long fc; union { - struct crypto_skcipher *blk; + struct crypto_sync_skcipher *blk; struct crypto_cipher *cip; } fallback; }; @@ -54,7 +54,7 @@ struct s390_xts_ctx { u8 pcc_key[32]; int key_len; unsigned long fc; - struct crypto_skcipher *fallback; + struct crypto_sync_skcipher *fallback; }; struct gcm_sg_walk { @@ -184,14 +184,15 @@ static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key, struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int ret; - crypto_skcipher_clear_flags(sctx->fallback.blk, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(sctx->fallback.blk, tfm->crt_flags & + crypto_sync_skcipher_clear_flags(sctx->fallback.blk, + CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(sctx->fallback.blk, tfm->crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(sctx->fallback.blk, key, len); + ret = crypto_sync_skcipher_setkey(sctx->fallback.blk, key, len); tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->crt_flags |= crypto_skcipher_get_flags(sctx->fallback.blk) & + tfm->crt_flags |= crypto_sync_skcipher_get_flags(sctx->fallback.blk) & CRYPTO_TFM_RES_MASK; return ret; @@ -204,9 +205,9 @@ static int fallback_blk_dec(struct blkcipher_desc *desc, unsigned int ret; struct crypto_blkcipher *tfm = desc->tfm; struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); - skcipher_request_set_tfm(req, sctx->fallback.blk); + skcipher_request_set_sync_tfm(req, sctx->fallback.blk); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -223,9 +224,9 @@ static int fallback_blk_enc(struct blkcipher_desc *desc, unsigned int ret; struct crypto_blkcipher *tfm = desc->tfm; struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); - skcipher_request_set_tfm(req, sctx->fallback.blk); + skcipher_request_set_sync_tfm(req, sctx->fallback.blk); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -306,8 +307,7 @@ static int fallback_init_blk(struct crypto_tfm *tfm) const char *name = tfm->__crt_alg->cra_name; struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - sctx->fallback.blk = crypto_alloc_skcipher(name, 0, - CRYPTO_ALG_ASYNC | + sctx->fallback.blk = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(sctx->fallback.blk)) { @@ -323,7 +323,7 @@ static void fallback_exit_blk(struct crypto_tfm *tfm) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(sctx->fallback.blk); + crypto_free_sync_skcipher(sctx->fallback.blk); } static struct crypto_alg ecb_aes_alg = { @@ -453,14 +453,15 @@ static int xts_fallback_setkey(struct crypto_tfm *tfm, const u8 *key, struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); unsigned int ret; - crypto_skcipher_clear_flags(xts_ctx->fallback, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(xts_ctx->fallback, tfm->crt_flags & + crypto_sync_skcipher_clear_flags(xts_ctx->fallback, + CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(xts_ctx->fallback, tfm->crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(xts_ctx->fallback, key, len); + ret = crypto_sync_skcipher_setkey(xts_ctx->fallback, key, len); tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->crt_flags |= crypto_skcipher_get_flags(xts_ctx->fallback) & + tfm->crt_flags |= crypto_sync_skcipher_get_flags(xts_ctx->fallback) & CRYPTO_TFM_RES_MASK; return ret; @@ -472,10 +473,10 @@ static int xts_fallback_decrypt(struct blkcipher_desc *desc, { struct crypto_blkcipher *tfm = desc->tfm; struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); unsigned int ret; - skcipher_request_set_tfm(req, xts_ctx->fallback); + skcipher_request_set_sync_tfm(req, xts_ctx->fallback); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -491,10 +492,10 @@ static int xts_fallback_encrypt(struct blkcipher_desc *desc, { struct crypto_blkcipher *tfm = desc->tfm; struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); unsigned int ret; - skcipher_request_set_tfm(req, xts_ctx->fallback); + skcipher_request_set_sync_tfm(req, xts_ctx->fallback); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -611,8 +612,7 @@ static int xts_fallback_init(struct crypto_tfm *tfm) const char *name = tfm->__crt_alg->cra_name; struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); - xts_ctx->fallback = crypto_alloc_skcipher(name, 0, - CRYPTO_ALG_ASYNC | + xts_ctx->fallback = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(xts_ctx->fallback)) { @@ -627,7 +627,7 @@ static void xts_fallback_exit(struct crypto_tfm *tfm) { struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(xts_ctx->fallback); + crypto_free_sync_skcipher(xts_ctx->fallback); } static struct crypto_alg xts_aes_alg = { diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 20add000dd6d..7cb6a52f727d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -221,7 +221,6 @@ CONFIG_CRYPTO_SALSA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_DEFLATE=m diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 97db2fba546a..63b46e30b2c3 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -9,6 +9,8 @@ #include <linux/sched/task_stack.h> #include <linux/thread_info.h> +#include <asm-generic/compat.h> + #define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p( \ typeof(0?(__force t)0:0ULL), u64)) @@ -51,34 +53,18 @@ #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "s390\0\0\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; typedef struct { u32 mask; diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 29c940bf8506..d5d24889c3bc 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -44,6 +44,7 @@ #define KVM_REQ_ICPT_OPEREXC KVM_ARCH_REQ(2) #define KVM_REQ_START_MIGRATION KVM_ARCH_REQ(3) #define KVM_REQ_STOP_MIGRATION KVM_ARCH_REQ(4) +#define KVM_REQ_VSIE_RESTART KVM_ARCH_REQ(5) #define SIGP_CTRL_C 0x80 #define SIGP_CTRL_SCN_MASK 0x3f @@ -186,6 +187,7 @@ struct kvm_s390_sie_block { #define ECA_AIV 0x00200000 #define ECA_VX 0x00020000 #define ECA_PROTEXCI 0x00002000 +#define ECA_APIE 0x00000008 #define ECA_SII 0x00000001 __u32 eca; /* 0x004c */ #define ICPT_INST 0x04 @@ -237,7 +239,11 @@ struct kvm_s390_sie_block { psw_t gpsw; /* 0x0090 */ __u64 gg14; /* 0x00a0 */ __u64 gg15; /* 0x00a8 */ - __u8 reservedb0[20]; /* 0x00b0 */ + __u8 reservedb0[8]; /* 0x00b0 */ +#define HPID_KVM 0x4 +#define HPID_VSIE 0x5 + __u8 hpid; /* 0x00b8 */ + __u8 reservedb9[11]; /* 0x00b9 */ __u16 extcpuaddr; /* 0x00c4 */ __u16 eic; /* 0x00c6 */ __u32 reservedc8; /* 0x00c8 */ @@ -255,6 +261,8 @@ struct kvm_s390_sie_block { __u8 reservede4[4]; /* 0x00e4 */ __u64 tecmc; /* 0x00e8 */ __u8 reservedf0[12]; /* 0x00f0 */ +#define CRYCB_FORMAT_MASK 0x00000003 +#define CRYCB_FORMAT0 0x00000000 #define CRYCB_FORMAT1 0x00000001 #define CRYCB_FORMAT2 0x00000003 __u32 crycbd; /* 0x00fc */ @@ -715,6 +723,7 @@ struct kvm_s390_crypto { __u32 crycbd; __u8 aes_kw; __u8 dea_kw; + __u8 apie; }; #define APCB0_MASK_SIZE 1 @@ -855,6 +864,10 @@ void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu, void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, struct kvm_async_pf *work); +void kvm_arch_crypto_clear_masks(struct kvm *kvm); +void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm, + unsigned long *aqm, unsigned long *adm); + extern int sie64a(struct kvm_s390_sie_block *, u64 *); extern char sie_exit; diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index fd79c0d35dc4..a1fbf15d53aa 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -15,6 +15,7 @@ #define __IGNORE_pkey_alloc #define __IGNORE_pkey_free +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME @@ -25,7 +26,6 @@ #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_MMAP @@ -34,6 +34,7 @@ #define __ARCH_WANT_SYS_SIGPROCMASK # ifdef CONFIG_COMPAT # define __ARCH_WANT_COMPAT_SYS_TIME +# define __ARCH_WANT_SYS_UTIME32 # endif #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_VFORK diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild index e364873e0d10..dc38a90cf091 100644 --- a/arch/s390/include/uapi/asm/Kbuild +++ b/arch/s390/include/uapi/asm/Kbuild @@ -18,3 +18,4 @@ generic-y += shmbuf.h generic-y += sockios.h generic-y += swab.h generic-y += termbits.h +generic-y += siginfo.h
\ No newline at end of file diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index 9a50f02b9894..16511d97e8dc 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -160,6 +160,8 @@ struct kvm_s390_vm_cpu_subfunc { #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 #define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 #define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 +#define KVM_S390_VM_CRYPTO_ENABLE_APIE 4 +#define KVM_S390_VM_CRYPTO_DISABLE_APIE 5 /* kvm attributes for migration mode */ #define KVM_S390_VM_MIGRATION_STOP 0 diff --git a/arch/s390/include/uapi/asm/siginfo.h b/arch/s390/include/uapi/asm/siginfo.h deleted file mode 100644 index 6984820f2f1c..000000000000 --- a/arch/s390/include/uapi/asm/siginfo.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * S390 version - * - * Derived from "include/asm-i386/siginfo.h" - */ - -#ifndef _S390_SIGINFO_H -#define _S390_SIGINFO_H - -#ifdef __s390x__ -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) -#endif - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ac5da6b0b862..fe24150ff666 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -40,6 +40,7 @@ #include <asm/sclp.h> #include <asm/cpacf.h> #include <asm/timex.h> +#include <asm/ap.h> #include "kvm-s390.h" #include "gaccess.h" @@ -844,20 +845,24 @@ void kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm) kvm_s390_vcpu_block_all(kvm); - kvm_for_each_vcpu(i, vcpu, kvm) + kvm_for_each_vcpu(i, vcpu, kvm) { kvm_s390_vcpu_crypto_setup(vcpu); + /* recreate the shadow crycb by leaving the VSIE handler */ + kvm_s390_sync_request(KVM_REQ_VSIE_RESTART, vcpu); + } kvm_s390_vcpu_unblock_all(kvm); } static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr) { - if (!test_kvm_facility(kvm, 76)) - return -EINVAL; - mutex_lock(&kvm->lock); switch (attr->attr) { case KVM_S390_VM_CRYPTO_ENABLE_AES_KW: + if (!test_kvm_facility(kvm, 76)) { + mutex_unlock(&kvm->lock); + return -EINVAL; + } get_random_bytes( kvm->arch.crypto.crycb->aes_wrapping_key_mask, sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask)); @@ -865,6 +870,10 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr) VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support"); break; case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW: + if (!test_kvm_facility(kvm, 76)) { + mutex_unlock(&kvm->lock); + return -EINVAL; + } get_random_bytes( kvm->arch.crypto.crycb->dea_wrapping_key_mask, sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask)); @@ -872,17 +881,39 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr) VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support"); break; case KVM_S390_VM_CRYPTO_DISABLE_AES_KW: + if (!test_kvm_facility(kvm, 76)) { + mutex_unlock(&kvm->lock); + return -EINVAL; + } kvm->arch.crypto.aes_kw = 0; memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0, sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask)); VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support"); break; case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW: + if (!test_kvm_facility(kvm, 76)) { + mutex_unlock(&kvm->lock); + return -EINVAL; + } kvm->arch.crypto.dea_kw = 0; memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0, sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask)); VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support"); break; + case KVM_S390_VM_CRYPTO_ENABLE_APIE: + if (!ap_instructions_available()) { + mutex_unlock(&kvm->lock); + return -EOPNOTSUPP; + } + kvm->arch.crypto.apie = 1; + break; + case KVM_S390_VM_CRYPTO_DISABLE_APIE: + if (!ap_instructions_available()) { + mutex_unlock(&kvm->lock); + return -EOPNOTSUPP; + } + kvm->arch.crypto.apie = 0; + break; default: mutex_unlock(&kvm->lock); return -ENXIO; @@ -1491,6 +1522,10 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW: ret = 0; break; + case KVM_S390_VM_CRYPTO_ENABLE_APIE: + case KVM_S390_VM_CRYPTO_DISABLE_APIE: + ret = ap_instructions_available() ? 0 : -ENXIO; + break; default: ret = -ENXIO; break; @@ -1992,55 +2027,101 @@ long kvm_arch_vm_ioctl(struct file *filp, return r; } -static int kvm_s390_query_ap_config(u8 *config) -{ - u32 fcn_code = 0x04000000UL; - u32 cc = 0; - - memset(config, 0, 128); - asm volatile( - "lgr 0,%1\n" - "lgr 2,%2\n" - ".long 0xb2af0000\n" /* PQAP(QCI) */ - "0: ipm %0\n" - "srl %0,28\n" - "1:\n" - EX_TABLE(0b, 1b) - : "+r" (cc) - : "r" (fcn_code), "r" (config) - : "cc", "0", "2", "memory" - ); - - return cc; -} - static int kvm_s390_apxa_installed(void) { - u8 config[128]; - int cc; + struct ap_config_info info; - if (test_facility(12)) { - cc = kvm_s390_query_ap_config(config); - - if (cc) - pr_err("PQAP(QCI) failed with cc=%d", cc); - else - return config[0] & 0x40; + if (ap_instructions_available()) { + if (ap_qci(&info) == 0) + return info.apxa; } return 0; } +/* + * The format of the crypto control block (CRYCB) is specified in the 3 low + * order bits of the CRYCB designation (CRYCBD) field as follows: + * Format 0: Neither the message security assist extension 3 (MSAX3) nor the + * AP extended addressing (APXA) facility are installed. + * Format 1: The APXA facility is not installed but the MSAX3 facility is. + * Format 2: Both the APXA and MSAX3 facilities are installed + */ static void kvm_s390_set_crycb_format(struct kvm *kvm) { kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb; + /* Clear the CRYCB format bits - i.e., set format 0 by default */ + kvm->arch.crypto.crycbd &= ~(CRYCB_FORMAT_MASK); + + /* Check whether MSAX3 is installed */ + if (!test_kvm_facility(kvm, 76)) + return; + if (kvm_s390_apxa_installed()) kvm->arch.crypto.crycbd |= CRYCB_FORMAT2; else kvm->arch.crypto.crycbd |= CRYCB_FORMAT1; } +void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm, + unsigned long *aqm, unsigned long *adm) +{ + struct kvm_s390_crypto_cb *crycb = kvm->arch.crypto.crycb; + + mutex_lock(&kvm->lock); + kvm_s390_vcpu_block_all(kvm); + + switch (kvm->arch.crypto.crycbd & CRYCB_FORMAT_MASK) { + case CRYCB_FORMAT2: /* APCB1 use 256 bits */ + memcpy(crycb->apcb1.apm, apm, 32); + VM_EVENT(kvm, 3, "SET CRYCB: apm %016lx %016lx %016lx %016lx", + apm[0], apm[1], apm[2], apm[3]); + memcpy(crycb->apcb1.aqm, aqm, 32); + VM_EVENT(kvm, 3, "SET CRYCB: aqm %016lx %016lx %016lx %016lx", + aqm[0], aqm[1], aqm[2], aqm[3]); + memcpy(crycb->apcb1.adm, adm, 32); + VM_EVENT(kvm, 3, "SET CRYCB: adm %016lx %016lx %016lx %016lx", + adm[0], adm[1], adm[2], adm[3]); + break; + case CRYCB_FORMAT1: + case CRYCB_FORMAT0: /* Fall through both use APCB0 */ + memcpy(crycb->apcb0.apm, apm, 8); + memcpy(crycb->apcb0.aqm, aqm, 2); + memcpy(crycb->apcb0.adm, adm, 2); + VM_EVENT(kvm, 3, "SET CRYCB: apm %016lx aqm %04x adm %04x", + apm[0], *((unsigned short *)aqm), + *((unsigned short *)adm)); + break; + default: /* Can not happen */ + break; + } + + /* recreate the shadow crycb for each vcpu */ + kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART); + kvm_s390_vcpu_unblock_all(kvm); + mutex_unlock(&kvm->lock); +} +EXPORT_SYMBOL_GPL(kvm_arch_crypto_set_masks); + +void kvm_arch_crypto_clear_masks(struct kvm *kvm) +{ + mutex_lock(&kvm->lock); + kvm_s390_vcpu_block_all(kvm); + + memset(&kvm->arch.crypto.crycb->apcb0, 0, + sizeof(kvm->arch.crypto.crycb->apcb0)); + memset(&kvm->arch.crypto.crycb->apcb1, 0, + sizeof(kvm->arch.crypto.crycb->apcb1)); + + VM_EVENT(kvm, 3, "%s", "CLR CRYCB:"); + /* recreate the shadow crycb for each vcpu */ + kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART); + kvm_s390_vcpu_unblock_all(kvm); + mutex_unlock(&kvm->lock); +} +EXPORT_SYMBOL_GPL(kvm_arch_crypto_clear_masks); + static u64 kvm_s390_get_initial_cpuid(void) { struct cpuid cpuid; @@ -2052,12 +2133,12 @@ static u64 kvm_s390_get_initial_cpuid(void) static void kvm_s390_crypto_init(struct kvm *kvm) { - if (!test_kvm_facility(kvm, 76)) - return; - kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb; kvm_s390_set_crycb_format(kvm); + if (!test_kvm_facility(kvm, 76)) + return; + /* Enable AES/DEA protected key functions by default */ kvm->arch.crypto.aes_kw = 1; kvm->arch.crypto.dea_kw = 1; @@ -2583,17 +2664,25 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu) { - if (!test_kvm_facility(vcpu->kvm, 76)) + /* + * If the AP instructions are not being interpreted and the MSAX3 + * facility is not configured for the guest, there is nothing to set up. + */ + if (!vcpu->kvm->arch.crypto.apie && !test_kvm_facility(vcpu->kvm, 76)) return; + vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd; vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA); + vcpu->arch.sie_block->eca &= ~ECA_APIE; + + if (vcpu->kvm->arch.crypto.apie) + vcpu->arch.sie_block->eca |= ECA_APIE; + /* Set up protected key support */ if (vcpu->kvm->arch.crypto.aes_kw) vcpu->arch.sie_block->ecb3 |= ECB3_AES; if (vcpu->kvm->arch.crypto.dea_kw) vcpu->arch.sie_block->ecb3 |= ECB3_DEA; - - vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd; } void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu) @@ -2685,6 +2774,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; + vcpu->arch.sie_block->hpid = HPID_KVM; + kvm_s390_vcpu_crypto_setup(vcpu); return rc; @@ -2768,18 +2859,25 @@ static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu) exit_sie(vcpu); } +bool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu) +{ + return atomic_read(&vcpu->arch.sie_block->prog20) & + (PROG_BLOCK_SIE | PROG_REQUEST); +} + static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu) { atomic_andnot(PROG_REQUEST, &vcpu->arch.sie_block->prog20); } /* - * Kick a guest cpu out of SIE and wait until SIE is not running. + * Kick a guest cpu out of (v)SIE and wait until (v)SIE is not running. * If the CPU is not running (e.g. waiting as idle) the function will * return immediately. */ void exit_sie(struct kvm_vcpu *vcpu) { kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT); + kvm_s390_vsie_kick(vcpu); while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE) cpu_relax(); } @@ -3196,6 +3294,8 @@ retry: /* nothing to do, just clear the request */ kvm_clear_request(KVM_REQ_UNHALT, vcpu); + /* we left the vsie handler, nothing to do, just clear the request */ + kvm_clear_request(KVM_REQ_VSIE_RESTART, vcpu); return 0; } diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 981e3ba97461..1f6e36cdce0d 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -290,6 +290,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu); void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu); void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu); void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu); +bool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu); void exit_sie(struct kvm_vcpu *vcpu); void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu); int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu); diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index a2b28cd1e3fe..a153257bf7d9 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -135,14 +135,148 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) atomic_set(&scb_s->cpuflags, newflags); return 0; } +/* Copy to APCB FORMAT1 from APCB FORMAT0 */ +static int setup_apcb10(struct kvm_vcpu *vcpu, struct kvm_s390_apcb1 *apcb_s, + unsigned long apcb_o, struct kvm_s390_apcb1 *apcb_h) +{ + struct kvm_s390_apcb0 tmp; -/* + if (read_guest_real(vcpu, apcb_o, &tmp, sizeof(struct kvm_s390_apcb0))) + return -EFAULT; + + apcb_s->apm[0] = apcb_h->apm[0] & tmp.apm[0]; + apcb_s->aqm[0] = apcb_h->aqm[0] & tmp.aqm[0] & 0xffff000000000000UL; + apcb_s->adm[0] = apcb_h->adm[0] & tmp.adm[0] & 0xffff000000000000UL; + + return 0; + +} + +/** + * setup_apcb00 - Copy to APCB FORMAT0 from APCB FORMAT0 + * @vcpu: pointer to the virtual CPU + * @apcb_s: pointer to start of apcb in the shadow crycb + * @apcb_o: pointer to start of original apcb in the guest2 + * @apcb_h: pointer to start of apcb in the guest1 + * + * Returns 0 and -EFAULT on error reading guest apcb + */ +static int setup_apcb00(struct kvm_vcpu *vcpu, unsigned long *apcb_s, + unsigned long apcb_o, unsigned long *apcb_h) +{ + if (read_guest_real(vcpu, apcb_o, apcb_s, + sizeof(struct kvm_s390_apcb0))) + return -EFAULT; + + bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb0)); + + return 0; +} + +/** + * setup_apcb11 - Copy the FORMAT1 APCB from the guest to the shadow CRYCB + * @vcpu: pointer to the virtual CPU + * @apcb_s: pointer to start of apcb in the shadow crycb + * @apcb_o: pointer to start of original guest apcb + * @apcb_h: pointer to start of apcb in the host + * + * Returns 0 and -EFAULT on error reading guest apcb + */ +static int setup_apcb11(struct kvm_vcpu *vcpu, unsigned long *apcb_s, + unsigned long apcb_o, + unsigned long *apcb_h) +{ + if (read_guest_real(vcpu, apcb_o, apcb_s, + sizeof(struct kvm_s390_apcb1))) + return -EFAULT; + + bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb1)); + + return 0; +} + +/** + * setup_apcb - Create a shadow copy of the apcb. + * @vcpu: pointer to the virtual CPU + * @crycb_s: pointer to shadow crycb + * @crycb_o: pointer to original guest crycb + * @crycb_h: pointer to the host crycb + * @fmt_o: format of the original guest crycb. + * @fmt_h: format of the host crycb. + * + * Checks the compatibility between the guest and host crycb and calls the + * appropriate copy function. + * + * Return 0 or an error number if the guest and host crycb are incompatible. + */ +static int setup_apcb(struct kvm_vcpu *vcpu, struct kvm_s390_crypto_cb *crycb_s, + const u32 crycb_o, + struct kvm_s390_crypto_cb *crycb_h, + int fmt_o, int fmt_h) +{ + struct kvm_s390_crypto_cb *crycb; + + crycb = (struct kvm_s390_crypto_cb *) (unsigned long)crycb_o; + + switch (fmt_o) { + case CRYCB_FORMAT2: + if ((crycb_o & PAGE_MASK) != ((crycb_o + 256) & PAGE_MASK)) + return -EACCES; + if (fmt_h != CRYCB_FORMAT2) + return -EINVAL; + return setup_apcb11(vcpu, (unsigned long *)&crycb_s->apcb1, + (unsigned long) &crycb->apcb1, + (unsigned long *)&crycb_h->apcb1); + case CRYCB_FORMAT1: + switch (fmt_h) { + case CRYCB_FORMAT2: + return setup_apcb10(vcpu, &crycb_s->apcb1, + (unsigned long) &crycb->apcb0, + &crycb_h->apcb1); + case CRYCB_FORMAT1: + return setup_apcb00(vcpu, + (unsigned long *) &crycb_s->apcb0, + (unsigned long) &crycb->apcb0, + (unsigned long *) &crycb_h->apcb0); + } + break; + case CRYCB_FORMAT0: + if ((crycb_o & PAGE_MASK) != ((crycb_o + 32) & PAGE_MASK)) + return -EACCES; + + switch (fmt_h) { + case CRYCB_FORMAT2: + return setup_apcb10(vcpu, &crycb_s->apcb1, + (unsigned long) &crycb->apcb0, + &crycb_h->apcb1); + case CRYCB_FORMAT1: + case CRYCB_FORMAT0: + return setup_apcb00(vcpu, + (unsigned long *) &crycb_s->apcb0, + (unsigned long) &crycb->apcb0, + (unsigned long *) &crycb_h->apcb0); + } + } + return -EINVAL; +} + +/** + * shadow_crycb - Create a shadow copy of the crycb block + * @vcpu: a pointer to the virtual CPU + * @vsie_page: a pointer to internal date used for the vSIE + * * Create a shadow copy of the crycb block and setup key wrapping, if * requested for guest 3 and enabled for guest 2. * - * We only accept format-1 (no AP in g2), but convert it into format-2 + * We accept format-1 or format-2, but we convert format-1 into format-2 + * in the shadow CRYCB. + * Using format-2 enables the firmware to choose the right format when + * scheduling the SIE. * There is nothing to do for format-0. * + * This function centralize the issuing of set_validity_icpt() for all + * the subfunctions working on the crycb. + * * Returns: - 0 if shadowed or nothing to do * - > 0 if control has to be given to guest 2 */ @@ -154,23 +288,40 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) const u32 crycb_addr = crycbd_o & 0x7ffffff8U; unsigned long *b1, *b2; u8 ecb3_flags; + int apie_h; + int key_msk = test_kvm_facility(vcpu->kvm, 76); + int fmt_o = crycbd_o & CRYCB_FORMAT_MASK; + int fmt_h = vcpu->arch.sie_block->crycbd & CRYCB_FORMAT_MASK; + int ret = 0; scb_s->crycbd = 0; - if (!(crycbd_o & vcpu->arch.sie_block->crycbd & CRYCB_FORMAT1)) - return 0; - /* format-1 is supported with message-security-assist extension 3 */ - if (!test_kvm_facility(vcpu->kvm, 76)) + + apie_h = vcpu->arch.sie_block->eca & ECA_APIE; + if (!apie_h && !key_msk) return 0; + + if (!crycb_addr) + return set_validity_icpt(scb_s, 0x0039U); + + if (fmt_o == CRYCB_FORMAT1) + if ((crycb_addr & PAGE_MASK) != + ((crycb_addr + 128) & PAGE_MASK)) + return set_validity_icpt(scb_s, 0x003CU); + + if (apie_h && (scb_o->eca & ECA_APIE)) { + ret = setup_apcb(vcpu, &vsie_page->crycb, crycb_addr, + vcpu->kvm->arch.crypto.crycb, + fmt_o, fmt_h); + if (ret) + goto end; + scb_s->eca |= scb_o->eca & ECA_APIE; + } + /* we may only allow it if enabled for guest 2 */ ecb3_flags = scb_o->ecb3 & vcpu->arch.sie_block->ecb3 & (ECB3_AES | ECB3_DEA); if (!ecb3_flags) - return 0; - - if ((crycb_addr & PAGE_MASK) != ((crycb_addr + 128) & PAGE_MASK)) - return set_validity_icpt(scb_s, 0x003CU); - else if (!crycb_addr) - return set_validity_icpt(scb_s, 0x0039U); + goto end; /* copy only the wrapping keys */ if (read_guest_real(vcpu, crycb_addr + 72, @@ -178,8 +329,6 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) return set_validity_icpt(scb_s, 0x0035U); scb_s->ecb3 |= ecb3_flags; - scb_s->crycbd = ((__u32)(__u64) &vsie_page->crycb) | CRYCB_FORMAT1 | - CRYCB_FORMAT2; /* xor both blocks in one run */ b1 = (unsigned long *) vsie_page->crycb.dea_wrapping_key_mask; @@ -187,6 +336,16 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) vcpu->kvm->arch.crypto.crycb->dea_wrapping_key_mask; /* as 56%8 == 0, bitmap_xor won't overwrite any data */ bitmap_xor(b1, b1, b2, BITS_PER_BYTE * 56); +end: + switch (ret) { + case -EINVAL: + return set_validity_icpt(scb_s, 0x0020U); + case -EFAULT: + return set_validity_icpt(scb_s, 0x0035U); + case -EACCES: + return set_validity_icpt(scb_s, 0x003CU); + } + scb_s->crycbd = ((__u32)(__u64) &vsie_page->crycb) | CRYCB_FORMAT2; return 0; } @@ -383,6 +542,8 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) if (test_kvm_facility(vcpu->kvm, 156)) scb_s->ecd |= scb_o->ecd & ECD_ETOKENF; + scb_s->hpid = HPID_VSIE; + prepare_ibc(vcpu, vsie_page); rc = shadow_crycb(vcpu, vsie_page); out: @@ -830,7 +991,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; int guest_bp_isolation; - int rc; + int rc = 0; handle_last_fault(vcpu, vsie_page); @@ -858,7 +1019,18 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) guest_enter_irqoff(); local_irq_enable(); - rc = sie64a(scb_s, vcpu->run->s.regs.gprs); + /* + * Simulate a SIE entry of the VCPU (see sie64a), so VCPU blocking + * and VCPU requests also hinder the vSIE from running and lead + * to an immediate exit. kvm_s390_vsie_kick() has to be used to + * also kick the vSIE. + */ + vcpu->arch.sie_block->prog0c |= PROG_IN_SIE; + barrier(); + if (!kvm_s390_vcpu_sie_inhibited(vcpu)) + rc = sie64a(scb_s, vcpu->run->s.regs.gprs); + barrier(); + vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE; local_irq_disable(); guest_exit_irqoff(); @@ -1005,7 +1177,8 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) if (rc == -EAGAIN) rc = 0; if (rc || scb_s->icptcode || signal_pending(current) || - kvm_s390_vcpu_has_irq(vcpu, 0)) + kvm_s390_vcpu_has_irq(vcpu, 0) || + kvm_s390_vcpu_sie_inhibited(vcpu)) break; } @@ -1122,7 +1295,8 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) if (unlikely(scb_addr & 0x1ffUL)) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); - if (signal_pending(current) || kvm_s390_vcpu_has_irq(vcpu, 0)) + if (signal_pending(current) || kvm_s390_vcpu_has_irq(vcpu, 0) || + kvm_s390_vcpu_sie_inhibited(vcpu)) return 0; vsie_page = get_vsie_page(vcpu->kvm, scb_addr); diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 911c7ded35f1..1e668b95e0c6 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -907,10 +907,16 @@ static inline pmd_t *gmap_pmd_op_walk(struct gmap *gmap, unsigned long gaddr) pmd_t *pmdp; BUG_ON(gmap_is_shadow(gmap)); - spin_lock(&gmap->guest_table_lock); pmdp = (pmd_t *) gmap_table_walk(gmap, gaddr, 1); + if (!pmdp) + return NULL; - if (!pmdp || pmd_none(*pmdp)) { + /* without huge pages, there is no need to take the table lock */ + if (!gmap->mm->context.allow_gmap_hpage_1m) + return pmd_none(*pmdp) ? NULL : pmdp; + + spin_lock(&gmap->guest_table_lock); + if (pmd_none(*pmdp)) { spin_unlock(&gmap->guest_table_lock); return NULL; } diff --git a/arch/s390/tools/gen_facilities.c b/arch/s390/tools/gen_facilities.c index 0c85aedcf9b3..fd788e0f2e5b 100644 --- a/arch/s390/tools/gen_facilities.c +++ b/arch/s390/tools/gen_facilities.c @@ -106,6 +106,8 @@ static struct facility_def facility_defs[] = { .name = "FACILITIES_KVM_CPUMODEL", .bits = (int[]){ + 12, /* AP Query Configuration Information */ + 15, /* AP Facilities Test */ 156, /* etoken facility */ -1 /* END */ } diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c index 26789ad28193..cde370cad4ae 100644 --- a/arch/sh/boards/of-generic.c +++ b/arch/sh/boards/of-generic.c @@ -64,7 +64,7 @@ static void sh_of_smp_probe(void) init_cpu_possible(cpumask_of(0)); - for_each_node_by_type(np, "cpu") { + for_each_of_cpu_node(np) { const __be32 *cell = of_get_property(np, "reg", NULL); u64 id = -1; if (cell) id = of_read_number(cell, of_n_addr_cells(np)); diff --git a/arch/sh/include/asm/hugetlb.h b/arch/sh/include/asm/hugetlb.h index 735939c0f513..6f025fe18146 100644 --- a/arch/sh/include/asm/hugetlb.h +++ b/arch/sh/include/asm/hugetlb.h @@ -4,8 +4,6 @@ #include <asm/cacheflush.h> #include <asm/page.h> -#include <asm-generic/hugetlb.h> - static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, @@ -17,6 +15,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, * If the arch doesn't supply something else, assume that hugepage * size aligned regions are ok without further preparation. */ +#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE static inline int prepare_hugepage_range(struct file *file, unsigned long addr, unsigned long len) { @@ -27,62 +26,17 @@ static inline int prepare_hugepage_range(struct file *file, return 0; } -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - return ptep_get_and_clear(mm, addr, ptep); -} - +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { } -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - -static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep, - pte_t pte, int dirty) -{ - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); -} - -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { clear_bit(PG_dcache_clean, &page->flags); } +#include <asm-generic/hugetlb.h> + #endif /* _ASM_SH_HUGETLB_H */ diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index b36200af9ce7..a99234b61051 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h @@ -5,6 +5,7 @@ # include <asm/unistd_64.h> # endif +# define __ARCH_WANT_NEW_STAT # define __ARCH_WANT_OLD_READDIR # define __ARCH_WANT_OLD_STAT # define __ARCH_WANT_STAT64 @@ -19,7 +20,6 @@ # define __ARCH_WANT_SYS_SOCKETCALL # define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_GETPGRP -# define __ARCH_WANT_SYS_LLSEEK # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLD_GETRLIMIT # define __ARCH_WANT_SYS_OLD_UNAME diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index cc62f6f98103..11866d4f60e1 100644 --- a/arch/sh/include/uapi/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h @@ -95,6 +95,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h index f71ef3729888..316faa0130ba 100644 --- a/arch/sparc/include/asm/cmpxchg_64.h +++ b/arch/sparc/include/asm/cmpxchg_64.h @@ -52,7 +52,12 @@ static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long return val; } -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) +#define xchg(ptr,x) \ +({ __typeof__(*(ptr)) __ret; \ + __ret = (__typeof__(*(ptr))) \ + __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))); \ + __ret; \ +}) void __xchg_called_with_bad_pointer(void); diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 4eb51d2dae98..30b1763580b1 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -6,38 +6,23 @@ */ #include <linux/types.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "sparc\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef s16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_key_t; -typedef s32 compat_timer_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; typedef u64 compat_u64; -typedef u32 compat_uptr_t; - struct compat_stat { compat_dev_t st_dev; compat_ino_t st_ino; @@ -47,11 +32,11 @@ struct compat_stat { __compat_gid_t st_gid; compat_dev_t st_rdev; compat_off_t st_size; - compat_time_t st_atime; + old_time32_t st_atime; compat_ulong_t st_atime_nsec; - compat_time_t st_mtime; + old_time32_t st_mtime; compat_ulong_t st_mtime_nsec; - compat_time_t st_ctime; + old_time32_t st_ctime; compat_ulong_t st_ctime_nsec; compat_off_t st_blksize; compat_off_t st_blocks; diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h index 300557c66698..3963f80d1cb3 100644 --- a/arch/sparc/include/asm/hugetlb.h +++ b/arch/sparc/include/asm/hugetlb.h @@ -3,7 +3,6 @@ #define _ASM_SPARC64_HUGETLB_H #include <asm/page.h> -#include <asm-generic/hugetlb.h> #ifdef CONFIG_HUGETLB_PAGE struct pud_huge_patch_entry { @@ -13,9 +12,11 @@ struct pud_huge_patch_entry { extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end; #endif +#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); +#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); @@ -25,37 +26,13 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, return 0; } -/* - * If the arch doesn't supply something else, assume that hugepage - * size aligned regions are ok without further preparation. - */ -static inline int prepare_hugepage_range(struct file *file, - unsigned long addr, unsigned long len) -{ - struct hstate *h = hstate_file(file); - - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (addr & ~huge_page_mask(h)) - return -EINVAL; - return 0; -} - +#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { } -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -63,6 +40,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); } +#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty) @@ -75,17 +53,15 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, return changed; } -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } +#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); +#include <asm-generic/hugetlb.h> + #endif /* _ASM_SPARC64_HUGETLB_H */ diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index d955c8df62d6..1902db27ff4b 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -24,9 +24,6 @@ #include <linux/atomic.h> #include <linux/irqdomain.h> -#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 -#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 - #define of_compat_cmp(s1, s2, l) strncmp((s1), (s2), (l)) #define of_prop_cmp(s1, s2) strcasecmp((s1), (s2)) #define of_node_cmp(s1, s2) strcmp((s1), (s2)) diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h index 4ff29b1406a9..b1d4e2e3210f 100644 --- a/arch/sparc/include/asm/switch_to_64.h +++ b/arch/sparc/include/asm/switch_to_64.h @@ -67,6 +67,7 @@ do { save_and_clear_fpu(); \ } while(0) void synchronize_user_stack(void); -void fault_in_user_windows(void); +struct pt_regs; +void fault_in_user_windows(struct pt_regs *); #endif /* __SPARC64_SWITCH_TO_64_H */ diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index b2a6a955113e..00f87dbd0b17 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -21,6 +21,7 @@ #else #define __NR_time 231 /* Linux sparc32 */ #endif +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM @@ -33,7 +34,6 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING @@ -42,6 +42,7 @@ #define __ARCH_WANT_SYS_IPC #else #define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME32 #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif diff --git a/arch/sparc/include/asm/vdso.h b/arch/sparc/include/asm/vdso.h index 56836eb01787..59e79d35cd73 100644 --- a/arch/sparc/include/asm/vdso.h +++ b/arch/sparc/include/asm/vdso.h @@ -9,8 +9,6 @@ struct vdso_image { void *data; unsigned long size; /* Always a multiple of PAGE_SIZE */ - unsigned long tick_patch, tick_patch_len; - long sym_vvar_start; /* Negative offset to the vvar area */ }; diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h index 2df52711e170..7fd2f5873c9e 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -27,6 +27,8 @@ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGRS485 _IOR('T', 0x41, struct serial_rs485) #define TIOCSRS485 _IOWR('T', 0x42, struct serial_rs485) +#define TIOCGISO7816 _IOR('T', 0x43, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x44, struct serial_iso7816) /* Note that all the ioctls that are not available in Linux have a * double underscore on the front to: a) avoid some programs to diff --git a/arch/sparc/include/uapi/asm/siginfo.h b/arch/sparc/include/uapi/asm/siginfo.h index e7049550ac82..68bdde4c2a2e 100644 --- a/arch/sparc/include/uapi/asm/siginfo.h +++ b/arch/sparc/include/uapi/asm/siginfo.h @@ -4,7 +4,6 @@ #if defined(__sparc__) && defined(__arch64__) -#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #define __ARCH_SI_BAND_T int #endif /* defined(__sparc__) && defined(__arch64__) */ @@ -17,10 +16,4 @@ #define SI_NOINFO 32767 /* no information in siginfo_t */ -/* - * SIGEMT si_codes - */ -#define EMT_TAGOVF 1 /* tag overflow */ -#define NSIGEMT 1 - #endif /* _UAPI__SPARC_SIGINFO_H */ diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 6c086086ca8f..59eaf6227af1 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -36,6 +36,7 @@ #include <linux/sysrq.h> #include <linux/nmi.h> #include <linux/context_tracking.h> +#include <linux/signal.h> #include <linux/uaccess.h> #include <asm/page.h> @@ -521,7 +522,12 @@ static void stack_unaligned(unsigned long sp) force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0, current); } -void fault_in_user_windows(void) +static const char uwfault32[] = KERN_INFO \ + "%s[%d]: bad register window fault: SP %08lx (orig_sp %08lx) TPC %08lx O7 %08lx\n"; +static const char uwfault64[] = KERN_INFO \ + "%s[%d]: bad register window fault: SP %016lx (orig_sp %016lx) TPC %08lx O7 %016lx\n"; + +void fault_in_user_windows(struct pt_regs *regs) { struct thread_info *t = current_thread_info(); unsigned long window; @@ -534,9 +540,9 @@ void fault_in_user_windows(void) do { struct reg_window *rwin = &t->reg_window[window]; int winsize = sizeof(struct reg_window); - unsigned long sp; + unsigned long sp, orig_sp; - sp = t->rwbuf_stkptrs[window]; + orig_sp = sp = t->rwbuf_stkptrs[window]; if (test_thread_64bit_stack(sp)) sp += STACK_BIAS; @@ -547,8 +553,16 @@ void fault_in_user_windows(void) stack_unaligned(sp); if (unlikely(copy_to_user((char __user *)sp, - rwin, winsize))) + rwin, winsize))) { + if (show_unhandled_signals) + printk_ratelimited(is_compat_task() ? + uwfault32 : uwfault64, + current->comm, current->pid, + sp, orig_sp, + regs->tpc, + regs->u_regs[UREG_I7]); goto barf; + } } while (window--); } set_thread_wsaved(0); @@ -556,8 +570,7 @@ void fault_in_user_windows(void) barf: set_thread_wsaved(window + 1); - user_exit(); - do_exit(SIGILL); + force_sig(SIGSEGV, current); } asmlinkage long sparc_do_fork(unsigned long clone_flags, diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 4073e2b87dd0..29aa34f11720 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -39,6 +39,7 @@ __handle_preemption: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate __handle_user_windows: + add %sp, PTREGS_OFF, %o0 call fault_in_user_windows 661: wrpr %g0, RTRAP_PSTATE, %pstate /* If userspace is using ADI, it could potentially pass diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 44d379db3f64..4c5b3fcbed94 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -371,7 +371,11 @@ static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs, get_sigframe(ksig, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) { - do_exit(SIGILL); + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_frame32: %08lx TPC %08lx O7 %08lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } @@ -501,7 +505,11 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, get_sigframe(ksig, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) { - do_exit(SIGILL); + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_rt_frame32: %08lx TPC %08lx O7 %08lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 48366e5eb5b2..e9de1803a22e 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -370,7 +370,11 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) get_sigframe(ksig, regs, sf_size); if (invalid_frame_pointer (sf)) { - do_exit(SIGILL); /* won't return, actually */ + if (show_unhandled_signals) + pr_info("%s[%d] bad frame in setup_rt_frame: %016lx TPC %016lx O7 %016lx\n", + current->comm, current->pid, (unsigned long)sf, + regs->tpc, regs->u_regs[UREG_I7]); + force_sigsegv(ksig->sig, current); return -EINVAL; } diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index f396048a0d68..39822f611c01 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1383,6 +1383,7 @@ int __node_distance(int from, int to) } return numa_latency[from][to]; } +EXPORT_SYMBOL(__node_distance); static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp) { diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 7b539ceebe13..55662c3b4513 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -90,16 +90,15 @@ notrace static __always_inline u64 vread_tick(void) { u64 ret; - __asm__ __volatile__("1:\n\t" - "rd %%tick, %0\n\t" - ".pushsection .tick_patch, \"a\"\n\t" - ".word 1b - ., 1f - .\n\t" - ".popsection\n\t" - ".pushsection .tick_patch_replacement, \"ax\"\n\t" - "1:\n\t" - "rd %%asr24, %0\n\t" - ".popsection\n" - : "=r" (ret)); + __asm__ __volatile__("rd %%tick, %0" : "=r" (ret)); + return ret; +} + +notrace static __always_inline u64 vread_tick_stick(void) +{ + u64 ret; + + __asm__ __volatile__("rd %%asr24, %0" : "=r" (ret)); return ret; } #else @@ -107,16 +106,18 @@ notrace static __always_inline u64 vread_tick(void) { register unsigned long long ret asm("o4"); - __asm__ __volatile__("1:\n\t" - "rd %%tick, %L0\n\t" - "srlx %L0, 32, %H0\n\t" - ".pushsection .tick_patch, \"a\"\n\t" - ".word 1b - ., 1f - .\n\t" - ".popsection\n\t" - ".pushsection .tick_patch_replacement, \"ax\"\n\t" - "1:\n\t" - "rd %%asr24, %L0\n\t" - ".popsection\n" + __asm__ __volatile__("rd %%tick, %L0\n\t" + "srlx %L0, 32, %H0" + : "=r" (ret)); + return ret; +} + +notrace static __always_inline u64 vread_tick_stick(void) +{ + register unsigned long long ret asm("o4"); + + __asm__ __volatile__("rd %%asr24, %L0\n\t" + "srlx %L0, 32, %H0" : "=r" (ret)); return ret; } @@ -132,6 +133,16 @@ notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) return v * vvar->clock.mult; } +notrace static __always_inline u64 vgetsns_stick(struct vvar_data *vvar) +{ + u64 v; + u64 cycles; + + cycles = vread_tick_stick(); + v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask; + return v * vvar->clock.mult; +} + notrace static __always_inline int do_realtime(struct vvar_data *vvar, struct timespec *ts) { @@ -152,6 +163,26 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar, return 0; } +notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar, + struct timespec *ts) +{ + unsigned long seq; + u64 ns; + + do { + seq = vvar_read_begin(vvar); + ts->tv_sec = vvar->wall_time_sec; + ns = vvar->wall_time_snsec; + ns += vgetsns_stick(vvar); + ns >>= vvar->clock.shift; + } while (unlikely(vvar_read_retry(vvar, seq))); + + ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); + ts->tv_nsec = ns; + + return 0; +} + notrace static __always_inline int do_monotonic(struct vvar_data *vvar, struct timespec *ts) { @@ -172,6 +203,26 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar, return 0; } +notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar, + struct timespec *ts) +{ + unsigned long seq; + u64 ns; + + do { + seq = vvar_read_begin(vvar); + ts->tv_sec = vvar->monotonic_time_sec; + ns = vvar->monotonic_time_snsec; + ns += vgetsns_stick(vvar); + ns >>= vvar->clock.shift; + } while (unlikely(vvar_read_retry(vvar, seq))); + + ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); + ts->tv_nsec = ns; + + return 0; +} + notrace static int do_realtime_coarse(struct vvar_data *vvar, struct timespec *ts) { @@ -228,6 +279,31 @@ clock_gettime(clockid_t, struct timespec *) __attribute__((weak, alias("__vdso_clock_gettime"))); notrace int +__vdso_clock_gettime_stick(clockid_t clock, struct timespec *ts) +{ + struct vvar_data *vvd = get_vvar_data(); + + switch (clock) { + case CLOCK_REALTIME: + if (unlikely(vvd->vclock_mode == VCLOCK_NONE)) + break; + return do_realtime_stick(vvd, ts); + case CLOCK_MONOTONIC: + if (unlikely(vvd->vclock_mode == VCLOCK_NONE)) + break; + return do_monotonic_stick(vvd, ts); + case CLOCK_REALTIME_COARSE: + return do_realtime_coarse(vvd, ts); + case CLOCK_MONOTONIC_COARSE: + return do_monotonic_coarse(vvd, ts); + } + /* + * Unknown clock ID ? Fall back to the syscall. + */ + return vdso_fallback_gettime(clock, ts); +} + +notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) { struct vvar_data *vvd = get_vvar_data(); @@ -262,3 +338,36 @@ __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) int gettimeofday(struct timeval *, struct timezone *) __attribute__((weak, alias("__vdso_gettimeofday"))); + +notrace int +__vdso_gettimeofday_stick(struct timeval *tv, struct timezone *tz) +{ + struct vvar_data *vvd = get_vvar_data(); + + if (likely(vvd->vclock_mode != VCLOCK_NONE)) { + if (likely(tv != NULL)) { + union tstv_t { + struct timespec ts; + struct timeval tv; + } *tstv = (union tstv_t *) tv; + do_realtime_stick(vvd, &tstv->ts); + /* + * Assign before dividing to ensure that the division is + * done in the type of tv_usec, not tv_nsec. + * + * There cannot be > 1 billion usec in a second: + * do_realtime() has already distributed such overflow + * into tv_sec. So we can assign it to an int safely. + */ + tstv->tv.tv_usec = tstv->ts.tv_nsec; + tstv->tv.tv_usec /= 1000; + } + if (unlikely(tz != NULL)) { + /* Avoid memcpy. Some old compilers fail to inline it */ + tz->tz_minuteswest = vvd->tz_minuteswest; + tz->tz_dsttime = vvd->tz_dsttime; + } + return 0; + } + return vdso_fallback_gettimeofday(tv, tz); +} diff --git a/arch/sparc/vdso/vdso-layout.lds.S b/arch/sparc/vdso/vdso-layout.lds.S index ed36d49e1617..d31e57e8a3bb 100644 --- a/arch/sparc/vdso/vdso-layout.lds.S +++ b/arch/sparc/vdso/vdso-layout.lds.S @@ -73,9 +73,6 @@ SECTIONS .text : { *(.text*) } :text =0x90909090, - .tick_patch : { *(.tick_patch) } :text - .tick_patch_insns : { *(.tick_patch_insns) } :text - /DISCARD/ : { *(.discard) *(.discard.*) diff --git a/arch/sparc/vdso/vdso.lds.S b/arch/sparc/vdso/vdso.lds.S index f3caa29a331c..629ab6900df7 100644 --- a/arch/sparc/vdso/vdso.lds.S +++ b/arch/sparc/vdso/vdso.lds.S @@ -18,8 +18,10 @@ VERSION { global: clock_gettime; __vdso_clock_gettime; + __vdso_clock_gettime_stick; gettimeofday; __vdso_gettimeofday; + __vdso_gettimeofday_stick; local: *; }; } diff --git a/arch/sparc/vdso/vdso2c.h b/arch/sparc/vdso/vdso2c.h index 4df005cf98c0..60d69acc748f 100644 --- a/arch/sparc/vdso/vdso2c.h +++ b/arch/sparc/vdso/vdso2c.h @@ -17,11 +17,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, unsigned long mapping_size; int i; unsigned long j; - ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr, - *patch_sec = NULL; + ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr; ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; ELF(Dyn) *dyn = 0, *dyn_end = 0; - const char *secstrings; INT_BITS syms[NSYMS] = {}; ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff)); @@ -64,18 +62,11 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, } /* Walk the section table */ - secstrings_hdr = raw_addr + GET_BE(&hdr->e_shoff) + - GET_BE(&hdr->e_shentsize)*GET_BE(&hdr->e_shstrndx); - secstrings = raw_addr + GET_BE(&secstrings_hdr->sh_offset); for (i = 0; i < GET_BE(&hdr->e_shnum); i++) { ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) + GET_BE(&hdr->e_shentsize) * i; if (GET_BE(&sh->sh_type) == SHT_SYMTAB) symtab_hdr = sh; - - if (!strcmp(secstrings + GET_BE(&sh->sh_name), - ".tick_patch")) - patch_sec = sh; } if (!symtab_hdr) @@ -142,12 +133,6 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name); fprintf(outfile, "\t.data = raw_data,\n"); fprintf(outfile, "\t.size = %lu,\n", mapping_size); - if (patch_sec) { - fprintf(outfile, "\t.tick_patch = %lu,\n", - (unsigned long)GET_BE(&patch_sec->sh_offset)); - fprintf(outfile, "\t.tick_patch_len = %lu,\n", - (unsigned long)GET_BE(&patch_sec->sh_size)); - } for (i = 0; i < NSYMS; i++) { if (required_syms[i].export && syms[i]) fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n", diff --git a/arch/sparc/vdso/vdso32/vdso32.lds.S b/arch/sparc/vdso/vdso32/vdso32.lds.S index 53575ee154c4..218930fdff03 100644 --- a/arch/sparc/vdso/vdso32/vdso32.lds.S +++ b/arch/sparc/vdso/vdso32/vdso32.lds.S @@ -17,8 +17,10 @@ VERSION { global: clock_gettime; __vdso_clock_gettime; + __vdso_clock_gettime_stick; gettimeofday; __vdso_gettimeofday; + __vdso_gettimeofday_stick; local: *; }; } diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c index 8874a27d8adc..154fe8adc090 100644 --- a/arch/sparc/vdso/vma.c +++ b/arch/sparc/vdso/vma.c @@ -42,24 +42,201 @@ static struct vm_special_mapping vdso_mapping32 = { struct vvar_data *vvar_data; -struct tick_patch_entry { - s32 orig, repl; +struct vdso_elfinfo32 { + Elf32_Ehdr *hdr; + Elf32_Sym *dynsym; + unsigned long dynsymsize; + const char *dynstr; + unsigned long text; }; -static void stick_patch(const struct vdso_image *image) +struct vdso_elfinfo64 { + Elf64_Ehdr *hdr; + Elf64_Sym *dynsym; + unsigned long dynsymsize; + const char *dynstr; + unsigned long text; +}; + +struct vdso_elfinfo { + union { + struct vdso_elfinfo32 elf32; + struct vdso_elfinfo64 elf64; + } u; +}; + +static void *one_section64(struct vdso_elfinfo64 *e, const char *name, + unsigned long *size) +{ + const char *snames; + Elf64_Shdr *shdrs; + unsigned int i; + + shdrs = (void *)e->hdr + e->hdr->e_shoff; + snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset; + for (i = 1; i < e->hdr->e_shnum; i++) { + if (!strcmp(snames+shdrs[i].sh_name, name)) { + if (size) + *size = shdrs[i].sh_size; + return (void *)e->hdr + shdrs[i].sh_offset; + } + } + return NULL; +} + +static int find_sections64(const struct vdso_image *image, struct vdso_elfinfo *_e) +{ + struct vdso_elfinfo64 *e = &_e->u.elf64; + + e->hdr = image->data; + e->dynsym = one_section64(e, ".dynsym", &e->dynsymsize); + e->dynstr = one_section64(e, ".dynstr", NULL); + + if (!e->dynsym || !e->dynstr) { + pr_err("VDSO64: Missing symbol sections.\n"); + return -ENODEV; + } + return 0; +} + +static Elf64_Sym *find_sym64(const struct vdso_elfinfo64 *e, const char *name) +{ + unsigned int i; + + for (i = 0; i < (e->dynsymsize / sizeof(Elf64_Sym)); i++) { + Elf64_Sym *s = &e->dynsym[i]; + if (s->st_name == 0) + continue; + if (!strcmp(e->dynstr + s->st_name, name)) + return s; + } + return NULL; +} + +static int patchsym64(struct vdso_elfinfo *_e, const char *orig, + const char *new) +{ + struct vdso_elfinfo64 *e = &_e->u.elf64; + Elf64_Sym *osym = find_sym64(e, orig); + Elf64_Sym *nsym = find_sym64(e, new); + + if (!nsym || !osym) { + pr_err("VDSO64: Missing symbols.\n"); + return -ENODEV; + } + osym->st_value = nsym->st_value; + osym->st_size = nsym->st_size; + osym->st_info = nsym->st_info; + osym->st_other = nsym->st_other; + osym->st_shndx = nsym->st_shndx; + + return 0; +} + +static void *one_section32(struct vdso_elfinfo32 *e, const char *name, + unsigned long *size) +{ + const char *snames; + Elf32_Shdr *shdrs; + unsigned int i; + + shdrs = (void *)e->hdr + e->hdr->e_shoff; + snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset; + for (i = 1; i < e->hdr->e_shnum; i++) { + if (!strcmp(snames+shdrs[i].sh_name, name)) { + if (size) + *size = shdrs[i].sh_size; + return (void *)e->hdr + shdrs[i].sh_offset; + } + } + return NULL; +} + +static int find_sections32(const struct vdso_image *image, struct vdso_elfinfo *_e) +{ + struct vdso_elfinfo32 *e = &_e->u.elf32; + + e->hdr = image->data; + e->dynsym = one_section32(e, ".dynsym", &e->dynsymsize); + e->dynstr = one_section32(e, ".dynstr", NULL); + + if (!e->dynsym || !e->dynstr) { + pr_err("VDSO32: Missing symbol sections.\n"); + return -ENODEV; + } + return 0; +} + +static Elf32_Sym *find_sym32(const struct vdso_elfinfo32 *e, const char *name) { - struct tick_patch_entry *p, *p_end; + unsigned int i; + + for (i = 0; i < (e->dynsymsize / sizeof(Elf32_Sym)); i++) { + Elf32_Sym *s = &e->dynsym[i]; + if (s->st_name == 0) + continue; + if (!strcmp(e->dynstr + s->st_name, name)) + return s; + } + return NULL; +} - p = image->data + image->tick_patch; - p_end = (void *)p + image->tick_patch_len; - while (p < p_end) { - u32 *instr = (void *)&p->orig + p->orig; - u32 *repl = (void *)&p->repl + p->repl; +static int patchsym32(struct vdso_elfinfo *_e, const char *orig, + const char *new) +{ + struct vdso_elfinfo32 *e = &_e->u.elf32; + Elf32_Sym *osym = find_sym32(e, orig); + Elf32_Sym *nsym = find_sym32(e, new); - *instr = *repl; - flushi(instr); - p++; + if (!nsym || !osym) { + pr_err("VDSO32: Missing symbols.\n"); + return -ENODEV; } + osym->st_value = nsym->st_value; + osym->st_size = nsym->st_size; + osym->st_info = nsym->st_info; + osym->st_other = nsym->st_other; + osym->st_shndx = nsym->st_shndx; + + return 0; +} + +static int find_sections(const struct vdso_image *image, struct vdso_elfinfo *e, + bool elf64) +{ + if (elf64) + return find_sections64(image, e); + else + return find_sections32(image, e); +} + +static int patch_one_symbol(struct vdso_elfinfo *e, const char *orig, + const char *new_target, bool elf64) +{ + if (elf64) + return patchsym64(e, orig, new_target); + else + return patchsym32(e, orig, new_target); +} + +static int stick_patch(const struct vdso_image *image, struct vdso_elfinfo *e, bool elf64) +{ + int err; + + err = find_sections(image, e, elf64); + if (err) + return err; + + err = patch_one_symbol(e, + "__vdso_gettimeofday", + "__vdso_gettimeofday_stick", elf64); + if (err) + return err; + + return patch_one_symbol(e, + "__vdso_clock_gettime", + "__vdso_clock_gettime_stick", elf64); + return 0; } /* @@ -67,13 +244,19 @@ static void stick_patch(const struct vdso_image *image) * kernel image. */ int __init init_vdso_image(const struct vdso_image *image, - struct vm_special_mapping *vdso_mapping) + struct vm_special_mapping *vdso_mapping, bool elf64) { - int i; + int cnpages = (image->size) / PAGE_SIZE; struct page *dp, **dpp = NULL; - int dnpages = 0; struct page *cp, **cpp = NULL; - int cnpages = (image->size) / PAGE_SIZE; + struct vdso_elfinfo ei; + int i, dnpages = 0; + + if (tlb_type != spitfire) { + int err = stick_patch(image, &ei, elf64); + if (err) + return err; + } /* * First, the vdso text. This is initialied data, an integral number of @@ -88,9 +271,6 @@ int __init init_vdso_image(const struct vdso_image *image, if (!cpp) goto oom; - if (tlb_type != spitfire) - stick_patch(image); - for (i = 0; i < cnpages; i++) { cp = alloc_page(GFP_KERNEL); if (!cp) @@ -153,13 +333,13 @@ static int __init init_vdso(void) { int err = 0; #ifdef CONFIG_SPARC64 - err = init_vdso_image(&vdso_image_64_builtin, &vdso_mapping64); + err = init_vdso_image(&vdso_image_64_builtin, &vdso_mapping64, true); if (err) return err; #endif #ifdef CONFIG_COMPAT - err = init_vdso_image(&vdso_image_32_builtin, &vdso_mapping32); + err = init_vdso_image(&vdso_image_32_builtin, &vdso_mapping32, false); #endif return err; diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 6b9938919f0b..10c15b8853ae 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -12,6 +12,8 @@ config UML select HAVE_UID16 select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_DEBUG_KMEMLEAK + select HAVE_MEMBLOCK + select NO_BOOTMEM select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES select GENERIC_CLOCKEVENTS diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index 7adb4e6b658a..4049f2c46387 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -53,8 +53,6 @@ CON_INITCALL } - SECURITY_INIT - .exitcall : { __exitcall_begin = .; *(.exitcall.exit) diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f02596e9931d..296a91a04598 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -5,6 +5,7 @@ #include <linux/module.h> #include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/pfn.h> #include <asm/page.h> @@ -80,28 +81,23 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, unsigned long len, unsigned long long highmem) { unsigned long reserve = reserve_end - start; - unsigned long pfn = PFN_UP(__pa(reserve_end)); - unsigned long delta = (len - reserve) >> PAGE_SHIFT; - unsigned long offset, bootmap_size; - long map_size; + long map_size = len - reserve; int err; - offset = uml_reserved - uml_physmem; - map_size = len - offset; if(map_size <= 0) { os_warn("Too few physical memory! Needed=%lu, given=%lu\n", - offset, len); + reserve, len); exit(1); } physmem_fd = create_mem_file(len + highmem); - err = os_map_memory((void *) uml_reserved, physmem_fd, offset, + err = os_map_memory((void *) reserve_end, physmem_fd, reserve, map_size, 1, 1, 1); if (err < 0) { os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p " "failed - errno = %d\n", map_size, - (void *) uml_reserved, err); + (void *) reserve_end, err); exit(1); } @@ -113,9 +109,11 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); os_fsync_file(physmem_fd); - bootmap_size = init_bootmem(pfn, pfn + delta); - free_bootmem(__pa(reserve_end) + bootmap_size, - len - bootmap_size - reserve); + memblock_add(__pa(start), len + highmem); + memblock_reserve(__pa(start), reserve); + + min_low_pfn = PFN_UP(__pa(reserve_end)); + max_low_pfn = min_low_pfn + (map_size >> PAGE_SHIFT); } int phys_mapping(unsigned long phys, unsigned long long *offset_out) diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index 3a3b40f79558..0c5111b206bd 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -6,6 +6,7 @@ config UNICORE32 select ARCH_MIGHT_HAVE_PC_SERIO select DMA_DIRECT_OPS select HAVE_MEMBLOCK + select NO_BOOTMEM select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP select HAVE_KERNEL_BZIP2 diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h index 93a56f3e2344..83c7687a0e61 100644 --- a/arch/unicore32/include/asm/bug.h +++ b/arch/unicore32/include/asm/bug.h @@ -17,6 +17,7 @@ struct siginfo; extern void die(const char *msg, struct pt_regs *regs, int err); extern void uc32_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, unsigned long err, unsigned long trap); + int sig, int code, void __user *addr, + unsigned long err, unsigned long trap); #endif /* __UNICORE_BUG_H__ */ diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h index 65856eaab163..1e8fe5941b8a 100644 --- a/arch/unicore32/include/uapi/asm/unistd.h +++ b/arch/unicore32/include/uapi/asm/unistd.h @@ -15,4 +15,5 @@ /* Use the standard ABI for syscalls. */ #include <asm-generic/unistd.h> +#define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_CLONE diff --git a/arch/unicore32/kernel/fpu-ucf64.c b/arch/unicore32/kernel/fpu-ucf64.c index 8594b168f25e..fc5dad32a982 100644 --- a/arch/unicore32/kernel/fpu-ucf64.c +++ b/arch/unicore32/kernel/fpu-ucf64.c @@ -54,14 +54,6 @@ */ void ucf64_raise_sigfpe(struct pt_regs *regs) { - siginfo_t info; - - clear_siginfo(&info); - - info.si_signo = SIGFPE; - info.si_code = FPE_FLTUNK; - info.si_addr = (void __user *)(instruction_pointer(regs) - 4); - /* * This is the same as NWFPE, because it's not clear what * this is used for @@ -69,7 +61,9 @@ void ucf64_raise_sigfpe(struct pt_regs *regs) current->thread.error_code = 0; current->thread.trap_no = 6; - send_sig_info(SIGFPE, &info, current); + send_sig_fault(SIGFPE, FPE_FLTUNK, + (void __user *)(instruction_pointer(regs) - 4), + current); } /* diff --git a/arch/unicore32/kernel/traps.c b/arch/unicore32/kernel/traps.c index c4ac6043ebb0..fb376d83e043 100644 --- a/arch/unicore32/kernel/traps.c +++ b/arch/unicore32/kernel/traps.c @@ -241,13 +241,14 @@ void die(const char *str, struct pt_regs *regs, int err) } void uc32_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, unsigned long err, unsigned long trap) + int sig, int code, void __user *addr, + unsigned long err, unsigned long trap) { if (user_mode(regs)) { current->thread.error_code = err; current->thread.trap_no = trap; - force_sig_info(info->si_signo, info, current); + force_sig_fault(sig, code, addr, current); } else die(str, regs, err); } diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c index 8f12a5b50a42..b9a3a50644c1 100644 --- a/arch/unicore32/mm/fault.c +++ b/arch/unicore32/mm/fault.c @@ -120,17 +120,10 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, unsigned int fsr, unsigned int sig, int code, struct pt_regs *regs) { - struct siginfo si; - tsk->thread.address = addr; tsk->thread.error_code = fsr; tsk->thread.trap_no = 14; - clear_siginfo(&si); - si.si_signo = sig; - si.si_errno = 0; - si.si_code = code; - si.si_addr = (void __user *)addr; - force_sig_info(sig, &si, tsk); + force_sig_fault(sig, code, (void __user *)addr, tsk); } void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -466,7 +459,6 @@ asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + fsr_fs(fsr); - struct siginfo info; if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; @@ -474,19 +466,14 @@ asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr, printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - uc32_notify_die("", regs, &info, fsr, 0); + uc32_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, + fsr, 0); } asmlinkage void do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + fsr_fs(ifsr); - struct siginfo info; if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; @@ -494,10 +481,6 @@ asmlinkage void do_PrefetchAbort(unsigned long addr, printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", inf->name, ifsr, addr); - clear_siginfo(&info); - info.si_signo = inf->sig; - info.si_errno = 0; - info.si_code = inf->code; - info.si_addr = (void __user *)addr; - uc32_notify_die("", regs, &info, ifsr, 0); + uc32_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, + ifsr, 0); } diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c index 5f72a8d1d953..8f8699e62bd5 100644 --- a/arch/unicore32/mm/init.c +++ b/arch/unicore32/mm/init.c @@ -84,58 +84,6 @@ static void __init find_limits(unsigned long *min, unsigned long *max_low, } } -static void __init uc32_bootmem_init(unsigned long start_pfn, - unsigned long end_pfn) -{ - struct memblock_region *reg; - unsigned int boot_pages; - phys_addr_t bitmap; - pg_data_t *pgdat; - - /* - * Allocate the bootmem bitmap page. This must be in a region - * of memory which has already been mapped. - */ - boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES, - __pfn_to_phys(end_pfn)); - - /* - * Initialise the bootmem allocator, handing the - * memory banks over to bootmem. - */ - node_set_online(0); - pgdat = NODE_DATA(0); - init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); - - /* Free the lowmem regions from memblock into bootmem. */ - for_each_memblock(memory, reg) { - unsigned long start = memblock_region_memory_base_pfn(reg); - unsigned long end = memblock_region_memory_end_pfn(reg); - - if (end >= end_pfn) - end = end_pfn; - if (start >= end) - break; - - free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT); - } - - /* Reserve the lowmem memblock reserved regions in bootmem. */ - for_each_memblock(reserved, reg) { - unsigned long start = memblock_region_reserved_base_pfn(reg); - unsigned long end = memblock_region_reserved_end_pfn(reg); - - if (end >= end_pfn) - end = end_pfn; - if (start >= end) - break; - - reserve_bootmem(__pfn_to_phys(start), - (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT); - } -} - static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low, unsigned long max_high) { @@ -232,7 +180,7 @@ void __init bootmem_init(void) find_limits(&min, &max_low, &max_high); - uc32_bootmem_init(min, max_low); + node_set_online(0); /* * Sparsemem tries to allocate bootmem in memory_present(), diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index a450ad573dcb..a4b0007a54e1 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -60,9 +60,6 @@ endif ifeq ($(avx2_supported),yes) obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o - obj-$(CONFIG_CRYPTO_SHA1_MB) += sha1-mb/ - obj-$(CONFIG_CRYPTO_SHA256_MB) += sha256-mb/ - obj-$(CONFIG_CRYPTO_SHA512_MB) += sha512-mb/ obj-$(CONFIG_CRYPTO_MORUS1280_AVX2) += morus1280-avx2.o endif @@ -106,7 +103,7 @@ ifeq ($(avx2_supported),yes) morus1280-avx2-y := morus1280-avx2-asm.o morus1280-avx2-glue.o endif -aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o +aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o aes_ctrby8_avx-x86_64.o ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index acbe7e8336d8..661f7daf43da 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -102,9 +102,6 @@ asmlinkage void aesni_cbc_enc(struct crypto_aes_ctx *ctx, u8 *out, asmlinkage void aesni_cbc_dec(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in, unsigned int len, u8 *iv); -int crypto_fpu_init(void); -void crypto_fpu_exit(void); - #define AVX_GEN2_OPTSIZE 640 #define AVX_GEN4_OPTSIZE 4096 @@ -817,7 +814,7 @@ static int gcmaes_crypt_by_sg(bool enc, struct aead_request *req, /* Linearize assoc, if not already linear */ if (req->src->length >= assoclen && req->src->length && (!PageHighMem(sg_page(req->src)) || - req->src->offset + req->src->length < PAGE_SIZE)) { + req->src->offset + req->src->length <= PAGE_SIZE)) { scatterwalk_start(&assoc_sg_walk, req->src); assoc = scatterwalk_map(&assoc_sg_walk); } else { @@ -1253,22 +1250,6 @@ static struct skcipher_alg aesni_skciphers[] = { static struct simd_skcipher_alg *aesni_simd_skciphers[ARRAY_SIZE(aesni_skciphers)]; -static struct { - const char *algname; - const char *drvname; - const char *basename; - struct simd_skcipher_alg *simd; -} aesni_simd_skciphers2[] = { -#if (defined(MODULE) && IS_ENABLED(CONFIG_CRYPTO_PCBC)) || \ - IS_BUILTIN(CONFIG_CRYPTO_PCBC) - { - .algname = "pcbc(aes)", - .drvname = "pcbc-aes-aesni", - .basename = "fpu(pcbc(__aes-aesni))", - }, -#endif -}; - #ifdef CONFIG_X86_64 static int generic_gcmaes_set_key(struct crypto_aead *aead, const u8 *key, unsigned int key_len) @@ -1422,10 +1403,6 @@ static void aesni_free_simds(void) for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers) && aesni_simd_skciphers[i]; i++) simd_skcipher_free(aesni_simd_skciphers[i]); - - for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2); i++) - if (aesni_simd_skciphers2[i].simd) - simd_skcipher_free(aesni_simd_skciphers2[i].simd); } static int __init aesni_init(void) @@ -1469,13 +1446,9 @@ static int __init aesni_init(void) #endif #endif - err = crypto_fpu_init(); - if (err) - return err; - err = crypto_register_algs(aesni_algs, ARRAY_SIZE(aesni_algs)); if (err) - goto fpu_exit; + return err; err = crypto_register_skciphers(aesni_skciphers, ARRAY_SIZE(aesni_skciphers)); @@ -1499,18 +1472,6 @@ static int __init aesni_init(void) aesni_simd_skciphers[i] = simd; } - for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2); i++) { - algname = aesni_simd_skciphers2[i].algname; - drvname = aesni_simd_skciphers2[i].drvname; - basename = aesni_simd_skciphers2[i].basename; - simd = simd_skcipher_create_compat(algname, drvname, basename); - err = PTR_ERR(simd); - if (IS_ERR(simd)) - continue; - - aesni_simd_skciphers2[i].simd = simd; - } - return 0; unregister_simds: @@ -1521,8 +1482,6 @@ unregister_skciphers: ARRAY_SIZE(aesni_skciphers)); unregister_algs: crypto_unregister_algs(aesni_algs, ARRAY_SIZE(aesni_algs)); -fpu_exit: - crypto_fpu_exit(); return err; } @@ -1533,8 +1492,6 @@ static void __exit aesni_exit(void) crypto_unregister_skciphers(aesni_skciphers, ARRAY_SIZE(aesni_skciphers)); crypto_unregister_algs(aesni_algs, ARRAY_SIZE(aesni_algs)); - - crypto_fpu_exit(); } late_initcall(aesni_init); diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c deleted file mode 100644 index 406680476c52..000000000000 --- a/arch/x86/crypto/fpu.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * FPU: Wrapper for blkcipher touching fpu - * - * Copyright (c) Intel Corp. - * Author: Huang Ying <ying.huang@intel.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include <crypto/internal/skcipher.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/fpu/api.h> - -struct crypto_fpu_ctx { - struct crypto_skcipher *child; -}; - -static int crypto_fpu_setkey(struct crypto_skcipher *parent, const u8 *key, - unsigned int keylen) -{ - struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(parent); - struct crypto_skcipher *child = ctx->child; - int err; - - crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & - CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; -} - -static int crypto_fpu_encrypt(struct skcipher_request *req) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_skcipher *child = ctx->child; - SKCIPHER_REQUEST_ON_STACK(subreq, child); - int err; - - skcipher_request_set_tfm(subreq, child); - skcipher_request_set_callback(subreq, 0, NULL, NULL); - skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, - req->iv); - - kernel_fpu_begin(); - err = crypto_skcipher_encrypt(subreq); - kernel_fpu_end(); - - skcipher_request_zero(subreq); - return err; -} - -static int crypto_fpu_decrypt(struct skcipher_request *req) -{ - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_skcipher *child = ctx->child; - SKCIPHER_REQUEST_ON_STACK(subreq, child); - int err; - - skcipher_request_set_tfm(subreq, child); - skcipher_request_set_callback(subreq, 0, NULL, NULL); - skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, - req->iv); - - kernel_fpu_begin(); - err = crypto_skcipher_decrypt(subreq); - kernel_fpu_end(); - - skcipher_request_zero(subreq); - return err; -} - -static int crypto_fpu_init_tfm(struct crypto_skcipher *tfm) -{ - struct skcipher_instance *inst = skcipher_alg_instance(tfm); - struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_skcipher_spawn *spawn; - struct crypto_skcipher *cipher; - - spawn = skcipher_instance_ctx(inst); - cipher = crypto_spawn_skcipher(spawn); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - ctx->child = cipher; - - return 0; -} - -static void crypto_fpu_exit_tfm(struct crypto_skcipher *tfm) -{ - struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - - crypto_free_skcipher(ctx->child); -} - -static void crypto_fpu_free(struct skcipher_instance *inst) -{ - crypto_drop_skcipher(skcipher_instance_ctx(inst)); - kfree(inst); -} - -static int crypto_fpu_create(struct crypto_template *tmpl, struct rtattr **tb) -{ - struct crypto_skcipher_spawn *spawn; - struct skcipher_instance *inst; - struct crypto_attr_type *algt; - struct skcipher_alg *alg; - const char *cipher_name; - int err; - - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return PTR_ERR(algt); - - if ((algt->type ^ (CRYPTO_ALG_INTERNAL | CRYPTO_ALG_TYPE_SKCIPHER)) & - algt->mask) - return -EINVAL; - - if (!(algt->mask & CRYPTO_ALG_INTERNAL)) - return -EINVAL; - - cipher_name = crypto_attr_alg_name(tb[1]); - if (IS_ERR(cipher_name)) - return PTR_ERR(cipher_name); - - inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); - if (!inst) - return -ENOMEM; - - spawn = skcipher_instance_ctx(inst); - - crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst)); - err = crypto_grab_skcipher(spawn, cipher_name, CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC); - if (err) - goto out_free_inst; - - alg = crypto_skcipher_spawn_alg(spawn); - - err = crypto_inst_setname(skcipher_crypto_instance(inst), "fpu", - &alg->base); - if (err) - goto out_drop_skcipher; - - inst->alg.base.cra_flags = CRYPTO_ALG_INTERNAL; - inst->alg.base.cra_priority = alg->base.cra_priority; - inst->alg.base.cra_blocksize = alg->base.cra_blocksize; - inst->alg.base.cra_alignmask = alg->base.cra_alignmask; - - inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg); - inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg); - inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg); - - inst->alg.base.cra_ctxsize = sizeof(struct crypto_fpu_ctx); - - inst->alg.init = crypto_fpu_init_tfm; - inst->alg.exit = crypto_fpu_exit_tfm; - - inst->alg.setkey = crypto_fpu_setkey; - inst->alg.encrypt = crypto_fpu_encrypt; - inst->alg.decrypt = crypto_fpu_decrypt; - - inst->free = crypto_fpu_free; - - err = skcipher_register_instance(tmpl, inst); - if (err) - goto out_drop_skcipher; - -out: - return err; - -out_drop_skcipher: - crypto_drop_skcipher(spawn); -out_free_inst: - kfree(inst); - goto out; -} - -static struct crypto_template crypto_fpu_tmpl = { - .name = "fpu", - .create = crypto_fpu_create, - .module = THIS_MODULE, -}; - -int __init crypto_fpu_init(void) -{ - return crypto_register_template(&crypto_fpu_tmpl); -} - -void crypto_fpu_exit(void) -{ - crypto_unregister_template(&crypto_fpu_tmpl); -} - -MODULE_ALIAS_CRYPTO("fpu"); diff --git a/arch/x86/crypto/sha1-mb/Makefile b/arch/x86/crypto/sha1-mb/Makefile deleted file mode 100644 index 815ded3ba90e..000000000000 --- a/arch/x86/crypto/sha1-mb/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Arch-specific CryptoAPI modules. -# - -OBJECT_FILES_NON_STANDARD := y - -avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\ - $(comma)4)$(comma)%ymm2,yes,no) -ifeq ($(avx2_supported),yes) - obj-$(CONFIG_CRYPTO_SHA1_MB) += sha1-mb.o - sha1-mb-y := sha1_mb.o sha1_mb_mgr_flush_avx2.o \ - sha1_mb_mgr_init_avx2.o sha1_mb_mgr_submit_avx2.o sha1_x8_avx2.o -endif diff --git a/arch/x86/crypto/sha1-mb/sha1_mb.c b/arch/x86/crypto/sha1-mb/sha1_mb.c deleted file mode 100644 index b93805664c1d..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Multi buffer SHA1 algorithm Glue Code - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <crypto/internal/hash.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/cryptohash.h> -#include <linux/types.h> -#include <linux/list.h> -#include <crypto/scatterwalk.h> -#include <crypto/sha.h> -#include <crypto/mcryptd.h> -#include <crypto/crypto_wq.h> -#include <asm/byteorder.h> -#include <linux/hardirq.h> -#include <asm/fpu/api.h> -#include "sha1_mb_ctx.h" - -#define FLUSH_INTERVAL 1000 /* in usec */ - -static struct mcryptd_alg_state sha1_mb_alg_state; - -struct sha1_mb_ctx { - struct mcryptd_ahash *mcryptd_tfm; -}; - -static inline struct mcryptd_hash_request_ctx - *cast_hash_to_mcryptd_ctx(struct sha1_hash_ctx *hash_ctx) -{ - struct ahash_request *areq; - - areq = container_of((void *) hash_ctx, struct ahash_request, __ctx); - return container_of(areq, struct mcryptd_hash_request_ctx, areq); -} - -static inline struct ahash_request - *cast_mcryptd_ctx_to_req(struct mcryptd_hash_request_ctx *ctx) -{ - return container_of((void *) ctx, struct ahash_request, __ctx); -} - -static void req_ctx_init(struct mcryptd_hash_request_ctx *rctx, - struct ahash_request *areq) -{ - rctx->flag = HASH_UPDATE; -} - -static asmlinkage void (*sha1_job_mgr_init)(struct sha1_mb_mgr *state); -static asmlinkage struct job_sha1* (*sha1_job_mgr_submit) - (struct sha1_mb_mgr *state, struct job_sha1 *job); -static asmlinkage struct job_sha1* (*sha1_job_mgr_flush) - (struct sha1_mb_mgr *state); -static asmlinkage struct job_sha1* (*sha1_job_mgr_get_comp_job) - (struct sha1_mb_mgr *state); - -static inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2], - uint64_t total_len) -{ - uint32_t i = total_len & (SHA1_BLOCK_SIZE - 1); - - memset(&padblock[i], 0, SHA1_BLOCK_SIZE); - padblock[i] = 0x80; - - i += ((SHA1_BLOCK_SIZE - 1) & - (0 - (total_len + SHA1_PADLENGTHFIELD_SIZE + 1))) - + 1 + SHA1_PADLENGTHFIELD_SIZE; - -#if SHA1_PADLENGTHFIELD_SIZE == 16 - *((uint64_t *) &padblock[i - 16]) = 0; -#endif - - *((uint64_t *) &padblock[i - 8]) = cpu_to_be64(total_len << 3); - - /* Number of extra blocks to hash */ - return i >> SHA1_LOG2_BLOCK_SIZE; -} - -static struct sha1_hash_ctx *sha1_ctx_mgr_resubmit(struct sha1_ctx_mgr *mgr, - struct sha1_hash_ctx *ctx) -{ - while (ctx) { - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Clear PROCESSING bit */ - ctx->status = HASH_CTX_STS_COMPLETE; - return ctx; - } - - /* - * If the extra blocks are empty, begin hashing what remains - * in the user's buffer. - */ - if (ctx->partial_block_buffer_length == 0 && - ctx->incoming_buffer_length) { - - const void *buffer = ctx->incoming_buffer; - uint32_t len = ctx->incoming_buffer_length; - uint32_t copy_len; - - /* - * Only entire blocks can be hashed. - * Copy remainder to extra blocks buffer. - */ - copy_len = len & (SHA1_BLOCK_SIZE-1); - - if (copy_len) { - len -= copy_len; - memcpy(ctx->partial_block_buffer, - ((const char *) buffer + len), - copy_len); - ctx->partial_block_buffer_length = copy_len; - } - - ctx->incoming_buffer_length = 0; - - /* len should be a multiple of the block size now */ - assert((len % SHA1_BLOCK_SIZE) == 0); - - /* Set len to the number of blocks to be hashed */ - len >>= SHA1_LOG2_BLOCK_SIZE; - - if (len) { - - ctx->job.buffer = (uint8_t *) buffer; - ctx->job.len = len; - ctx = (struct sha1_hash_ctx *)sha1_job_mgr_submit(&mgr->mgr, - &ctx->job); - continue; - } - } - - /* - * If the extra blocks are not empty, then we are - * either on the last block(s) or we need more - * user input before continuing. - */ - if (ctx->status & HASH_CTX_STS_LAST) { - - uint8_t *buf = ctx->partial_block_buffer; - uint32_t n_extra_blocks = - sha1_pad(buf, ctx->total_length); - - ctx->status = (HASH_CTX_STS_PROCESSING | - HASH_CTX_STS_COMPLETE); - ctx->job.buffer = buf; - ctx->job.len = (uint32_t) n_extra_blocks; - ctx = (struct sha1_hash_ctx *) - sha1_job_mgr_submit(&mgr->mgr, &ctx->job); - continue; - } - - ctx->status = HASH_CTX_STS_IDLE; - return ctx; - } - - return NULL; -} - -static struct sha1_hash_ctx - *sha1_ctx_mgr_get_comp_ctx(struct sha1_ctx_mgr *mgr) -{ - /* - * If get_comp_job returns NULL, there are no jobs complete. - * If get_comp_job returns a job, verify that it is safe to return to - * the user. - * If it is not ready, resubmit the job to finish processing. - * If sha1_ctx_mgr_resubmit returned a job, it is ready to be returned. - * Otherwise, all jobs currently being managed by the hash_ctx_mgr - * still need processing. - */ - struct sha1_hash_ctx *ctx; - - ctx = (struct sha1_hash_ctx *) sha1_job_mgr_get_comp_job(&mgr->mgr); - return sha1_ctx_mgr_resubmit(mgr, ctx); -} - -static void sha1_ctx_mgr_init(struct sha1_ctx_mgr *mgr) -{ - sha1_job_mgr_init(&mgr->mgr); -} - -static struct sha1_hash_ctx *sha1_ctx_mgr_submit(struct sha1_ctx_mgr *mgr, - struct sha1_hash_ctx *ctx, - const void *buffer, - uint32_t len, - int flags) -{ - if (flags & ~(HASH_UPDATE | HASH_LAST)) { - /* User should not pass anything other than UPDATE or LAST */ - ctx->error = HASH_CTX_ERROR_INVALID_FLAGS; - return ctx; - } - - if (ctx->status & HASH_CTX_STS_PROCESSING) { - /* Cannot submit to a currently processing job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_PROCESSING; - return ctx; - } - - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Cannot update a finished job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_COMPLETED; - return ctx; - } - - /* - * If we made it here, there were no errors during this call to - * submit - */ - ctx->error = HASH_CTX_ERROR_NONE; - - /* Store buffer ptr info from user */ - ctx->incoming_buffer = buffer; - ctx->incoming_buffer_length = len; - - /* - * Store the user's request flags and mark this ctx as currently - * being processed. - */ - ctx->status = (flags & HASH_LAST) ? - (HASH_CTX_STS_PROCESSING | HASH_CTX_STS_LAST) : - HASH_CTX_STS_PROCESSING; - - /* Advance byte counter */ - ctx->total_length += len; - - /* - * If there is anything currently buffered in the extra blocks, - * append to it until it contains a whole block. - * Or if the user's buffer contains less than a whole block, - * append as much as possible to the extra block. - */ - if (ctx->partial_block_buffer_length || len < SHA1_BLOCK_SIZE) { - /* - * Compute how many bytes to copy from user buffer into - * extra block - */ - uint32_t copy_len = SHA1_BLOCK_SIZE - - ctx->partial_block_buffer_length; - if (len < copy_len) - copy_len = len; - - if (copy_len) { - /* Copy and update relevant pointers and counters */ - memcpy(&ctx->partial_block_buffer[ctx->partial_block_buffer_length], - buffer, copy_len); - - ctx->partial_block_buffer_length += copy_len; - ctx->incoming_buffer = (const void *) - ((const char *)buffer + copy_len); - ctx->incoming_buffer_length = len - copy_len; - } - - /* - * The extra block should never contain more than 1 block - * here - */ - assert(ctx->partial_block_buffer_length <= SHA1_BLOCK_SIZE); - - /* - * If the extra block buffer contains exactly 1 block, it can - * be hashed. - */ - if (ctx->partial_block_buffer_length >= SHA1_BLOCK_SIZE) { - ctx->partial_block_buffer_length = 0; - - ctx->job.buffer = ctx->partial_block_buffer; - ctx->job.len = 1; - ctx = (struct sha1_hash_ctx *) - sha1_job_mgr_submit(&mgr->mgr, &ctx->job); - } - } - - return sha1_ctx_mgr_resubmit(mgr, ctx); -} - -static struct sha1_hash_ctx *sha1_ctx_mgr_flush(struct sha1_ctx_mgr *mgr) -{ - struct sha1_hash_ctx *ctx; - - while (1) { - ctx = (struct sha1_hash_ctx *) sha1_job_mgr_flush(&mgr->mgr); - - /* If flush returned 0, there are no more jobs in flight. */ - if (!ctx) - return NULL; - - /* - * If flush returned a job, resubmit the job to finish - * processing. - */ - ctx = sha1_ctx_mgr_resubmit(mgr, ctx); - - /* - * If sha1_ctx_mgr_resubmit returned a job, it is ready to be - * returned. Otherwise, all jobs currently being managed by the - * sha1_ctx_mgr still need processing. Loop. - */ - if (ctx) - return ctx; - } -} - -static int sha1_mb_init(struct ahash_request *areq) -{ - struct sha1_hash_ctx *sctx = ahash_request_ctx(areq); - - hash_ctx_init(sctx); - sctx->job.result_digest[0] = SHA1_H0; - sctx->job.result_digest[1] = SHA1_H1; - sctx->job.result_digest[2] = SHA1_H2; - sctx->job.result_digest[3] = SHA1_H3; - sctx->job.result_digest[4] = SHA1_H4; - sctx->total_length = 0; - sctx->partial_block_buffer_length = 0; - sctx->status = HASH_CTX_STS_IDLE; - - return 0; -} - -static int sha1_mb_set_results(struct mcryptd_hash_request_ctx *rctx) -{ - int i; - struct sha1_hash_ctx *sctx = ahash_request_ctx(&rctx->areq); - __be32 *dst = (__be32 *) rctx->out; - - for (i = 0; i < 5; ++i) - dst[i] = cpu_to_be32(sctx->job.result_digest[i]); - - return 0; -} - -static int sha_finish_walk(struct mcryptd_hash_request_ctx **ret_rctx, - struct mcryptd_alg_cstate *cstate, bool flush) -{ - int flag = HASH_UPDATE; - int nbytes, err = 0; - struct mcryptd_hash_request_ctx *rctx = *ret_rctx; - struct sha1_hash_ctx *sha_ctx; - - /* more work ? */ - while (!(rctx->flag & HASH_DONE)) { - nbytes = crypto_ahash_walk_done(&rctx->walk, 0); - if (nbytes < 0) { - err = nbytes; - goto out; - } - /* check if the walk is done */ - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - if (rctx->flag & HASH_FINAL) - flag |= HASH_LAST; - - } - sha_ctx = (struct sha1_hash_ctx *) - ahash_request_ctx(&rctx->areq); - kernel_fpu_begin(); - sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx, - rctx->walk.data, nbytes, flag); - if (!sha_ctx) { - if (flush) - sha_ctx = sha1_ctx_mgr_flush(cstate->mgr); - } - kernel_fpu_end(); - if (sha_ctx) - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - else { - rctx = NULL; - goto out; - } - } - - /* copy the results */ - if (rctx->flag & HASH_FINAL) - sha1_mb_set_results(rctx); - -out: - *ret_rctx = rctx; - return err; -} - -static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate, - int err) -{ - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha1_hash_ctx *sha_ctx; - struct mcryptd_hash_request_ctx *req_ctx; - int ret; - - /* remove from work list */ - spin_lock(&cstate->work_lock); - list_del(&rctx->waiter); - spin_unlock(&cstate->work_lock); - - if (irqs_disabled()) - rctx->complete(&req->base, err); - else { - local_bh_disable(); - rctx->complete(&req->base, err); - local_bh_enable(); - } - - /* check to see if there are other jobs that are done */ - sha_ctx = sha1_ctx_mgr_get_comp_ctx(cstate->mgr); - while (sha_ctx) { - req_ctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&req_ctx, cstate, false); - if (req_ctx) { - spin_lock(&cstate->work_lock); - list_del(&req_ctx->waiter); - spin_unlock(&cstate->work_lock); - - req = cast_mcryptd_ctx_to_req(req_ctx); - if (irqs_disabled()) - req_ctx->complete(&req->base, ret); - else { - local_bh_disable(); - req_ctx->complete(&req->base, ret); - local_bh_enable(); - } - } - sha_ctx = sha1_ctx_mgr_get_comp_ctx(cstate->mgr); - } - - return 0; -} - -static void sha1_mb_add_list(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate) -{ - unsigned long next_flush; - unsigned long delay = usecs_to_jiffies(FLUSH_INTERVAL); - - /* initialize tag */ - rctx->tag.arrival = jiffies; /* tag the arrival time */ - rctx->tag.seq_num = cstate->next_seq_num++; - next_flush = rctx->tag.arrival + delay; - rctx->tag.expire = next_flush; - - spin_lock(&cstate->work_lock); - list_add_tail(&rctx->waiter, &cstate->work_list); - spin_unlock(&cstate->work_lock); - - mcryptd_arm_flusher(cstate, delay); -} - -static int sha1_mb_update(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha1_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha1_hash_ctx *sha_ctx; - int ret = 0, nbytes; - - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) - rctx->flag |= HASH_DONE; - - /* submit */ - sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq); - sha1_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx, rctx->walk.data, - nbytes, HASH_UPDATE); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha1_mb_finup(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha1_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha1_hash_ctx *sha_ctx; - int ret = 0, flag = HASH_UPDATE, nbytes; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - flag = HASH_LAST; - } - - /* submit */ - rctx->flag |= HASH_FINAL; - sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq); - sha1_mb_add_list(rctx, cstate); - - kernel_fpu_begin(); - sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx, rctx->walk.data, - nbytes, flag); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha1_mb_final(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha1_mb_alg_state.alg_cstate); - - struct sha1_hash_ctx *sha_ctx; - int ret = 0; - u8 data; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - rctx->flag |= HASH_DONE | HASH_FINAL; - - sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq); - /* flag HASH_FINAL and 0 data size */ - sha1_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx, &data, 0, - HASH_LAST); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha1_mb_export(struct ahash_request *areq, void *out) -{ - struct sha1_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(out, sctx, sizeof(*sctx)); - - return 0; -} - -static int sha1_mb_import(struct ahash_request *areq, const void *in) -{ - struct sha1_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(sctx, in, sizeof(*sctx)); - - return 0; -} - -static int sha1_mb_async_init_tfm(struct crypto_tfm *tfm) -{ - struct mcryptd_ahash *mcryptd_tfm; - struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm); - struct mcryptd_hash_ctx *mctx; - - mcryptd_tfm = mcryptd_alloc_ahash("__intel_sha1-mb", - CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL); - if (IS_ERR(mcryptd_tfm)) - return PTR_ERR(mcryptd_tfm); - mctx = crypto_ahash_ctx(&mcryptd_tfm->base); - mctx->alg_state = &sha1_mb_alg_state; - ctx->mcryptd_tfm = mcryptd_tfm; - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - crypto_ahash_reqsize(&mcryptd_tfm->base)); - - return 0; -} - -static void sha1_mb_async_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static int sha1_mb_areq_init_tfm(struct crypto_tfm *tfm) -{ - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - sizeof(struct sha1_hash_ctx)); - - return 0; -} - -static void sha1_mb_areq_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static struct ahash_alg sha1_mb_areq_alg = { - .init = sha1_mb_init, - .update = sha1_mb_update, - .final = sha1_mb_final, - .finup = sha1_mb_finup, - .export = sha1_mb_export, - .import = sha1_mb_import, - .halg = { - .digestsize = SHA1_DIGEST_SIZE, - .statesize = sizeof(struct sha1_hash_ctx), - .base = { - .cra_name = "__sha1-mb", - .cra_driver_name = "__intel_sha1-mb", - .cra_priority = 100, - /* - * use ASYNC flag as some buffers in multi-buffer - * algo may not have completed before hashing thread - * sleep - */ - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT - (sha1_mb_areq_alg.halg.base.cra_list), - .cra_init = sha1_mb_areq_init_tfm, - .cra_exit = sha1_mb_areq_exit_tfm, - .cra_ctxsize = sizeof(struct sha1_hash_ctx), - } - } -}; - -static int sha1_mb_async_init(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_init(mcryptd_req); -} - -static int sha1_mb_async_update(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_update(mcryptd_req); -} - -static int sha1_mb_async_finup(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_finup(mcryptd_req); -} - -static int sha1_mb_async_final(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_final(mcryptd_req); -} - -static int sha1_mb_async_digest(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_digest(mcryptd_req); -} - -static int sha1_mb_async_export(struct ahash_request *req, void *out) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_export(mcryptd_req, out); -} - -static int sha1_mb_async_import(struct ahash_request *req, const void *in) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - struct crypto_ahash *child = mcryptd_ahash_child(mcryptd_tfm); - struct mcryptd_hash_request_ctx *rctx; - struct ahash_request *areq; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - rctx = ahash_request_ctx(mcryptd_req); - areq = &rctx->areq; - - ahash_request_set_tfm(areq, child); - ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_SLEEP, - rctx->complete, req); - - return crypto_ahash_import(mcryptd_req, in); -} - -static struct ahash_alg sha1_mb_async_alg = { - .init = sha1_mb_async_init, - .update = sha1_mb_async_update, - .final = sha1_mb_async_final, - .finup = sha1_mb_async_finup, - .digest = sha1_mb_async_digest, - .export = sha1_mb_async_export, - .import = sha1_mb_async_import, - .halg = { - .digestsize = SHA1_DIGEST_SIZE, - .statesize = sizeof(struct sha1_hash_ctx), - .base = { - .cra_name = "sha1", - .cra_driver_name = "sha1_mb", - /* - * Low priority, since with few concurrent hash requests - * this is extremely slow due to the flush delay. Users - * whose workloads would benefit from this can request - * it explicitly by driver name, or can increase its - * priority at runtime using NETLINK_CRYPTO. - */ - .cra_priority = 50, - .cra_flags = CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(sha1_mb_async_alg.halg.base.cra_list), - .cra_init = sha1_mb_async_init_tfm, - .cra_exit = sha1_mb_async_exit_tfm, - .cra_ctxsize = sizeof(struct sha1_mb_ctx), - .cra_alignmask = 0, - }, - }, -}; - -static unsigned long sha1_mb_flusher(struct mcryptd_alg_cstate *cstate) -{ - struct mcryptd_hash_request_ctx *rctx; - unsigned long cur_time; - unsigned long next_flush = 0; - struct sha1_hash_ctx *sha_ctx; - - - cur_time = jiffies; - - while (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - if (time_before(cur_time, rctx->tag.expire)) - break; - kernel_fpu_begin(); - sha_ctx = (struct sha1_hash_ctx *) - sha1_ctx_mgr_flush(cstate->mgr); - kernel_fpu_end(); - if (!sha_ctx) { - pr_err("sha1_mb error: nothing got flushed for non-empty list\n"); - break; - } - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - sha_finish_walk(&rctx, cstate, true); - sha_complete_job(rctx, cstate, 0); - } - - if (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - /* get the hash context and then flush time */ - next_flush = rctx->tag.expire; - mcryptd_arm_flusher(cstate, get_delay(next_flush)); - } - return next_flush; -} - -static int __init sha1_mb_mod_init(void) -{ - - int cpu; - int err; - struct mcryptd_alg_cstate *cpu_state; - - /* check for dependent cpu features */ - if (!boot_cpu_has(X86_FEATURE_AVX2) || - !boot_cpu_has(X86_FEATURE_BMI2)) - return -ENODEV; - - /* initialize multibuffer structures */ - sha1_mb_alg_state.alg_cstate = alloc_percpu(struct mcryptd_alg_cstate); - - sha1_job_mgr_init = sha1_mb_mgr_init_avx2; - sha1_job_mgr_submit = sha1_mb_mgr_submit_avx2; - sha1_job_mgr_flush = sha1_mb_mgr_flush_avx2; - sha1_job_mgr_get_comp_job = sha1_mb_mgr_get_comp_job_avx2; - - if (!sha1_mb_alg_state.alg_cstate) - return -ENOMEM; - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha1_mb_alg_state.alg_cstate, cpu); - cpu_state->next_flush = 0; - cpu_state->next_seq_num = 0; - cpu_state->flusher_engaged = false; - INIT_DELAYED_WORK(&cpu_state->flush, mcryptd_flusher); - cpu_state->cpu = cpu; - cpu_state->alg_state = &sha1_mb_alg_state; - cpu_state->mgr = kzalloc(sizeof(struct sha1_ctx_mgr), - GFP_KERNEL); - if (!cpu_state->mgr) - goto err2; - sha1_ctx_mgr_init(cpu_state->mgr); - INIT_LIST_HEAD(&cpu_state->work_list); - spin_lock_init(&cpu_state->work_lock); - } - sha1_mb_alg_state.flusher = &sha1_mb_flusher; - - err = crypto_register_ahash(&sha1_mb_areq_alg); - if (err) - goto err2; - err = crypto_register_ahash(&sha1_mb_async_alg); - if (err) - goto err1; - - - return 0; -err1: - crypto_unregister_ahash(&sha1_mb_areq_alg); -err2: - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha1_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha1_mb_alg_state.alg_cstate); - return -ENODEV; -} - -static void __exit sha1_mb_mod_fini(void) -{ - int cpu; - struct mcryptd_alg_cstate *cpu_state; - - crypto_unregister_ahash(&sha1_mb_async_alg); - crypto_unregister_ahash(&sha1_mb_areq_alg); - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha1_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha1_mb_alg_state.alg_cstate); -} - -module_init(sha1_mb_mod_init); -module_exit(sha1_mb_mod_fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, multi buffer accelerated"); - -MODULE_ALIAS_CRYPTO("sha1"); diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h b/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h deleted file mode 100644 index 9454bd16f9f8..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Header file for multi buffer SHA context - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -#ifndef _SHA_MB_CTX_INTERNAL_H -#define _SHA_MB_CTX_INTERNAL_H - -#include "sha1_mb_mgr.h" - -#define HASH_UPDATE 0x00 -#define HASH_LAST 0x01 -#define HASH_DONE 0x02 -#define HASH_FINAL 0x04 - -#define HASH_CTX_STS_IDLE 0x00 -#define HASH_CTX_STS_PROCESSING 0x01 -#define HASH_CTX_STS_LAST 0x02 -#define HASH_CTX_STS_COMPLETE 0x04 - -enum hash_ctx_error { - HASH_CTX_ERROR_NONE = 0, - HASH_CTX_ERROR_INVALID_FLAGS = -1, - HASH_CTX_ERROR_ALREADY_PROCESSING = -2, - HASH_CTX_ERROR_ALREADY_COMPLETED = -3, - -#ifdef HASH_CTX_DEBUG - HASH_CTX_ERROR_DEBUG_DIGEST_MISMATCH = -4, -#endif -}; - - -#define hash_ctx_user_data(ctx) ((ctx)->user_data) -#define hash_ctx_digest(ctx) ((ctx)->job.result_digest) -#define hash_ctx_processing(ctx) ((ctx)->status & HASH_CTX_STS_PROCESSING) -#define hash_ctx_complete(ctx) ((ctx)->status == HASH_CTX_STS_COMPLETE) -#define hash_ctx_status(ctx) ((ctx)->status) -#define hash_ctx_error(ctx) ((ctx)->error) -#define hash_ctx_init(ctx) \ - do { \ - (ctx)->error = HASH_CTX_ERROR_NONE; \ - (ctx)->status = HASH_CTX_STS_COMPLETE; \ - } while (0) - - -/* Hash Constants and Typedefs */ -#define SHA1_DIGEST_LENGTH 5 -#define SHA1_LOG2_BLOCK_SIZE 6 - -#define SHA1_PADLENGTHFIELD_SIZE 8 - -#ifdef SHA_MB_DEBUG -#define assert(expr) \ -do { \ - if (unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } \ -} while (0) -#else -#define assert(expr) do {} while (0) -#endif - -struct sha1_ctx_mgr { - struct sha1_mb_mgr mgr; -}; - -/* typedef struct sha1_ctx_mgr sha1_ctx_mgr; */ - -struct sha1_hash_ctx { - /* Must be at struct offset 0 */ - struct job_sha1 job; - /* status flag */ - int status; - /* error flag */ - int error; - - uint64_t total_length; - const void *incoming_buffer; - uint32_t incoming_buffer_length; - uint8_t partial_block_buffer[SHA1_BLOCK_SIZE * 2]; - uint32_t partial_block_buffer_length; - void *user_data; -}; - -#endif diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_mgr.h b/arch/x86/crypto/sha1-mb/sha1_mb_mgr.h deleted file mode 100644 index 08ad1a9acfd7..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_mgr.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Header file for multi buffer SHA1 algorithm manager - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * James Guilford <james.guilford@intel.com> - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ -#ifndef __SHA_MB_MGR_H -#define __SHA_MB_MGR_H - - -#include <linux/types.h> - -#define NUM_SHA1_DIGEST_WORDS 5 - -enum job_sts { STS_UNKNOWN = 0, - STS_BEING_PROCESSED = 1, - STS_COMPLETED = 2, - STS_INTERNAL_ERROR = 3, - STS_ERROR = 4 -}; - -struct job_sha1 { - u8 *buffer; - u32 len; - u32 result_digest[NUM_SHA1_DIGEST_WORDS] __aligned(32); - enum job_sts status; - void *user_data; -}; - -/* SHA1 out-of-order scheduler */ - -/* typedef uint32_t sha1_digest_array[5][8]; */ - -struct sha1_args_x8 { - uint32_t digest[5][8]; - uint8_t *data_ptr[8]; -}; - -struct sha1_lane_data { - struct job_sha1 *job_in_lane; -}; - -struct sha1_mb_mgr { - struct sha1_args_x8 args; - - uint32_t lens[8]; - - /* each byte is index (0...7) of unused lanes */ - uint64_t unused_lanes; - /* byte 4 is set to FF as a flag */ - struct sha1_lane_data ldata[8]; -}; - - -#define SHA1_MB_MGR_NUM_LANES_AVX2 8 - -void sha1_mb_mgr_init_avx2(struct sha1_mb_mgr *state); -struct job_sha1 *sha1_mb_mgr_submit_avx2(struct sha1_mb_mgr *state, - struct job_sha1 *job); -struct job_sha1 *sha1_mb_mgr_flush_avx2(struct sha1_mb_mgr *state); -struct job_sha1 *sha1_mb_mgr_get_comp_job_avx2(struct sha1_mb_mgr *state); - -#endif diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_datastruct.S b/arch/x86/crypto/sha1-mb/sha1_mb_mgr_datastruct.S deleted file mode 100644 index 86688c6e7a25..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_datastruct.S +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Header file for multi buffer SHA1 algorithm data structure - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * James Guilford <james.guilford@intel.com> - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -# Macros for defining data structures - -# Usage example - -#START_FIELDS # JOB_AES -### name size align -#FIELD _plaintext, 8, 8 # pointer to plaintext -#FIELD _ciphertext, 8, 8 # pointer to ciphertext -#FIELD _IV, 16, 8 # IV -#FIELD _keys, 8, 8 # pointer to keys -#FIELD _len, 4, 4 # length in bytes -#FIELD _status, 4, 4 # status enumeration -#FIELD _user_data, 8, 8 # pointer to user data -#UNION _union, size1, align1, \ -# size2, align2, \ -# size3, align3, \ -# ... -#END_FIELDS -#%assign _JOB_AES_size _FIELD_OFFSET -#%assign _JOB_AES_align _STRUCT_ALIGN - -######################################################################### - -# Alternate "struc-like" syntax: -# STRUCT job_aes2 -# RES_Q .plaintext, 1 -# RES_Q .ciphertext, 1 -# RES_DQ .IV, 1 -# RES_B .nested, _JOB_AES_SIZE, _JOB_AES_ALIGN -# RES_U .union, size1, align1, \ -# size2, align2, \ -# ... -# ENDSTRUCT -# # Following only needed if nesting -# %assign job_aes2_size _FIELD_OFFSET -# %assign job_aes2_align _STRUCT_ALIGN -# -# RES_* macros take a name, a count and an optional alignment. -# The count in in terms of the base size of the macro, and the -# default alignment is the base size. -# The macros are: -# Macro Base size -# RES_B 1 -# RES_W 2 -# RES_D 4 -# RES_Q 8 -# RES_DQ 16 -# RES_Y 32 -# RES_Z 64 -# -# RES_U defines a union. It's arguments are a name and two or more -# pairs of "size, alignment" -# -# The two assigns are only needed if this structure is being nested -# within another. Even if the assigns are not done, one can still use -# STRUCT_NAME_size as the size of the structure. -# -# Note that for nesting, you still need to assign to STRUCT_NAME_size. -# -# The differences between this and using "struc" directly are that each -# type is implicitly aligned to its natural length (although this can be -# over-ridden with an explicit third parameter), and that the structure -# is padded at the end to its overall alignment. -# - -######################################################################### - -#ifndef _SHA1_MB_MGR_DATASTRUCT_ASM_ -#define _SHA1_MB_MGR_DATASTRUCT_ASM_ - -## START_FIELDS -.macro START_FIELDS - _FIELD_OFFSET = 0 - _STRUCT_ALIGN = 0 -.endm - -## FIELD name size align -.macro FIELD name size align - _FIELD_OFFSET = (_FIELD_OFFSET + (\align) - 1) & (~ ((\align)-1)) - \name = _FIELD_OFFSET - _FIELD_OFFSET = _FIELD_OFFSET + (\size) -.if (\align > _STRUCT_ALIGN) - _STRUCT_ALIGN = \align -.endif -.endm - -## END_FIELDS -.macro END_FIELDS - _FIELD_OFFSET = (_FIELD_OFFSET + _STRUCT_ALIGN-1) & (~ (_STRUCT_ALIGN-1)) -.endm - -######################################################################## - -.macro STRUCT p1 -START_FIELDS -.struc \p1 -.endm - -.macro ENDSTRUCT - tmp = _FIELD_OFFSET - END_FIELDS - tmp = (_FIELD_OFFSET - %%tmp) -.if (tmp > 0) - .lcomm tmp -.endif -.endstruc -.endm - -## RES_int name size align -.macro RES_int p1 p2 p3 - name = \p1 - size = \p2 - align = .\p3 - - _FIELD_OFFSET = (_FIELD_OFFSET + (align) - 1) & (~ ((align)-1)) -.align align -.lcomm name size - _FIELD_OFFSET = _FIELD_OFFSET + (size) -.if (align > _STRUCT_ALIGN) - _STRUCT_ALIGN = align -.endif -.endm - - - -# macro RES_B name, size [, align] -.macro RES_B _name, _size, _align=1 -RES_int _name _size _align -.endm - -# macro RES_W name, size [, align] -.macro RES_W _name, _size, _align=2 -RES_int _name 2*(_size) _align -.endm - -# macro RES_D name, size [, align] -.macro RES_D _name, _size, _align=4 -RES_int _name 4*(_size) _align -.endm - -# macro RES_Q name, size [, align] -.macro RES_Q _name, _size, _align=8 -RES_int _name 8*(_size) _align -.endm - -# macro RES_DQ name, size [, align] -.macro RES_DQ _name, _size, _align=16 -RES_int _name 16*(_size) _align -.endm - -# macro RES_Y name, size [, align] -.macro RES_Y _name, _size, _align=32 -RES_int _name 32*(_size) _align -.endm - -# macro RES_Z name, size [, align] -.macro RES_Z _name, _size, _align=64 -RES_int _name 64*(_size) _align -.endm - - -#endif - -######################################################################## -#### Define constants -######################################################################## - -######################################################################## -#### Define SHA1 Out Of Order Data Structures -######################################################################## - -START_FIELDS # LANE_DATA -### name size align -FIELD _job_in_lane, 8, 8 # pointer to job object -END_FIELDS - -_LANE_DATA_size = _FIELD_OFFSET -_LANE_DATA_align = _STRUCT_ALIGN - -######################################################################## - -START_FIELDS # SHA1_ARGS_X8 -### name size align -FIELD _digest, 4*5*8, 16 # transposed digest -FIELD _data_ptr, 8*8, 8 # array of pointers to data -END_FIELDS - -_SHA1_ARGS_X4_size = _FIELD_OFFSET -_SHA1_ARGS_X4_align = _STRUCT_ALIGN -_SHA1_ARGS_X8_size = _FIELD_OFFSET -_SHA1_ARGS_X8_align = _STRUCT_ALIGN - -######################################################################## - -START_FIELDS # MB_MGR -### name size align -FIELD _args, _SHA1_ARGS_X4_size, _SHA1_ARGS_X4_align -FIELD _lens, 4*8, 8 -FIELD _unused_lanes, 8, 8 -FIELD _ldata, _LANE_DATA_size*8, _LANE_DATA_align -END_FIELDS - -_MB_MGR_size = _FIELD_OFFSET -_MB_MGR_align = _STRUCT_ALIGN - -_args_digest = _args + _digest -_args_data_ptr = _args + _data_ptr - - -######################################################################## -#### Define constants -######################################################################## - -#define STS_UNKNOWN 0 -#define STS_BEING_PROCESSED 1 -#define STS_COMPLETED 2 - -######################################################################## -#### Define JOB_SHA1 structure -######################################################################## - -START_FIELDS # JOB_SHA1 - -### name size align -FIELD _buffer, 8, 8 # pointer to buffer -FIELD _len, 4, 4 # length in bytes -FIELD _result_digest, 5*4, 32 # Digest (output) -FIELD _status, 4, 4 -FIELD _user_data, 8, 8 -END_FIELDS - -_JOB_SHA1_size = _FIELD_OFFSET -_JOB_SHA1_align = _STRUCT_ALIGN diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha1-mb/sha1_mb_mgr_flush_avx2.S deleted file mode 100644 index 7cfba738f104..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_flush_avx2.S +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Flush routine for SHA1 multibuffer - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * James Guilford <james.guilford@intel.com> - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha1_mb_mgr_datastruct.S" - - -.extern sha1_x8_avx2 - -# LINUX register definitions -#define arg1 %rdi -#define arg2 %rsi - -# Common definitions -#define state arg1 -#define job arg2 -#define len2 arg2 - -# idx must be a register not clobbered by sha1_x8_avx2 -#define idx %r8 -#define DWORD_idx %r8d - -#define unused_lanes %rbx -#define lane_data %rbx -#define tmp2 %rbx -#define tmp2_w %ebx - -#define job_rax %rax -#define tmp1 %rax -#define size_offset %rax -#define tmp %rax -#define start_offset %rax - -#define tmp3 %arg1 - -#define extra_blocks %arg2 -#define p %arg2 - -.macro LABEL prefix n -\prefix\n\(): -.endm - -.macro JNE_SKIP i -jne skip_\i -.endm - -.altmacro -.macro SET_OFFSET _offset -offset = \_offset -.endm -.noaltmacro - -# JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state) -# arg 1 : rcx : state -ENTRY(sha1_mb_mgr_flush_avx2) - FRAME_BEGIN - push %rbx - - # If bit (32+3) is set, then all lanes are empty - mov _unused_lanes(state), unused_lanes - bt $32+3, unused_lanes - jc return_null - - # find a lane with a non-null job - xor idx, idx - offset = (_ldata + 1 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne one(%rip), idx - offset = (_ldata + 2 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne two(%rip), idx - offset = (_ldata + 3 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne three(%rip), idx - offset = (_ldata + 4 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne four(%rip), idx - offset = (_ldata + 5 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne five(%rip), idx - offset = (_ldata + 6 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne six(%rip), idx - offset = (_ldata + 7 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne seven(%rip), idx - - # copy idx to empty lanes -copy_lane_data: - offset = (_args + _data_ptr) - mov offset(state,idx,8), tmp - - I = 0 -.rep 8 - offset = (_ldata + I * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) -.altmacro - JNE_SKIP %I - offset = (_args + _data_ptr + 8*I) - mov tmp, offset(state) - offset = (_lens + 4*I) - movl $0xFFFFFFFF, offset(state) -LABEL skip_ %I - I = (I+1) -.noaltmacro -.endr - - # Find min length - vmovdqu _lens+0*16(state), %xmm0 - vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min value in low dword - - vmovd %xmm2, DWORD_idx - mov idx, len2 - and $0xF, idx - shr $4, len2 - jz len_is_0 - - vpand clear_low_nibble(%rip), %xmm2, %xmm2 - vpshufd $0, %xmm2, %xmm2 - - vpsubd %xmm2, %xmm0, %xmm0 - vpsubd %xmm2, %xmm1, %xmm1 - - vmovdqu %xmm0, _lens+0*16(state) - vmovdqu %xmm1, _lens+1*16(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha1_x8_avx2 - # state and idx are intact - - -len_is_0: - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $4, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens(state, idx, 4) - - vmovd _args_digest(state , idx, 4) , %xmm0 - vpinsrd $1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0 - movl _args_digest+4*32(state, idx, 4), tmp2_w - - vmovdqu %xmm0, _result_digest(job_rax) - offset = (_result_digest + 1*16) - mov tmp2_w, offset(job_rax) - -return: - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return -ENDPROC(sha1_mb_mgr_flush_avx2) - - -################################################################# - -.align 16 -ENTRY(sha1_mb_mgr_get_comp_job_avx2) - push %rbx - - ## if bit 32+3 is set, then all lanes are empty - mov _unused_lanes(state), unused_lanes - bt $(32+3), unused_lanes - jc .return_null - - # Find min length - vmovdqu _lens(state), %xmm0 - vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min value in low dword - - vmovd %xmm2, DWORD_idx - test $~0xF, idx - jnz .return_null - - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $4, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens(state, idx, 4) - - vmovd _args_digest(state, idx, 4), %xmm0 - vpinsrd $1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0 - movl _args_digest+4*32(state, idx, 4), tmp2_w - - vmovdqu %xmm0, _result_digest(job_rax) - movl tmp2_w, _result_digest+1*16(job_rax) - - pop %rbx - - ret - -.return_null: - xor job_rax, job_rax - pop %rbx - ret -ENDPROC(sha1_mb_mgr_get_comp_job_avx2) - -.section .rodata.cst16.clear_low_nibble, "aM", @progbits, 16 -.align 16 -clear_low_nibble: -.octa 0x000000000000000000000000FFFFFFF0 - -.section .rodata.cst8, "aM", @progbits, 8 -.align 8 -one: -.quad 1 -two: -.quad 2 -three: -.quad 3 -four: -.quad 4 -five: -.quad 5 -six: -.quad 6 -seven: -.quad 7 diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_init_avx2.c b/arch/x86/crypto/sha1-mb/sha1_mb_mgr_init_avx2.c deleted file mode 100644 index d2add0d35f43..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_init_avx2.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Initialization code for multi buffer SHA1 algorithm for AVX2 - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -#include "sha1_mb_mgr.h" - -void sha1_mb_mgr_init_avx2(struct sha1_mb_mgr *state) -{ - unsigned int j; - state->unused_lanes = 0xF76543210ULL; - for (j = 0; j < 8; j++) { - state->lens[j] = 0xFFFFFFFF; - state->ldata[j].job_in_lane = NULL; - } -} diff --git a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_submit_avx2.S b/arch/x86/crypto/sha1-mb/sha1_mb_mgr_submit_avx2.S deleted file mode 100644 index 7a93b1c0d69a..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_mb_mgr_submit_avx2.S +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Buffer submit code for multi buffer SHA1 algorithm - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * James Guilford <james.guilford@intel.com> - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha1_mb_mgr_datastruct.S" - - -.extern sha1_x8_avx - -# LINUX register definitions -arg1 = %rdi -arg2 = %rsi -size_offset = %rcx -tmp2 = %rcx -extra_blocks = %rdx - -# Common definitions -#define state arg1 -#define job %rsi -#define len2 arg2 -#define p2 arg2 - -# idx must be a register not clobberred by sha1_x8_avx2 -idx = %r8 -DWORD_idx = %r8d -last_len = %r8 - -p = %r11 -start_offset = %r11 - -unused_lanes = %rbx -BYTE_unused_lanes = %bl - -job_rax = %rax -len = %rax -DWORD_len = %eax - -lane = %r12 -tmp3 = %r12 - -tmp = %r9 -DWORD_tmp = %r9d - -lane_data = %r10 - -# JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job) -# arg 1 : rcx : state -# arg 2 : rdx : job -ENTRY(sha1_mb_mgr_submit_avx2) - FRAME_BEGIN - push %rbx - push %r12 - - mov _unused_lanes(state), unused_lanes - mov unused_lanes, lane - and $0xF, lane - shr $4, unused_lanes - imul $_LANE_DATA_size, lane, lane_data - movl $STS_BEING_PROCESSED, _status(job) - lea _ldata(state, lane_data), lane_data - mov unused_lanes, _unused_lanes(state) - movl _len(job), DWORD_len - - mov job, _job_in_lane(lane_data) - shl $4, len - or lane, len - - movl DWORD_len, _lens(state , lane, 4) - - # Load digest words from result_digest - vmovdqu _result_digest(job), %xmm0 - mov _result_digest+1*16(job), DWORD_tmp - vmovd %xmm0, _args_digest(state, lane, 4) - vpextrd $1, %xmm0, _args_digest+1*32(state , lane, 4) - vpextrd $2, %xmm0, _args_digest+2*32(state , lane, 4) - vpextrd $3, %xmm0, _args_digest+3*32(state , lane, 4) - movl DWORD_tmp, _args_digest+4*32(state , lane, 4) - - mov _buffer(job), p - mov p, _args_data_ptr(state, lane, 8) - - cmp $0xF, unused_lanes - jne return_null - -start_loop: - # Find min length - vmovdqa _lens(state), %xmm0 - vmovdqa _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min value in low dword - - vmovd %xmm2, DWORD_idx - mov idx, len2 - and $0xF, idx - shr $4, len2 - jz len_is_0 - - vpand clear_low_nibble(%rip), %xmm2, %xmm2 - vpshufd $0, %xmm2, %xmm2 - - vpsubd %xmm2, %xmm0, %xmm0 - vpsubd %xmm2, %xmm1, %xmm1 - - vmovdqa %xmm0, _lens + 0*16(state) - vmovdqa %xmm1, _lens + 1*16(state) - - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha1_x8_avx2 - - # state and idx are intact - -len_is_0: - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - mov _unused_lanes(state), unused_lanes - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - shl $4, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens(state, idx, 4) - - vmovd _args_digest(state, idx, 4), %xmm0 - vpinsrd $1, _args_digest+1*32(state , idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state , idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state , idx, 4), %xmm0, %xmm0 - movl _args_digest+4*32(state, idx, 4), DWORD_tmp - - vmovdqu %xmm0, _result_digest(job_rax) - movl DWORD_tmp, _result_digest+1*16(job_rax) - -return: - pop %r12 - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return - -ENDPROC(sha1_mb_mgr_submit_avx2) - -.section .rodata.cst16.clear_low_nibble, "aM", @progbits, 16 -.align 16 -clear_low_nibble: - .octa 0x000000000000000000000000FFFFFFF0 diff --git a/arch/x86/crypto/sha1-mb/sha1_x8_avx2.S b/arch/x86/crypto/sha1-mb/sha1_x8_avx2.S deleted file mode 100644 index 20f77aa633de..000000000000 --- a/arch/x86/crypto/sha1-mb/sha1_x8_avx2.S +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Multi-buffer SHA1 algorithm hash compute routine - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2014 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * James Guilford <james.guilford@intel.com> - * Tim Chen <tim.c.chen@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2014 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include "sha1_mb_mgr_datastruct.S" - -## code to compute oct SHA1 using SSE-256 -## outer calling routine takes care of save and restore of XMM registers - -## Function clobbers: rax, rcx, rdx, rbx, rsi, rdi, r9-r15# ymm0-15 -## -## Linux clobbers: rax rbx rcx rdx rsi r9 r10 r11 r12 r13 r14 r15 -## Linux preserves: rdi rbp r8 -## -## clobbers ymm0-15 - - -# TRANSPOSE8 r0, r1, r2, r3, r4, r5, r6, r7, t0, t1 -# "transpose" data in {r0...r7} using temps {t0...t1} -# Input looks like: {r0 r1 r2 r3 r4 r5 r6 r7} -# r0 = {a7 a6 a5 a4 a3 a2 a1 a0} -# r1 = {b7 b6 b5 b4 b3 b2 b1 b0} -# r2 = {c7 c6 c5 c4 c3 c2 c1 c0} -# r3 = {d7 d6 d5 d4 d3 d2 d1 d0} -# r4 = {e7 e6 e5 e4 e3 e2 e1 e0} -# r5 = {f7 f6 f5 f4 f3 f2 f1 f0} -# r6 = {g7 g6 g5 g4 g3 g2 g1 g0} -# r7 = {h7 h6 h5 h4 h3 h2 h1 h0} -# -# Output looks like: {r0 r1 r2 r3 r4 r5 r6 r7} -# r0 = {h0 g0 f0 e0 d0 c0 b0 a0} -# r1 = {h1 g1 f1 e1 d1 c1 b1 a1} -# r2 = {h2 g2 f2 e2 d2 c2 b2 a2} -# r3 = {h3 g3 f3 e3 d3 c3 b3 a3} -# r4 = {h4 g4 f4 e4 d4 c4 b4 a4} -# r5 = {h5 g5 f5 e5 d5 c5 b5 a5} -# r6 = {h6 g6 f6 e6 d6 c6 b6 a6} -# r7 = {h7 g7 f7 e7 d7 c7 b7 a7} -# - -.macro TRANSPOSE8 r0 r1 r2 r3 r4 r5 r6 r7 t0 t1 - # process top half (r0..r3) {a...d} - vshufps $0x44, \r1, \r0, \t0 # t0 = {b5 b4 a5 a4 b1 b0 a1 a0} - vshufps $0xEE, \r1, \r0, \r0 # r0 = {b7 b6 a7 a6 b3 b2 a3 a2} - vshufps $0x44, \r3, \r2, \t1 # t1 = {d5 d4 c5 c4 d1 d0 c1 c0} - vshufps $0xEE, \r3, \r2, \r2 # r2 = {d7 d6 c7 c6 d3 d2 c3 c2} - vshufps $0xDD, \t1, \t0, \r3 # r3 = {d5 c5 b5 a5 d1 c1 b1 a1} - vshufps $0x88, \r2, \r0, \r1 # r1 = {d6 c6 b6 a6 d2 c2 b2 a2} - vshufps $0xDD, \r2, \r0, \r0 # r0 = {d7 c7 b7 a7 d3 c3 b3 a3} - vshufps $0x88, \t1, \t0, \t0 # t0 = {d4 c4 b4 a4 d0 c0 b0 a0} - - # use r2 in place of t0 - # process bottom half (r4..r7) {e...h} - vshufps $0x44, \r5, \r4, \r2 # r2 = {f5 f4 e5 e4 f1 f0 e1 e0} - vshufps $0xEE, \r5, \r4, \r4 # r4 = {f7 f6 e7 e6 f3 f2 e3 e2} - vshufps $0x44, \r7, \r6, \t1 # t1 = {h5 h4 g5 g4 h1 h0 g1 g0} - vshufps $0xEE, \r7, \r6, \r6 # r6 = {h7 h6 g7 g6 h3 h2 g3 g2} - vshufps $0xDD, \t1, \r2, \r7 # r7 = {h5 g5 f5 e5 h1 g1 f1 e1} - vshufps $0x88, \r6, \r4, \r5 # r5 = {h6 g6 f6 e6 h2 g2 f2 e2} - vshufps $0xDD, \r6, \r4, \r4 # r4 = {h7 g7 f7 e7 h3 g3 f3 e3} - vshufps $0x88, \t1, \r2, \t1 # t1 = {h4 g4 f4 e4 h0 g0 f0 e0} - - vperm2f128 $0x13, \r1, \r5, \r6 # h6...a6 - vperm2f128 $0x02, \r1, \r5, \r2 # h2...a2 - vperm2f128 $0x13, \r3, \r7, \r5 # h5...a5 - vperm2f128 $0x02, \r3, \r7, \r1 # h1...a1 - vperm2f128 $0x13, \r0, \r4, \r7 # h7...a7 - vperm2f128 $0x02, \r0, \r4, \r3 # h3...a3 - vperm2f128 $0x13, \t0, \t1, \r4 # h4...a4 - vperm2f128 $0x02, \t0, \t1, \r0 # h0...a0 - -.endm -## -## Magic functions defined in FIPS 180-1 -## -# macro MAGIC_F0 F,B,C,D,T ## F = (D ^ (B & (C ^ D))) -.macro MAGIC_F0 regF regB regC regD regT - vpxor \regD, \regC, \regF - vpand \regB, \regF, \regF - vpxor \regD, \regF, \regF -.endm - -# macro MAGIC_F1 F,B,C,D,T ## F = (B ^ C ^ D) -.macro MAGIC_F1 regF regB regC regD regT - vpxor \regC, \regD, \regF - vpxor \regB, \regF, \regF -.endm - -# macro MAGIC_F2 F,B,C,D,T ## F = ((B & C) | (B & D) | (C & D)) -.macro MAGIC_F2 regF regB regC regD regT - vpor \regC, \regB, \regF - vpand \regC, \regB, \regT - vpand \regD, \regF, \regF - vpor \regT, \regF, \regF -.endm - -# macro MAGIC_F3 F,B,C,D,T ## F = (B ^ C ^ D) -.macro MAGIC_F3 regF regB regC regD regT - MAGIC_F1 \regF,\regB,\regC,\regD,\regT -.endm - -# PROLD reg, imm, tmp -.macro PROLD reg imm tmp - vpsrld $(32-\imm), \reg, \tmp - vpslld $\imm, \reg, \reg - vpor \tmp, \reg, \reg -.endm - -.macro PROLD_nd reg imm tmp src - vpsrld $(32-\imm), \src, \tmp - vpslld $\imm, \src, \reg - vpor \tmp, \reg, \reg -.endm - -.macro SHA1_STEP_00_15 regA regB regC regD regE regT regF memW immCNT MAGIC - vpaddd \immCNT, \regE, \regE - vpaddd \memW*32(%rsp), \regE, \regE - PROLD_nd \regT, 5, \regF, \regA - vpaddd \regT, \regE, \regE - \MAGIC \regF, \regB, \regC, \regD, \regT - PROLD \regB, 30, \regT - vpaddd \regF, \regE, \regE -.endm - -.macro SHA1_STEP_16_79 regA regB regC regD regE regT regF memW immCNT MAGIC - vpaddd \immCNT, \regE, \regE - offset = ((\memW - 14) & 15) * 32 - vmovdqu offset(%rsp), W14 - vpxor W14, W16, W16 - offset = ((\memW - 8) & 15) * 32 - vpxor offset(%rsp), W16, W16 - offset = ((\memW - 3) & 15) * 32 - vpxor offset(%rsp), W16, W16 - vpsrld $(32-1), W16, \regF - vpslld $1, W16, W16 - vpor W16, \regF, \regF - - ROTATE_W - - offset = ((\memW - 0) & 15) * 32 - vmovdqu \regF, offset(%rsp) - vpaddd \regF, \regE, \regE - PROLD_nd \regT, 5, \regF, \regA - vpaddd \regT, \regE, \regE - \MAGIC \regF,\regB,\regC,\regD,\regT ## FUN = MAGIC_Fi(B,C,D) - PROLD \regB,30, \regT - vpaddd \regF, \regE, \regE -.endm - -######################################################################## -######################################################################## -######################################################################## - -## FRAMESZ plus pushes must be an odd multiple of 8 -YMM_SAVE = (15-15)*32 -FRAMESZ = 32*16 + YMM_SAVE -_YMM = FRAMESZ - YMM_SAVE - -#define VMOVPS vmovups - -IDX = %rax -inp0 = %r9 -inp1 = %r10 -inp2 = %r11 -inp3 = %r12 -inp4 = %r13 -inp5 = %r14 -inp6 = %r15 -inp7 = %rcx -arg1 = %rdi -arg2 = %rsi -RSP_SAVE = %rdx - -# ymm0 A -# ymm1 B -# ymm2 C -# ymm3 D -# ymm4 E -# ymm5 F AA -# ymm6 T0 BB -# ymm7 T1 CC -# ymm8 T2 DD -# ymm9 T3 EE -# ymm10 T4 TMP -# ymm11 T5 FUN -# ymm12 T6 K -# ymm13 T7 W14 -# ymm14 T8 W15 -# ymm15 T9 W16 - - -A = %ymm0 -B = %ymm1 -C = %ymm2 -D = %ymm3 -E = %ymm4 -F = %ymm5 -T0 = %ymm6 -T1 = %ymm7 -T2 = %ymm8 -T3 = %ymm9 -T4 = %ymm10 -T5 = %ymm11 -T6 = %ymm12 -T7 = %ymm13 -T8 = %ymm14 -T9 = %ymm15 - -AA = %ymm5 -BB = %ymm6 -CC = %ymm7 -DD = %ymm8 -EE = %ymm9 -TMP = %ymm10 -FUN = %ymm11 -K = %ymm12 -W14 = %ymm13 -W15 = %ymm14 -W16 = %ymm15 - -.macro ROTATE_ARGS - TMP_ = E - E = D - D = C - C = B - B = A - A = TMP_ -.endm - -.macro ROTATE_W -TMP_ = W16 -W16 = W15 -W15 = W14 -W14 = TMP_ -.endm - -# 8 streams x 5 32bit words per digest x 4 bytes per word -#define DIGEST_SIZE (8*5*4) - -.align 32 - -# void sha1_x8_avx2(void **input_data, UINT128 *digest, UINT32 size) -# arg 1 : pointer to array[4] of pointer to input data -# arg 2 : size (in blocks) ;; assumed to be >= 1 -# -ENTRY(sha1_x8_avx2) - - # save callee-saved clobbered registers to comply with C function ABI - push %r12 - push %r13 - push %r14 - push %r15 - - #save rsp - mov %rsp, RSP_SAVE - sub $FRAMESZ, %rsp - - #align rsp to 32 Bytes - and $~0x1F, %rsp - - ## Initialize digests - vmovdqu 0*32(arg1), A - vmovdqu 1*32(arg1), B - vmovdqu 2*32(arg1), C - vmovdqu 3*32(arg1), D - vmovdqu 4*32(arg1), E - - ## transpose input onto stack - mov _data_ptr+0*8(arg1),inp0 - mov _data_ptr+1*8(arg1),inp1 - mov _data_ptr+2*8(arg1),inp2 - mov _data_ptr+3*8(arg1),inp3 - mov _data_ptr+4*8(arg1),inp4 - mov _data_ptr+5*8(arg1),inp5 - mov _data_ptr+6*8(arg1),inp6 - mov _data_ptr+7*8(arg1),inp7 - - xor IDX, IDX -lloop: - vmovdqu PSHUFFLE_BYTE_FLIP_MASK(%rip), F - I=0 -.rep 2 - VMOVPS (inp0, IDX), T0 - VMOVPS (inp1, IDX), T1 - VMOVPS (inp2, IDX), T2 - VMOVPS (inp3, IDX), T3 - VMOVPS (inp4, IDX), T4 - VMOVPS (inp5, IDX), T5 - VMOVPS (inp6, IDX), T6 - VMOVPS (inp7, IDX), T7 - - TRANSPOSE8 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 - vpshufb F, T0, T0 - vmovdqu T0, (I*8)*32(%rsp) - vpshufb F, T1, T1 - vmovdqu T1, (I*8+1)*32(%rsp) - vpshufb F, T2, T2 - vmovdqu T2, (I*8+2)*32(%rsp) - vpshufb F, T3, T3 - vmovdqu T3, (I*8+3)*32(%rsp) - vpshufb F, T4, T4 - vmovdqu T4, (I*8+4)*32(%rsp) - vpshufb F, T5, T5 - vmovdqu T5, (I*8+5)*32(%rsp) - vpshufb F, T6, T6 - vmovdqu T6, (I*8+6)*32(%rsp) - vpshufb F, T7, T7 - vmovdqu T7, (I*8+7)*32(%rsp) - add $32, IDX - I = (I+1) -.endr - # save old digests - vmovdqu A,AA - vmovdqu B,BB - vmovdqu C,CC - vmovdqu D,DD - vmovdqu E,EE - -## -## perform 0-79 steps -## - vmovdqu K00_19(%rip), K -## do rounds 0...15 - I = 0 -.rep 16 - SHA1_STEP_00_15 A,B,C,D,E, TMP,FUN, I, K, MAGIC_F0 - ROTATE_ARGS - I = (I+1) -.endr - -## do rounds 16...19 - vmovdqu ((16 - 16) & 15) * 32 (%rsp), W16 - vmovdqu ((16 - 15) & 15) * 32 (%rsp), W15 -.rep 4 - SHA1_STEP_16_79 A,B,C,D,E, TMP,FUN, I, K, MAGIC_F0 - ROTATE_ARGS - I = (I+1) -.endr - -## do rounds 20...39 - vmovdqu K20_39(%rip), K -.rep 20 - SHA1_STEP_16_79 A,B,C,D,E, TMP,FUN, I, K, MAGIC_F1 - ROTATE_ARGS - I = (I+1) -.endr - -## do rounds 40...59 - vmovdqu K40_59(%rip), K -.rep 20 - SHA1_STEP_16_79 A,B,C,D,E, TMP,FUN, I, K, MAGIC_F2 - ROTATE_ARGS - I = (I+1) -.endr - -## do rounds 60...79 - vmovdqu K60_79(%rip), K -.rep 20 - SHA1_STEP_16_79 A,B,C,D,E, TMP,FUN, I, K, MAGIC_F3 - ROTATE_ARGS - I = (I+1) -.endr - - vpaddd AA,A,A - vpaddd BB,B,B - vpaddd CC,C,C - vpaddd DD,D,D - vpaddd EE,E,E - - sub $1, arg2 - jne lloop - - # write out digests - vmovdqu A, 0*32(arg1) - vmovdqu B, 1*32(arg1) - vmovdqu C, 2*32(arg1) - vmovdqu D, 3*32(arg1) - vmovdqu E, 4*32(arg1) - - # update input pointers - add IDX, inp0 - add IDX, inp1 - add IDX, inp2 - add IDX, inp3 - add IDX, inp4 - add IDX, inp5 - add IDX, inp6 - add IDX, inp7 - mov inp0, _data_ptr (arg1) - mov inp1, _data_ptr + 1*8(arg1) - mov inp2, _data_ptr + 2*8(arg1) - mov inp3, _data_ptr + 3*8(arg1) - mov inp4, _data_ptr + 4*8(arg1) - mov inp5, _data_ptr + 5*8(arg1) - mov inp6, _data_ptr + 6*8(arg1) - mov inp7, _data_ptr + 7*8(arg1) - - ################ - ## Postamble - - mov RSP_SAVE, %rsp - - # restore callee-saved clobbered registers - pop %r15 - pop %r14 - pop %r13 - pop %r12 - - ret -ENDPROC(sha1_x8_avx2) - - -.section .rodata.cst32.K00_19, "aM", @progbits, 32 -.align 32 -K00_19: -.octa 0x5A8279995A8279995A8279995A827999 -.octa 0x5A8279995A8279995A8279995A827999 - -.section .rodata.cst32.K20_39, "aM", @progbits, 32 -.align 32 -K20_39: -.octa 0x6ED9EBA16ED9EBA16ED9EBA16ED9EBA1 -.octa 0x6ED9EBA16ED9EBA16ED9EBA16ED9EBA1 - -.section .rodata.cst32.K40_59, "aM", @progbits, 32 -.align 32 -K40_59: -.octa 0x8F1BBCDC8F1BBCDC8F1BBCDC8F1BBCDC -.octa 0x8F1BBCDC8F1BBCDC8F1BBCDC8F1BBCDC - -.section .rodata.cst32.K60_79, "aM", @progbits, 32 -.align 32 -K60_79: -.octa 0xCA62C1D6CA62C1D6CA62C1D6CA62C1D6 -.octa 0xCA62C1D6CA62C1D6CA62C1D6CA62C1D6 - -.section .rodata.cst32.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 32 -.align 32 -PSHUFFLE_BYTE_FLIP_MASK: -.octa 0x0c0d0e0f08090a0b0405060700010203 -.octa 0x0c0d0e0f08090a0b0405060700010203 diff --git a/arch/x86/crypto/sha256-mb/Makefile b/arch/x86/crypto/sha256-mb/Makefile deleted file mode 100644 index 53ad6e7db747..000000000000 --- a/arch/x86/crypto/sha256-mb/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Arch-specific CryptoAPI modules. -# - -OBJECT_FILES_NON_STANDARD := y - -avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\ - $(comma)4)$(comma)%ymm2,yes,no) -ifeq ($(avx2_supported),yes) - obj-$(CONFIG_CRYPTO_SHA256_MB) += sha256-mb.o - sha256-mb-y := sha256_mb.o sha256_mb_mgr_flush_avx2.o \ - sha256_mb_mgr_init_avx2.o sha256_mb_mgr_submit_avx2.o sha256_x8_avx2.o -endif diff --git a/arch/x86/crypto/sha256-mb/sha256_mb.c b/arch/x86/crypto/sha256-mb/sha256_mb.c deleted file mode 100644 index 97c5fc43e115..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb.c +++ /dev/null @@ -1,1013 +0,0 @@ -/* - * Multi buffer SHA256 algorithm Glue Code - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <crypto/internal/hash.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/cryptohash.h> -#include <linux/types.h> -#include <linux/list.h> -#include <crypto/scatterwalk.h> -#include <crypto/sha.h> -#include <crypto/mcryptd.h> -#include <crypto/crypto_wq.h> -#include <asm/byteorder.h> -#include <linux/hardirq.h> -#include <asm/fpu/api.h> -#include "sha256_mb_ctx.h" - -#define FLUSH_INTERVAL 1000 /* in usec */ - -static struct mcryptd_alg_state sha256_mb_alg_state; - -struct sha256_mb_ctx { - struct mcryptd_ahash *mcryptd_tfm; -}; - -static inline struct mcryptd_hash_request_ctx - *cast_hash_to_mcryptd_ctx(struct sha256_hash_ctx *hash_ctx) -{ - struct ahash_request *areq; - - areq = container_of((void *) hash_ctx, struct ahash_request, __ctx); - return container_of(areq, struct mcryptd_hash_request_ctx, areq); -} - -static inline struct ahash_request - *cast_mcryptd_ctx_to_req(struct mcryptd_hash_request_ctx *ctx) -{ - return container_of((void *) ctx, struct ahash_request, __ctx); -} - -static void req_ctx_init(struct mcryptd_hash_request_ctx *rctx, - struct ahash_request *areq) -{ - rctx->flag = HASH_UPDATE; -} - -static asmlinkage void (*sha256_job_mgr_init)(struct sha256_mb_mgr *state); -static asmlinkage struct job_sha256* (*sha256_job_mgr_submit) - (struct sha256_mb_mgr *state, struct job_sha256 *job); -static asmlinkage struct job_sha256* (*sha256_job_mgr_flush) - (struct sha256_mb_mgr *state); -static asmlinkage struct job_sha256* (*sha256_job_mgr_get_comp_job) - (struct sha256_mb_mgr *state); - -inline uint32_t sha256_pad(uint8_t padblock[SHA256_BLOCK_SIZE * 2], - uint64_t total_len) -{ - uint32_t i = total_len & (SHA256_BLOCK_SIZE - 1); - - memset(&padblock[i], 0, SHA256_BLOCK_SIZE); - padblock[i] = 0x80; - - i += ((SHA256_BLOCK_SIZE - 1) & - (0 - (total_len + SHA256_PADLENGTHFIELD_SIZE + 1))) - + 1 + SHA256_PADLENGTHFIELD_SIZE; - -#if SHA256_PADLENGTHFIELD_SIZE == 16 - *((uint64_t *) &padblock[i - 16]) = 0; -#endif - - *((uint64_t *) &padblock[i - 8]) = cpu_to_be64(total_len << 3); - - /* Number of extra blocks to hash */ - return i >> SHA256_LOG2_BLOCK_SIZE; -} - -static struct sha256_hash_ctx - *sha256_ctx_mgr_resubmit(struct sha256_ctx_mgr *mgr, - struct sha256_hash_ctx *ctx) -{ - while (ctx) { - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Clear PROCESSING bit */ - ctx->status = HASH_CTX_STS_COMPLETE; - return ctx; - } - - /* - * If the extra blocks are empty, begin hashing what remains - * in the user's buffer. - */ - if (ctx->partial_block_buffer_length == 0 && - ctx->incoming_buffer_length) { - - const void *buffer = ctx->incoming_buffer; - uint32_t len = ctx->incoming_buffer_length; - uint32_t copy_len; - - /* - * Only entire blocks can be hashed. - * Copy remainder to extra blocks buffer. - */ - copy_len = len & (SHA256_BLOCK_SIZE-1); - - if (copy_len) { - len -= copy_len; - memcpy(ctx->partial_block_buffer, - ((const char *) buffer + len), - copy_len); - ctx->partial_block_buffer_length = copy_len; - } - - ctx->incoming_buffer_length = 0; - - /* len should be a multiple of the block size now */ - assert((len % SHA256_BLOCK_SIZE) == 0); - - /* Set len to the number of blocks to be hashed */ - len >>= SHA256_LOG2_BLOCK_SIZE; - - if (len) { - - ctx->job.buffer = (uint8_t *) buffer; - ctx->job.len = len; - ctx = (struct sha256_hash_ctx *) - sha256_job_mgr_submit(&mgr->mgr, &ctx->job); - continue; - } - } - - /* - * If the extra blocks are not empty, then we are - * either on the last block(s) or we need more - * user input before continuing. - */ - if (ctx->status & HASH_CTX_STS_LAST) { - - uint8_t *buf = ctx->partial_block_buffer; - uint32_t n_extra_blocks = - sha256_pad(buf, ctx->total_length); - - ctx->status = (HASH_CTX_STS_PROCESSING | - HASH_CTX_STS_COMPLETE); - ctx->job.buffer = buf; - ctx->job.len = (uint32_t) n_extra_blocks; - ctx = (struct sha256_hash_ctx *) - sha256_job_mgr_submit(&mgr->mgr, &ctx->job); - continue; - } - - ctx->status = HASH_CTX_STS_IDLE; - return ctx; - } - - return NULL; -} - -static struct sha256_hash_ctx - *sha256_ctx_mgr_get_comp_ctx(struct sha256_ctx_mgr *mgr) -{ - /* - * If get_comp_job returns NULL, there are no jobs complete. - * If get_comp_job returns a job, verify that it is safe to return to - * the user. If it is not ready, resubmit the job to finish processing. - * If sha256_ctx_mgr_resubmit returned a job, it is ready to be - * returned. Otherwise, all jobs currently being managed by the - * hash_ctx_mgr still need processing. - */ - struct sha256_hash_ctx *ctx; - - ctx = (struct sha256_hash_ctx *) sha256_job_mgr_get_comp_job(&mgr->mgr); - return sha256_ctx_mgr_resubmit(mgr, ctx); -} - -static void sha256_ctx_mgr_init(struct sha256_ctx_mgr *mgr) -{ - sha256_job_mgr_init(&mgr->mgr); -} - -static struct sha256_hash_ctx *sha256_ctx_mgr_submit(struct sha256_ctx_mgr *mgr, - struct sha256_hash_ctx *ctx, - const void *buffer, - uint32_t len, - int flags) -{ - if (flags & ~(HASH_UPDATE | HASH_LAST)) { - /* User should not pass anything other than UPDATE or LAST */ - ctx->error = HASH_CTX_ERROR_INVALID_FLAGS; - return ctx; - } - - if (ctx->status & HASH_CTX_STS_PROCESSING) { - /* Cannot submit to a currently processing job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_PROCESSING; - return ctx; - } - - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Cannot update a finished job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_COMPLETED; - return ctx; - } - - /* If we made it here, there was no error during this call to submit */ - ctx->error = HASH_CTX_ERROR_NONE; - - /* Store buffer ptr info from user */ - ctx->incoming_buffer = buffer; - ctx->incoming_buffer_length = len; - - /* - * Store the user's request flags and mark this ctx as currently - * being processed. - */ - ctx->status = (flags & HASH_LAST) ? - (HASH_CTX_STS_PROCESSING | HASH_CTX_STS_LAST) : - HASH_CTX_STS_PROCESSING; - - /* Advance byte counter */ - ctx->total_length += len; - - /* - * If there is anything currently buffered in the extra blocks, - * append to it until it contains a whole block. - * Or if the user's buffer contains less than a whole block, - * append as much as possible to the extra block. - */ - if (ctx->partial_block_buffer_length || len < SHA256_BLOCK_SIZE) { - /* - * Compute how many bytes to copy from user buffer into - * extra block - */ - uint32_t copy_len = SHA256_BLOCK_SIZE - - ctx->partial_block_buffer_length; - if (len < copy_len) - copy_len = len; - - if (copy_len) { - /* Copy and update relevant pointers and counters */ - memcpy( - &ctx->partial_block_buffer[ctx->partial_block_buffer_length], - buffer, copy_len); - - ctx->partial_block_buffer_length += copy_len; - ctx->incoming_buffer = (const void *) - ((const char *)buffer + copy_len); - ctx->incoming_buffer_length = len - copy_len; - } - - /* The extra block should never contain more than 1 block */ - assert(ctx->partial_block_buffer_length <= SHA256_BLOCK_SIZE); - - /* - * If the extra block buffer contains exactly 1 block, - * it can be hashed. - */ - if (ctx->partial_block_buffer_length >= SHA256_BLOCK_SIZE) { - ctx->partial_block_buffer_length = 0; - - ctx->job.buffer = ctx->partial_block_buffer; - ctx->job.len = 1; - ctx = (struct sha256_hash_ctx *) - sha256_job_mgr_submit(&mgr->mgr, &ctx->job); - } - } - - return sha256_ctx_mgr_resubmit(mgr, ctx); -} - -static struct sha256_hash_ctx *sha256_ctx_mgr_flush(struct sha256_ctx_mgr *mgr) -{ - struct sha256_hash_ctx *ctx; - - while (1) { - ctx = (struct sha256_hash_ctx *) - sha256_job_mgr_flush(&mgr->mgr); - - /* If flush returned 0, there are no more jobs in flight. */ - if (!ctx) - return NULL; - - /* - * If flush returned a job, resubmit the job to finish - * processing. - */ - ctx = sha256_ctx_mgr_resubmit(mgr, ctx); - - /* - * If sha256_ctx_mgr_resubmit returned a job, it is ready to - * be returned. Otherwise, all jobs currently being managed by - * the sha256_ctx_mgr still need processing. Loop. - */ - if (ctx) - return ctx; - } -} - -static int sha256_mb_init(struct ahash_request *areq) -{ - struct sha256_hash_ctx *sctx = ahash_request_ctx(areq); - - hash_ctx_init(sctx); - sctx->job.result_digest[0] = SHA256_H0; - sctx->job.result_digest[1] = SHA256_H1; - sctx->job.result_digest[2] = SHA256_H2; - sctx->job.result_digest[3] = SHA256_H3; - sctx->job.result_digest[4] = SHA256_H4; - sctx->job.result_digest[5] = SHA256_H5; - sctx->job.result_digest[6] = SHA256_H6; - sctx->job.result_digest[7] = SHA256_H7; - sctx->total_length = 0; - sctx->partial_block_buffer_length = 0; - sctx->status = HASH_CTX_STS_IDLE; - - return 0; -} - -static int sha256_mb_set_results(struct mcryptd_hash_request_ctx *rctx) -{ - int i; - struct sha256_hash_ctx *sctx = ahash_request_ctx(&rctx->areq); - __be32 *dst = (__be32 *) rctx->out; - - for (i = 0; i < 8; ++i) - dst[i] = cpu_to_be32(sctx->job.result_digest[i]); - - return 0; -} - -static int sha_finish_walk(struct mcryptd_hash_request_ctx **ret_rctx, - struct mcryptd_alg_cstate *cstate, bool flush) -{ - int flag = HASH_UPDATE; - int nbytes, err = 0; - struct mcryptd_hash_request_ctx *rctx = *ret_rctx; - struct sha256_hash_ctx *sha_ctx; - - /* more work ? */ - while (!(rctx->flag & HASH_DONE)) { - nbytes = crypto_ahash_walk_done(&rctx->walk, 0); - if (nbytes < 0) { - err = nbytes; - goto out; - } - /* check if the walk is done */ - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - if (rctx->flag & HASH_FINAL) - flag |= HASH_LAST; - - } - sha_ctx = (struct sha256_hash_ctx *) - ahash_request_ctx(&rctx->areq); - kernel_fpu_begin(); - sha_ctx = sha256_ctx_mgr_submit(cstate->mgr, sha_ctx, - rctx->walk.data, nbytes, flag); - if (!sha_ctx) { - if (flush) - sha_ctx = sha256_ctx_mgr_flush(cstate->mgr); - } - kernel_fpu_end(); - if (sha_ctx) - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - else { - rctx = NULL; - goto out; - } - } - - /* copy the results */ - if (rctx->flag & HASH_FINAL) - sha256_mb_set_results(rctx); - -out: - *ret_rctx = rctx; - return err; -} - -static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate, - int err) -{ - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha256_hash_ctx *sha_ctx; - struct mcryptd_hash_request_ctx *req_ctx; - int ret; - - /* remove from work list */ - spin_lock(&cstate->work_lock); - list_del(&rctx->waiter); - spin_unlock(&cstate->work_lock); - - if (irqs_disabled()) - rctx->complete(&req->base, err); - else { - local_bh_disable(); - rctx->complete(&req->base, err); - local_bh_enable(); - } - - /* check to see if there are other jobs that are done */ - sha_ctx = sha256_ctx_mgr_get_comp_ctx(cstate->mgr); - while (sha_ctx) { - req_ctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&req_ctx, cstate, false); - if (req_ctx) { - spin_lock(&cstate->work_lock); - list_del(&req_ctx->waiter); - spin_unlock(&cstate->work_lock); - - req = cast_mcryptd_ctx_to_req(req_ctx); - if (irqs_disabled()) - req_ctx->complete(&req->base, ret); - else { - local_bh_disable(); - req_ctx->complete(&req->base, ret); - local_bh_enable(); - } - } - sha_ctx = sha256_ctx_mgr_get_comp_ctx(cstate->mgr); - } - - return 0; -} - -static void sha256_mb_add_list(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate) -{ - unsigned long next_flush; - unsigned long delay = usecs_to_jiffies(FLUSH_INTERVAL); - - /* initialize tag */ - rctx->tag.arrival = jiffies; /* tag the arrival time */ - rctx->tag.seq_num = cstate->next_seq_num++; - next_flush = rctx->tag.arrival + delay; - rctx->tag.expire = next_flush; - - spin_lock(&cstate->work_lock); - list_add_tail(&rctx->waiter, &cstate->work_list); - spin_unlock(&cstate->work_lock); - - mcryptd_arm_flusher(cstate, delay); -} - -static int sha256_mb_update(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha256_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha256_hash_ctx *sha_ctx; - int ret = 0, nbytes; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) - rctx->flag |= HASH_DONE; - - /* submit */ - sha_ctx = (struct sha256_hash_ctx *) ahash_request_ctx(areq); - sha256_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha256_ctx_mgr_submit(cstate->mgr, sha_ctx, rctx->walk.data, - nbytes, HASH_UPDATE); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha256_mb_finup(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha256_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha256_hash_ctx *sha_ctx; - int ret = 0, flag = HASH_UPDATE, nbytes; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - flag = HASH_LAST; - } - - /* submit */ - rctx->flag |= HASH_FINAL; - sha_ctx = (struct sha256_hash_ctx *) ahash_request_ctx(areq); - sha256_mb_add_list(rctx, cstate); - - kernel_fpu_begin(); - sha_ctx = sha256_ctx_mgr_submit(cstate->mgr, sha_ctx, rctx->walk.data, - nbytes, flag); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha256_mb_final(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, - areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha256_mb_alg_state.alg_cstate); - - struct sha256_hash_ctx *sha_ctx; - int ret = 0; - u8 data; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - rctx->flag |= HASH_DONE | HASH_FINAL; - - sha_ctx = (struct sha256_hash_ctx *) ahash_request_ctx(areq); - /* flag HASH_FINAL and 0 data size */ - sha256_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha256_ctx_mgr_submit(cstate->mgr, sha_ctx, &data, 0, - HASH_LAST); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha256_mb_export(struct ahash_request *areq, void *out) -{ - struct sha256_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(out, sctx, sizeof(*sctx)); - - return 0; -} - -static int sha256_mb_import(struct ahash_request *areq, const void *in) -{ - struct sha256_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(sctx, in, sizeof(*sctx)); - - return 0; -} - -static int sha256_mb_async_init_tfm(struct crypto_tfm *tfm) -{ - struct mcryptd_ahash *mcryptd_tfm; - struct sha256_mb_ctx *ctx = crypto_tfm_ctx(tfm); - struct mcryptd_hash_ctx *mctx; - - mcryptd_tfm = mcryptd_alloc_ahash("__intel_sha256-mb", - CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL); - if (IS_ERR(mcryptd_tfm)) - return PTR_ERR(mcryptd_tfm); - mctx = crypto_ahash_ctx(&mcryptd_tfm->base); - mctx->alg_state = &sha256_mb_alg_state; - ctx->mcryptd_tfm = mcryptd_tfm; - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - crypto_ahash_reqsize(&mcryptd_tfm->base)); - - return 0; -} - -static void sha256_mb_async_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha256_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static int sha256_mb_areq_init_tfm(struct crypto_tfm *tfm) -{ - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - sizeof(struct sha256_hash_ctx)); - - return 0; -} - -static void sha256_mb_areq_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha256_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static struct ahash_alg sha256_mb_areq_alg = { - .init = sha256_mb_init, - .update = sha256_mb_update, - .final = sha256_mb_final, - .finup = sha256_mb_finup, - .export = sha256_mb_export, - .import = sha256_mb_import, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, - .statesize = sizeof(struct sha256_hash_ctx), - .base = { - .cra_name = "__sha256-mb", - .cra_driver_name = "__intel_sha256-mb", - .cra_priority = 100, - /* - * use ASYNC flag as some buffers in multi-buffer - * algo may not have completed before hashing thread - * sleep - */ - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = SHA256_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT - (sha256_mb_areq_alg.halg.base.cra_list), - .cra_init = sha256_mb_areq_init_tfm, - .cra_exit = sha256_mb_areq_exit_tfm, - .cra_ctxsize = sizeof(struct sha256_hash_ctx), - } - } -}; - -static int sha256_mb_async_init(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_init(mcryptd_req); -} - -static int sha256_mb_async_update(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_update(mcryptd_req); -} - -static int sha256_mb_async_finup(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_finup(mcryptd_req); -} - -static int sha256_mb_async_final(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_final(mcryptd_req); -} - -static int sha256_mb_async_digest(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_digest(mcryptd_req); -} - -static int sha256_mb_async_export(struct ahash_request *req, void *out) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_export(mcryptd_req, out); -} - -static int sha256_mb_async_import(struct ahash_request *req, const void *in) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha256_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - struct crypto_ahash *child = mcryptd_ahash_child(mcryptd_tfm); - struct mcryptd_hash_request_ctx *rctx; - struct ahash_request *areq; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - rctx = ahash_request_ctx(mcryptd_req); - areq = &rctx->areq; - - ahash_request_set_tfm(areq, child); - ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_SLEEP, - rctx->complete, req); - - return crypto_ahash_import(mcryptd_req, in); -} - -static struct ahash_alg sha256_mb_async_alg = { - .init = sha256_mb_async_init, - .update = sha256_mb_async_update, - .final = sha256_mb_async_final, - .finup = sha256_mb_async_finup, - .export = sha256_mb_async_export, - .import = sha256_mb_async_import, - .digest = sha256_mb_async_digest, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, - .statesize = sizeof(struct sha256_hash_ctx), - .base = { - .cra_name = "sha256", - .cra_driver_name = "sha256_mb", - /* - * Low priority, since with few concurrent hash requests - * this is extremely slow due to the flush delay. Users - * whose workloads would benefit from this can request - * it explicitly by driver name, or can increase its - * priority at runtime using NETLINK_CRYPTO. - */ - .cra_priority = 50, - .cra_flags = CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA256_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT - (sha256_mb_async_alg.halg.base.cra_list), - .cra_init = sha256_mb_async_init_tfm, - .cra_exit = sha256_mb_async_exit_tfm, - .cra_ctxsize = sizeof(struct sha256_mb_ctx), - .cra_alignmask = 0, - }, - }, -}; - -static unsigned long sha256_mb_flusher(struct mcryptd_alg_cstate *cstate) -{ - struct mcryptd_hash_request_ctx *rctx; - unsigned long cur_time; - unsigned long next_flush = 0; - struct sha256_hash_ctx *sha_ctx; - - - cur_time = jiffies; - - while (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - if (time_before(cur_time, rctx->tag.expire)) - break; - kernel_fpu_begin(); - sha_ctx = (struct sha256_hash_ctx *) - sha256_ctx_mgr_flush(cstate->mgr); - kernel_fpu_end(); - if (!sha_ctx) { - pr_err("sha256_mb error: nothing got" - " flushed for non-empty list\n"); - break; - } - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - sha_finish_walk(&rctx, cstate, true); - sha_complete_job(rctx, cstate, 0); - } - - if (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - /* get the hash context and then flush time */ - next_flush = rctx->tag.expire; - mcryptd_arm_flusher(cstate, get_delay(next_flush)); - } - return next_flush; -} - -static int __init sha256_mb_mod_init(void) -{ - - int cpu; - int err; - struct mcryptd_alg_cstate *cpu_state; - - /* check for dependent cpu features */ - if (!boot_cpu_has(X86_FEATURE_AVX2) || - !boot_cpu_has(X86_FEATURE_BMI2)) - return -ENODEV; - - /* initialize multibuffer structures */ - sha256_mb_alg_state.alg_cstate = alloc_percpu - (struct mcryptd_alg_cstate); - - sha256_job_mgr_init = sha256_mb_mgr_init_avx2; - sha256_job_mgr_submit = sha256_mb_mgr_submit_avx2; - sha256_job_mgr_flush = sha256_mb_mgr_flush_avx2; - sha256_job_mgr_get_comp_job = sha256_mb_mgr_get_comp_job_avx2; - - if (!sha256_mb_alg_state.alg_cstate) - return -ENOMEM; - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha256_mb_alg_state.alg_cstate, cpu); - cpu_state->next_flush = 0; - cpu_state->next_seq_num = 0; - cpu_state->flusher_engaged = false; - INIT_DELAYED_WORK(&cpu_state->flush, mcryptd_flusher); - cpu_state->cpu = cpu; - cpu_state->alg_state = &sha256_mb_alg_state; - cpu_state->mgr = kzalloc(sizeof(struct sha256_ctx_mgr), - GFP_KERNEL); - if (!cpu_state->mgr) - goto err2; - sha256_ctx_mgr_init(cpu_state->mgr); - INIT_LIST_HEAD(&cpu_state->work_list); - spin_lock_init(&cpu_state->work_lock); - } - sha256_mb_alg_state.flusher = &sha256_mb_flusher; - - err = crypto_register_ahash(&sha256_mb_areq_alg); - if (err) - goto err2; - err = crypto_register_ahash(&sha256_mb_async_alg); - if (err) - goto err1; - - - return 0; -err1: - crypto_unregister_ahash(&sha256_mb_areq_alg); -err2: - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha256_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha256_mb_alg_state.alg_cstate); - return -ENODEV; -} - -static void __exit sha256_mb_mod_fini(void) -{ - int cpu; - struct mcryptd_alg_cstate *cpu_state; - - crypto_unregister_ahash(&sha256_mb_async_alg); - crypto_unregister_ahash(&sha256_mb_areq_alg); - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha256_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha256_mb_alg_state.alg_cstate); -} - -module_init(sha256_mb_mod_init); -module_exit(sha256_mb_mod_fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, multi buffer accelerated"); - -MODULE_ALIAS_CRYPTO("sha256"); diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h b/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h deleted file mode 100644 index 7c432543dc7f..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Header file for multi buffer SHA256 context - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#ifndef _SHA_MB_CTX_INTERNAL_H -#define _SHA_MB_CTX_INTERNAL_H - -#include "sha256_mb_mgr.h" - -#define HASH_UPDATE 0x00 -#define HASH_LAST 0x01 -#define HASH_DONE 0x02 -#define HASH_FINAL 0x04 - -#define HASH_CTX_STS_IDLE 0x00 -#define HASH_CTX_STS_PROCESSING 0x01 -#define HASH_CTX_STS_LAST 0x02 -#define HASH_CTX_STS_COMPLETE 0x04 - -enum hash_ctx_error { - HASH_CTX_ERROR_NONE = 0, - HASH_CTX_ERROR_INVALID_FLAGS = -1, - HASH_CTX_ERROR_ALREADY_PROCESSING = -2, - HASH_CTX_ERROR_ALREADY_COMPLETED = -3, - -#ifdef HASH_CTX_DEBUG - HASH_CTX_ERROR_DEBUG_DIGEST_MISMATCH = -4, -#endif -}; - - -#define hash_ctx_user_data(ctx) ((ctx)->user_data) -#define hash_ctx_digest(ctx) ((ctx)->job.result_digest) -#define hash_ctx_processing(ctx) ((ctx)->status & HASH_CTX_STS_PROCESSING) -#define hash_ctx_complete(ctx) ((ctx)->status == HASH_CTX_STS_COMPLETE) -#define hash_ctx_status(ctx) ((ctx)->status) -#define hash_ctx_error(ctx) ((ctx)->error) -#define hash_ctx_init(ctx) \ - do { \ - (ctx)->error = HASH_CTX_ERROR_NONE; \ - (ctx)->status = HASH_CTX_STS_COMPLETE; \ - } while (0) - - -/* Hash Constants and Typedefs */ -#define SHA256_DIGEST_LENGTH 8 -#define SHA256_LOG2_BLOCK_SIZE 6 - -#define SHA256_PADLENGTHFIELD_SIZE 8 - -#ifdef SHA_MB_DEBUG -#define assert(expr) \ -do { \ - if (unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } \ -} while (0) -#else -#define assert(expr) do {} while (0) -#endif - -struct sha256_ctx_mgr { - struct sha256_mb_mgr mgr; -}; - -/* typedef struct sha256_ctx_mgr sha256_ctx_mgr; */ - -struct sha256_hash_ctx { - /* Must be at struct offset 0 */ - struct job_sha256 job; - /* status flag */ - int status; - /* error flag */ - int error; - - uint64_t total_length; - const void *incoming_buffer; - uint32_t incoming_buffer_length; - uint8_t partial_block_buffer[SHA256_BLOCK_SIZE * 2]; - uint32_t partial_block_buffer_length; - void *user_data; -}; - -#endif diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr.h b/arch/x86/crypto/sha256-mb/sha256_mb_mgr.h deleted file mode 100644 index b01ae408c56d..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Header file for multi buffer SHA256 algorithm manager - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ -#ifndef __SHA_MB_MGR_H -#define __SHA_MB_MGR_H - -#include <linux/types.h> - -#define NUM_SHA256_DIGEST_WORDS 8 - -enum job_sts { STS_UNKNOWN = 0, - STS_BEING_PROCESSED = 1, - STS_COMPLETED = 2, - STS_INTERNAL_ERROR = 3, - STS_ERROR = 4 -}; - -struct job_sha256 { - u8 *buffer; - u32 len; - u32 result_digest[NUM_SHA256_DIGEST_WORDS] __aligned(32); - enum job_sts status; - void *user_data; -}; - -/* SHA256 out-of-order scheduler */ - -/* typedef uint32_t sha8_digest_array[8][8]; */ - -struct sha256_args_x8 { - uint32_t digest[8][8]; - uint8_t *data_ptr[8]; -}; - -struct sha256_lane_data { - struct job_sha256 *job_in_lane; -}; - -struct sha256_mb_mgr { - struct sha256_args_x8 args; - - uint32_t lens[8]; - - /* each byte is index (0...7) of unused lanes */ - uint64_t unused_lanes; - /* byte 4 is set to FF as a flag */ - struct sha256_lane_data ldata[8]; -}; - - -#define SHA256_MB_MGR_NUM_LANES_AVX2 8 - -void sha256_mb_mgr_init_avx2(struct sha256_mb_mgr *state); -struct job_sha256 *sha256_mb_mgr_submit_avx2(struct sha256_mb_mgr *state, - struct job_sha256 *job); -struct job_sha256 *sha256_mb_mgr_flush_avx2(struct sha256_mb_mgr *state); -struct job_sha256 *sha256_mb_mgr_get_comp_job_avx2(struct sha256_mb_mgr *state); - -#endif diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_datastruct.S b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_datastruct.S deleted file mode 100644 index 5c377bac21d0..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_datastruct.S +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Header file for multi buffer SHA256 algorithm data structure - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -# Macros for defining data structures - -# Usage example - -#START_FIELDS # JOB_AES -### name size align -#FIELD _plaintext, 8, 8 # pointer to plaintext -#FIELD _ciphertext, 8, 8 # pointer to ciphertext -#FIELD _IV, 16, 8 # IV -#FIELD _keys, 8, 8 # pointer to keys -#FIELD _len, 4, 4 # length in bytes -#FIELD _status, 4, 4 # status enumeration -#FIELD _user_data, 8, 8 # pointer to user data -#UNION _union, size1, align1, \ -# size2, align2, \ -# size3, align3, \ -# ... -#END_FIELDS -#%assign _JOB_AES_size _FIELD_OFFSET -#%assign _JOB_AES_align _STRUCT_ALIGN - -######################################################################### - -# Alternate "struc-like" syntax: -# STRUCT job_aes2 -# RES_Q .plaintext, 1 -# RES_Q .ciphertext, 1 -# RES_DQ .IV, 1 -# RES_B .nested, _JOB_AES_SIZE, _JOB_AES_ALIGN -# RES_U .union, size1, align1, \ -# size2, align2, \ -# ... -# ENDSTRUCT -# # Following only needed if nesting -# %assign job_aes2_size _FIELD_OFFSET -# %assign job_aes2_align _STRUCT_ALIGN -# -# RES_* macros take a name, a count and an optional alignment. -# The count in in terms of the base size of the macro, and the -# default alignment is the base size. -# The macros are: -# Macro Base size -# RES_B 1 -# RES_W 2 -# RES_D 4 -# RES_Q 8 -# RES_DQ 16 -# RES_Y 32 -# RES_Z 64 -# -# RES_U defines a union. It's arguments are a name and two or more -# pairs of "size, alignment" -# -# The two assigns are only needed if this structure is being nested -# within another. Even if the assigns are not done, one can still use -# STRUCT_NAME_size as the size of the structure. -# -# Note that for nesting, you still need to assign to STRUCT_NAME_size. -# -# The differences between this and using "struc" directly are that each -# type is implicitly aligned to its natural length (although this can be -# over-ridden with an explicit third parameter), and that the structure -# is padded at the end to its overall alignment. -# - -######################################################################### - -#ifndef _DATASTRUCT_ASM_ -#define _DATASTRUCT_ASM_ - -#define SZ8 8*SHA256_DIGEST_WORD_SIZE -#define ROUNDS 64*SZ8 -#define PTR_SZ 8 -#define SHA256_DIGEST_WORD_SIZE 4 -#define MAX_SHA256_LANES 8 -#define SHA256_DIGEST_WORDS 8 -#define SHA256_DIGEST_ROW_SIZE (MAX_SHA256_LANES * SHA256_DIGEST_WORD_SIZE) -#define SHA256_DIGEST_SIZE (SHA256_DIGEST_ROW_SIZE * SHA256_DIGEST_WORDS) -#define SHA256_BLK_SZ 64 - -# START_FIELDS -.macro START_FIELDS - _FIELD_OFFSET = 0 - _STRUCT_ALIGN = 0 -.endm - -# FIELD name size align -.macro FIELD name size align - _FIELD_OFFSET = (_FIELD_OFFSET + (\align) - 1) & (~ ((\align)-1)) - \name = _FIELD_OFFSET - _FIELD_OFFSET = _FIELD_OFFSET + (\size) -.if (\align > _STRUCT_ALIGN) - _STRUCT_ALIGN = \align -.endif -.endm - -# END_FIELDS -.macro END_FIELDS - _FIELD_OFFSET = (_FIELD_OFFSET + _STRUCT_ALIGN-1) & (~ (_STRUCT_ALIGN-1)) -.endm - -######################################################################## - -.macro STRUCT p1 -START_FIELDS -.struc \p1 -.endm - -.macro ENDSTRUCT - tmp = _FIELD_OFFSET - END_FIELDS - tmp = (_FIELD_OFFSET - %%tmp) -.if (tmp > 0) - .lcomm tmp -.endif -.endstruc -.endm - -## RES_int name size align -.macro RES_int p1 p2 p3 - name = \p1 - size = \p2 - align = .\p3 - - _FIELD_OFFSET = (_FIELD_OFFSET + (align) - 1) & (~ ((align)-1)) -.align align -.lcomm name size - _FIELD_OFFSET = _FIELD_OFFSET + (size) -.if (align > _STRUCT_ALIGN) - _STRUCT_ALIGN = align -.endif -.endm - -# macro RES_B name, size [, align] -.macro RES_B _name, _size, _align=1 -RES_int _name _size _align -.endm - -# macro RES_W name, size [, align] -.macro RES_W _name, _size, _align=2 -RES_int _name 2*(_size) _align -.endm - -# macro RES_D name, size [, align] -.macro RES_D _name, _size, _align=4 -RES_int _name 4*(_size) _align -.endm - -# macro RES_Q name, size [, align] -.macro RES_Q _name, _size, _align=8 -RES_int _name 8*(_size) _align -.endm - -# macro RES_DQ name, size [, align] -.macro RES_DQ _name, _size, _align=16 -RES_int _name 16*(_size) _align -.endm - -# macro RES_Y name, size [, align] -.macro RES_Y _name, _size, _align=32 -RES_int _name 32*(_size) _align -.endm - -# macro RES_Z name, size [, align] -.macro RES_Z _name, _size, _align=64 -RES_int _name 64*(_size) _align -.endm - -#endif - - -######################################################################## -#### Define SHA256 Out Of Order Data Structures -######################################################################## - -START_FIELDS # LANE_DATA -### name size align -FIELD _job_in_lane, 8, 8 # pointer to job object -END_FIELDS - - _LANE_DATA_size = _FIELD_OFFSET - _LANE_DATA_align = _STRUCT_ALIGN - -######################################################################## - -START_FIELDS # SHA256_ARGS_X4 -### name size align -FIELD _digest, 4*8*8, 4 # transposed digest -FIELD _data_ptr, 8*8, 8 # array of pointers to data -END_FIELDS - - _SHA256_ARGS_X4_size = _FIELD_OFFSET - _SHA256_ARGS_X4_align = _STRUCT_ALIGN - _SHA256_ARGS_X8_size = _FIELD_OFFSET - _SHA256_ARGS_X8_align = _STRUCT_ALIGN - -####################################################################### - -START_FIELDS # MB_MGR -### name size align -FIELD _args, _SHA256_ARGS_X4_size, _SHA256_ARGS_X4_align -FIELD _lens, 4*8, 8 -FIELD _unused_lanes, 8, 8 -FIELD _ldata, _LANE_DATA_size*8, _LANE_DATA_align -END_FIELDS - - _MB_MGR_size = _FIELD_OFFSET - _MB_MGR_align = _STRUCT_ALIGN - -_args_digest = _args + _digest -_args_data_ptr = _args + _data_ptr - -####################################################################### - -START_FIELDS #STACK_FRAME -### name size align -FIELD _data, 16*SZ8, 1 # transposed digest -FIELD _digest, 8*SZ8, 1 # array of pointers to data -FIELD _ytmp, 4*SZ8, 1 -FIELD _rsp, 8, 1 -END_FIELDS - - _STACK_FRAME_size = _FIELD_OFFSET - _STACK_FRAME_align = _STRUCT_ALIGN - -####################################################################### - -######################################################################## -#### Define constants -######################################################################## - -#define STS_UNKNOWN 0 -#define STS_BEING_PROCESSED 1 -#define STS_COMPLETED 2 - -######################################################################## -#### Define JOB_SHA256 structure -######################################################################## - -START_FIELDS # JOB_SHA256 - -### name size align -FIELD _buffer, 8, 8 # pointer to buffer -FIELD _len, 8, 8 # length in bytes -FIELD _result_digest, 8*4, 32 # Digest (output) -FIELD _status, 4, 4 -FIELD _user_data, 8, 8 -END_FIELDS - - _JOB_SHA256_size = _FIELD_OFFSET - _JOB_SHA256_align = _STRUCT_ALIGN diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S deleted file mode 100644 index d2364c55bbde..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_flush_avx2.S +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Flush routine for SHA256 multibuffer - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha256_mb_mgr_datastruct.S" - -.extern sha256_x8_avx2 - -#LINUX register definitions -#define arg1 %rdi -#define arg2 %rsi - -# Common register definitions -#define state arg1 -#define job arg2 -#define len2 arg2 - -# idx must be a register not clobberred by sha1_mult -#define idx %r8 -#define DWORD_idx %r8d - -#define unused_lanes %rbx -#define lane_data %rbx -#define tmp2 %rbx -#define tmp2_w %ebx - -#define job_rax %rax -#define tmp1 %rax -#define size_offset %rax -#define tmp %rax -#define start_offset %rax - -#define tmp3 %arg1 - -#define extra_blocks %arg2 -#define p %arg2 - -.macro LABEL prefix n -\prefix\n\(): -.endm - -.macro JNE_SKIP i -jne skip_\i -.endm - -.altmacro -.macro SET_OFFSET _offset -offset = \_offset -.endm -.noaltmacro - -# JOB_SHA256* sha256_mb_mgr_flush_avx2(MB_MGR *state) -# arg 1 : rcx : state -ENTRY(sha256_mb_mgr_flush_avx2) - FRAME_BEGIN - push %rbx - - # If bit (32+3) is set, then all lanes are empty - mov _unused_lanes(state), unused_lanes - bt $32+3, unused_lanes - jc return_null - - # find a lane with a non-null job - xor idx, idx - offset = (_ldata + 1 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne one(%rip), idx - offset = (_ldata + 2 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne two(%rip), idx - offset = (_ldata + 3 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne three(%rip), idx - offset = (_ldata + 4 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne four(%rip), idx - offset = (_ldata + 5 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne five(%rip), idx - offset = (_ldata + 6 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne six(%rip), idx - offset = (_ldata + 7 * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne seven(%rip), idx - - # copy idx to empty lanes -copy_lane_data: - offset = (_args + _data_ptr) - mov offset(state,idx,8), tmp - - I = 0 -.rep 8 - offset = (_ldata + I * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) -.altmacro - JNE_SKIP %I - offset = (_args + _data_ptr + 8*I) - mov tmp, offset(state) - offset = (_lens + 4*I) - movl $0xFFFFFFFF, offset(state) -LABEL skip_ %I - I = (I+1) -.noaltmacro -.endr - - # Find min length - vmovdqu _lens+0*16(state), %xmm0 - vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min val in low dword - - vmovd %xmm2, DWORD_idx - mov idx, len2 - and $0xF, idx - shr $4, len2 - jz len_is_0 - - vpand clear_low_nibble(%rip), %xmm2, %xmm2 - vpshufd $0, %xmm2, %xmm2 - - vpsubd %xmm2, %xmm0, %xmm0 - vpsubd %xmm2, %xmm1, %xmm1 - - vmovdqu %xmm0, _lens+0*16(state) - vmovdqu %xmm1, _lens+1*16(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha256_x8_avx2 - # state and idx are intact - -len_is_0: - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $4, unused_lanes - or idx, unused_lanes - - mov unused_lanes, _unused_lanes(state) - movl $0xFFFFFFFF, _lens(state,idx,4) - - vmovd _args_digest(state , idx, 4) , %xmm0 - vpinsrd $1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0 - vmovd _args_digest+4*32(state, idx, 4), %xmm1 - vpinsrd $1, _args_digest+5*32(state, idx, 4), %xmm1, %xmm1 - vpinsrd $2, _args_digest+6*32(state, idx, 4), %xmm1, %xmm1 - vpinsrd $3, _args_digest+7*32(state, idx, 4), %xmm1, %xmm1 - - vmovdqu %xmm0, _result_digest(job_rax) - offset = (_result_digest + 1*16) - vmovdqu %xmm1, offset(job_rax) - -return: - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return -ENDPROC(sha256_mb_mgr_flush_avx2) - -############################################################################## - -.align 16 -ENTRY(sha256_mb_mgr_get_comp_job_avx2) - push %rbx - - ## if bit 32+3 is set, then all lanes are empty - mov _unused_lanes(state), unused_lanes - bt $(32+3), unused_lanes - jc .return_null - - # Find min length - vmovdqu _lens(state), %xmm0 - vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min val in low dword - - vmovd %xmm2, DWORD_idx - test $~0xF, idx - jnz .return_null - - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $4, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens(state, idx, 4) - - vmovd _args_digest(state, idx, 4), %xmm0 - vpinsrd $1, _args_digest+1*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state, idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state, idx, 4), %xmm0, %xmm0 - vmovd _args_digest+4*32(state, idx, 4), %xmm1 - vpinsrd $1, _args_digest+5*32(state, idx, 4), %xmm1, %xmm1 - vpinsrd $2, _args_digest+6*32(state, idx, 4), %xmm1, %xmm1 - vpinsrd $3, _args_digest+7*32(state, idx, 4), %xmm1, %xmm1 - - vmovdqu %xmm0, _result_digest(job_rax) - offset = (_result_digest + 1*16) - vmovdqu %xmm1, offset(job_rax) - - pop %rbx - - ret - -.return_null: - xor job_rax, job_rax - pop %rbx - ret -ENDPROC(sha256_mb_mgr_get_comp_job_avx2) - -.section .rodata.cst16.clear_low_nibble, "aM", @progbits, 16 -.align 16 -clear_low_nibble: -.octa 0x000000000000000000000000FFFFFFF0 - -.section .rodata.cst8, "aM", @progbits, 8 -.align 8 -one: -.quad 1 -two: -.quad 2 -three: -.quad 3 -four: -.quad 4 -five: -.quad 5 -six: -.quad 6 -seven: -.quad 7 diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_init_avx2.c b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_init_avx2.c deleted file mode 100644 index b0c498371e67..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_init_avx2.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Initialization code for multi buffer SHA256 algorithm for AVX2 - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include "sha256_mb_mgr.h" - -void sha256_mb_mgr_init_avx2(struct sha256_mb_mgr *state) -{ - unsigned int j; - - state->unused_lanes = 0xF76543210ULL; - for (j = 0; j < 8; j++) { - state->lens[j] = 0xFFFFFFFF; - state->ldata[j].job_in_lane = NULL; - } -} diff --git a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_submit_avx2.S b/arch/x86/crypto/sha256-mb/sha256_mb_mgr_submit_avx2.S deleted file mode 100644 index b36ae7454084..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_mb_mgr_submit_avx2.S +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Buffer submit code for multi buffer SHA256 algorithm - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha256_mb_mgr_datastruct.S" - -.extern sha256_x8_avx2 - -# LINUX register definitions -arg1 = %rdi -arg2 = %rsi -size_offset = %rcx -tmp2 = %rcx -extra_blocks = %rdx - -# Common definitions -#define state arg1 -#define job %rsi -#define len2 arg2 -#define p2 arg2 - -# idx must be a register not clobberred by sha1_x8_avx2 -idx = %r8 -DWORD_idx = %r8d -last_len = %r8 - -p = %r11 -start_offset = %r11 - -unused_lanes = %rbx -BYTE_unused_lanes = %bl - -job_rax = %rax -len = %rax -DWORD_len = %eax - -lane = %r12 -tmp3 = %r12 - -tmp = %r9 -DWORD_tmp = %r9d - -lane_data = %r10 - -# JOB* sha256_mb_mgr_submit_avx2(MB_MGR *state, JOB_SHA256 *job) -# arg 1 : rcx : state -# arg 2 : rdx : job -ENTRY(sha256_mb_mgr_submit_avx2) - FRAME_BEGIN - push %rbx - push %r12 - - mov _unused_lanes(state), unused_lanes - mov unused_lanes, lane - and $0xF, lane - shr $4, unused_lanes - imul $_LANE_DATA_size, lane, lane_data - movl $STS_BEING_PROCESSED, _status(job) - lea _ldata(state, lane_data), lane_data - mov unused_lanes, _unused_lanes(state) - movl _len(job), DWORD_len - - mov job, _job_in_lane(lane_data) - shl $4, len - or lane, len - - movl DWORD_len, _lens(state , lane, 4) - - # Load digest words from result_digest - vmovdqu _result_digest(job), %xmm0 - vmovdqu _result_digest+1*16(job), %xmm1 - vmovd %xmm0, _args_digest(state, lane, 4) - vpextrd $1, %xmm0, _args_digest+1*32(state , lane, 4) - vpextrd $2, %xmm0, _args_digest+2*32(state , lane, 4) - vpextrd $3, %xmm0, _args_digest+3*32(state , lane, 4) - vmovd %xmm1, _args_digest+4*32(state , lane, 4) - - vpextrd $1, %xmm1, _args_digest+5*32(state , lane, 4) - vpextrd $2, %xmm1, _args_digest+6*32(state , lane, 4) - vpextrd $3, %xmm1, _args_digest+7*32(state , lane, 4) - - mov _buffer(job), p - mov p, _args_data_ptr(state, lane, 8) - - cmp $0xF, unused_lanes - jne return_null - -start_loop: - # Find min length - vmovdqa _lens(state), %xmm0 - vmovdqa _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has {x,x,E,F} - vpalignr $4, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,x,E} - vpminud %xmm3, %xmm2, %xmm2 # xmm2 has min val in low dword - - vmovd %xmm2, DWORD_idx - mov idx, len2 - and $0xF, idx - shr $4, len2 - jz len_is_0 - - vpand clear_low_nibble(%rip), %xmm2, %xmm2 - vpshufd $0, %xmm2, %xmm2 - - vpsubd %xmm2, %xmm0, %xmm0 - vpsubd %xmm2, %xmm1, %xmm1 - - vmovdqa %xmm0, _lens + 0*16(state) - vmovdqa %xmm1, _lens + 1*16(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha256_x8_avx2 - - # state and idx are intact - -len_is_0: - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - mov _unused_lanes(state), unused_lanes - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - shl $4, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens(state,idx,4) - - vmovd _args_digest(state, idx, 4), %xmm0 - vpinsrd $1, _args_digest+1*32(state , idx, 4), %xmm0, %xmm0 - vpinsrd $2, _args_digest+2*32(state , idx, 4), %xmm0, %xmm0 - vpinsrd $3, _args_digest+3*32(state , idx, 4), %xmm0, %xmm0 - vmovd _args_digest+4*32(state, idx, 4), %xmm1 - - vpinsrd $1, _args_digest+5*32(state , idx, 4), %xmm1, %xmm1 - vpinsrd $2, _args_digest+6*32(state , idx, 4), %xmm1, %xmm1 - vpinsrd $3, _args_digest+7*32(state , idx, 4), %xmm1, %xmm1 - - vmovdqu %xmm0, _result_digest(job_rax) - vmovdqu %xmm1, _result_digest+1*16(job_rax) - -return: - pop %r12 - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return - -ENDPROC(sha256_mb_mgr_submit_avx2) - -.section .rodata.cst16.clear_low_nibble, "aM", @progbits, 16 -.align 16 -clear_low_nibble: - .octa 0x000000000000000000000000FFFFFFF0 diff --git a/arch/x86/crypto/sha256-mb/sha256_x8_avx2.S b/arch/x86/crypto/sha256-mb/sha256_x8_avx2.S deleted file mode 100644 index 1687c80c5995..000000000000 --- a/arch/x86/crypto/sha256-mb/sha256_x8_avx2.S +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Multi-buffer SHA256 algorithm hash compute routine - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include "sha256_mb_mgr_datastruct.S" - -## code to compute oct SHA256 using SSE-256 -## outer calling routine takes care of save and restore of XMM registers -## Logic designed/laid out by JDG - -## Function clobbers: rax, rcx, rdx, rbx, rsi, rdi, r9-r15; %ymm0-15 -## Linux clobbers: rax rbx rcx rdx rsi r9 r10 r11 r12 r13 r14 r15 -## Linux preserves: rdi rbp r8 -## -## clobbers %ymm0-15 - -arg1 = %rdi -arg2 = %rsi -reg3 = %rcx -reg4 = %rdx - -# Common definitions -STATE = arg1 -INP_SIZE = arg2 - -IDX = %rax -ROUND = %rbx -TBL = reg3 - -inp0 = %r9 -inp1 = %r10 -inp2 = %r11 -inp3 = %r12 -inp4 = %r13 -inp5 = %r14 -inp6 = %r15 -inp7 = reg4 - -a = %ymm0 -b = %ymm1 -c = %ymm2 -d = %ymm3 -e = %ymm4 -f = %ymm5 -g = %ymm6 -h = %ymm7 - -T1 = %ymm8 - -a0 = %ymm12 -a1 = %ymm13 -a2 = %ymm14 -TMP = %ymm15 -TMP0 = %ymm6 -TMP1 = %ymm7 - -TT0 = %ymm8 -TT1 = %ymm9 -TT2 = %ymm10 -TT3 = %ymm11 -TT4 = %ymm12 -TT5 = %ymm13 -TT6 = %ymm14 -TT7 = %ymm15 - -# Define stack usage - -# Assume stack aligned to 32 bytes before call -# Therefore FRAMESZ mod 32 must be 32-8 = 24 - -#define FRAMESZ 0x388 - -#define VMOVPS vmovups - -# TRANSPOSE8 r0, r1, r2, r3, r4, r5, r6, r7, t0, t1 -# "transpose" data in {r0...r7} using temps {t0...t1} -# Input looks like: {r0 r1 r2 r3 r4 r5 r6 r7} -# r0 = {a7 a6 a5 a4 a3 a2 a1 a0} -# r1 = {b7 b6 b5 b4 b3 b2 b1 b0} -# r2 = {c7 c6 c5 c4 c3 c2 c1 c0} -# r3 = {d7 d6 d5 d4 d3 d2 d1 d0} -# r4 = {e7 e6 e5 e4 e3 e2 e1 e0} -# r5 = {f7 f6 f5 f4 f3 f2 f1 f0} -# r6 = {g7 g6 g5 g4 g3 g2 g1 g0} -# r7 = {h7 h6 h5 h4 h3 h2 h1 h0} -# -# Output looks like: {r0 r1 r2 r3 r4 r5 r6 r7} -# r0 = {h0 g0 f0 e0 d0 c0 b0 a0} -# r1 = {h1 g1 f1 e1 d1 c1 b1 a1} -# r2 = {h2 g2 f2 e2 d2 c2 b2 a2} -# r3 = {h3 g3 f3 e3 d3 c3 b3 a3} -# r4 = {h4 g4 f4 e4 d4 c4 b4 a4} -# r5 = {h5 g5 f5 e5 d5 c5 b5 a5} -# r6 = {h6 g6 f6 e6 d6 c6 b6 a6} -# r7 = {h7 g7 f7 e7 d7 c7 b7 a7} -# - -.macro TRANSPOSE8 r0 r1 r2 r3 r4 r5 r6 r7 t0 t1 - # process top half (r0..r3) {a...d} - vshufps $0x44, \r1, \r0, \t0 # t0 = {b5 b4 a5 a4 b1 b0 a1 a0} - vshufps $0xEE, \r1, \r0, \r0 # r0 = {b7 b6 a7 a6 b3 b2 a3 a2} - vshufps $0x44, \r3, \r2, \t1 # t1 = {d5 d4 c5 c4 d1 d0 c1 c0} - vshufps $0xEE, \r3, \r2, \r2 # r2 = {d7 d6 c7 c6 d3 d2 c3 c2} - vshufps $0xDD, \t1, \t0, \r3 # r3 = {d5 c5 b5 a5 d1 c1 b1 a1} - vshufps $0x88, \r2, \r0, \r1 # r1 = {d6 c6 b6 a6 d2 c2 b2 a2} - vshufps $0xDD, \r2, \r0, \r0 # r0 = {d7 c7 b7 a7 d3 c3 b3 a3} - vshufps $0x88, \t1, \t0, \t0 # t0 = {d4 c4 b4 a4 d0 c0 b0 a0} - - # use r2 in place of t0 - # process bottom half (r4..r7) {e...h} - vshufps $0x44, \r5, \r4, \r2 # r2 = {f5 f4 e5 e4 f1 f0 e1 e0} - vshufps $0xEE, \r5, \r4, \r4 # r4 = {f7 f6 e7 e6 f3 f2 e3 e2} - vshufps $0x44, \r7, \r6, \t1 # t1 = {h5 h4 g5 g4 h1 h0 g1 g0} - vshufps $0xEE, \r7, \r6, \r6 # r6 = {h7 h6 g7 g6 h3 h2 g3 g2} - vshufps $0xDD, \t1, \r2, \r7 # r7 = {h5 g5 f5 e5 h1 g1 f1 e1} - vshufps $0x88, \r6, \r4, \r5 # r5 = {h6 g6 f6 e6 h2 g2 f2 e2} - vshufps $0xDD, \r6, \r4, \r4 # r4 = {h7 g7 f7 e7 h3 g3 f3 e3} - vshufps $0x88, \t1, \r2, \t1 # t1 = {h4 g4 f4 e4 h0 g0 f0 e0} - - vperm2f128 $0x13, \r1, \r5, \r6 # h6...a6 - vperm2f128 $0x02, \r1, \r5, \r2 # h2...a2 - vperm2f128 $0x13, \r3, \r7, \r5 # h5...a5 - vperm2f128 $0x02, \r3, \r7, \r1 # h1...a1 - vperm2f128 $0x13, \r0, \r4, \r7 # h7...a7 - vperm2f128 $0x02, \r0, \r4, \r3 # h3...a3 - vperm2f128 $0x13, \t0, \t1, \r4 # h4...a4 - vperm2f128 $0x02, \t0, \t1, \r0 # h0...a0 - -.endm - -.macro ROTATE_ARGS -TMP_ = h -h = g -g = f -f = e -e = d -d = c -c = b -b = a -a = TMP_ -.endm - -.macro _PRORD reg imm tmp - vpslld $(32-\imm),\reg,\tmp - vpsrld $\imm,\reg, \reg - vpor \tmp,\reg, \reg -.endm - -# PRORD_nd reg, imm, tmp, src -.macro _PRORD_nd reg imm tmp src - vpslld $(32-\imm), \src, \tmp - vpsrld $\imm, \src, \reg - vpor \tmp, \reg, \reg -.endm - -# PRORD dst/src, amt -.macro PRORD reg imm - _PRORD \reg,\imm,TMP -.endm - -# PRORD_nd dst, src, amt -.macro PRORD_nd reg tmp imm - _PRORD_nd \reg, \imm, TMP, \tmp -.endm - -# arguments passed implicitly in preprocessor symbols i, a...h -.macro ROUND_00_15 _T1 i - PRORD_nd a0,e,5 # sig1: a0 = (e >> 5) - - vpxor g, f, a2 # ch: a2 = f^g - vpand e,a2, a2 # ch: a2 = (f^g)&e - vpxor g, a2, a2 # a2 = ch - - PRORD_nd a1,e,25 # sig1: a1 = (e >> 25) - - vmovdqu \_T1,(SZ8*(\i & 0xf))(%rsp) - vpaddd (TBL,ROUND,1), \_T1, \_T1 # T1 = W + K - vpxor e,a0, a0 # sig1: a0 = e ^ (e >> 5) - PRORD a0, 6 # sig1: a0 = (e >> 6) ^ (e >> 11) - vpaddd a2, h, h # h = h + ch - PRORD_nd a2,a,11 # sig0: a2 = (a >> 11) - vpaddd \_T1,h, h # h = h + ch + W + K - vpxor a1, a0, a0 # a0 = sigma1 - PRORD_nd a1,a,22 # sig0: a1 = (a >> 22) - vpxor c, a, \_T1 # maj: T1 = a^c - add $SZ8, ROUND # ROUND++ - vpand b, \_T1, \_T1 # maj: T1 = (a^c)&b - vpaddd a0, h, h - vpaddd h, d, d - vpxor a, a2, a2 # sig0: a2 = a ^ (a >> 11) - PRORD a2,2 # sig0: a2 = (a >> 2) ^ (a >> 13) - vpxor a1, a2, a2 # a2 = sig0 - vpand c, a, a1 # maj: a1 = a&c - vpor \_T1, a1, a1 # a1 = maj - vpaddd a1, h, h # h = h + ch + W + K + maj - vpaddd a2, h, h # h = h + ch + W + K + maj + sigma0 - ROTATE_ARGS -.endm - -# arguments passed implicitly in preprocessor symbols i, a...h -.macro ROUND_16_XX _T1 i - vmovdqu (SZ8*((\i-15)&0xf))(%rsp), \_T1 - vmovdqu (SZ8*((\i-2)&0xf))(%rsp), a1 - vmovdqu \_T1, a0 - PRORD \_T1,11 - vmovdqu a1, a2 - PRORD a1,2 - vpxor a0, \_T1, \_T1 - PRORD \_T1, 7 - vpxor a2, a1, a1 - PRORD a1, 17 - vpsrld $3, a0, a0 - vpxor a0, \_T1, \_T1 - vpsrld $10, a2, a2 - vpxor a2, a1, a1 - vpaddd (SZ8*((\i-16)&0xf))(%rsp), \_T1, \_T1 - vpaddd (SZ8*((\i-7)&0xf))(%rsp), a1, a1 - vpaddd a1, \_T1, \_T1 - - ROUND_00_15 \_T1,\i -.endm - -# SHA256_ARGS: -# UINT128 digest[8]; // transposed digests -# UINT8 *data_ptr[4]; - -# void sha256_x8_avx2(SHA256_ARGS *args, UINT64 bytes); -# arg 1 : STATE : pointer to array of pointers to input data -# arg 2 : INP_SIZE : size of input in blocks - # general registers preserved in outer calling routine - # outer calling routine saves all the XMM registers - # save rsp, allocate 32-byte aligned for local variables -ENTRY(sha256_x8_avx2) - - # save callee-saved clobbered registers to comply with C function ABI - push %r12 - push %r13 - push %r14 - push %r15 - - mov %rsp, IDX - sub $FRAMESZ, %rsp - and $~0x1F, %rsp - mov IDX, _rsp(%rsp) - - # Load the pre-transposed incoming digest. - vmovdqu 0*SHA256_DIGEST_ROW_SIZE(STATE),a - vmovdqu 1*SHA256_DIGEST_ROW_SIZE(STATE),b - vmovdqu 2*SHA256_DIGEST_ROW_SIZE(STATE),c - vmovdqu 3*SHA256_DIGEST_ROW_SIZE(STATE),d - vmovdqu 4*SHA256_DIGEST_ROW_SIZE(STATE),e - vmovdqu 5*SHA256_DIGEST_ROW_SIZE(STATE),f - vmovdqu 6*SHA256_DIGEST_ROW_SIZE(STATE),g - vmovdqu 7*SHA256_DIGEST_ROW_SIZE(STATE),h - - lea K256_8(%rip),TBL - - # load the address of each of the 4 message lanes - # getting ready to transpose input onto stack - mov _args_data_ptr+0*PTR_SZ(STATE),inp0 - mov _args_data_ptr+1*PTR_SZ(STATE),inp1 - mov _args_data_ptr+2*PTR_SZ(STATE),inp2 - mov _args_data_ptr+3*PTR_SZ(STATE),inp3 - mov _args_data_ptr+4*PTR_SZ(STATE),inp4 - mov _args_data_ptr+5*PTR_SZ(STATE),inp5 - mov _args_data_ptr+6*PTR_SZ(STATE),inp6 - mov _args_data_ptr+7*PTR_SZ(STATE),inp7 - - xor IDX, IDX -lloop: - xor ROUND, ROUND - - # save old digest - vmovdqu a, _digest(%rsp) - vmovdqu b, _digest+1*SZ8(%rsp) - vmovdqu c, _digest+2*SZ8(%rsp) - vmovdqu d, _digest+3*SZ8(%rsp) - vmovdqu e, _digest+4*SZ8(%rsp) - vmovdqu f, _digest+5*SZ8(%rsp) - vmovdqu g, _digest+6*SZ8(%rsp) - vmovdqu h, _digest+7*SZ8(%rsp) - i = 0 -.rep 2 - VMOVPS i*32(inp0, IDX), TT0 - VMOVPS i*32(inp1, IDX), TT1 - VMOVPS i*32(inp2, IDX), TT2 - VMOVPS i*32(inp3, IDX), TT3 - VMOVPS i*32(inp4, IDX), TT4 - VMOVPS i*32(inp5, IDX), TT5 - VMOVPS i*32(inp6, IDX), TT6 - VMOVPS i*32(inp7, IDX), TT7 - vmovdqu g, _ytmp(%rsp) - vmovdqu h, _ytmp+1*SZ8(%rsp) - TRANSPOSE8 TT0, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TMP0, TMP1 - vmovdqu PSHUFFLE_BYTE_FLIP_MASK(%rip), TMP1 - vmovdqu _ytmp(%rsp), g - vpshufb TMP1, TT0, TT0 - vpshufb TMP1, TT1, TT1 - vpshufb TMP1, TT2, TT2 - vpshufb TMP1, TT3, TT3 - vpshufb TMP1, TT4, TT4 - vpshufb TMP1, TT5, TT5 - vpshufb TMP1, TT6, TT6 - vpshufb TMP1, TT7, TT7 - vmovdqu _ytmp+1*SZ8(%rsp), h - vmovdqu TT4, _ytmp(%rsp) - vmovdqu TT5, _ytmp+1*SZ8(%rsp) - vmovdqu TT6, _ytmp+2*SZ8(%rsp) - vmovdqu TT7, _ytmp+3*SZ8(%rsp) - ROUND_00_15 TT0,(i*8+0) - vmovdqu _ytmp(%rsp), TT0 - ROUND_00_15 TT1,(i*8+1) - vmovdqu _ytmp+1*SZ8(%rsp), TT1 - ROUND_00_15 TT2,(i*8+2) - vmovdqu _ytmp+2*SZ8(%rsp), TT2 - ROUND_00_15 TT3,(i*8+3) - vmovdqu _ytmp+3*SZ8(%rsp), TT3 - ROUND_00_15 TT0,(i*8+4) - ROUND_00_15 TT1,(i*8+5) - ROUND_00_15 TT2,(i*8+6) - ROUND_00_15 TT3,(i*8+7) - i = (i+1) -.endr - add $64, IDX - i = (i*8) - - jmp Lrounds_16_xx -.align 16 -Lrounds_16_xx: -.rep 16 - ROUND_16_XX T1, i - i = (i+1) -.endr - - cmp $ROUNDS,ROUND - jb Lrounds_16_xx - - # add old digest - vpaddd _digest+0*SZ8(%rsp), a, a - vpaddd _digest+1*SZ8(%rsp), b, b - vpaddd _digest+2*SZ8(%rsp), c, c - vpaddd _digest+3*SZ8(%rsp), d, d - vpaddd _digest+4*SZ8(%rsp), e, e - vpaddd _digest+5*SZ8(%rsp), f, f - vpaddd _digest+6*SZ8(%rsp), g, g - vpaddd _digest+7*SZ8(%rsp), h, h - - sub $1, INP_SIZE # unit is blocks - jne lloop - - # write back to memory (state object) the transposed digest - vmovdqu a, 0*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu b, 1*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu c, 2*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu d, 3*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu e, 4*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu f, 5*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu g, 6*SHA256_DIGEST_ROW_SIZE(STATE) - vmovdqu h, 7*SHA256_DIGEST_ROW_SIZE(STATE) - - # update input pointers - add IDX, inp0 - mov inp0, _args_data_ptr+0*8(STATE) - add IDX, inp1 - mov inp1, _args_data_ptr+1*8(STATE) - add IDX, inp2 - mov inp2, _args_data_ptr+2*8(STATE) - add IDX, inp3 - mov inp3, _args_data_ptr+3*8(STATE) - add IDX, inp4 - mov inp4, _args_data_ptr+4*8(STATE) - add IDX, inp5 - mov inp5, _args_data_ptr+5*8(STATE) - add IDX, inp6 - mov inp6, _args_data_ptr+6*8(STATE) - add IDX, inp7 - mov inp7, _args_data_ptr+7*8(STATE) - - # Postamble - mov _rsp(%rsp), %rsp - - # restore callee-saved clobbered registers - pop %r15 - pop %r14 - pop %r13 - pop %r12 - - ret -ENDPROC(sha256_x8_avx2) - -.section .rodata.K256_8, "a", @progbits -.align 64 -K256_8: - .octa 0x428a2f98428a2f98428a2f98428a2f98 - .octa 0x428a2f98428a2f98428a2f98428a2f98 - .octa 0x71374491713744917137449171374491 - .octa 0x71374491713744917137449171374491 - .octa 0xb5c0fbcfb5c0fbcfb5c0fbcfb5c0fbcf - .octa 0xb5c0fbcfb5c0fbcfb5c0fbcfb5c0fbcf - .octa 0xe9b5dba5e9b5dba5e9b5dba5e9b5dba5 - .octa 0xe9b5dba5e9b5dba5e9b5dba5e9b5dba5 - .octa 0x3956c25b3956c25b3956c25b3956c25b - .octa 0x3956c25b3956c25b3956c25b3956c25b - .octa 0x59f111f159f111f159f111f159f111f1 - .octa 0x59f111f159f111f159f111f159f111f1 - .octa 0x923f82a4923f82a4923f82a4923f82a4 - .octa 0x923f82a4923f82a4923f82a4923f82a4 - .octa 0xab1c5ed5ab1c5ed5ab1c5ed5ab1c5ed5 - .octa 0xab1c5ed5ab1c5ed5ab1c5ed5ab1c5ed5 - .octa 0xd807aa98d807aa98d807aa98d807aa98 - .octa 0xd807aa98d807aa98d807aa98d807aa98 - .octa 0x12835b0112835b0112835b0112835b01 - .octa 0x12835b0112835b0112835b0112835b01 - .octa 0x243185be243185be243185be243185be - .octa 0x243185be243185be243185be243185be - .octa 0x550c7dc3550c7dc3550c7dc3550c7dc3 - .octa 0x550c7dc3550c7dc3550c7dc3550c7dc3 - .octa 0x72be5d7472be5d7472be5d7472be5d74 - .octa 0x72be5d7472be5d7472be5d7472be5d74 - .octa 0x80deb1fe80deb1fe80deb1fe80deb1fe - .octa 0x80deb1fe80deb1fe80deb1fe80deb1fe - .octa 0x9bdc06a79bdc06a79bdc06a79bdc06a7 - .octa 0x9bdc06a79bdc06a79bdc06a79bdc06a7 - .octa 0xc19bf174c19bf174c19bf174c19bf174 - .octa 0xc19bf174c19bf174c19bf174c19bf174 - .octa 0xe49b69c1e49b69c1e49b69c1e49b69c1 - .octa 0xe49b69c1e49b69c1e49b69c1e49b69c1 - .octa 0xefbe4786efbe4786efbe4786efbe4786 - .octa 0xefbe4786efbe4786efbe4786efbe4786 - .octa 0x0fc19dc60fc19dc60fc19dc60fc19dc6 - .octa 0x0fc19dc60fc19dc60fc19dc60fc19dc6 - .octa 0x240ca1cc240ca1cc240ca1cc240ca1cc - .octa 0x240ca1cc240ca1cc240ca1cc240ca1cc - .octa 0x2de92c6f2de92c6f2de92c6f2de92c6f - .octa 0x2de92c6f2de92c6f2de92c6f2de92c6f - .octa 0x4a7484aa4a7484aa4a7484aa4a7484aa - .octa 0x4a7484aa4a7484aa4a7484aa4a7484aa - .octa 0x5cb0a9dc5cb0a9dc5cb0a9dc5cb0a9dc - .octa 0x5cb0a9dc5cb0a9dc5cb0a9dc5cb0a9dc - .octa 0x76f988da76f988da76f988da76f988da - .octa 0x76f988da76f988da76f988da76f988da - .octa 0x983e5152983e5152983e5152983e5152 - .octa 0x983e5152983e5152983e5152983e5152 - .octa 0xa831c66da831c66da831c66da831c66d - .octa 0xa831c66da831c66da831c66da831c66d - .octa 0xb00327c8b00327c8b00327c8b00327c8 - .octa 0xb00327c8b00327c8b00327c8b00327c8 - .octa 0xbf597fc7bf597fc7bf597fc7bf597fc7 - .octa 0xbf597fc7bf597fc7bf597fc7bf597fc7 - .octa 0xc6e00bf3c6e00bf3c6e00bf3c6e00bf3 - .octa 0xc6e00bf3c6e00bf3c6e00bf3c6e00bf3 - .octa 0xd5a79147d5a79147d5a79147d5a79147 - .octa 0xd5a79147d5a79147d5a79147d5a79147 - .octa 0x06ca635106ca635106ca635106ca6351 - .octa 0x06ca635106ca635106ca635106ca6351 - .octa 0x14292967142929671429296714292967 - .octa 0x14292967142929671429296714292967 - .octa 0x27b70a8527b70a8527b70a8527b70a85 - .octa 0x27b70a8527b70a8527b70a8527b70a85 - .octa 0x2e1b21382e1b21382e1b21382e1b2138 - .octa 0x2e1b21382e1b21382e1b21382e1b2138 - .octa 0x4d2c6dfc4d2c6dfc4d2c6dfc4d2c6dfc - .octa 0x4d2c6dfc4d2c6dfc4d2c6dfc4d2c6dfc - .octa 0x53380d1353380d1353380d1353380d13 - .octa 0x53380d1353380d1353380d1353380d13 - .octa 0x650a7354650a7354650a7354650a7354 - .octa 0x650a7354650a7354650a7354650a7354 - .octa 0x766a0abb766a0abb766a0abb766a0abb - .octa 0x766a0abb766a0abb766a0abb766a0abb - .octa 0x81c2c92e81c2c92e81c2c92e81c2c92e - .octa 0x81c2c92e81c2c92e81c2c92e81c2c92e - .octa 0x92722c8592722c8592722c8592722c85 - .octa 0x92722c8592722c8592722c8592722c85 - .octa 0xa2bfe8a1a2bfe8a1a2bfe8a1a2bfe8a1 - .octa 0xa2bfe8a1a2bfe8a1a2bfe8a1a2bfe8a1 - .octa 0xa81a664ba81a664ba81a664ba81a664b - .octa 0xa81a664ba81a664ba81a664ba81a664b - .octa 0xc24b8b70c24b8b70c24b8b70c24b8b70 - .octa 0xc24b8b70c24b8b70c24b8b70c24b8b70 - .octa 0xc76c51a3c76c51a3c76c51a3c76c51a3 - .octa 0xc76c51a3c76c51a3c76c51a3c76c51a3 - .octa 0xd192e819d192e819d192e819d192e819 - .octa 0xd192e819d192e819d192e819d192e819 - .octa 0xd6990624d6990624d6990624d6990624 - .octa 0xd6990624d6990624d6990624d6990624 - .octa 0xf40e3585f40e3585f40e3585f40e3585 - .octa 0xf40e3585f40e3585f40e3585f40e3585 - .octa 0x106aa070106aa070106aa070106aa070 - .octa 0x106aa070106aa070106aa070106aa070 - .octa 0x19a4c11619a4c11619a4c11619a4c116 - .octa 0x19a4c11619a4c11619a4c11619a4c116 - .octa 0x1e376c081e376c081e376c081e376c08 - .octa 0x1e376c081e376c081e376c081e376c08 - .octa 0x2748774c2748774c2748774c2748774c - .octa 0x2748774c2748774c2748774c2748774c - .octa 0x34b0bcb534b0bcb534b0bcb534b0bcb5 - .octa 0x34b0bcb534b0bcb534b0bcb534b0bcb5 - .octa 0x391c0cb3391c0cb3391c0cb3391c0cb3 - .octa 0x391c0cb3391c0cb3391c0cb3391c0cb3 - .octa 0x4ed8aa4a4ed8aa4a4ed8aa4a4ed8aa4a - .octa 0x4ed8aa4a4ed8aa4a4ed8aa4a4ed8aa4a - .octa 0x5b9cca4f5b9cca4f5b9cca4f5b9cca4f - .octa 0x5b9cca4f5b9cca4f5b9cca4f5b9cca4f - .octa 0x682e6ff3682e6ff3682e6ff3682e6ff3 - .octa 0x682e6ff3682e6ff3682e6ff3682e6ff3 - .octa 0x748f82ee748f82ee748f82ee748f82ee - .octa 0x748f82ee748f82ee748f82ee748f82ee - .octa 0x78a5636f78a5636f78a5636f78a5636f - .octa 0x78a5636f78a5636f78a5636f78a5636f - .octa 0x84c8781484c8781484c8781484c87814 - .octa 0x84c8781484c8781484c8781484c87814 - .octa 0x8cc702088cc702088cc702088cc70208 - .octa 0x8cc702088cc702088cc702088cc70208 - .octa 0x90befffa90befffa90befffa90befffa - .octa 0x90befffa90befffa90befffa90befffa - .octa 0xa4506ceba4506ceba4506ceba4506ceb - .octa 0xa4506ceba4506ceba4506ceba4506ceb - .octa 0xbef9a3f7bef9a3f7bef9a3f7bef9a3f7 - .octa 0xbef9a3f7bef9a3f7bef9a3f7bef9a3f7 - .octa 0xc67178f2c67178f2c67178f2c67178f2 - .octa 0xc67178f2c67178f2c67178f2c67178f2 - -.section .rodata.cst32.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 32 -.align 32 -PSHUFFLE_BYTE_FLIP_MASK: -.octa 0x0c0d0e0f08090a0b0405060700010203 -.octa 0x0c0d0e0f08090a0b0405060700010203 - -.section .rodata.cst256.K256, "aM", @progbits, 256 -.align 64 -.global K256 -K256: - .int 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 - .int 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 - .int 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 - .int 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 - .int 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc - .int 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da - .int 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 - .int 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 - .int 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 - .int 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 - .int 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 - .int 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 - .int 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 - .int 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 - .int 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 - .int 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 diff --git a/arch/x86/crypto/sha512-mb/Makefile b/arch/x86/crypto/sha512-mb/Makefile deleted file mode 100644 index 90f1ef69152e..000000000000 --- a/arch/x86/crypto/sha512-mb/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Arch-specific CryptoAPI modules. -# - -avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\ - $(comma)4)$(comma)%ymm2,yes,no) -ifeq ($(avx2_supported),yes) - obj-$(CONFIG_CRYPTO_SHA512_MB) += sha512-mb.o - sha512-mb-y := sha512_mb.o sha512_mb_mgr_flush_avx2.o \ - sha512_mb_mgr_init_avx2.o sha512_mb_mgr_submit_avx2.o sha512_x4_avx2.o -endif diff --git a/arch/x86/crypto/sha512-mb/sha512_mb.c b/arch/x86/crypto/sha512-mb/sha512_mb.c deleted file mode 100644 index 26b85678012d..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - * Multi buffer SHA512 algorithm Glue Code - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <crypto/internal/hash.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/cryptohash.h> -#include <linux/types.h> -#include <linux/list.h> -#include <crypto/scatterwalk.h> -#include <crypto/sha.h> -#include <crypto/mcryptd.h> -#include <crypto/crypto_wq.h> -#include <asm/byteorder.h> -#include <linux/hardirq.h> -#include <asm/fpu/api.h> -#include "sha512_mb_ctx.h" - -#define FLUSH_INTERVAL 1000 /* in usec */ - -static struct mcryptd_alg_state sha512_mb_alg_state; - -struct sha512_mb_ctx { - struct mcryptd_ahash *mcryptd_tfm; -}; - -static inline struct mcryptd_hash_request_ctx - *cast_hash_to_mcryptd_ctx(struct sha512_hash_ctx *hash_ctx) -{ - struct ahash_request *areq; - - areq = container_of((void *) hash_ctx, struct ahash_request, __ctx); - return container_of(areq, struct mcryptd_hash_request_ctx, areq); -} - -static inline struct ahash_request - *cast_mcryptd_ctx_to_req(struct mcryptd_hash_request_ctx *ctx) -{ - return container_of((void *) ctx, struct ahash_request, __ctx); -} - -static void req_ctx_init(struct mcryptd_hash_request_ctx *rctx, - struct ahash_request *areq) -{ - rctx->flag = HASH_UPDATE; -} - -static asmlinkage void (*sha512_job_mgr_init)(struct sha512_mb_mgr *state); -static asmlinkage struct job_sha512* (*sha512_job_mgr_submit) - (struct sha512_mb_mgr *state, - struct job_sha512 *job); -static asmlinkage struct job_sha512* (*sha512_job_mgr_flush) - (struct sha512_mb_mgr *state); -static asmlinkage struct job_sha512* (*sha512_job_mgr_get_comp_job) - (struct sha512_mb_mgr *state); - -inline uint32_t sha512_pad(uint8_t padblock[SHA512_BLOCK_SIZE * 2], - uint64_t total_len) -{ - uint32_t i = total_len & (SHA512_BLOCK_SIZE - 1); - - memset(&padblock[i], 0, SHA512_BLOCK_SIZE); - padblock[i] = 0x80; - - i += ((SHA512_BLOCK_SIZE - 1) & - (0 - (total_len + SHA512_PADLENGTHFIELD_SIZE + 1))) - + 1 + SHA512_PADLENGTHFIELD_SIZE; - -#if SHA512_PADLENGTHFIELD_SIZE == 16 - *((uint64_t *) &padblock[i - 16]) = 0; -#endif - - *((uint64_t *) &padblock[i - 8]) = cpu_to_be64(total_len << 3); - - /* Number of extra blocks to hash */ - return i >> SHA512_LOG2_BLOCK_SIZE; -} - -static struct sha512_hash_ctx *sha512_ctx_mgr_resubmit - (struct sha512_ctx_mgr *mgr, struct sha512_hash_ctx *ctx) -{ - while (ctx) { - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Clear PROCESSING bit */ - ctx->status = HASH_CTX_STS_COMPLETE; - return ctx; - } - - /* - * If the extra blocks are empty, begin hashing what remains - * in the user's buffer. - */ - if (ctx->partial_block_buffer_length == 0 && - ctx->incoming_buffer_length) { - - const void *buffer = ctx->incoming_buffer; - uint32_t len = ctx->incoming_buffer_length; - uint32_t copy_len; - - /* - * Only entire blocks can be hashed. - * Copy remainder to extra blocks buffer. - */ - copy_len = len & (SHA512_BLOCK_SIZE-1); - - if (copy_len) { - len -= copy_len; - memcpy(ctx->partial_block_buffer, - ((const char *) buffer + len), - copy_len); - ctx->partial_block_buffer_length = copy_len; - } - - ctx->incoming_buffer_length = 0; - - /* len should be a multiple of the block size now */ - assert((len % SHA512_BLOCK_SIZE) == 0); - - /* Set len to the number of blocks to be hashed */ - len >>= SHA512_LOG2_BLOCK_SIZE; - - if (len) { - - ctx->job.buffer = (uint8_t *) buffer; - ctx->job.len = len; - ctx = (struct sha512_hash_ctx *) - sha512_job_mgr_submit(&mgr->mgr, - &ctx->job); - continue; - } - } - - /* - * If the extra blocks are not empty, then we are - * either on the last block(s) or we need more - * user input before continuing. - */ - if (ctx->status & HASH_CTX_STS_LAST) { - - uint8_t *buf = ctx->partial_block_buffer; - uint32_t n_extra_blocks = - sha512_pad(buf, ctx->total_length); - - ctx->status = (HASH_CTX_STS_PROCESSING | - HASH_CTX_STS_COMPLETE); - ctx->job.buffer = buf; - ctx->job.len = (uint32_t) n_extra_blocks; - ctx = (struct sha512_hash_ctx *) - sha512_job_mgr_submit(&mgr->mgr, &ctx->job); - continue; - } - - if (ctx) - ctx->status = HASH_CTX_STS_IDLE; - return ctx; - } - - return NULL; -} - -static struct sha512_hash_ctx - *sha512_ctx_mgr_get_comp_ctx(struct mcryptd_alg_cstate *cstate) -{ - /* - * If get_comp_job returns NULL, there are no jobs complete. - * If get_comp_job returns a job, verify that it is safe to return to - * the user. - * If it is not ready, resubmit the job to finish processing. - * If sha512_ctx_mgr_resubmit returned a job, it is ready to be - * returned. - * Otherwise, all jobs currently being managed by the hash_ctx_mgr - * still need processing. - */ - struct sha512_ctx_mgr *mgr; - struct sha512_hash_ctx *ctx; - unsigned long flags; - - mgr = cstate->mgr; - spin_lock_irqsave(&cstate->work_lock, flags); - ctx = (struct sha512_hash_ctx *) - sha512_job_mgr_get_comp_job(&mgr->mgr); - ctx = sha512_ctx_mgr_resubmit(mgr, ctx); - spin_unlock_irqrestore(&cstate->work_lock, flags); - return ctx; -} - -static void sha512_ctx_mgr_init(struct sha512_ctx_mgr *mgr) -{ - sha512_job_mgr_init(&mgr->mgr); -} - -static struct sha512_hash_ctx - *sha512_ctx_mgr_submit(struct mcryptd_alg_cstate *cstate, - struct sha512_hash_ctx *ctx, - const void *buffer, - uint32_t len, - int flags) -{ - struct sha512_ctx_mgr *mgr; - unsigned long irqflags; - - mgr = cstate->mgr; - spin_lock_irqsave(&cstate->work_lock, irqflags); - if (flags & ~(HASH_UPDATE | HASH_LAST)) { - /* User should not pass anything other than UPDATE or LAST */ - ctx->error = HASH_CTX_ERROR_INVALID_FLAGS; - goto unlock; - } - - if (ctx->status & HASH_CTX_STS_PROCESSING) { - /* Cannot submit to a currently processing job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_PROCESSING; - goto unlock; - } - - if (ctx->status & HASH_CTX_STS_COMPLETE) { - /* Cannot update a finished job. */ - ctx->error = HASH_CTX_ERROR_ALREADY_COMPLETED; - goto unlock; - } - - /* - * If we made it here, there were no errors during this call to - * submit - */ - ctx->error = HASH_CTX_ERROR_NONE; - - /* Store buffer ptr info from user */ - ctx->incoming_buffer = buffer; - ctx->incoming_buffer_length = len; - - /* - * Store the user's request flags and mark this ctx as currently being - * processed. - */ - ctx->status = (flags & HASH_LAST) ? - (HASH_CTX_STS_PROCESSING | HASH_CTX_STS_LAST) : - HASH_CTX_STS_PROCESSING; - - /* Advance byte counter */ - ctx->total_length += len; - - /* - * If there is anything currently buffered in the extra blocks, - * append to it until it contains a whole block. - * Or if the user's buffer contains less than a whole block, - * append as much as possible to the extra block. - */ - if (ctx->partial_block_buffer_length || len < SHA512_BLOCK_SIZE) { - /* Compute how many bytes to copy from user buffer into extra - * block - */ - uint32_t copy_len = SHA512_BLOCK_SIZE - - ctx->partial_block_buffer_length; - if (len < copy_len) - copy_len = len; - - if (copy_len) { - /* Copy and update relevant pointers and counters */ - memcpy - (&ctx->partial_block_buffer[ctx->partial_block_buffer_length], - buffer, copy_len); - - ctx->partial_block_buffer_length += copy_len; - ctx->incoming_buffer = (const void *) - ((const char *)buffer + copy_len); - ctx->incoming_buffer_length = len - copy_len; - } - - /* The extra block should never contain more than 1 block - * here - */ - assert(ctx->partial_block_buffer_length <= SHA512_BLOCK_SIZE); - - /* If the extra block buffer contains exactly 1 block, it can - * be hashed. - */ - if (ctx->partial_block_buffer_length >= SHA512_BLOCK_SIZE) { - ctx->partial_block_buffer_length = 0; - - ctx->job.buffer = ctx->partial_block_buffer; - ctx->job.len = 1; - ctx = (struct sha512_hash_ctx *) - sha512_job_mgr_submit(&mgr->mgr, &ctx->job); - } - } - - ctx = sha512_ctx_mgr_resubmit(mgr, ctx); -unlock: - spin_unlock_irqrestore(&cstate->work_lock, irqflags); - return ctx; -} - -static struct sha512_hash_ctx *sha512_ctx_mgr_flush(struct mcryptd_alg_cstate *cstate) -{ - struct sha512_ctx_mgr *mgr; - struct sha512_hash_ctx *ctx; - unsigned long flags; - - mgr = cstate->mgr; - spin_lock_irqsave(&cstate->work_lock, flags); - while (1) { - ctx = (struct sha512_hash_ctx *) - sha512_job_mgr_flush(&mgr->mgr); - - /* If flush returned 0, there are no more jobs in flight. */ - if (!ctx) - break; - - /* - * If flush returned a job, resubmit the job to finish - * processing. - */ - ctx = sha512_ctx_mgr_resubmit(mgr, ctx); - - /* - * If sha512_ctx_mgr_resubmit returned a job, it is ready to - * be returned. Otherwise, all jobs currently being managed by - * the sha512_ctx_mgr still need processing. Loop. - */ - if (ctx) - break; - } - spin_unlock_irqrestore(&cstate->work_lock, flags); - return ctx; -} - -static int sha512_mb_init(struct ahash_request *areq) -{ - struct sha512_hash_ctx *sctx = ahash_request_ctx(areq); - - hash_ctx_init(sctx); - sctx->job.result_digest[0] = SHA512_H0; - sctx->job.result_digest[1] = SHA512_H1; - sctx->job.result_digest[2] = SHA512_H2; - sctx->job.result_digest[3] = SHA512_H3; - sctx->job.result_digest[4] = SHA512_H4; - sctx->job.result_digest[5] = SHA512_H5; - sctx->job.result_digest[6] = SHA512_H6; - sctx->job.result_digest[7] = SHA512_H7; - sctx->total_length = 0; - sctx->partial_block_buffer_length = 0; - sctx->status = HASH_CTX_STS_IDLE; - - return 0; -} - -static int sha512_mb_set_results(struct mcryptd_hash_request_ctx *rctx) -{ - int i; - struct sha512_hash_ctx *sctx = ahash_request_ctx(&rctx->areq); - __be64 *dst = (__be64 *) rctx->out; - - for (i = 0; i < 8; ++i) - dst[i] = cpu_to_be64(sctx->job.result_digest[i]); - - return 0; -} - -static int sha_finish_walk(struct mcryptd_hash_request_ctx **ret_rctx, - struct mcryptd_alg_cstate *cstate, bool flush) -{ - int flag = HASH_UPDATE; - int nbytes, err = 0; - struct mcryptd_hash_request_ctx *rctx = *ret_rctx; - struct sha512_hash_ctx *sha_ctx; - - /* more work ? */ - while (!(rctx->flag & HASH_DONE)) { - nbytes = crypto_ahash_walk_done(&rctx->walk, 0); - if (nbytes < 0) { - err = nbytes; - goto out; - } - /* check if the walk is done */ - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - if (rctx->flag & HASH_FINAL) - flag |= HASH_LAST; - - } - sha_ctx = (struct sha512_hash_ctx *) - ahash_request_ctx(&rctx->areq); - kernel_fpu_begin(); - sha_ctx = sha512_ctx_mgr_submit(cstate, sha_ctx, - rctx->walk.data, nbytes, flag); - if (!sha_ctx) { - if (flush) - sha_ctx = sha512_ctx_mgr_flush(cstate); - } - kernel_fpu_end(); - if (sha_ctx) - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - else { - rctx = NULL; - goto out; - } - } - - /* copy the results */ - if (rctx->flag & HASH_FINAL) - sha512_mb_set_results(rctx); - -out: - *ret_rctx = rctx; - return err; -} - -static int sha_complete_job(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate, - int err) -{ - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha512_hash_ctx *sha_ctx; - struct mcryptd_hash_request_ctx *req_ctx; - int ret; - unsigned long flags; - - /* remove from work list */ - spin_lock_irqsave(&cstate->work_lock, flags); - list_del(&rctx->waiter); - spin_unlock_irqrestore(&cstate->work_lock, flags); - - if (irqs_disabled()) - rctx->complete(&req->base, err); - else { - local_bh_disable(); - rctx->complete(&req->base, err); - local_bh_enable(); - } - - /* check to see if there are other jobs that are done */ - sha_ctx = sha512_ctx_mgr_get_comp_ctx(cstate); - while (sha_ctx) { - req_ctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&req_ctx, cstate, false); - if (req_ctx) { - spin_lock_irqsave(&cstate->work_lock, flags); - list_del(&req_ctx->waiter); - spin_unlock_irqrestore(&cstate->work_lock, flags); - - req = cast_mcryptd_ctx_to_req(req_ctx); - if (irqs_disabled()) - req_ctx->complete(&req->base, ret); - else { - local_bh_disable(); - req_ctx->complete(&req->base, ret); - local_bh_enable(); - } - } - sha_ctx = sha512_ctx_mgr_get_comp_ctx(cstate); - } - - return 0; -} - -static void sha512_mb_add_list(struct mcryptd_hash_request_ctx *rctx, - struct mcryptd_alg_cstate *cstate) -{ - unsigned long next_flush; - unsigned long delay = usecs_to_jiffies(FLUSH_INTERVAL); - unsigned long flags; - - /* initialize tag */ - rctx->tag.arrival = jiffies; /* tag the arrival time */ - rctx->tag.seq_num = cstate->next_seq_num++; - next_flush = rctx->tag.arrival + delay; - rctx->tag.expire = next_flush; - - spin_lock_irqsave(&cstate->work_lock, flags); - list_add_tail(&rctx->waiter, &cstate->work_list); - spin_unlock_irqrestore(&cstate->work_lock, flags); - - mcryptd_arm_flusher(cstate, delay); -} - -static int sha512_mb_update(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, - areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha512_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha512_hash_ctx *sha_ctx; - int ret = 0, nbytes; - - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) - rctx->flag |= HASH_DONE; - - /* submit */ - sha_ctx = (struct sha512_hash_ctx *) ahash_request_ctx(areq); - sha512_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha512_ctx_mgr_submit(cstate, sha_ctx, rctx->walk.data, - nbytes, HASH_UPDATE); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha512_mb_finup(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, - areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha512_mb_alg_state.alg_cstate); - - struct ahash_request *req = cast_mcryptd_ctx_to_req(rctx); - struct sha512_hash_ctx *sha_ctx; - int ret = 0, flag = HASH_UPDATE, nbytes; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - nbytes = crypto_ahash_walk_first(req, &rctx->walk); - - if (nbytes < 0) { - ret = nbytes; - goto done; - } - - if (crypto_ahash_walk_last(&rctx->walk)) { - rctx->flag |= HASH_DONE; - flag = HASH_LAST; - } - - /* submit */ - rctx->flag |= HASH_FINAL; - sha_ctx = (struct sha512_hash_ctx *) ahash_request_ctx(areq); - sha512_mb_add_list(rctx, cstate); - - kernel_fpu_begin(); - sha_ctx = sha512_ctx_mgr_submit(cstate, sha_ctx, rctx->walk.data, - nbytes, flag); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha512_mb_final(struct ahash_request *areq) -{ - struct mcryptd_hash_request_ctx *rctx = - container_of(areq, struct mcryptd_hash_request_ctx, - areq); - struct mcryptd_alg_cstate *cstate = - this_cpu_ptr(sha512_mb_alg_state.alg_cstate); - - struct sha512_hash_ctx *sha_ctx; - int ret = 0; - u8 data; - - /* sanity check */ - if (rctx->tag.cpu != smp_processor_id()) { - pr_err("mcryptd error: cpu clash\n"); - goto done; - } - - /* need to init context */ - req_ctx_init(rctx, areq); - - rctx->flag |= HASH_DONE | HASH_FINAL; - - sha_ctx = (struct sha512_hash_ctx *) ahash_request_ctx(areq); - /* flag HASH_FINAL and 0 data size */ - sha512_mb_add_list(rctx, cstate); - kernel_fpu_begin(); - sha_ctx = sha512_ctx_mgr_submit(cstate, sha_ctx, &data, 0, HASH_LAST); - kernel_fpu_end(); - - /* check if anything is returned */ - if (!sha_ctx) - return -EINPROGRESS; - - if (sha_ctx->error) { - ret = sha_ctx->error; - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - goto done; - } - - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - ret = sha_finish_walk(&rctx, cstate, false); - if (!rctx) - return -EINPROGRESS; -done: - sha_complete_job(rctx, cstate, ret); - return ret; -} - -static int sha512_mb_export(struct ahash_request *areq, void *out) -{ - struct sha512_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(out, sctx, sizeof(*sctx)); - - return 0; -} - -static int sha512_mb_import(struct ahash_request *areq, const void *in) -{ - struct sha512_hash_ctx *sctx = ahash_request_ctx(areq); - - memcpy(sctx, in, sizeof(*sctx)); - - return 0; -} - -static int sha512_mb_async_init_tfm(struct crypto_tfm *tfm) -{ - struct mcryptd_ahash *mcryptd_tfm; - struct sha512_mb_ctx *ctx = crypto_tfm_ctx(tfm); - struct mcryptd_hash_ctx *mctx; - - mcryptd_tfm = mcryptd_alloc_ahash("__intel_sha512-mb", - CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL); - if (IS_ERR(mcryptd_tfm)) - return PTR_ERR(mcryptd_tfm); - mctx = crypto_ahash_ctx(&mcryptd_tfm->base); - mctx->alg_state = &sha512_mb_alg_state; - ctx->mcryptd_tfm = mcryptd_tfm; - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - crypto_ahash_reqsize(&mcryptd_tfm->base)); - - return 0; -} - -static void sha512_mb_async_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha512_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static int sha512_mb_areq_init_tfm(struct crypto_tfm *tfm) -{ - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct ahash_request) + - sizeof(struct sha512_hash_ctx)); - - return 0; -} - -static void sha512_mb_areq_exit_tfm(struct crypto_tfm *tfm) -{ - struct sha512_mb_ctx *ctx = crypto_tfm_ctx(tfm); - - mcryptd_free_ahash(ctx->mcryptd_tfm); -} - -static struct ahash_alg sha512_mb_areq_alg = { - .init = sha512_mb_init, - .update = sha512_mb_update, - .final = sha512_mb_final, - .finup = sha512_mb_finup, - .export = sha512_mb_export, - .import = sha512_mb_import, - .halg = { - .digestsize = SHA512_DIGEST_SIZE, - .statesize = sizeof(struct sha512_hash_ctx), - .base = { - .cra_name = "__sha512-mb", - .cra_driver_name = "__intel_sha512-mb", - .cra_priority = 100, - /* - * use ASYNC flag as some buffers in multi-buffer - * algo may not have completed before hashing thread - * sleep - */ - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT - (sha512_mb_areq_alg.halg.base.cra_list), - .cra_init = sha512_mb_areq_init_tfm, - .cra_exit = sha512_mb_areq_exit_tfm, - .cra_ctxsize = sizeof(struct sha512_hash_ctx), - } - } -}; - -static int sha512_mb_async_init(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_init(mcryptd_req); -} - -static int sha512_mb_async_update(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_update(mcryptd_req); -} - -static int sha512_mb_async_finup(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_finup(mcryptd_req); -} - -static int sha512_mb_async_final(struct ahash_request *req) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_final(mcryptd_req); -} - -static int sha512_mb_async_digest(struct ahash_request *req) -{ - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_digest(mcryptd_req); -} - -static int sha512_mb_async_export(struct ahash_request *req, void *out) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - return crypto_ahash_export(mcryptd_req, out); -} - -static int sha512_mb_async_import(struct ahash_request *req, const void *in) -{ - struct ahash_request *mcryptd_req = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sha512_mb_ctx *ctx = crypto_ahash_ctx(tfm); - struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; - struct crypto_ahash *child = mcryptd_ahash_child(mcryptd_tfm); - struct mcryptd_hash_request_ctx *rctx; - struct ahash_request *areq; - - memcpy(mcryptd_req, req, sizeof(*req)); - ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); - rctx = ahash_request_ctx(mcryptd_req); - - areq = &rctx->areq; - - ahash_request_set_tfm(areq, child); - ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_SLEEP, - rctx->complete, req); - - return crypto_ahash_import(mcryptd_req, in); -} - -static struct ahash_alg sha512_mb_async_alg = { - .init = sha512_mb_async_init, - .update = sha512_mb_async_update, - .final = sha512_mb_async_final, - .finup = sha512_mb_async_finup, - .digest = sha512_mb_async_digest, - .export = sha512_mb_async_export, - .import = sha512_mb_async_import, - .halg = { - .digestsize = SHA512_DIGEST_SIZE, - .statesize = sizeof(struct sha512_hash_ctx), - .base = { - .cra_name = "sha512", - .cra_driver_name = "sha512_mb", - /* - * Low priority, since with few concurrent hash requests - * this is extremely slow due to the flush delay. Users - * whose workloads would benefit from this can request - * it explicitly by driver name, or can increase its - * priority at runtime using NETLINK_CRYPTO. - */ - .cra_priority = 50, - .cra_flags = CRYPTO_ALG_ASYNC, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT - (sha512_mb_async_alg.halg.base.cra_list), - .cra_init = sha512_mb_async_init_tfm, - .cra_exit = sha512_mb_async_exit_tfm, - .cra_ctxsize = sizeof(struct sha512_mb_ctx), - .cra_alignmask = 0, - }, - }, -}; - -static unsigned long sha512_mb_flusher(struct mcryptd_alg_cstate *cstate) -{ - struct mcryptd_hash_request_ctx *rctx; - unsigned long cur_time; - unsigned long next_flush = 0; - struct sha512_hash_ctx *sha_ctx; - - - cur_time = jiffies; - - while (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - if time_before(cur_time, rctx->tag.expire) - break; - kernel_fpu_begin(); - sha_ctx = (struct sha512_hash_ctx *) - sha512_ctx_mgr_flush(cstate); - kernel_fpu_end(); - if (!sha_ctx) { - pr_err("sha512_mb error: nothing got flushed for" - " non-empty list\n"); - break; - } - rctx = cast_hash_to_mcryptd_ctx(sha_ctx); - sha_finish_walk(&rctx, cstate, true); - sha_complete_job(rctx, cstate, 0); - } - - if (!list_empty(&cstate->work_list)) { - rctx = list_entry(cstate->work_list.next, - struct mcryptd_hash_request_ctx, waiter); - /* get the hash context and then flush time */ - next_flush = rctx->tag.expire; - mcryptd_arm_flusher(cstate, get_delay(next_flush)); - } - return next_flush; -} - -static int __init sha512_mb_mod_init(void) -{ - - int cpu; - int err; - struct mcryptd_alg_cstate *cpu_state; - - /* check for dependent cpu features */ - if (!boot_cpu_has(X86_FEATURE_AVX2) || - !boot_cpu_has(X86_FEATURE_BMI2)) - return -ENODEV; - - /* initialize multibuffer structures */ - sha512_mb_alg_state.alg_cstate = - alloc_percpu(struct mcryptd_alg_cstate); - - sha512_job_mgr_init = sha512_mb_mgr_init_avx2; - sha512_job_mgr_submit = sha512_mb_mgr_submit_avx2; - sha512_job_mgr_flush = sha512_mb_mgr_flush_avx2; - sha512_job_mgr_get_comp_job = sha512_mb_mgr_get_comp_job_avx2; - - if (!sha512_mb_alg_state.alg_cstate) - return -ENOMEM; - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha512_mb_alg_state.alg_cstate, cpu); - cpu_state->next_flush = 0; - cpu_state->next_seq_num = 0; - cpu_state->flusher_engaged = false; - INIT_DELAYED_WORK(&cpu_state->flush, mcryptd_flusher); - cpu_state->cpu = cpu; - cpu_state->alg_state = &sha512_mb_alg_state; - cpu_state->mgr = kzalloc(sizeof(struct sha512_ctx_mgr), - GFP_KERNEL); - if (!cpu_state->mgr) - goto err2; - sha512_ctx_mgr_init(cpu_state->mgr); - INIT_LIST_HEAD(&cpu_state->work_list); - spin_lock_init(&cpu_state->work_lock); - } - sha512_mb_alg_state.flusher = &sha512_mb_flusher; - - err = crypto_register_ahash(&sha512_mb_areq_alg); - if (err) - goto err2; - err = crypto_register_ahash(&sha512_mb_async_alg); - if (err) - goto err1; - - - return 0; -err1: - crypto_unregister_ahash(&sha512_mb_areq_alg); -err2: - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha512_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha512_mb_alg_state.alg_cstate); - return -ENODEV; -} - -static void __exit sha512_mb_mod_fini(void) -{ - int cpu; - struct mcryptd_alg_cstate *cpu_state; - - crypto_unregister_ahash(&sha512_mb_async_alg); - crypto_unregister_ahash(&sha512_mb_areq_alg); - for_each_possible_cpu(cpu) { - cpu_state = per_cpu_ptr(sha512_mb_alg_state.alg_cstate, cpu); - kfree(cpu_state->mgr); - } - free_percpu(sha512_mb_alg_state.alg_cstate); -} - -module_init(sha512_mb_mod_init); -module_exit(sha512_mb_mod_fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, multi buffer accelerated"); - -MODULE_ALIAS("sha512"); diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h b/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h deleted file mode 100644 index e5c465bd821e..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Header file for multi buffer SHA512 context - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#ifndef _SHA_MB_CTX_INTERNAL_H -#define _SHA_MB_CTX_INTERNAL_H - -#include "sha512_mb_mgr.h" - -#define HASH_UPDATE 0x00 -#define HASH_LAST 0x01 -#define HASH_DONE 0x02 -#define HASH_FINAL 0x04 - -#define HASH_CTX_STS_IDLE 0x00 -#define HASH_CTX_STS_PROCESSING 0x01 -#define HASH_CTX_STS_LAST 0x02 -#define HASH_CTX_STS_COMPLETE 0x04 - -enum hash_ctx_error { - HASH_CTX_ERROR_NONE = 0, - HASH_CTX_ERROR_INVALID_FLAGS = -1, - HASH_CTX_ERROR_ALREADY_PROCESSING = -2, - HASH_CTX_ERROR_ALREADY_COMPLETED = -3, -}; - -#define hash_ctx_user_data(ctx) ((ctx)->user_data) -#define hash_ctx_digest(ctx) ((ctx)->job.result_digest) -#define hash_ctx_processing(ctx) ((ctx)->status & HASH_CTX_STS_PROCESSING) -#define hash_ctx_complete(ctx) ((ctx)->status == HASH_CTX_STS_COMPLETE) -#define hash_ctx_status(ctx) ((ctx)->status) -#define hash_ctx_error(ctx) ((ctx)->error) -#define hash_ctx_init(ctx) \ - do { \ - (ctx)->error = HASH_CTX_ERROR_NONE; \ - (ctx)->status = HASH_CTX_STS_COMPLETE; \ - } while (0) - -/* Hash Constants and Typedefs */ -#define SHA512_DIGEST_LENGTH 8 -#define SHA512_LOG2_BLOCK_SIZE 7 - -#define SHA512_PADLENGTHFIELD_SIZE 16 - -#ifdef SHA_MB_DEBUG -#define assert(expr) \ -do { \ - if (unlikely(!(expr))) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ - } \ -} while (0) -#else -#define assert(expr) do {} while (0) -#endif - -struct sha512_ctx_mgr { - struct sha512_mb_mgr mgr; -}; - -/* typedef struct sha512_ctx_mgr sha512_ctx_mgr; */ - -struct sha512_hash_ctx { - /* Must be at struct offset 0 */ - struct job_sha512 job; - /* status flag */ - int status; - /* error flag */ - int error; - - uint64_t total_length; - const void *incoming_buffer; - uint32_t incoming_buffer_length; - uint8_t partial_block_buffer[SHA512_BLOCK_SIZE * 2]; - uint32_t partial_block_buffer_length; - void *user_data; -}; - -#endif diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr.h b/arch/x86/crypto/sha512-mb/sha512_mb_mgr.h deleted file mode 100644 index 178f17eef382..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Header file for multi buffer SHA512 algorithm manager - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#ifndef __SHA_MB_MGR_H -#define __SHA_MB_MGR_H - -#include <linux/types.h> - -#define NUM_SHA512_DIGEST_WORDS 8 - -enum job_sts {STS_UNKNOWN = 0, - STS_BEING_PROCESSED = 1, - STS_COMPLETED = 2, - STS_INTERNAL_ERROR = 3, - STS_ERROR = 4 -}; - -struct job_sha512 { - u8 *buffer; - u64 len; - u64 result_digest[NUM_SHA512_DIGEST_WORDS] __aligned(32); - enum job_sts status; - void *user_data; -}; - -struct sha512_args_x4 { - uint64_t digest[8][4]; - uint8_t *data_ptr[4]; -}; - -struct sha512_lane_data { - struct job_sha512 *job_in_lane; -}; - -struct sha512_mb_mgr { - struct sha512_args_x4 args; - - uint64_t lens[4]; - - /* each byte is index (0...7) of unused lanes */ - uint64_t unused_lanes; - /* byte 4 is set to FF as a flag */ - struct sha512_lane_data ldata[4]; -}; - -#define SHA512_MB_MGR_NUM_LANES_AVX2 4 - -void sha512_mb_mgr_init_avx2(struct sha512_mb_mgr *state); -struct job_sha512 *sha512_mb_mgr_submit_avx2(struct sha512_mb_mgr *state, - struct job_sha512 *job); -struct job_sha512 *sha512_mb_mgr_flush_avx2(struct sha512_mb_mgr *state); -struct job_sha512 *sha512_mb_mgr_get_comp_job_avx2(struct sha512_mb_mgr *state); - -#endif diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_datastruct.S b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_datastruct.S deleted file mode 100644 index cf2636d4c9ba..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_datastruct.S +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Header file for multi buffer SHA256 algorithm data structure - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -# Macros for defining data structures - -# Usage example - -#START_FIELDS # JOB_AES -### name size align -#FIELD _plaintext, 8, 8 # pointer to plaintext -#FIELD _ciphertext, 8, 8 # pointer to ciphertext -#FIELD _IV, 16, 8 # IV -#FIELD _keys, 8, 8 # pointer to keys -#FIELD _len, 4, 4 # length in bytes -#FIELD _status, 4, 4 # status enumeration -#FIELD _user_data, 8, 8 # pointer to user data -#UNION _union, size1, align1, \ -# size2, align2, \ -# size3, align3, \ -# ... -#END_FIELDS -#%assign _JOB_AES_size _FIELD_OFFSET -#%assign _JOB_AES_align _STRUCT_ALIGN - -######################################################################### - -# Alternate "struc-like" syntax: -# STRUCT job_aes2 -# RES_Q .plaintext, 1 -# RES_Q .ciphertext, 1 -# RES_DQ .IV, 1 -# RES_B .nested, _JOB_AES_SIZE, _JOB_AES_ALIGN -# RES_U .union, size1, align1, \ -# size2, align2, \ -# ... -# ENDSTRUCT -# # Following only needed if nesting -# %assign job_aes2_size _FIELD_OFFSET -# %assign job_aes2_align _STRUCT_ALIGN -# -# RES_* macros take a name, a count and an optional alignment. -# The count in in terms of the base size of the macro, and the -# default alignment is the base size. -# The macros are: -# Macro Base size -# RES_B 1 -# RES_W 2 -# RES_D 4 -# RES_Q 8 -# RES_DQ 16 -# RES_Y 32 -# RES_Z 64 -# -# RES_U defines a union. It's arguments are a name and two or more -# pairs of "size, alignment" -# -# The two assigns are only needed if this structure is being nested -# within another. Even if the assigns are not done, one can still use -# STRUCT_NAME_size as the size of the structure. -# -# Note that for nesting, you still need to assign to STRUCT_NAME_size. -# -# The differences between this and using "struc" directly are that each -# type is implicitly aligned to its natural length (although this can be -# over-ridden with an explicit third parameter), and that the structure -# is padded at the end to its overall alignment. -# - -######################################################################### - -#ifndef _DATASTRUCT_ASM_ -#define _DATASTRUCT_ASM_ - -#define PTR_SZ 8 -#define SHA512_DIGEST_WORD_SIZE 8 -#define SHA512_MB_MGR_NUM_LANES_AVX2 4 -#define NUM_SHA512_DIGEST_WORDS 8 -#define SZ4 4*SHA512_DIGEST_WORD_SIZE -#define ROUNDS 80*SZ4 -#define SHA512_DIGEST_ROW_SIZE (SHA512_MB_MGR_NUM_LANES_AVX2 * 8) - -# START_FIELDS -.macro START_FIELDS - _FIELD_OFFSET = 0 - _STRUCT_ALIGN = 0 -.endm - -# FIELD name size align -.macro FIELD name size align - _FIELD_OFFSET = (_FIELD_OFFSET + (\align) - 1) & (~ ((\align)-1)) - \name = _FIELD_OFFSET - _FIELD_OFFSET = _FIELD_OFFSET + (\size) -.if (\align > _STRUCT_ALIGN) - _STRUCT_ALIGN = \align -.endif -.endm - -# END_FIELDS -.macro END_FIELDS - _FIELD_OFFSET = (_FIELD_OFFSET + _STRUCT_ALIGN-1) & (~ (_STRUCT_ALIGN-1)) -.endm - -.macro STRUCT p1 -START_FIELDS -.struc \p1 -.endm - -.macro ENDSTRUCT - tmp = _FIELD_OFFSET - END_FIELDS - tmp = (_FIELD_OFFSET - ##tmp) -.if (tmp > 0) - .lcomm tmp -.endm - -## RES_int name size align -.macro RES_int p1 p2 p3 - name = \p1 - size = \p2 - align = .\p3 - - _FIELD_OFFSET = (_FIELD_OFFSET + (align) - 1) & (~ ((align)-1)) -.align align -.lcomm name size - _FIELD_OFFSET = _FIELD_OFFSET + (size) -.if (align > _STRUCT_ALIGN) - _STRUCT_ALIGN = align -.endif -.endm - -# macro RES_B name, size [, align] -.macro RES_B _name, _size, _align=1 -RES_int _name _size _align -.endm - -# macro RES_W name, size [, align] -.macro RES_W _name, _size, _align=2 -RES_int _name 2*(_size) _align -.endm - -# macro RES_D name, size [, align] -.macro RES_D _name, _size, _align=4 -RES_int _name 4*(_size) _align -.endm - -# macro RES_Q name, size [, align] -.macro RES_Q _name, _size, _align=8 -RES_int _name 8*(_size) _align -.endm - -# macro RES_DQ name, size [, align] -.macro RES_DQ _name, _size, _align=16 -RES_int _name 16*(_size) _align -.endm - -# macro RES_Y name, size [, align] -.macro RES_Y _name, _size, _align=32 -RES_int _name 32*(_size) _align -.endm - -# macro RES_Z name, size [, align] -.macro RES_Z _name, _size, _align=64 -RES_int _name 64*(_size) _align -.endm - -#endif - -################################################################### -### Define SHA512 Out Of Order Data Structures -################################################################### - -START_FIELDS # LANE_DATA -### name size align -FIELD _job_in_lane, 8, 8 # pointer to job object -END_FIELDS - - _LANE_DATA_size = _FIELD_OFFSET - _LANE_DATA_align = _STRUCT_ALIGN - -#################################################################### - -START_FIELDS # SHA512_ARGS_X4 -### name size align -FIELD _digest, 8*8*4, 4 # transposed digest -FIELD _data_ptr, 8*4, 8 # array of pointers to data -END_FIELDS - - _SHA512_ARGS_X4_size = _FIELD_OFFSET - _SHA512_ARGS_X4_align = _STRUCT_ALIGN - -##################################################################### - -START_FIELDS # MB_MGR -### name size align -FIELD _args, _SHA512_ARGS_X4_size, _SHA512_ARGS_X4_align -FIELD _lens, 8*4, 8 -FIELD _unused_lanes, 8, 8 -FIELD _ldata, _LANE_DATA_size*4, _LANE_DATA_align -END_FIELDS - - _MB_MGR_size = _FIELD_OFFSET - _MB_MGR_align = _STRUCT_ALIGN - -_args_digest = _args + _digest -_args_data_ptr = _args + _data_ptr - -####################################################################### - -####################################################################### -#### Define constants -####################################################################### - -#define STS_UNKNOWN 0 -#define STS_BEING_PROCESSED 1 -#define STS_COMPLETED 2 - -####################################################################### -#### Define JOB_SHA512 structure -####################################################################### - -START_FIELDS # JOB_SHA512 -### name size align -FIELD _buffer, 8, 8 # pointer to buffer -FIELD _len, 8, 8 # length in bytes -FIELD _result_digest, 8*8, 32 # Digest (output) -FIELD _status, 4, 4 -FIELD _user_data, 8, 8 -END_FIELDS - - _JOB_SHA512_size = _FIELD_OFFSET - _JOB_SHA512_align = _STRUCT_ALIGN diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_flush_avx2.S deleted file mode 100644 index 7c629caebc05..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_flush_avx2.S +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Flush routine for SHA512 multibuffer - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha512_mb_mgr_datastruct.S" - -.extern sha512_x4_avx2 - -# LINUX register definitions -#define arg1 %rdi -#define arg2 %rsi - -# idx needs to be other than arg1, arg2, rbx, r12 -#define idx %rdx - -# Common definitions -#define state arg1 -#define job arg2 -#define len2 arg2 - -#define unused_lanes %rbx -#define lane_data %rbx -#define tmp2 %rbx - -#define job_rax %rax -#define tmp1 %rax -#define size_offset %rax -#define tmp %rax -#define start_offset %rax - -#define tmp3 arg1 - -#define extra_blocks arg2 -#define p arg2 - -#define tmp4 %r8 -#define lens0 %r8 - -#define lens1 %r9 -#define lens2 %r10 -#define lens3 %r11 - -.macro LABEL prefix n -\prefix\n\(): -.endm - -.macro JNE_SKIP i -jne skip_\i -.endm - -.altmacro -.macro SET_OFFSET _offset -offset = \_offset -.endm -.noaltmacro - -# JOB* sha512_mb_mgr_flush_avx2(MB_MGR *state) -# arg 1 : rcx : state -ENTRY(sha512_mb_mgr_flush_avx2) - FRAME_BEGIN - push %rbx - - # If bit (32+3) is set, then all lanes are empty - mov _unused_lanes(state), unused_lanes - bt $32+7, unused_lanes - jc return_null - - # find a lane with a non-null job - xor idx, idx - offset = (_ldata + 1*_LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne one(%rip), idx - offset = (_ldata + 2*_LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne two(%rip), idx - offset = (_ldata + 3*_LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) - cmovne three(%rip), idx - - # copy idx to empty lanes -copy_lane_data: - offset = (_args + _data_ptr) - mov offset(state,idx,8), tmp - - I = 0 -.rep 4 - offset = (_ldata + I * _LANE_DATA_size + _job_in_lane) - cmpq $0, offset(state) -.altmacro - JNE_SKIP %I - offset = (_args + _data_ptr + 8*I) - mov tmp, offset(state) - offset = (_lens + 8*I +4) - movl $0xFFFFFFFF, offset(state) -LABEL skip_ %I - I = (I+1) -.noaltmacro -.endr - - # Find min length - mov _lens + 0*8(state),lens0 - mov lens0,idx - mov _lens + 1*8(state),lens1 - cmp idx,lens1 - cmovb lens1,idx - mov _lens + 2*8(state),lens2 - cmp idx,lens2 - cmovb lens2,idx - mov _lens + 3*8(state),lens3 - cmp idx,lens3 - cmovb lens3,idx - mov idx,len2 - and $0xF,idx - and $~0xFF,len2 - jz len_is_0 - - sub len2, lens0 - sub len2, lens1 - sub len2, lens2 - sub len2, lens3 - shr $32,len2 - mov lens0, _lens + 0*8(state) - mov lens1, _lens + 1*8(state) - mov lens2, _lens + 2*8(state) - mov lens3, _lens + 3*8(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha512_x4_avx2 - # state and idx are intact - -len_is_0: - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $8, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens+4(state, idx, 8) - - vmovq _args_digest+0*32(state, idx, 8), %xmm0 - vpinsrq $1, _args_digest+1*32(state, idx, 8), %xmm0, %xmm0 - vmovq _args_digest+2*32(state, idx, 8), %xmm1 - vpinsrq $1, _args_digest+3*32(state, idx, 8), %xmm1, %xmm1 - vmovq _args_digest+4*32(state, idx, 8), %xmm2 - vpinsrq $1, _args_digest+5*32(state, idx, 8), %xmm2, %xmm2 - vmovq _args_digest+6*32(state, idx, 8), %xmm3 - vpinsrq $1, _args_digest+7*32(state, idx, 8), %xmm3, %xmm3 - - vmovdqu %xmm0, _result_digest(job_rax) - vmovdqu %xmm1, _result_digest+1*16(job_rax) - vmovdqu %xmm2, _result_digest+2*16(job_rax) - vmovdqu %xmm3, _result_digest+3*16(job_rax) - -return: - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return -ENDPROC(sha512_mb_mgr_flush_avx2) -.align 16 - -ENTRY(sha512_mb_mgr_get_comp_job_avx2) - push %rbx - - mov _unused_lanes(state), unused_lanes - bt $(32+7), unused_lanes - jc .return_null - - # Find min length - mov _lens(state),lens0 - mov lens0,idx - mov _lens+1*8(state),lens1 - cmp idx,lens1 - cmovb lens1,idx - mov _lens+2*8(state),lens2 - cmp idx,lens2 - cmovb lens2,idx - mov _lens+3*8(state),lens3 - cmp idx,lens3 - cmovb lens3,idx - test $~0xF,idx - jnz .return_null - and $0xF,idx - - #process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - mov _unused_lanes(state), unused_lanes - shl $8, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF, _lens+4(state, idx, 8) - - vmovq _args_digest(state, idx, 8), %xmm0 - vpinsrq $1, _args_digest+1*32(state, idx, 8), %xmm0, %xmm0 - vmovq _args_digest+2*32(state, idx, 8), %xmm1 - vpinsrq $1, _args_digest+3*32(state, idx, 8), %xmm1, %xmm1 - vmovq _args_digest+4*32(state, idx, 8), %xmm2 - vpinsrq $1, _args_digest+5*32(state, idx, 8), %xmm2, %xmm2 - vmovq _args_digest+6*32(state, idx, 8), %xmm3 - vpinsrq $1, _args_digest+7*32(state, idx, 8), %xmm3, %xmm3 - - vmovdqu %xmm0, _result_digest+0*16(job_rax) - vmovdqu %xmm1, _result_digest+1*16(job_rax) - vmovdqu %xmm2, _result_digest+2*16(job_rax) - vmovdqu %xmm3, _result_digest+3*16(job_rax) - - pop %rbx - - ret - -.return_null: - xor job_rax, job_rax - pop %rbx - ret -ENDPROC(sha512_mb_mgr_get_comp_job_avx2) - -.section .rodata.cst8.one, "aM", @progbits, 8 -.align 8 -one: -.quad 1 - -.section .rodata.cst8.two, "aM", @progbits, 8 -.align 8 -two: -.quad 2 - -.section .rodata.cst8.three, "aM", @progbits, 8 -.align 8 -three: -.quad 3 diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c deleted file mode 100644 index d08805032f01..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Initialization code for multi buffer SHA256 algorithm for AVX2 - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include "sha512_mb_mgr.h" - -void sha512_mb_mgr_init_avx2(struct sha512_mb_mgr *state) -{ - unsigned int j; - - /* initially all lanes are unused */ - state->lens[0] = 0xFFFFFFFF00000000; - state->lens[1] = 0xFFFFFFFF00000001; - state->lens[2] = 0xFFFFFFFF00000002; - state->lens[3] = 0xFFFFFFFF00000003; - - state->unused_lanes = 0xFF03020100; - for (j = 0; j < 4; j++) - state->ldata[j].job_in_lane = NULL; -} diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_submit_avx2.S b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_submit_avx2.S deleted file mode 100644 index 4ba709ba78e5..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_submit_avx2.S +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Buffer submit code for multi buffer SHA512 algorithm - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -#include <linux/linkage.h> -#include <asm/frame.h> -#include "sha512_mb_mgr_datastruct.S" - -.extern sha512_x4_avx2 - -#define arg1 %rdi -#define arg2 %rsi - -#define idx %rdx -#define last_len %rdx - -#define size_offset %rcx -#define tmp2 %rcx - -# Common definitions -#define state arg1 -#define job arg2 -#define len2 arg2 -#define p2 arg2 - -#define p %r11 -#define start_offset %r11 - -#define unused_lanes %rbx - -#define job_rax %rax -#define len %rax - -#define lane %r12 -#define tmp3 %r12 -#define lens3 %r12 - -#define extra_blocks %r8 -#define lens0 %r8 - -#define tmp %r9 -#define lens1 %r9 - -#define lane_data %r10 -#define lens2 %r10 - -#define DWORD_len %eax - -# JOB* sha512_mb_mgr_submit_avx2(MB_MGR *state, JOB *job) -# arg 1 : rcx : state -# arg 2 : rdx : job -ENTRY(sha512_mb_mgr_submit_avx2) - FRAME_BEGIN - push %rbx - push %r12 - - mov _unused_lanes(state), unused_lanes - movzb %bl,lane - shr $8, unused_lanes - imul $_LANE_DATA_size, lane,lane_data - movl $STS_BEING_PROCESSED, _status(job) - lea _ldata(state, lane_data), lane_data - mov unused_lanes, _unused_lanes(state) - movl _len(job), DWORD_len - - mov job, _job_in_lane(lane_data) - movl DWORD_len,_lens+4(state , lane, 8) - - # Load digest words from result_digest - vmovdqu _result_digest+0*16(job), %xmm0 - vmovdqu _result_digest+1*16(job), %xmm1 - vmovdqu _result_digest+2*16(job), %xmm2 - vmovdqu _result_digest+3*16(job), %xmm3 - - vmovq %xmm0, _args_digest(state, lane, 8) - vpextrq $1, %xmm0, _args_digest+1*32(state , lane, 8) - vmovq %xmm1, _args_digest+2*32(state , lane, 8) - vpextrq $1, %xmm1, _args_digest+3*32(state , lane, 8) - vmovq %xmm2, _args_digest+4*32(state , lane, 8) - vpextrq $1, %xmm2, _args_digest+5*32(state , lane, 8) - vmovq %xmm3, _args_digest+6*32(state , lane, 8) - vpextrq $1, %xmm3, _args_digest+7*32(state , lane, 8) - - mov _buffer(job), p - mov p, _args_data_ptr(state, lane, 8) - - cmp $0xFF, unused_lanes - jne return_null - -start_loop: - - # Find min length - mov _lens+0*8(state),lens0 - mov lens0,idx - mov _lens+1*8(state),lens1 - cmp idx,lens1 - cmovb lens1, idx - mov _lens+2*8(state),lens2 - cmp idx,lens2 - cmovb lens2,idx - mov _lens+3*8(state),lens3 - cmp idx,lens3 - cmovb lens3,idx - mov idx,len2 - and $0xF,idx - and $~0xFF,len2 - jz len_is_0 - - sub len2,lens0 - sub len2,lens1 - sub len2,lens2 - sub len2,lens3 - shr $32,len2 - mov lens0, _lens + 0*8(state) - mov lens1, _lens + 1*8(state) - mov lens2, _lens + 2*8(state) - mov lens3, _lens + 3*8(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 - call sha512_x4_avx2 - # state and idx are intact - -len_is_0: - - # process completed job "idx" - imul $_LANE_DATA_size, idx, lane_data - lea _ldata(state, lane_data), lane_data - - mov _job_in_lane(lane_data), job_rax - mov _unused_lanes(state), unused_lanes - movq $0, _job_in_lane(lane_data) - movl $STS_COMPLETED, _status(job_rax) - shl $8, unused_lanes - or idx, unused_lanes - mov unused_lanes, _unused_lanes(state) - - movl $0xFFFFFFFF,_lens+4(state,idx,8) - vmovq _args_digest+0*32(state , idx, 8), %xmm0 - vpinsrq $1, _args_digest+1*32(state , idx, 8), %xmm0, %xmm0 - vmovq _args_digest+2*32(state , idx, 8), %xmm1 - vpinsrq $1, _args_digest+3*32(state , idx, 8), %xmm1, %xmm1 - vmovq _args_digest+4*32(state , idx, 8), %xmm2 - vpinsrq $1, _args_digest+5*32(state , idx, 8), %xmm2, %xmm2 - vmovq _args_digest+6*32(state , idx, 8), %xmm3 - vpinsrq $1, _args_digest+7*32(state , idx, 8), %xmm3, %xmm3 - - vmovdqu %xmm0, _result_digest + 0*16(job_rax) - vmovdqu %xmm1, _result_digest + 1*16(job_rax) - vmovdqu %xmm2, _result_digest + 2*16(job_rax) - vmovdqu %xmm3, _result_digest + 3*16(job_rax) - -return: - pop %r12 - pop %rbx - FRAME_END - ret - -return_null: - xor job_rax, job_rax - jmp return -ENDPROC(sha512_mb_mgr_submit_avx2) - -/* UNUSED? -.section .rodata.cst16, "aM", @progbits, 16 -.align 16 -H0: .int 0x6a09e667 -H1: .int 0xbb67ae85 -H2: .int 0x3c6ef372 -H3: .int 0xa54ff53a -H4: .int 0x510e527f -H5: .int 0x9b05688c -H6: .int 0x1f83d9ab -H7: .int 0x5be0cd19 -*/ diff --git a/arch/x86/crypto/sha512-mb/sha512_x4_avx2.S b/arch/x86/crypto/sha512-mb/sha512_x4_avx2.S deleted file mode 100644 index e22e907643a6..000000000000 --- a/arch/x86/crypto/sha512-mb/sha512_x4_avx2.S +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Multi-buffer SHA512 algorithm hash compute routine - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact Information: - * Megha Dey <megha.dey@linux.intel.com> - * - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. - * - * 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 Intel 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. - */ - -# code to compute quad SHA512 using AVX2 -# use YMMs to tackle the larger digest size -# outer calling routine takes care of save and restore of XMM registers -# Logic designed/laid out by JDG - -# Function clobbers: rax, rcx, rdx, rbx, rsi, rdi, r9-r15; ymm0-15 -# Stack must be aligned to 32 bytes before call -# Linux clobbers: rax rbx rcx rsi r8 r9 r10 r11 r12 -# Linux preserves: rcx rdx rdi rbp r13 r14 r15 -# clobbers ymm0-15 - -#include <linux/linkage.h> -#include "sha512_mb_mgr_datastruct.S" - -arg1 = %rdi -arg2 = %rsi - -# Common definitions -STATE = arg1 -INP_SIZE = arg2 - -IDX = %rax -ROUND = %rbx -TBL = %r8 - -inp0 = %r9 -inp1 = %r10 -inp2 = %r11 -inp3 = %r12 - -a = %ymm0 -b = %ymm1 -c = %ymm2 -d = %ymm3 -e = %ymm4 -f = %ymm5 -g = %ymm6 -h = %ymm7 - -a0 = %ymm8 -a1 = %ymm9 -a2 = %ymm10 - -TT0 = %ymm14 -TT1 = %ymm13 -TT2 = %ymm12 -TT3 = %ymm11 -TT4 = %ymm10 -TT5 = %ymm9 - -T1 = %ymm14 -TMP = %ymm15 - -# Define stack usage -STACK_SPACE1 = SZ4*16 + NUM_SHA512_DIGEST_WORDS*SZ4 + 24 - -#define VMOVPD vmovupd -_digest = SZ4*16 - -# transpose r0, r1, r2, r3, t0, t1 -# "transpose" data in {r0..r3} using temps {t0..t3} -# Input looks like: {r0 r1 r2 r3} -# r0 = {a7 a6 a5 a4 a3 a2 a1 a0} -# r1 = {b7 b6 b5 b4 b3 b2 b1 b0} -# r2 = {c7 c6 c5 c4 c3 c2 c1 c0} -# r3 = {d7 d6 d5 d4 d3 d2 d1 d0} -# -# output looks like: {t0 r1 r0 r3} -# t0 = {d1 d0 c1 c0 b1 b0 a1 a0} -# r1 = {d3 d2 c3 c2 b3 b2 a3 a2} -# r0 = {d5 d4 c5 c4 b5 b4 a5 a4} -# r3 = {d7 d6 c7 c6 b7 b6 a7 a6} - -.macro TRANSPOSE r0 r1 r2 r3 t0 t1 - vshufps $0x44, \r1, \r0, \t0 # t0 = {b5 b4 a5 a4 b1 b0 a1 a0} - vshufps $0xEE, \r1, \r0, \r0 # r0 = {b7 b6 a7 a6 b3 b2 a3 a2} - vshufps $0x44, \r3, \r2, \t1 # t1 = {d5 d4 c5 c4 d1 d0 c1 c0} - vshufps $0xEE, \r3, \r2, \r2 # r2 = {d7 d6 c7 c6 d3 d2 c3 c2} - - vperm2f128 $0x20, \r2, \r0, \r1 # h6...a6 - vperm2f128 $0x31, \r2, \r0, \r3 # h2...a2 - vperm2f128 $0x31, \t1, \t0, \r0 # h5...a5 - vperm2f128 $0x20, \t1, \t0, \t0 # h1...a1 -.endm - -.macro ROTATE_ARGS -TMP_ = h -h = g -g = f -f = e -e = d -d = c -c = b -b = a -a = TMP_ -.endm - -# PRORQ reg, imm, tmp -# packed-rotate-right-double -# does a rotate by doing two shifts and an or -.macro _PRORQ reg imm tmp - vpsllq $(64-\imm),\reg,\tmp - vpsrlq $\imm,\reg, \reg - vpor \tmp,\reg, \reg -.endm - -# non-destructive -# PRORQ_nd reg, imm, tmp, src -.macro _PRORQ_nd reg imm tmp src - vpsllq $(64-\imm), \src, \tmp - vpsrlq $\imm, \src, \reg - vpor \tmp, \reg, \reg -.endm - -# PRORQ dst/src, amt -.macro PRORQ reg imm - _PRORQ \reg, \imm, TMP -.endm - -# PRORQ_nd dst, src, amt -.macro PRORQ_nd reg tmp imm - _PRORQ_nd \reg, \imm, TMP, \tmp -.endm - -#; arguments passed implicitly in preprocessor symbols i, a...h -.macro ROUND_00_15 _T1 i - PRORQ_nd a0, e, (18-14) # sig1: a0 = (e >> 4) - - vpxor g, f, a2 # ch: a2 = f^g - vpand e,a2, a2 # ch: a2 = (f^g)&e - vpxor g, a2, a2 # a2 = ch - - PRORQ_nd a1,e,41 # sig1: a1 = (e >> 25) - - offset = SZ4*(\i & 0xf) - vmovdqu \_T1,offset(%rsp) - vpaddq (TBL,ROUND,1), \_T1, \_T1 # T1 = W + K - vpxor e,a0, a0 # sig1: a0 = e ^ (e >> 5) - PRORQ a0, 14 # sig1: a0 = (e >> 6) ^ (e >> 11) - vpaddq a2, h, h # h = h + ch - PRORQ_nd a2,a,6 # sig0: a2 = (a >> 11) - vpaddq \_T1,h, h # h = h + ch + W + K - vpxor a1, a0, a0 # a0 = sigma1 - vmovdqu a,\_T1 - PRORQ_nd a1,a,39 # sig0: a1 = (a >> 22) - vpxor c, \_T1, \_T1 # maj: T1 = a^c - add $SZ4, ROUND # ROUND++ - vpand b, \_T1, \_T1 # maj: T1 = (a^c)&b - vpaddq a0, h, h - vpaddq h, d, d - vpxor a, a2, a2 # sig0: a2 = a ^ (a >> 11) - PRORQ a2,28 # sig0: a2 = (a >> 2) ^ (a >> 13) - vpxor a1, a2, a2 # a2 = sig0 - vpand c, a, a1 # maj: a1 = a&c - vpor \_T1, a1, a1 # a1 = maj - vpaddq a1, h, h # h = h + ch + W + K + maj - vpaddq a2, h, h # h = h + ch + W + K + maj + sigma0 - ROTATE_ARGS -.endm - - -#; arguments passed implicitly in preprocessor symbols i, a...h -.macro ROUND_16_XX _T1 i - vmovdqu SZ4*((\i-15)&0xf)(%rsp), \_T1 - vmovdqu SZ4*((\i-2)&0xf)(%rsp), a1 - vmovdqu \_T1, a0 - PRORQ \_T1,7 - vmovdqu a1, a2 - PRORQ a1,42 - vpxor a0, \_T1, \_T1 - PRORQ \_T1, 1 - vpxor a2, a1, a1 - PRORQ a1, 19 - vpsrlq $7, a0, a0 - vpxor a0, \_T1, \_T1 - vpsrlq $6, a2, a2 - vpxor a2, a1, a1 - vpaddq SZ4*((\i-16)&0xf)(%rsp), \_T1, \_T1 - vpaddq SZ4*((\i-7)&0xf)(%rsp), a1, a1 - vpaddq a1, \_T1, \_T1 - - ROUND_00_15 \_T1,\i -.endm - - -# void sha512_x4_avx2(void *STATE, const int INP_SIZE) -# arg 1 : STATE : pointer to input data -# arg 2 : INP_SIZE : size of data in blocks (assumed >= 1) -ENTRY(sha512_x4_avx2) - # general registers preserved in outer calling routine - # outer calling routine saves all the XMM registers - # save callee-saved clobbered registers to comply with C function ABI - push %r12 - push %r13 - push %r14 - push %r15 - - sub $STACK_SPACE1, %rsp - - # Load the pre-transposed incoming digest. - vmovdqu 0*SHA512_DIGEST_ROW_SIZE(STATE),a - vmovdqu 1*SHA512_DIGEST_ROW_SIZE(STATE),b - vmovdqu 2*SHA512_DIGEST_ROW_SIZE(STATE),c - vmovdqu 3*SHA512_DIGEST_ROW_SIZE(STATE),d - vmovdqu 4*SHA512_DIGEST_ROW_SIZE(STATE),e - vmovdqu 5*SHA512_DIGEST_ROW_SIZE(STATE),f - vmovdqu 6*SHA512_DIGEST_ROW_SIZE(STATE),g - vmovdqu 7*SHA512_DIGEST_ROW_SIZE(STATE),h - - lea K512_4(%rip),TBL - - # load the address of each of the 4 message lanes - # getting ready to transpose input onto stack - mov _data_ptr+0*PTR_SZ(STATE),inp0 - mov _data_ptr+1*PTR_SZ(STATE),inp1 - mov _data_ptr+2*PTR_SZ(STATE),inp2 - mov _data_ptr+3*PTR_SZ(STATE),inp3 - - xor IDX, IDX -lloop: - xor ROUND, ROUND - - # save old digest - vmovdqu a, _digest(%rsp) - vmovdqu b, _digest+1*SZ4(%rsp) - vmovdqu c, _digest+2*SZ4(%rsp) - vmovdqu d, _digest+3*SZ4(%rsp) - vmovdqu e, _digest+4*SZ4(%rsp) - vmovdqu f, _digest+5*SZ4(%rsp) - vmovdqu g, _digest+6*SZ4(%rsp) - vmovdqu h, _digest+7*SZ4(%rsp) - i = 0 -.rep 4 - vmovdqu PSHUFFLE_BYTE_FLIP_MASK(%rip), TMP - VMOVPD i*32(inp0, IDX), TT2 - VMOVPD i*32(inp1, IDX), TT1 - VMOVPD i*32(inp2, IDX), TT4 - VMOVPD i*32(inp3, IDX), TT3 - TRANSPOSE TT2, TT1, TT4, TT3, TT0, TT5 - vpshufb TMP, TT0, TT0 - vpshufb TMP, TT1, TT1 - vpshufb TMP, TT2, TT2 - vpshufb TMP, TT3, TT3 - ROUND_00_15 TT0,(i*4+0) - ROUND_00_15 TT1,(i*4+1) - ROUND_00_15 TT2,(i*4+2) - ROUND_00_15 TT3,(i*4+3) - i = (i+1) -.endr - add $128, IDX - - i = (i*4) - - jmp Lrounds_16_xx -.align 16 -Lrounds_16_xx: -.rep 16 - ROUND_16_XX T1, i - i = (i+1) -.endr - cmp $0xa00,ROUND - jb Lrounds_16_xx - - # add old digest - vpaddq _digest(%rsp), a, a - vpaddq _digest+1*SZ4(%rsp), b, b - vpaddq _digest+2*SZ4(%rsp), c, c - vpaddq _digest+3*SZ4(%rsp), d, d - vpaddq _digest+4*SZ4(%rsp), e, e - vpaddq _digest+5*SZ4(%rsp), f, f - vpaddq _digest+6*SZ4(%rsp), g, g - vpaddq _digest+7*SZ4(%rsp), h, h - - sub $1, INP_SIZE # unit is blocks - jne lloop - - # write back to memory (state object) the transposed digest - vmovdqu a, 0*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu b, 1*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu c, 2*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu d, 3*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu e, 4*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu f, 5*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu g, 6*SHA512_DIGEST_ROW_SIZE(STATE) - vmovdqu h, 7*SHA512_DIGEST_ROW_SIZE(STATE) - - # update input data pointers - add IDX, inp0 - mov inp0, _data_ptr+0*PTR_SZ(STATE) - add IDX, inp1 - mov inp1, _data_ptr+1*PTR_SZ(STATE) - add IDX, inp2 - mov inp2, _data_ptr+2*PTR_SZ(STATE) - add IDX, inp3 - mov inp3, _data_ptr+3*PTR_SZ(STATE) - - #;;;;;;;;;;;;;;; - #; Postamble - add $STACK_SPACE1, %rsp - # restore callee-saved clobbered registers - - pop %r15 - pop %r14 - pop %r13 - pop %r12 - - # outer calling routine restores XMM and other GP registers - ret -ENDPROC(sha512_x4_avx2) - -.section .rodata.K512_4, "a", @progbits -.align 64 -K512_4: - .octa 0x428a2f98d728ae22428a2f98d728ae22,\ - 0x428a2f98d728ae22428a2f98d728ae22 - .octa 0x7137449123ef65cd7137449123ef65cd,\ - 0x7137449123ef65cd7137449123ef65cd - .octa 0xb5c0fbcfec4d3b2fb5c0fbcfec4d3b2f,\ - 0xb5c0fbcfec4d3b2fb5c0fbcfec4d3b2f - .octa 0xe9b5dba58189dbbce9b5dba58189dbbc,\ - 0xe9b5dba58189dbbce9b5dba58189dbbc - .octa 0x3956c25bf348b5383956c25bf348b538,\ - 0x3956c25bf348b5383956c25bf348b538 - .octa 0x59f111f1b605d01959f111f1b605d019,\ - 0x59f111f1b605d01959f111f1b605d019 - .octa 0x923f82a4af194f9b923f82a4af194f9b,\ - 0x923f82a4af194f9b923f82a4af194f9b - .octa 0xab1c5ed5da6d8118ab1c5ed5da6d8118,\ - 0xab1c5ed5da6d8118ab1c5ed5da6d8118 - .octa 0xd807aa98a3030242d807aa98a3030242,\ - 0xd807aa98a3030242d807aa98a3030242 - .octa 0x12835b0145706fbe12835b0145706fbe,\ - 0x12835b0145706fbe12835b0145706fbe - .octa 0x243185be4ee4b28c243185be4ee4b28c,\ - 0x243185be4ee4b28c243185be4ee4b28c - .octa 0x550c7dc3d5ffb4e2550c7dc3d5ffb4e2,\ - 0x550c7dc3d5ffb4e2550c7dc3d5ffb4e2 - .octa 0x72be5d74f27b896f72be5d74f27b896f,\ - 0x72be5d74f27b896f72be5d74f27b896f - .octa 0x80deb1fe3b1696b180deb1fe3b1696b1,\ - 0x80deb1fe3b1696b180deb1fe3b1696b1 - .octa 0x9bdc06a725c712359bdc06a725c71235,\ - 0x9bdc06a725c712359bdc06a725c71235 - .octa 0xc19bf174cf692694c19bf174cf692694,\ - 0xc19bf174cf692694c19bf174cf692694 - .octa 0xe49b69c19ef14ad2e49b69c19ef14ad2,\ - 0xe49b69c19ef14ad2e49b69c19ef14ad2 - .octa 0xefbe4786384f25e3efbe4786384f25e3,\ - 0xefbe4786384f25e3efbe4786384f25e3 - .octa 0x0fc19dc68b8cd5b50fc19dc68b8cd5b5,\ - 0x0fc19dc68b8cd5b50fc19dc68b8cd5b5 - .octa 0x240ca1cc77ac9c65240ca1cc77ac9c65,\ - 0x240ca1cc77ac9c65240ca1cc77ac9c65 - .octa 0x2de92c6f592b02752de92c6f592b0275,\ - 0x2de92c6f592b02752de92c6f592b0275 - .octa 0x4a7484aa6ea6e4834a7484aa6ea6e483,\ - 0x4a7484aa6ea6e4834a7484aa6ea6e483 - .octa 0x5cb0a9dcbd41fbd45cb0a9dcbd41fbd4,\ - 0x5cb0a9dcbd41fbd45cb0a9dcbd41fbd4 - .octa 0x76f988da831153b576f988da831153b5,\ - 0x76f988da831153b576f988da831153b5 - .octa 0x983e5152ee66dfab983e5152ee66dfab,\ - 0x983e5152ee66dfab983e5152ee66dfab - .octa 0xa831c66d2db43210a831c66d2db43210,\ - 0xa831c66d2db43210a831c66d2db43210 - .octa 0xb00327c898fb213fb00327c898fb213f,\ - 0xb00327c898fb213fb00327c898fb213f - .octa 0xbf597fc7beef0ee4bf597fc7beef0ee4,\ - 0xbf597fc7beef0ee4bf597fc7beef0ee4 - .octa 0xc6e00bf33da88fc2c6e00bf33da88fc2,\ - 0xc6e00bf33da88fc2c6e00bf33da88fc2 - .octa 0xd5a79147930aa725d5a79147930aa725,\ - 0xd5a79147930aa725d5a79147930aa725 - .octa 0x06ca6351e003826f06ca6351e003826f,\ - 0x06ca6351e003826f06ca6351e003826f - .octa 0x142929670a0e6e70142929670a0e6e70,\ - 0x142929670a0e6e70142929670a0e6e70 - .octa 0x27b70a8546d22ffc27b70a8546d22ffc,\ - 0x27b70a8546d22ffc27b70a8546d22ffc - .octa 0x2e1b21385c26c9262e1b21385c26c926,\ - 0x2e1b21385c26c9262e1b21385c26c926 - .octa 0x4d2c6dfc5ac42aed4d2c6dfc5ac42aed,\ - 0x4d2c6dfc5ac42aed4d2c6dfc5ac42aed - .octa 0x53380d139d95b3df53380d139d95b3df,\ - 0x53380d139d95b3df53380d139d95b3df - .octa 0x650a73548baf63de650a73548baf63de,\ - 0x650a73548baf63de650a73548baf63de - .octa 0x766a0abb3c77b2a8766a0abb3c77b2a8,\ - 0x766a0abb3c77b2a8766a0abb3c77b2a8 - .octa 0x81c2c92e47edaee681c2c92e47edaee6,\ - 0x81c2c92e47edaee681c2c92e47edaee6 - .octa 0x92722c851482353b92722c851482353b,\ - 0x92722c851482353b92722c851482353b - .octa 0xa2bfe8a14cf10364a2bfe8a14cf10364,\ - 0xa2bfe8a14cf10364a2bfe8a14cf10364 - .octa 0xa81a664bbc423001a81a664bbc423001,\ - 0xa81a664bbc423001a81a664bbc423001 - .octa 0xc24b8b70d0f89791c24b8b70d0f89791,\ - 0xc24b8b70d0f89791c24b8b70d0f89791 - .octa 0xc76c51a30654be30c76c51a30654be30,\ - 0xc76c51a30654be30c76c51a30654be30 - .octa 0xd192e819d6ef5218d192e819d6ef5218,\ - 0xd192e819d6ef5218d192e819d6ef5218 - .octa 0xd69906245565a910d69906245565a910,\ - 0xd69906245565a910d69906245565a910 - .octa 0xf40e35855771202af40e35855771202a,\ - 0xf40e35855771202af40e35855771202a - .octa 0x106aa07032bbd1b8106aa07032bbd1b8,\ - 0x106aa07032bbd1b8106aa07032bbd1b8 - .octa 0x19a4c116b8d2d0c819a4c116b8d2d0c8,\ - 0x19a4c116b8d2d0c819a4c116b8d2d0c8 - .octa 0x1e376c085141ab531e376c085141ab53,\ - 0x1e376c085141ab531e376c085141ab53 - .octa 0x2748774cdf8eeb992748774cdf8eeb99,\ - 0x2748774cdf8eeb992748774cdf8eeb99 - .octa 0x34b0bcb5e19b48a834b0bcb5e19b48a8,\ - 0x34b0bcb5e19b48a834b0bcb5e19b48a8 - .octa 0x391c0cb3c5c95a63391c0cb3c5c95a63,\ - 0x391c0cb3c5c95a63391c0cb3c5c95a63 - .octa 0x4ed8aa4ae3418acb4ed8aa4ae3418acb,\ - 0x4ed8aa4ae3418acb4ed8aa4ae3418acb - .octa 0x5b9cca4f7763e3735b9cca4f7763e373,\ - 0x5b9cca4f7763e3735b9cca4f7763e373 - .octa 0x682e6ff3d6b2b8a3682e6ff3d6b2b8a3,\ - 0x682e6ff3d6b2b8a3682e6ff3d6b2b8a3 - .octa 0x748f82ee5defb2fc748f82ee5defb2fc,\ - 0x748f82ee5defb2fc748f82ee5defb2fc - .octa 0x78a5636f43172f6078a5636f43172f60,\ - 0x78a5636f43172f6078a5636f43172f60 - .octa 0x84c87814a1f0ab7284c87814a1f0ab72,\ - 0x84c87814a1f0ab7284c87814a1f0ab72 - .octa 0x8cc702081a6439ec8cc702081a6439ec,\ - 0x8cc702081a6439ec8cc702081a6439ec - .octa 0x90befffa23631e2890befffa23631e28,\ - 0x90befffa23631e2890befffa23631e28 - .octa 0xa4506cebde82bde9a4506cebde82bde9,\ - 0xa4506cebde82bde9a4506cebde82bde9 - .octa 0xbef9a3f7b2c67915bef9a3f7b2c67915,\ - 0xbef9a3f7b2c67915bef9a3f7b2c67915 - .octa 0xc67178f2e372532bc67178f2e372532b,\ - 0xc67178f2e372532bc67178f2e372532b - .octa 0xca273eceea26619cca273eceea26619c,\ - 0xca273eceea26619cca273eceea26619c - .octa 0xd186b8c721c0c207d186b8c721c0c207,\ - 0xd186b8c721c0c207d186b8c721c0c207 - .octa 0xeada7dd6cde0eb1eeada7dd6cde0eb1e,\ - 0xeada7dd6cde0eb1eeada7dd6cde0eb1e - .octa 0xf57d4f7fee6ed178f57d4f7fee6ed178,\ - 0xf57d4f7fee6ed178f57d4f7fee6ed178 - .octa 0x06f067aa72176fba06f067aa72176fba,\ - 0x06f067aa72176fba06f067aa72176fba - .octa 0x0a637dc5a2c898a60a637dc5a2c898a6,\ - 0x0a637dc5a2c898a60a637dc5a2c898a6 - .octa 0x113f9804bef90dae113f9804bef90dae,\ - 0x113f9804bef90dae113f9804bef90dae - .octa 0x1b710b35131c471b1b710b35131c471b,\ - 0x1b710b35131c471b1b710b35131c471b - .octa 0x28db77f523047d8428db77f523047d84,\ - 0x28db77f523047d8428db77f523047d84 - .octa 0x32caab7b40c7249332caab7b40c72493,\ - 0x32caab7b40c7249332caab7b40c72493 - .octa 0x3c9ebe0a15c9bebc3c9ebe0a15c9bebc,\ - 0x3c9ebe0a15c9bebc3c9ebe0a15c9bebc - .octa 0x431d67c49c100d4c431d67c49c100d4c,\ - 0x431d67c49c100d4c431d67c49c100d4c - .octa 0x4cc5d4becb3e42b64cc5d4becb3e42b6,\ - 0x4cc5d4becb3e42b64cc5d4becb3e42b6 - .octa 0x597f299cfc657e2a597f299cfc657e2a,\ - 0x597f299cfc657e2a597f299cfc657e2a - .octa 0x5fcb6fab3ad6faec5fcb6fab3ad6faec,\ - 0x5fcb6fab3ad6faec5fcb6fab3ad6faec - .octa 0x6c44198c4a4758176c44198c4a475817,\ - 0x6c44198c4a4758176c44198c4a475817 - -.section .rodata.cst32.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 32 -.align 32 -PSHUFFLE_BYTE_FLIP_MASK: .octa 0x08090a0b0c0d0e0f0001020304050607 - .octa 0x18191a1b1c1d1e1f1011121314151617 diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 3f9d43f26f63..7eb878561910 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -39,7 +39,7 @@ void __init init_vdso_image(const struct vdso_image *image) struct linux_binprm; -static int vdso_fault(const struct vm_special_mapping *sm, +static vm_fault_t vdso_fault(const struct vm_special_mapping *sm, struct vm_area_struct *vma, struct vm_fault *vmf) { const struct vdso_image *image = vma->vm_mm->context.vdso_image; @@ -84,12 +84,11 @@ static int vdso_mremap(const struct vm_special_mapping *sm, return 0; } -static int vvar_fault(const struct vm_special_mapping *sm, +static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, struct vm_area_struct *vma, struct vm_fault *vmf) { const struct vdso_image *image = vma->vm_mm->context.vdso_image; long sym_offset; - int ret = -EFAULT; if (!image) return VM_FAULT_SIGBUS; @@ -108,29 +107,24 @@ static int vvar_fault(const struct vm_special_mapping *sm, return VM_FAULT_SIGBUS; if (sym_offset == image->sym_vvar_page) { - ret = vm_insert_pfn(vma, vmf->address, - __pa_symbol(&__vvar_page) >> PAGE_SHIFT); + return vmf_insert_pfn(vma, vmf->address, + __pa_symbol(&__vvar_page) >> PAGE_SHIFT); } else if (sym_offset == image->sym_pvclock_page) { struct pvclock_vsyscall_time_info *pvti = pvclock_get_pvti_cpu0_va(); if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) { - ret = vm_insert_pfn_prot( - vma, - vmf->address, - __pa(pvti) >> PAGE_SHIFT, - pgprot_decrypted(vma->vm_page_prot)); + 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) { struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page(); if (tsc_pg && vclock_was_used(VCLOCK_HVCLOCK)) - ret = vm_insert_pfn(vma, vmf->address, - vmalloc_to_pfn(tsc_pg)); + return vmf_insert_pfn(vma, vmf->address, + vmalloc_to_pfn(tsc_pg)); } - if (ret == 0 || ret == -EBUSY) - return VM_FAULT_NOPAGE; - return VM_FAULT_SIGBUS; } diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index 82ed001e8909..85fd85d52ffd 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -100,20 +100,13 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size) */ if (!access_ok(VERIFY_WRITE, (void __user *)ptr, size)) { - siginfo_t info; struct thread_struct *thread = ¤t->thread; thread->error_code = 6; /* user fault, no page, write */ thread->cr2 = ptr; thread->trap_nr = X86_TRAP_PF; - clear_siginfo(&info); - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = (void __user *)ptr; - - force_sig_info(SIGSEGV, &info, current); + force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)ptr, current); return false; } else { return true; diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index fb97cf7c4137..fab4df16a3c4 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -12,38 +12,23 @@ #include <asm/user32.h> #include <asm/unistd.h> +#include <asm-generic/compat.h> + #define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "i686\0\0" -typedef u32 compat_size_t; -typedef s32 compat_ssize_t; -typedef s32 compat_clock_t; -typedef s32 compat_pid_t; typedef u16 __compat_uid_t; typedef u16 __compat_gid_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; typedef u16 compat_mode_t; -typedef u32 compat_ino_t; typedef u16 compat_dev_t; -typedef s32 compat_off_t; -typedef s64 compat_loff_t; typedef u16 compat_nlink_t; typedef u16 compat_ipc_pid_t; -typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; typedef __kernel_fsid_t compat_fsid_t; -typedef s32 compat_timer_t; -typedef s32 compat_key_t; - -typedef s32 compat_int_t; -typedef s32 compat_long_t; typedef s64 __attribute__((aligned(4))) compat_s64; -typedef u32 compat_uint_t; -typedef u32 compat_ulong_t; -typedef u32 compat_u32; typedef u64 __attribute__((aligned(4))) compat_u64; -typedef u32 compat_uptr_t; struct compat_stat { compat_dev_t st_dev; @@ -240,6 +225,6 @@ static inline bool in_compat_syscall(void) struct compat_siginfo; int __copy_siginfo_to_user32(struct compat_siginfo __user *to, - const siginfo_t *from, bool x32_ABI); + const kernel_siginfo_t *from, bool x32_ABI); #endif /* _ASM_X86_COMPAT_H */ diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h index 5ed826da5e07..7469d321f072 100644 --- a/arch/x86/include/asm/hugetlb.h +++ b/arch/x86/include/asm/hugetlb.h @@ -13,75 +13,6 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, return 0; } -/* - * If the arch doesn't supply something else, assume that hugepage - * size aligned regions are ok without further preparation. - */ -static inline int prepare_hugepage_range(struct file *file, - unsigned long addr, unsigned long len) -{ - struct hstate *h = hstate_file(file); - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (addr & ~huge_page_mask(h)) - return -EINVAL; - return 0; -} - -static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, - unsigned long addr, unsigned long end, - unsigned long floor, - unsigned long ceiling) -{ - free_pgd_range(tlb, addr, end, floor, ceiling); -} - -static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pte) -{ - set_pte_at(mm, addr, ptep, pte); -} - -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - return ptep_get_and_clear(mm, addr, ptep); -} - -static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep) -{ - ptep_clear_flush(vma, addr, ptep); -} - -static inline int huge_pte_none(pte_t pte) -{ - return pte_none(pte); -} - -static inline pte_t huge_pte_wrprotect(pte_t pte) -{ - return pte_wrprotect(pte); -} - -static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - ptep_set_wrprotect(mm, addr, ptep); -} - -static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep, - pte_t pte, int dirty) -{ - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); -} - -static inline pte_t huge_ptep_get(pte_t *ptep) -{ - return *ptep; -} - static inline void arch_clear_hugepage_flags(struct page *page) { } diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h index 3de0489deade..5270ff39b9af 100644 --- a/arch/x86/include/asm/iosf_mbi.h +++ b/arch/x86/include/asm/iosf_mbi.h @@ -105,8 +105,10 @@ int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask); * the PMIC bus while another driver is also accessing the PMIC bus various bad * things happen. * - * To avoid these problems this function must be called before accessing the - * P-Unit or the PMIC, be it through iosf_mbi* functions or through other means. + * Call this function before sending requests to the P-Unit which may make it + * access the PMIC, be it through iosf_mbi* functions or through other means. + * This function will block all kernel access to the PMIC I2C bus, so that the + * P-Unit can safely access the PMIC over the shared I2C bus. * * Note on these systems the i2c-bus driver will request a sempahore from the * P-Unit for exclusive access to the PMIC bus when i2c drivers are accessing @@ -123,6 +125,31 @@ void iosf_mbi_punit_acquire(void); void iosf_mbi_punit_release(void); /** + * iosf_mbi_block_punit_i2c_access() - Block P-Unit accesses to the PMIC bus + * + * Call this function to block P-Unit access to the PMIC I2C bus, so that the + * kernel can safely access the PMIC over the shared I2C bus. + * + * This function acquires the P-Unit bus semaphore and notifies + * pmic_bus_access_notifier listeners that they may no longer access the + * P-Unit in a way which may cause it to access the shared I2C bus. + * + * Note this function may be called multiple times and the bus will not + * be released until iosf_mbi_unblock_punit_i2c_access() has been called the + * same amount of times. + * + * Return: Nonzero on error + */ +int iosf_mbi_block_punit_i2c_access(void); + +/* + * iosf_mbi_unblock_punit_i2c_access() - Release PMIC I2C bus block + * + * Release i2c access block gotten through iosf_mbi_block_punit_i2c_access(). + */ +void iosf_mbi_unblock_punit_i2c_access(void); + +/** * iosf_mbi_register_pmic_bus_access_notifier - Register PMIC bus notifier * * This function can be used by drivers which may need to acquire P-Unit @@ -159,14 +186,6 @@ int iosf_mbi_unregister_pmic_bus_access_notifier_unlocked( struct notifier_block *nb); /** - * iosf_mbi_call_pmic_bus_access_notifier_chain - Call PMIC bus notifier chain - * - * @val: action to pass into listener's notifier_call function - * @v: data pointer to pass into listener's notifier_call function - */ -int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v); - -/** * iosf_mbi_assert_punit_acquired - Assert that the P-Unit has been acquired. */ void iosf_mbi_assert_punit_acquired(void); diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 5f26962eff42..67ed72f31cc2 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -45,6 +45,8 @@ struct vcpu_data { #ifdef CONFIG_IRQ_REMAP +extern raw_spinlock_t irq_2_ir_lock; + extern bool irq_remapping_cap(enum irq_remap_cap cap); extern void set_irq_remapping_broken(void); extern int irq_remapping_prepare(void); diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 09b2e3e2cf1b..55e51ff7e421 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -102,7 +102,15 @@ #define UNMAPPED_GVA (~(gpa_t)0) /* KVM Hugepage definitions for x86 */ -#define KVM_NR_PAGE_SIZES 3 +enum { + PT_PAGE_TABLE_LEVEL = 1, + PT_DIRECTORY_LEVEL = 2, + PT_PDPE_LEVEL = 3, + /* set max level to the biggest one */ + PT_MAX_HUGEPAGE_LEVEL = PT_PDPE_LEVEL, +}; +#define KVM_NR_PAGE_SIZES (PT_MAX_HUGEPAGE_LEVEL - \ + PT_PAGE_TABLE_LEVEL + 1) #define KVM_HPAGE_GFN_SHIFT(x) (((x) - 1) * 9) #define KVM_HPAGE_SHIFT(x) (PAGE_SHIFT + KVM_HPAGE_GFN_SHIFT(x)) #define KVM_HPAGE_SIZE(x) (1UL << KVM_HPAGE_SHIFT(x)) @@ -177,6 +185,7 @@ enum { #define DR6_BD (1 << 13) #define DR6_BS (1 << 14) +#define DR6_BT (1 << 15) #define DR6_RTM (1 << 16) #define DR6_FIXED_1 0xfffe0ff0 #define DR6_INIT 0xffff0ff0 @@ -247,7 +256,7 @@ struct kvm_mmu_memory_cache { * @nxe, @cr0_wp, @smep_andnot_wp and @smap_andnot_wp. */ union kvm_mmu_page_role { - unsigned word; + u32 word; struct { unsigned level:4; unsigned cr4_pae:1; @@ -273,6 +282,34 @@ union kvm_mmu_page_role { }; }; +union kvm_mmu_extended_role { +/* + * This structure complements kvm_mmu_page_role caching everything needed for + * MMU configuration. If nothing in both these structures changed, MMU + * re-configuration can be skipped. @valid bit is set on first usage so we don't + * treat all-zero structure as valid data. + */ + u32 word; + struct { + unsigned int valid:1; + unsigned int execonly:1; + unsigned int cr0_pg:1; + unsigned int cr4_pse:1; + unsigned int cr4_pke:1; + unsigned int cr4_smap:1; + unsigned int cr4_smep:1; + unsigned int cr4_la57:1; + }; +}; + +union kvm_mmu_role { + u64 as_u64; + struct { + union kvm_mmu_page_role base; + union kvm_mmu_extended_role ext; + }; +}; + struct kvm_rmap_head { unsigned long val; }; @@ -280,18 +317,18 @@ struct kvm_rmap_head { struct kvm_mmu_page { struct list_head link; struct hlist_node hash_link; + bool unsync; /* * The following two entries are used to key the shadow page in the * hash table. */ - gfn_t gfn; union kvm_mmu_page_role role; + gfn_t gfn; u64 *spt; /* hold the gfn of each spte inside spt */ gfn_t *gfns; - bool unsync; int root_count; /* Currently serving as active root */ unsigned int unsync_children; struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */ @@ -360,7 +397,7 @@ struct kvm_mmu { void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, u64 *spte, const void *pte); hpa_t root_hpa; - union kvm_mmu_page_role base_role; + union kvm_mmu_role mmu_role; u8 root_level; u8 shadow_root_level; u8 ept_ad; @@ -490,7 +527,7 @@ struct kvm_vcpu_hv { struct kvm_hyperv_exit exit; struct kvm_vcpu_hv_stimer stimer[HV_SYNIC_STIMER_COUNT]; DECLARE_BITMAP(stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT); - cpumask_t tlb_lush; + cpumask_t tlb_flush; }; struct kvm_vcpu_arch { @@ -534,7 +571,13 @@ struct kvm_vcpu_arch { * the paging mode of the l1 guest. This context is always used to * handle faults. */ - struct kvm_mmu mmu; + struct kvm_mmu *mmu; + + /* Non-nested MMU for L1 */ + struct kvm_mmu root_mmu; + + /* L1 MMU when running nested */ + struct kvm_mmu guest_mmu; /* * Paging state of an L2 guest (used for nested npt) @@ -585,6 +628,8 @@ struct kvm_vcpu_arch { bool has_error_code; u8 nr; u32 error_code; + unsigned long payload; + bool has_payload; u8 nested_apf; } exception; @@ -781,6 +826,9 @@ struct kvm_hv { u64 hv_reenlightenment_control; u64 hv_tsc_emulation_control; u64 hv_tsc_emulation_status; + + /* How many vCPUs have VP index != vCPU index */ + atomic_t num_mismatched_vp_indexes; }; enum kvm_irqchip_mode { @@ -871,6 +919,7 @@ struct kvm_arch { bool x2apic_broadcast_quirk_disabled; bool guest_can_read_msr_platform_info; + bool exception_payload_enabled; }; struct kvm_vm_stat { @@ -1133,6 +1182,9 @@ struct kvm_x86_ops { int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp); int (*get_msr_feature)(struct kvm_msr_entry *entry); + + int (*nested_enable_evmcs)(struct kvm_vcpu *vcpu, + uint16_t *vmcs_version); }; struct kvm_arch_async_pf { @@ -1170,7 +1222,6 @@ void kvm_mmu_module_exit(void); void kvm_mmu_destroy(struct kvm_vcpu *vcpu); int kvm_mmu_create(struct kvm_vcpu *vcpu); -void kvm_mmu_setup(struct kvm_vcpu *vcpu); void kvm_mmu_init_vm(struct kvm *kvm); void kvm_mmu_uninit_vm(struct kvm *kvm); void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, @@ -1324,7 +1375,8 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu); int kvm_mmu_load(struct kvm_vcpu *vcpu); void kvm_mmu_unload(struct kvm_vcpu *vcpu); void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu); -void kvm_mmu_free_roots(struct kvm_vcpu *vcpu, ulong roots_to_free); +void kvm_mmu_free_roots(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, + ulong roots_to_free); gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access, struct x86_exception *exception); gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h index 61eb4b63c5ec..d0b1434fb0b6 100644 --- a/arch/x86/include/asm/mpx.h +++ b/arch/x86/include/asm/mpx.h @@ -57,8 +57,14 @@ #define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1)) #define MPX_BNDSTA_ERROR_CODE 0x3 +struct mpx_fault_info { + void __user *addr; + void __user *lower; + void __user *upper; +}; + #ifdef CONFIG_X86_INTEL_MPX -siginfo_t *mpx_generate_siginfo(struct pt_regs *regs); +int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs); int mpx_handle_bd_fault(void); static inline int kernel_managing_mpx_tables(struct mm_struct *mm) { @@ -78,9 +84,9 @@ void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long mpx_unmapped_area_check(unsigned long addr, unsigned long len, unsigned long flags); #else -static inline siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) +static inline int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs) { - return NULL; + return -EINVAL; } static inline int mpx_handle_bd_fault(void) { diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index f236bcd5485d..143c99499531 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -293,7 +293,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, #define arch_has_block_step() (boot_cpu_data.x86 >= 6) #endif -#define ARCH_HAS_USER_SINGLE_STEP_INFO +#define ARCH_HAS_USER_SINGLE_STEP_REPORT /* * When hitting ptrace_stop(), we cannot return using SYSRET because diff --git a/arch/x86/include/asm/trace/mpx.h b/arch/x86/include/asm/trace/mpx.h index 7bd92db09e8d..54133017267c 100644 --- a/arch/x86/include/asm/trace/mpx.h +++ b/arch/x86/include/asm/trace/mpx.h @@ -11,12 +11,12 @@ TRACE_EVENT(mpx_bounds_register_exception, - TP_PROTO(void *addr_referenced, + TP_PROTO(void __user *addr_referenced, const struct mpx_bndreg *bndreg), TP_ARGS(addr_referenced, bndreg), TP_STRUCT__entry( - __field(void *, addr_referenced) + __field(void __user *, addr_referenced) __field(u64, lower_bound) __field(u64, upper_bound) ), diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 51c4eee00732..dc4ed8bc2382 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -24,6 +24,7 @@ # include <asm/unistd_64.h> # include <asm/unistd_64_x32.h> # define __ARCH_WANT_COMPAT_SYS_TIME +# define __ARCH_WANT_SYS_UTIME32 # define __ARCH_WANT_COMPAT_SYS_PREADV64 # define __ARCH_WANT_COMPAT_SYS_PWRITEV64 # define __ARCH_WANT_COMPAT_SYS_PREADV64V2 @@ -31,13 +32,13 @@ # endif +# define __ARCH_WANT_NEW_STAT # define __ARCH_WANT_OLD_READDIR # define __ARCH_WANT_OLD_STAT # define __ARCH_WANT_SYS_ALARM # define __ARCH_WANT_SYS_FADVISE64 # define __ARCH_WANT_SYS_GETHOSTNAME # define __ARCH_WANT_SYS_GETPGRP -# define __ARCH_WANT_SYS_LLSEEK # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLDUMOUNT # define __ARCH_WANT_SYS_OLD_GETRLIMIT diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h index e05e0d309244..1fc7a0d1e877 100644 --- a/arch/x86/include/asm/virtext.h +++ b/arch/x86/include/asm/virtext.h @@ -40,7 +40,7 @@ static inline int cpu_has_vmx(void) */ static inline void cpu_vmxoff(void) { - asm volatile (ASM_VMX_VMXOFF : : : "cc"); + asm volatile ("vmxoff"); cr4_clear_bits(X86_CR4_VMXE); } diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 9527ba5d62da..ade0f153947d 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -503,19 +503,6 @@ enum vmcs_field { #define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul - -#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30" -#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2" -#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3" -#define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30" -#define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0" -#define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0" -#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4" -#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4" -#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30" -#define ASM_VMX_INVEPT ".byte 0x66, 0x0f, 0x38, 0x80, 0x08" -#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08" - struct vmx_msr_entry { u32 index; u32 reserved; diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index fd23d5778ea1..dabfcf7c3941 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -288,6 +288,7 @@ struct kvm_reinject_control { #define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 #define KVM_VCPUEVENT_VALID_SMM 0x00000008 +#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 /* Interrupt shadow states */ #define KVM_X86_SHADOW_INT_MOV_SS 0x01 @@ -299,7 +300,7 @@ struct kvm_vcpu_events { __u8 injected; __u8 nr; __u8 has_error_code; - __u8 pad; + __u8 pending; __u32 error_code; } exception; struct { @@ -322,7 +323,9 @@ struct kvm_vcpu_events { __u8 smm_inside_nmi; __u8 latched_init; } smi; - __u32 reserved[9]; + __u8 reserved[27]; + __u8 exception_has_payload; + __u64 exception_payload; }; /* for KVM_GET/SET_DEBUGREGS */ @@ -381,6 +384,7 @@ struct kvm_sync_regs { #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 +#define KVM_STATE_NESTED_EVMCS 0x00000004 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002 diff --git a/arch/x86/include/uapi/asm/siginfo.h b/arch/x86/include/uapi/asm/siginfo.h index b3d157957177..6642d8be40c4 100644 --- a/arch/x86/include/uapi/asm/siginfo.h +++ b/arch/x86/include/uapi/asm/siginfo.h @@ -7,8 +7,6 @@ typedef long long __kernel_si_clock_t __attribute__((aligned(4))); # define __ARCH_SI_CLOCK_T __kernel_si_clock_t # define __ARCH_SI_ATTRIBUTES __attribute__((aligned(8))) -# else /* x86-64 */ -# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) # endif #endif diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index f39f3a06c26f..7299dcbf8e85 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -140,7 +140,7 @@ static void __init dtb_cpu_setup(void) int ret; version = GET_APIC_VERSION(apic_read(APIC_LVR)); - for_each_node_by_type(dn, "cpu") { + for_each_of_cpu_node(dn) { ret = of_property_read_u32(dn, "reg", &apic_id); if (ret < 0) { pr_warn("%pOF: missing local APIC ID\n", dn); diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index c88c23c658c1..d1f25c831447 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1248,7 +1248,6 @@ void __init e820__memblock_setup(void) { int i; u64 end; - u64 addr = 0; /* * The bootstrap memblock region count maximum is 128 entries @@ -1265,21 +1264,13 @@ void __init e820__memblock_setup(void) struct e820_entry *entry = &e820_table->entries[i]; end = entry->addr + entry->size; - if (addr < entry->addr) - memblock_reserve(addr, entry->addr - addr); - addr = end; if (end != (resource_size_t)end) continue; - /* - * all !E820_TYPE_RAM ranges (including gap ranges) are put - * into memblock.reserved to make sure that struct pages in - * such regions are not left uninitialized after bootup. - */ if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN) - memblock_reserve(entry->addr, entry->size); - else - memblock_add(entry->addr, entry->size); + continue; + + memblock_add(entry->addr, entry->size); } /* Throw away partial pages: */ diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index d8f49c7384a3..ffae9b9740fd 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1359,33 +1359,18 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) #endif } -static void fill_sigtrap_info(struct task_struct *tsk, - struct pt_regs *regs, - int error_code, int si_code, - struct siginfo *info) +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) { tsk->thread.trap_nr = X86_TRAP_DB; tsk->thread.error_code = error_code; - info->si_signo = SIGTRAP; - info->si_code = si_code; - info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; -} - -void user_single_step_siginfo(struct task_struct *tsk, - struct pt_regs *regs, - struct siginfo *info) -{ - fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); + /* Send us the fake SIGTRAP */ + force_sig_fault(SIGTRAP, si_code, + user_mode(regs) ? (void __user *)regs->ip : NULL, tsk); } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, - int error_code, int si_code) +void user_single_step_report(struct pt_regs *regs) { - struct siginfo info; - - clear_siginfo(&info); - fill_sigtrap_info(tsk, regs, error_code, si_code, &info); - /* Send us the fake SIGTRAP */ - force_sig_info(SIGTRAP, &info, tsk); + send_sigtrap(current, regs, 0, TRAP_BRKPT); } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 5bd0a997d81e..8f6dcd88202e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -189,7 +189,7 @@ int fixup_bug(struct pt_regs *regs, int trapnr) } static nokprobe_inline int -do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, +do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, struct pt_regs *regs, long error_code) { if (v8086_mode(regs)) { @@ -202,10 +202,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, error_code, trapnr)) return 0; } - return -1; - } - - if (!user_mode(regs)) { + } else if (!user_mode(regs)) { if (fixup_exception(regs, trapnr, error_code, 0)) return 0; @@ -214,49 +211,6 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, die(str, regs, error_code); } - return -1; -} - -static siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr, - siginfo_t *info) -{ - unsigned long siaddr; - int sicode; - - switch (trapnr) { - default: - return SEND_SIG_PRIV; - - case X86_TRAP_DE: - sicode = FPE_INTDIV; - siaddr = uprobe_get_trap_addr(regs); - break; - case X86_TRAP_UD: - sicode = ILL_ILLOPN; - siaddr = uprobe_get_trap_addr(regs); - break; - case X86_TRAP_AC: - sicode = BUS_ADRALN; - siaddr = 0; - break; - } - - info->si_signo = signr; - info->si_errno = 0; - info->si_code = sicode; - info->si_addr = (void __user *)siaddr; - return info; -} - -static void -do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, - long error_code, siginfo_t *info) -{ - struct task_struct *tsk = current; - - - if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code)) - return; /* * We want error_code and trap_nr set for userspace faults and * kernelspace faults which result in die(), but not @@ -269,24 +223,45 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, tsk->thread.error_code = error_code; tsk->thread.trap_nr = trapnr; + return -1; +} + +static void show_signal(struct task_struct *tsk, int signr, + const char *type, const char *desc, + struct pt_regs *regs, long error_code) +{ if (show_unhandled_signals && unhandled_signal(tsk, signr) && printk_ratelimit()) { - pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx", - tsk->comm, tsk->pid, str, + pr_info("%s[%d] %s%s ip:%lx sp:%lx error:%lx", + tsk->comm, task_pid_nr(tsk), type, desc, regs->ip, regs->sp, error_code); print_vma_addr(KERN_CONT " in ", regs->ip); pr_cont("\n"); } +} + +static void +do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, + long error_code, int sicode, void __user *addr) +{ + struct task_struct *tsk = current; + + + if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code)) + return; + + show_signal(tsk, signr, "trap ", str, regs, error_code); - force_sig_info(signr, info ?: SEND_SIG_PRIV, tsk); + if (!sicode) + force_sig(signr, tsk); + else + force_sig_fault(signr, sicode, addr, tsk); } NOKPROBE_SYMBOL(do_trap); static void do_error_trap(struct pt_regs *regs, long error_code, char *str, - unsigned long trapnr, int signr) + unsigned long trapnr, int signr, int sicode, void __user *addr) { - siginfo_t info; - RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); /* @@ -299,26 +274,26 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str, if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != NOTIFY_STOP) { cond_local_irq_enable(regs); - clear_siginfo(&info); - do_trap(trapnr, signr, str, regs, error_code, - fill_trap_info(regs, signr, trapnr, &info)); + do_trap(trapnr, signr, str, regs, error_code, sicode, addr); } } -#define DO_ERROR(trapnr, signr, str, name) \ -dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ -{ \ - do_error_trap(regs, error_code, str, trapnr, signr); \ +#define IP ((void __user *)uprobe_get_trap_addr(regs)) +#define DO_ERROR(trapnr, signr, sicode, addr, str, name) \ +dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ +{ \ + do_error_trap(regs, error_code, str, trapnr, signr, sicode, addr); \ } -DO_ERROR(X86_TRAP_DE, SIGFPE, "divide error", divide_error) -DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow) -DO_ERROR(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op) -DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",coprocessor_segment_overrun) -DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS) -DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present) -DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment) -DO_ERROR(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check) +DO_ERROR(X86_TRAP_DE, SIGFPE, FPE_INTDIV, IP, "divide error", divide_error) +DO_ERROR(X86_TRAP_OF, SIGSEGV, 0, NULL, "overflow", overflow) +DO_ERROR(X86_TRAP_UD, SIGILL, ILL_ILLOPN, IP, "invalid opcode", invalid_op) +DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, 0, NULL, "coprocessor segment overrun", coprocessor_segment_overrun) +DO_ERROR(X86_TRAP_TS, SIGSEGV, 0, NULL, "invalid TSS", invalid_TSS) +DO_ERROR(X86_TRAP_NP, SIGBUS, 0, NULL, "segment not present", segment_not_present) +DO_ERROR(X86_TRAP_SS, SIGBUS, 0, NULL, "stack segment", stack_segment) +DO_ERROR(X86_TRAP_AC, SIGBUS, BUS_ADRALN, NULL, "alignment check", alignment_check) +#undef IP #ifdef CONFIG_VMAP_STACK __visible void __noreturn handle_stack_overflow(const char *message, @@ -459,7 +434,6 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) { const struct mpx_bndcsr *bndcsr; - siginfo_t *info; RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); if (notify_die(DIE_TRAP, "bounds", regs, error_code, @@ -497,8 +471,11 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) goto exit_trap; break; /* Success, it was handled */ case 1: /* Bound violation. */ - info = mpx_generate_siginfo(regs); - if (IS_ERR(info)) { + { + struct task_struct *tsk = current; + struct mpx_fault_info mpx; + + if (mpx_fault_info(&mpx, regs)) { /* * We failed to decode the MPX instruction. Act as if * the exception was not caused by MPX. @@ -507,14 +484,20 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) } /* * Success, we decoded the instruction and retrieved - * an 'info' containing the address being accessed + * an 'mpx' containing the address being accessed * which caused the exception. This information * allows and application to possibly handle the * #BR exception itself. */ - do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, info); - kfree(info); + if (!do_trap_no_signal(tsk, X86_TRAP_BR, "bounds", regs, + error_code)) + break; + + show_signal(tsk, SIGSEGV, "trap ", "bounds", regs, error_code); + + force_sig_bnderr(mpx.addr, mpx.lower, mpx.upper); break; + } case 0: /* No exception caused by Intel MPX operations. */ goto exit_trap; default: @@ -531,12 +514,13 @@ exit_trap: * up here if the kernel has MPX turned off at compile * time.. */ - do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, NULL); + do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, 0, NULL); } dotraplinkage void do_general_protection(struct pt_regs *regs, long error_code) { + const char *desc = "general protection fault"; struct task_struct *tsk; RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); @@ -570,25 +554,18 @@ do_general_protection(struct pt_regs *regs, long error_code) kprobe_fault_handler(regs, X86_TRAP_GP)) return; - if (notify_die(DIE_GPF, "general protection fault", regs, error_code, + if (notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) - die("general protection fault", regs, error_code); + die(desc, regs, error_code); return; } tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; - if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && - printk_ratelimit()) { - pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx", - tsk->comm, task_pid_nr(tsk), - regs->ip, regs->sp, error_code); - print_vma_addr(KERN_CONT " in ", regs->ip); - pr_cont("\n"); - } + show_signal(tsk, SIGSEGV, "", desc, regs, error_code); - force_sig_info(SIGSEGV, SEND_SIG_PRIV, tsk); + force_sig(SIGSEGV, tsk); } NOKPROBE_SYMBOL(do_general_protection); @@ -631,7 +608,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) goto exit; cond_local_irq_enable(regs); - do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); + do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, 0, NULL); cond_local_irq_disable(regs); exit: @@ -845,7 +822,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) { struct task_struct *task = current; struct fpu *fpu = &task->thread.fpu; - siginfo_t info; + int si_code; char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : "simd exception"; @@ -871,18 +848,14 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) task->thread.trap_nr = trapnr; task->thread.error_code = error_code; - clear_siginfo(&info); - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *)uprobe_get_trap_addr(regs); - - info.si_code = fpu__exception_code(fpu, trapnr); + si_code = fpu__exception_code(fpu, trapnr); /* Retry when we get spurious exceptions: */ - if (!info.si_code) + if (!si_code) return; - force_sig_info(SIGFPE, &info, task); + force_sig_fault(SIGFPE, si_code, + (void __user *)uprobe_get_trap_addr(regs), task); } dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) @@ -942,20 +915,13 @@ NOKPROBE_SYMBOL(do_device_not_available); #ifdef CONFIG_X86_32 dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) { - siginfo_t info; - RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); local_irq_enable(); - clear_siginfo(&info); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_BADSTK; - info.si_addr = NULL; if (notify_die(DIE_TRAP, "iret exception", regs, error_code, X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) { do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, - &info); + ILL_BADSTK, (void __user *)NULL); } } #endif diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c index ff20b35e98dd..f8f3cfda01ae 100644 --- a/arch/x86/kernel/umip.c +++ b/arch/x86/kernel/umip.c @@ -271,19 +271,13 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst, */ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) { - siginfo_t info; struct task_struct *tsk = current; tsk->thread.cr2 = (unsigned long)addr; tsk->thread.error_code = X86_PF_USER | X86_PF_WRITE; tsk->thread.trap_nr = X86_TRAP_PF; - clear_siginfo(&info); - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = addr; - force_sig_info(SIGSEGV, &info, tsk); + force_sig_fault(SIGSEGV, SEGV_MAPERR, addr, tsk); if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) return; diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index deb576b23b7c..843feb94a950 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -1086,7 +1086,7 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs pr_err("return address clobbered: pid=%d, %%sp=%#lx, %%ip=%#lx\n", current->pid, regs->sp, regs->ip); - force_sig_info(SIGSEGV, SEND_SIG_FORCED, current); + force_sig(SIGSEGV, current); } return -1; diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 01d209ab5481..4e80080f277a 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -36,6 +36,8 @@ #include "trace.h" +#define KVM_HV_MAX_SPARSE_VCPU_SET_BITS DIV_ROUND_UP(KVM_MAX_VCPUS, 64) + static inline u64 synic_read_sint(struct kvm_vcpu_hv_synic *synic, int sint) { return atomic64_read(&synic->sint[sint]); @@ -132,8 +134,10 @@ static struct kvm_vcpu *get_vcpu_by_vpidx(struct kvm *kvm, u32 vpidx) struct kvm_vcpu *vcpu = NULL; int i; - if (vpidx < KVM_MAX_VCPUS) - vcpu = kvm_get_vcpu(kvm, vpidx); + if (vpidx >= KVM_MAX_VCPUS) + return NULL; + + vcpu = kvm_get_vcpu(kvm, vpidx); if (vcpu && vcpu_to_hv_vcpu(vcpu)->vp_index == vpidx) return vcpu; kvm_for_each_vcpu(i, vcpu, kvm) @@ -689,6 +693,24 @@ void kvm_hv_vcpu_uninit(struct kvm_vcpu *vcpu) stimer_cleanup(&hv_vcpu->stimer[i]); } +bool kvm_hv_assist_page_enabled(struct kvm_vcpu *vcpu) +{ + if (!(vcpu->arch.hyperv.hv_vapic & HV_X64_MSR_VP_ASSIST_PAGE_ENABLE)) + return false; + return vcpu->arch.pv_eoi.msr_val & KVM_MSR_ENABLED; +} +EXPORT_SYMBOL_GPL(kvm_hv_assist_page_enabled); + +bool kvm_hv_get_assist_page(struct kvm_vcpu *vcpu, + struct hv_vp_assist_page *assist_page) +{ + if (!kvm_hv_assist_page_enabled(vcpu)) + return false; + return !kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.pv_eoi.data, + assist_page, sizeof(*assist_page)); +} +EXPORT_SYMBOL_GPL(kvm_hv_get_assist_page); + static void stimer_prepare_msg(struct kvm_vcpu_hv_stimer *stimer) { struct hv_message *msg = &stimer->msg; @@ -1040,21 +1062,41 @@ static u64 current_task_runtime_100ns(void) static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) { - struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv; + struct kvm_vcpu_hv *hv_vcpu = &vcpu->arch.hyperv; switch (msr) { - case HV_X64_MSR_VP_INDEX: - if (!host) + case HV_X64_MSR_VP_INDEX: { + struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; + int vcpu_idx = kvm_vcpu_get_idx(vcpu); + u32 new_vp_index = (u32)data; + + if (!host || new_vp_index >= KVM_MAX_VCPUS) return 1; - hv->vp_index = (u32)data; + + if (new_vp_index == hv_vcpu->vp_index) + return 0; + + /* + * The VP index is initialized to vcpu_index by + * kvm_hv_vcpu_postcreate so they initially match. Now the + * VP index is changing, adjust num_mismatched_vp_indexes if + * it now matches or no longer matches vcpu_idx. + */ + if (hv_vcpu->vp_index == vcpu_idx) + atomic_inc(&hv->num_mismatched_vp_indexes); + else if (new_vp_index == vcpu_idx) + atomic_dec(&hv->num_mismatched_vp_indexes); + + hv_vcpu->vp_index = new_vp_index; break; + } case HV_X64_MSR_VP_ASSIST_PAGE: { u64 gfn; unsigned long addr; if (!(data & HV_X64_MSR_VP_ASSIST_PAGE_ENABLE)) { - hv->hv_vapic = data; - if (kvm_lapic_enable_pv_eoi(vcpu, 0)) + hv_vcpu->hv_vapic = data; + if (kvm_lapic_enable_pv_eoi(vcpu, 0, 0)) return 1; break; } @@ -1062,12 +1104,19 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); if (kvm_is_error_hva(addr)) return 1; - if (__clear_user((void __user *)addr, PAGE_SIZE)) + + /* + * Clear apic_assist portion of f(struct hv_vp_assist_page + * only, there can be valuable data in the rest which needs + * to be preserved e.g. on migration. + */ + if (__clear_user((void __user *)addr, sizeof(u32))) return 1; - hv->hv_vapic = data; + hv_vcpu->hv_vapic = data; kvm_vcpu_mark_page_dirty(vcpu, gfn); if (kvm_lapic_enable_pv_eoi(vcpu, - gfn_to_gpa(gfn) | KVM_MSR_ENABLED)) + gfn_to_gpa(gfn) | KVM_MSR_ENABLED, + sizeof(struct hv_vp_assist_page))) return 1; break; } @@ -1080,7 +1129,7 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) case HV_X64_MSR_VP_RUNTIME: if (!host) return 1; - hv->runtime_offset = data - current_task_runtime_100ns(); + hv_vcpu->runtime_offset = data - current_task_runtime_100ns(); break; case HV_X64_MSR_SCONTROL: case HV_X64_MSR_SVERSION: @@ -1172,11 +1221,11 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) { u64 data = 0; - struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv; + struct kvm_vcpu_hv *hv_vcpu = &vcpu->arch.hyperv; switch (msr) { case HV_X64_MSR_VP_INDEX: - data = hv->vp_index; + data = hv_vcpu->vp_index; break; case HV_X64_MSR_EOI: return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata); @@ -1185,10 +1234,10 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, case HV_X64_MSR_TPR: return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata); case HV_X64_MSR_VP_ASSIST_PAGE: - data = hv->hv_vapic; + data = hv_vcpu->hv_vapic; break; case HV_X64_MSR_VP_RUNTIME: - data = current_task_runtime_100ns() + hv->runtime_offset; + data = current_task_runtime_100ns() + hv_vcpu->runtime_offset; break; case HV_X64_MSR_SCONTROL: case HV_X64_MSR_SVERSION: @@ -1255,32 +1304,47 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) return kvm_hv_get_msr(vcpu, msr, pdata, host); } -static __always_inline int get_sparse_bank_no(u64 valid_bank_mask, int bank_no) +static __always_inline unsigned long *sparse_set_to_vcpu_mask( + struct kvm *kvm, u64 *sparse_banks, u64 valid_bank_mask, + u64 *vp_bitmap, unsigned long *vcpu_bitmap) { - int i = 0, j; + struct kvm_hv *hv = &kvm->arch.hyperv; + struct kvm_vcpu *vcpu; + int i, bank, sbank = 0; - if (!(valid_bank_mask & BIT_ULL(bank_no))) - return -1; + memset(vp_bitmap, 0, + KVM_HV_MAX_SPARSE_VCPU_SET_BITS * sizeof(*vp_bitmap)); + for_each_set_bit(bank, (unsigned long *)&valid_bank_mask, + KVM_HV_MAX_SPARSE_VCPU_SET_BITS) + vp_bitmap[bank] = sparse_banks[sbank++]; - for (j = 0; j < bank_no; j++) - if (valid_bank_mask & BIT_ULL(j)) - i++; + if (likely(!atomic_read(&hv->num_mismatched_vp_indexes))) { + /* for all vcpus vp_index == vcpu_idx */ + return (unsigned long *)vp_bitmap; + } - return i; + bitmap_zero(vcpu_bitmap, KVM_MAX_VCPUS); + kvm_for_each_vcpu(i, vcpu, kvm) { + if (test_bit(vcpu_to_hv_vcpu(vcpu)->vp_index, + (unsigned long *)vp_bitmap)) + __set_bit(i, vcpu_bitmap); + } + return vcpu_bitmap; } static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, u16 rep_cnt, bool ex) { struct kvm *kvm = current_vcpu->kvm; - struct kvm_vcpu_hv *hv_current = ¤t_vcpu->arch.hyperv; + struct kvm_vcpu_hv *hv_vcpu = ¤t_vcpu->arch.hyperv; struct hv_tlb_flush_ex flush_ex; struct hv_tlb_flush flush; - struct kvm_vcpu *vcpu; - unsigned long vcpu_bitmap[BITS_TO_LONGS(KVM_MAX_VCPUS)] = {0}; - unsigned long valid_bank_mask = 0; + u64 vp_bitmap[KVM_HV_MAX_SPARSE_VCPU_SET_BITS]; + DECLARE_BITMAP(vcpu_bitmap, KVM_MAX_VCPUS); + unsigned long *vcpu_mask; + u64 valid_bank_mask; u64 sparse_banks[64]; - int sparse_banks_len, i; + int sparse_banks_len; bool all_cpus; if (!ex) { @@ -1290,6 +1354,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, trace_kvm_hv_flush_tlb(flush.processor_mask, flush.address_space, flush.flags); + valid_bank_mask = BIT_ULL(0); sparse_banks[0] = flush.processor_mask; all_cpus = flush.flags & HV_FLUSH_ALL_PROCESSORS; } else { @@ -1306,7 +1371,8 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, all_cpus = flush_ex.hv_vp_set.format != HV_GENERIC_SET_SPARSE_4K; - sparse_banks_len = bitmap_weight(&valid_bank_mask, 64) * + sparse_banks_len = + bitmap_weight((unsigned long *)&valid_bank_mask, 64) * sizeof(sparse_banks[0]); if (!sparse_banks_len && !all_cpus) @@ -1321,48 +1387,19 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, return HV_STATUS_INVALID_HYPERCALL_INPUT; } - cpumask_clear(&hv_current->tlb_lush); - - kvm_for_each_vcpu(i, vcpu, kvm) { - struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv; - int bank = hv->vp_index / 64, sbank = 0; - - if (!all_cpus) { - /* Banks >64 can't be represented */ - if (bank >= 64) - continue; - - /* Non-ex hypercalls can only address first 64 vCPUs */ - if (!ex && bank) - continue; - - if (ex) { - /* - * Check is the bank of this vCPU is in sparse - * set and get the sparse bank number. - */ - sbank = get_sparse_bank_no(valid_bank_mask, - bank); - - if (sbank < 0) - continue; - } - - if (!(sparse_banks[sbank] & BIT_ULL(hv->vp_index % 64))) - continue; - } + cpumask_clear(&hv_vcpu->tlb_flush); - /* - * vcpu->arch.cr3 may not be up-to-date for running vCPUs so we - * can't analyze it here, flush TLB regardless of the specified - * address space. - */ - __set_bit(i, vcpu_bitmap); - } + vcpu_mask = all_cpus ? NULL : + sparse_set_to_vcpu_mask(kvm, sparse_banks, valid_bank_mask, + vp_bitmap, vcpu_bitmap); + /* + * vcpu->arch.cr3 may not be up-to-date for running vCPUs so we can't + * analyze it here, flush TLB regardless of the specified address space. + */ kvm_make_vcpus_request_mask(kvm, KVM_REQ_TLB_FLUSH | KVM_REQUEST_NO_WAKEUP, - vcpu_bitmap, &hv_current->tlb_lush); + vcpu_mask, &hv_vcpu->tlb_flush); ret_success: /* We always do full TLB flush, set rep_done = rep_cnt. */ @@ -1370,6 +1407,99 @@ ret_success: ((u64)rep_cnt << HV_HYPERCALL_REP_COMP_OFFSET); } +static void kvm_send_ipi_to_many(struct kvm *kvm, u32 vector, + unsigned long *vcpu_bitmap) +{ + struct kvm_lapic_irq irq = { + .delivery_mode = APIC_DM_FIXED, + .vector = vector + }; + struct kvm_vcpu *vcpu; + int i; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (vcpu_bitmap && !test_bit(i, vcpu_bitmap)) + continue; + + /* We fail only when APIC is disabled */ + kvm_apic_set_irq(vcpu, &irq, NULL); + } +} + +static u64 kvm_hv_send_ipi(struct kvm_vcpu *current_vcpu, u64 ingpa, u64 outgpa, + bool ex, bool fast) +{ + struct kvm *kvm = current_vcpu->kvm; + struct hv_send_ipi_ex send_ipi_ex; + struct hv_send_ipi send_ipi; + u64 vp_bitmap[KVM_HV_MAX_SPARSE_VCPU_SET_BITS]; + DECLARE_BITMAP(vcpu_bitmap, KVM_MAX_VCPUS); + unsigned long *vcpu_mask; + unsigned long valid_bank_mask; + u64 sparse_banks[64]; + int sparse_banks_len; + u32 vector; + bool all_cpus; + + if (!ex) { + if (!fast) { + if (unlikely(kvm_read_guest(kvm, ingpa, &send_ipi, + sizeof(send_ipi)))) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + sparse_banks[0] = send_ipi.cpu_mask; + vector = send_ipi.vector; + } else { + /* 'reserved' part of hv_send_ipi should be 0 */ + if (unlikely(ingpa >> 32 != 0)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + sparse_banks[0] = outgpa; + vector = (u32)ingpa; + } + all_cpus = false; + valid_bank_mask = BIT_ULL(0); + + trace_kvm_hv_send_ipi(vector, sparse_banks[0]); + } else { + if (unlikely(kvm_read_guest(kvm, ingpa, &send_ipi_ex, + sizeof(send_ipi_ex)))) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + + trace_kvm_hv_send_ipi_ex(send_ipi_ex.vector, + send_ipi_ex.vp_set.format, + send_ipi_ex.vp_set.valid_bank_mask); + + vector = send_ipi_ex.vector; + valid_bank_mask = send_ipi_ex.vp_set.valid_bank_mask; + sparse_banks_len = bitmap_weight(&valid_bank_mask, 64) * + sizeof(sparse_banks[0]); + + all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL; + + if (!sparse_banks_len) + goto ret_success; + + if (!all_cpus && + kvm_read_guest(kvm, + ingpa + offsetof(struct hv_send_ipi_ex, + vp_set.bank_contents), + sparse_banks, + sparse_banks_len)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } + + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + + vcpu_mask = all_cpus ? NULL : + sparse_set_to_vcpu_mask(kvm, sparse_banks, valid_bank_mask, + vp_bitmap, vcpu_bitmap); + + kvm_send_ipi_to_many(kvm, vector, vcpu_mask); + +ret_success: + return HV_STATUS_SUCCESS; +} + bool kvm_hv_hypercall_enabled(struct kvm *kvm) { return READ_ONCE(kvm->arch.hyperv.hv_hypercall) & HV_X64_MSR_HYPERCALL_ENABLE; @@ -1539,6 +1669,20 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) } ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true); break; + case HVCALL_SEND_IPI: + if (unlikely(rep)) { + ret = HV_STATUS_INVALID_HYPERCALL_INPUT; + break; + } + ret = kvm_hv_send_ipi(vcpu, ingpa, outgpa, false, fast); + break; + case HVCALL_SEND_IPI_EX: + if (unlikely(fast || rep)) { + ret = HV_STATUS_INVALID_HYPERCALL_INPUT; + break; + } + ret = kvm_hv_send_ipi(vcpu, ingpa, outgpa, true, false); + break; default: ret = HV_STATUS_INVALID_HYPERCALL_CODE; break; diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index d6aa969e20f1..0e66c12ed2c3 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -62,6 +62,10 @@ void kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); void kvm_hv_vcpu_postcreate(struct kvm_vcpu *vcpu); void kvm_hv_vcpu_uninit(struct kvm_vcpu *vcpu); +bool kvm_hv_assist_page_enabled(struct kvm_vcpu *vcpu); +bool kvm_hv_get_assist_page(struct kvm_vcpu *vcpu, + struct hv_vp_assist_page *assist_page); + static inline struct kvm_vcpu_hv_stimer *vcpu_to_stimer(struct kvm_vcpu *vcpu, int timer_index) { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index fbb0e6df121b..3cd227ff807f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -70,6 +70,11 @@ #define APIC_BROADCAST 0xFF #define X2APIC_BROADCAST 0xFFFFFFFFul +static bool lapic_timer_advance_adjust_done = false; +#define LAPIC_TIMER_ADVANCE_ADJUST_DONE 100 +/* step-by-step approximation to mitigate fluctuation */ +#define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8 + static inline int apic_test_vector(int vec, void *bitmap) { return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); @@ -955,14 +960,14 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, map = rcu_dereference(kvm->arch.apic_map); ret = kvm_apic_map_get_dest_lapic(kvm, &src, irq, map, &dst, &bitmap); - if (ret) + if (ret) { + *r = 0; for_each_set_bit(i, &bitmap, 16) { if (!dst[i]) continue; - if (*r < 0) - *r = 0; *r += kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map); } + } rcu_read_unlock(); return ret; @@ -1472,7 +1477,7 @@ static bool lapic_timer_int_injected(struct kvm_vcpu *vcpu) void wait_lapic_expire(struct kvm_vcpu *vcpu) { struct kvm_lapic *apic = vcpu->arch.apic; - u64 guest_tsc, tsc_deadline; + u64 guest_tsc, tsc_deadline, ns; if (!lapic_in_kernel(vcpu)) return; @@ -1492,6 +1497,24 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu) if (guest_tsc < tsc_deadline) __delay(min(tsc_deadline - guest_tsc, nsec_to_cycles(vcpu, lapic_timer_advance_ns))); + + if (!lapic_timer_advance_adjust_done) { + /* too early */ + if (guest_tsc < tsc_deadline) { + ns = (tsc_deadline - guest_tsc) * 1000000ULL; + do_div(ns, vcpu->arch.virtual_tsc_khz); + lapic_timer_advance_ns -= min((unsigned int)ns, + lapic_timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP); + } else { + /* too late */ + ns = (guest_tsc - tsc_deadline) * 1000000ULL; + do_div(ns, vcpu->arch.virtual_tsc_khz); + lapic_timer_advance_ns += min((unsigned int)ns, + lapic_timer_advance_ns / LAPIC_TIMER_ADVANCE_ADJUST_STEP); + } + if (abs(guest_tsc - tsc_deadline) < LAPIC_TIMER_ADVANCE_ADJUST_DONE) + lapic_timer_advance_adjust_done = true; + } } static void start_sw_tscdeadline(struct kvm_lapic *apic) @@ -2621,17 +2644,25 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) return 0; } -int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data) +int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len) { u64 addr = data & ~KVM_MSR_ENABLED; + struct gfn_to_hva_cache *ghc = &vcpu->arch.pv_eoi.data; + unsigned long new_len; + if (!IS_ALIGNED(addr, 4)) return 1; vcpu->arch.pv_eoi.msr_val = data; if (!pv_eoi_enabled(vcpu)) return 0; - return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data, - addr, sizeof(u8)); + + if (addr == ghc->gpa && len <= ghc->len) + new_len = ghc->len; + else + new_len = len; + + return kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, addr, new_len); } void kvm_apic_accept_events(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index ed0ed39abd36..ff6ef9c3d760 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -120,7 +120,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) return vcpu->arch.hyperv.hv_vapic & HV_X64_MSR_VP_ASSIST_PAGE_ENABLE; } -int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); +int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len); void kvm_lapic_init(void); void kvm_lapic_exit(void); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 51b953ad9d4e..cf5f572f2305 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -932,7 +932,7 @@ static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, while (cache->nobjs < ARRAY_SIZE(cache->objects)) { obj = kmem_cache_zalloc(base_cache, GFP_KERNEL); if (!obj) - return -ENOMEM; + return cache->nobjs >= min ? 0 : -ENOMEM; cache->objects[cache->nobjs++] = obj; } return 0; @@ -960,7 +960,7 @@ static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache, while (cache->nobjs < ARRAY_SIZE(cache->objects)) { page = (void *)__get_free_page(GFP_KERNEL_ACCOUNT); if (!page) - return -ENOMEM; + return cache->nobjs >= min ? 0 : -ENOMEM; cache->objects[cache->nobjs++] = page; } return 0; @@ -1265,24 +1265,24 @@ pte_list_desc_remove_entry(struct kvm_rmap_head *rmap_head, mmu_free_pte_list_desc(desc); } -static void pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head) +static void __pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head) { struct pte_list_desc *desc; struct pte_list_desc *prev_desc; int i; if (!rmap_head->val) { - printk(KERN_ERR "pte_list_remove: %p 0->BUG\n", spte); + pr_err("%s: %p 0->BUG\n", __func__, spte); BUG(); } else if (!(rmap_head->val & 1)) { - rmap_printk("pte_list_remove: %p 1->0\n", spte); + rmap_printk("%s: %p 1->0\n", __func__, spte); if ((u64 *)rmap_head->val != spte) { - printk(KERN_ERR "pte_list_remove: %p 1->BUG\n", spte); + pr_err("%s: %p 1->BUG\n", __func__, spte); BUG(); } rmap_head->val = 0; } else { - rmap_printk("pte_list_remove: %p many->many\n", spte); + rmap_printk("%s: %p many->many\n", __func__, spte); desc = (struct pte_list_desc *)(rmap_head->val & ~1ul); prev_desc = NULL; while (desc) { @@ -1296,11 +1296,17 @@ static void pte_list_remove(u64 *spte, struct kvm_rmap_head *rmap_head) prev_desc = desc; desc = desc->more; } - pr_err("pte_list_remove: %p many->many\n", spte); + pr_err("%s: %p many->many\n", __func__, spte); BUG(); } } +static void pte_list_remove(struct kvm_rmap_head *rmap_head, u64 *sptep) +{ + mmu_spte_clear_track_bits(sptep); + __pte_list_remove(sptep, rmap_head); +} + static struct kvm_rmap_head *__gfn_to_rmap(gfn_t gfn, int level, struct kvm_memory_slot *slot) { @@ -1349,7 +1355,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) sp = page_header(__pa(spte)); gfn = kvm_mmu_page_get_gfn(sp, spte - sp->spt); rmap_head = gfn_to_rmap(kvm, gfn, sp); - pte_list_remove(spte, rmap_head); + __pte_list_remove(spte, rmap_head); } /* @@ -1685,7 +1691,7 @@ static bool kvm_zap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head) while ((sptep = rmap_get_first(rmap_head, &iter))) { rmap_printk("%s: spte %p %llx.\n", __func__, sptep, *sptep); - drop_spte(kvm, sptep); + pte_list_remove(rmap_head, sptep); flush = true; } @@ -1721,7 +1727,7 @@ restart: need_flush = 1; if (pte_write(*ptep)) { - drop_spte(kvm, sptep); + pte_list_remove(rmap_head, sptep); goto restart; } else { new_spte = *sptep & ~PT64_BASE_ADDR_MASK; @@ -1988,7 +1994,7 @@ static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu, static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp, u64 *parent_pte) { - pte_list_remove(parent_pte, &sp->parent_ptes); + __pte_list_remove(parent_pte, &sp->parent_ptes); } static void drop_parent_pte(struct kvm_mmu_page *sp, @@ -2181,7 +2187,7 @@ static bool __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, struct list_head *invalid_list) { if (sp->role.cr4_pae != !!is_pae(vcpu) - || vcpu->arch.mmu.sync_page(vcpu, sp) == 0) { + || vcpu->arch.mmu->sync_page(vcpu, sp) == 0) { kvm_mmu_prepare_zap_page(vcpu->kvm, sp, invalid_list); return false; } @@ -2375,14 +2381,14 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, int collisions = 0; LIST_HEAD(invalid_list); - role = vcpu->arch.mmu.base_role; + role = vcpu->arch.mmu->mmu_role.base; role.level = level; role.direct = direct; if (role.direct) role.cr4_pae = 0; role.access = access; - if (!vcpu->arch.mmu.direct_map - && vcpu->arch.mmu.root_level <= PT32_ROOT_LEVEL) { + if (!vcpu->arch.mmu->direct_map + && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) { quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level)); quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1; role.quadrant = quadrant; @@ -2457,11 +2463,11 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato { iterator->addr = addr; iterator->shadow_addr = root; - iterator->level = vcpu->arch.mmu.shadow_root_level; + iterator->level = vcpu->arch.mmu->shadow_root_level; if (iterator->level == PT64_ROOT_4LEVEL && - vcpu->arch.mmu.root_level < PT64_ROOT_4LEVEL && - !vcpu->arch.mmu.direct_map) + vcpu->arch.mmu->root_level < PT64_ROOT_4LEVEL && + !vcpu->arch.mmu->direct_map) --iterator->level; if (iterator->level == PT32E_ROOT_LEVEL) { @@ -2469,10 +2475,10 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato * prev_root is currently only used for 64-bit hosts. So only * the active root_hpa is valid here. */ - BUG_ON(root != vcpu->arch.mmu.root_hpa); + BUG_ON(root != vcpu->arch.mmu->root_hpa); iterator->shadow_addr - = vcpu->arch.mmu.pae_root[(addr >> 30) & 3]; + = vcpu->arch.mmu->pae_root[(addr >> 30) & 3]; iterator->shadow_addr &= PT64_BASE_ADDR_MASK; --iterator->level; if (!iterator->shadow_addr) @@ -2483,7 +2489,7 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato static void shadow_walk_init(struct kvm_shadow_walk_iterator *iterator, struct kvm_vcpu *vcpu, u64 addr) { - shadow_walk_init_using_root(iterator, vcpu, vcpu->arch.mmu.root_hpa, + shadow_walk_init_using_root(iterator, vcpu, vcpu->arch.mmu->root_hpa, addr); } @@ -3095,7 +3101,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, int write, int map_writable, int emulate = 0; gfn_t pseudo_gfn; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return 0; for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) { @@ -3125,16 +3131,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, int write, int map_writable, static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *tsk) { - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_MCEERR_AR; - info.si_addr = (void __user *)address; - info.si_addr_lsb = PAGE_SHIFT; - - send_sig_info(SIGBUS, &info, tsk); + send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, PAGE_SHIFT, tsk); } static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn) @@ -3310,7 +3307,7 @@ static bool fast_page_fault(struct kvm_vcpu *vcpu, gva_t gva, int level, u64 spte = 0ull; uint retry_count = 0; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return false; if (!page_fault_can_be_fast(error_code)) @@ -3480,11 +3477,11 @@ static void mmu_free_root_page(struct kvm *kvm, hpa_t *root_hpa, } /* roots_to_free must be some combination of the KVM_MMU_ROOT_* flags */ -void kvm_mmu_free_roots(struct kvm_vcpu *vcpu, ulong roots_to_free) +void kvm_mmu_free_roots(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, + ulong roots_to_free) { int i; LIST_HEAD(invalid_list); - struct kvm_mmu *mmu = &vcpu->arch.mmu; bool free_active_root = roots_to_free & KVM_MMU_ROOT_CURRENT; BUILD_BUG_ON(KVM_MMU_NUM_PREV_ROOTS >= BITS_PER_LONG); @@ -3544,20 +3541,20 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) struct kvm_mmu_page *sp; unsigned i; - if (vcpu->arch.mmu.shadow_root_level >= PT64_ROOT_4LEVEL) { + if (vcpu->arch.mmu->shadow_root_level >= PT64_ROOT_4LEVEL) { spin_lock(&vcpu->kvm->mmu_lock); if(make_mmu_pages_available(vcpu) < 0) { spin_unlock(&vcpu->kvm->mmu_lock); return -ENOSPC; } sp = kvm_mmu_get_page(vcpu, 0, 0, - vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL); + vcpu->arch.mmu->shadow_root_level, 1, ACC_ALL); ++sp->root_count; spin_unlock(&vcpu->kvm->mmu_lock); - vcpu->arch.mmu.root_hpa = __pa(sp->spt); - } else if (vcpu->arch.mmu.shadow_root_level == PT32E_ROOT_LEVEL) { + vcpu->arch.mmu->root_hpa = __pa(sp->spt); + } else if (vcpu->arch.mmu->shadow_root_level == PT32E_ROOT_LEVEL) { for (i = 0; i < 4; ++i) { - hpa_t root = vcpu->arch.mmu.pae_root[i]; + hpa_t root = vcpu->arch.mmu->pae_root[i]; MMU_WARN_ON(VALID_PAGE(root)); spin_lock(&vcpu->kvm->mmu_lock); @@ -3570,9 +3567,9 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) root = __pa(sp->spt); ++sp->root_count; spin_unlock(&vcpu->kvm->mmu_lock); - vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK; + vcpu->arch.mmu->pae_root[i] = root | PT_PRESENT_MASK; } - vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); + vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->pae_root); } else BUG(); @@ -3586,7 +3583,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) gfn_t root_gfn; int i; - root_gfn = vcpu->arch.mmu.get_cr3(vcpu) >> PAGE_SHIFT; + root_gfn = vcpu->arch.mmu->get_cr3(vcpu) >> PAGE_SHIFT; if (mmu_check_root(vcpu, root_gfn)) return 1; @@ -3595,8 +3592,8 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) * Do we shadow a long mode page table? If so we need to * write-protect the guests page table root. */ - if (vcpu->arch.mmu.root_level >= PT64_ROOT_4LEVEL) { - hpa_t root = vcpu->arch.mmu.root_hpa; + if (vcpu->arch.mmu->root_level >= PT64_ROOT_4LEVEL) { + hpa_t root = vcpu->arch.mmu->root_hpa; MMU_WARN_ON(VALID_PAGE(root)); @@ -3606,11 +3603,11 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) return -ENOSPC; } sp = kvm_mmu_get_page(vcpu, root_gfn, 0, - vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL); + vcpu->arch.mmu->shadow_root_level, 0, ACC_ALL); root = __pa(sp->spt); ++sp->root_count; spin_unlock(&vcpu->kvm->mmu_lock); - vcpu->arch.mmu.root_hpa = root; + vcpu->arch.mmu->root_hpa = root; return 0; } @@ -3620,17 +3617,17 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) * the shadow page table may be a PAE or a long mode page table. */ pm_mask = PT_PRESENT_MASK; - if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_4LEVEL) + if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL) pm_mask |= PT_ACCESSED_MASK | PT_WRITABLE_MASK | PT_USER_MASK; for (i = 0; i < 4; ++i) { - hpa_t root = vcpu->arch.mmu.pae_root[i]; + hpa_t root = vcpu->arch.mmu->pae_root[i]; MMU_WARN_ON(VALID_PAGE(root)); - if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) { - pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i); + if (vcpu->arch.mmu->root_level == PT32E_ROOT_LEVEL) { + pdptr = vcpu->arch.mmu->get_pdptr(vcpu, i); if (!(pdptr & PT_PRESENT_MASK)) { - vcpu->arch.mmu.pae_root[i] = 0; + vcpu->arch.mmu->pae_root[i] = 0; continue; } root_gfn = pdptr >> PAGE_SHIFT; @@ -3648,16 +3645,16 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) ++sp->root_count; spin_unlock(&vcpu->kvm->mmu_lock); - vcpu->arch.mmu.pae_root[i] = root | pm_mask; + vcpu->arch.mmu->pae_root[i] = root | pm_mask; } - vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); + vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->pae_root); /* * If we shadow a 32 bit page table with a long mode page * table we enter this path. */ - if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_4LEVEL) { - if (vcpu->arch.mmu.lm_root == NULL) { + if (vcpu->arch.mmu->shadow_root_level == PT64_ROOT_4LEVEL) { + if (vcpu->arch.mmu->lm_root == NULL) { /* * The additional page necessary for this is only * allocated on demand. @@ -3669,12 +3666,12 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) if (lm_root == NULL) return 1; - lm_root[0] = __pa(vcpu->arch.mmu.pae_root) | pm_mask; + lm_root[0] = __pa(vcpu->arch.mmu->pae_root) | pm_mask; - vcpu->arch.mmu.lm_root = lm_root; + vcpu->arch.mmu->lm_root = lm_root; } - vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.lm_root); + vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->lm_root); } return 0; @@ -3682,7 +3679,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) static int mmu_alloc_roots(struct kvm_vcpu *vcpu) { - if (vcpu->arch.mmu.direct_map) + if (vcpu->arch.mmu->direct_map) return mmu_alloc_direct_roots(vcpu); else return mmu_alloc_shadow_roots(vcpu); @@ -3693,17 +3690,16 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) int i; struct kvm_mmu_page *sp; - if (vcpu->arch.mmu.direct_map) + if (vcpu->arch.mmu->direct_map) return; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return; vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY); - if (vcpu->arch.mmu.root_level >= PT64_ROOT_4LEVEL) { - hpa_t root = vcpu->arch.mmu.root_hpa; - + if (vcpu->arch.mmu->root_level >= PT64_ROOT_4LEVEL) { + hpa_t root = vcpu->arch.mmu->root_hpa; sp = page_header(root); /* @@ -3734,7 +3730,7 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC); for (i = 0; i < 4; ++i) { - hpa_t root = vcpu->arch.mmu.pae_root[i]; + hpa_t root = vcpu->arch.mmu->pae_root[i]; if (root && VALID_PAGE(root)) { root &= PT64_BASE_ADDR_MASK; @@ -3808,7 +3804,7 @@ walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep) int root, leaf; bool reserved = false; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) goto exit; walk_shadow_page_lockless_begin(vcpu); @@ -3825,7 +3821,7 @@ walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep) if (!is_shadow_present_pte(spte)) break; - reserved |= is_shadow_zero_bits_set(&vcpu->arch.mmu, spte, + reserved |= is_shadow_zero_bits_set(vcpu->arch.mmu, spte, iterator.level); } @@ -3904,7 +3900,7 @@ static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr) struct kvm_shadow_walk_iterator iterator; u64 spte; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return; walk_shadow_page_lockless_begin(vcpu); @@ -3931,7 +3927,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, if (r) return r; - MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)); return nonpaging_map(vcpu, gva & PAGE_MASK, @@ -3944,8 +3940,8 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn) arch.token = (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id; arch.gfn = gfn; - arch.direct_map = vcpu->arch.mmu.direct_map; - arch.cr3 = vcpu->arch.mmu.get_cr3(vcpu); + arch.direct_map = vcpu->arch.mmu->direct_map; + arch.cr3 = vcpu->arch.mmu->get_cr3(vcpu); return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch); } @@ -4051,7 +4047,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, int write = error_code & PFERR_WRITE_MASK; bool map_writable; - MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa)); if (page_fault_handle_page_track(vcpu, error_code, gfn)) return RET_PF_EMULATE; @@ -4127,7 +4123,7 @@ static bool cached_root_available(struct kvm_vcpu *vcpu, gpa_t new_cr3, { uint i; struct kvm_mmu_root_info root; - struct kvm_mmu *mmu = &vcpu->arch.mmu; + struct kvm_mmu *mmu = vcpu->arch.mmu; root.cr3 = mmu->get_cr3(vcpu); root.hpa = mmu->root_hpa; @@ -4150,7 +4146,7 @@ static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3, union kvm_mmu_page_role new_role, bool skip_tlb_flush) { - struct kvm_mmu *mmu = &vcpu->arch.mmu; + struct kvm_mmu *mmu = vcpu->arch.mmu; /* * For now, limit the fast switch to 64-bit hosts+VMs in order to avoid @@ -4201,7 +4197,8 @@ static void __kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3, bool skip_tlb_flush) { if (!fast_cr3_switch(vcpu, new_cr3, new_role, skip_tlb_flush)) - kvm_mmu_free_roots(vcpu, KVM_MMU_ROOT_CURRENT); + kvm_mmu_free_roots(vcpu, vcpu->arch.mmu, + KVM_MMU_ROOT_CURRENT); } void kvm_mmu_new_cr3(struct kvm_vcpu *vcpu, gpa_t new_cr3, bool skip_tlb_flush) @@ -4219,7 +4216,7 @@ static unsigned long get_cr3(struct kvm_vcpu *vcpu) static void inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault) { - vcpu->arch.mmu.inject_page_fault(vcpu, fault); + vcpu->arch.mmu->inject_page_fault(vcpu, fault); } static bool sync_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, gfn_t gfn, @@ -4423,7 +4420,8 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu, void reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context) { - bool uses_nx = context->nx || context->base_role.smep_andnot_wp; + bool uses_nx = context->nx || + context->mmu_role.base.smep_andnot_wp; struct rsvd_bits_validate *shadow_zero_check; int i; @@ -4562,7 +4560,7 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu, * SMAP:kernel-mode data accesses from user-mode * mappings should fault. A fault is considered * as a SMAP violation if all of the following - * conditions are ture: + * conditions are true: * - X86_CR4_SMAP is set in CR4 * - A user page is accessed * - The access is not a fetch @@ -4723,27 +4721,65 @@ static void paging32E_init_context(struct kvm_vcpu *vcpu, paging64_init_context_common(vcpu, context, PT32E_ROOT_LEVEL); } -static union kvm_mmu_page_role -kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu) +static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu) +{ + union kvm_mmu_extended_role ext = {0}; + + ext.cr0_pg = !!is_paging(vcpu); + ext.cr4_smep = !!kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); + ext.cr4_smap = !!kvm_read_cr4_bits(vcpu, X86_CR4_SMAP); + ext.cr4_pse = !!is_pse(vcpu); + ext.cr4_pke = !!kvm_read_cr4_bits(vcpu, X86_CR4_PKE); + ext.cr4_la57 = !!kvm_read_cr4_bits(vcpu, X86_CR4_LA57); + + ext.valid = 1; + + return ext; +} + +static union kvm_mmu_role kvm_calc_mmu_role_common(struct kvm_vcpu *vcpu, + bool base_only) { - union kvm_mmu_page_role role = {0}; + union kvm_mmu_role role = {0}; - role.guest_mode = is_guest_mode(vcpu); - role.smm = is_smm(vcpu); - role.ad_disabled = (shadow_accessed_mask == 0); - role.level = kvm_x86_ops->get_tdp_level(vcpu); - role.direct = true; - role.access = ACC_ALL; + role.base.access = ACC_ALL; + role.base.nxe = !!is_nx(vcpu); + role.base.cr4_pae = !!is_pae(vcpu); + role.base.cr0_wp = is_write_protection(vcpu); + role.base.smm = is_smm(vcpu); + role.base.guest_mode = is_guest_mode(vcpu); + + if (base_only) + return role; + + role.ext = kvm_calc_mmu_role_ext(vcpu); + + return role; +} + +static union kvm_mmu_role +kvm_calc_tdp_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) +{ + union kvm_mmu_role role = kvm_calc_mmu_role_common(vcpu, base_only); + + role.base.ad_disabled = (shadow_accessed_mask == 0); + role.base.level = kvm_x86_ops->get_tdp_level(vcpu); + role.base.direct = true; return role; } static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = &vcpu->arch.mmu; + struct kvm_mmu *context = vcpu->arch.mmu; + union kvm_mmu_role new_role = + kvm_calc_tdp_mmu_root_page_role(vcpu, false); + + new_role.base.word &= mmu_base_role_mask.word; + if (new_role.as_u64 == context->mmu_role.as_u64) + return; - context->base_role.word = mmu_base_role_mask.word & - kvm_calc_tdp_mmu_root_page_role(vcpu).word; + context->mmu_role.as_u64 = new_role.as_u64; context->page_fault = tdp_page_fault; context->sync_page = nonpaging_sync_page; context->invlpg = nonpaging_invlpg; @@ -4783,36 +4819,36 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) reset_tdp_shadow_zero_bits_mask(vcpu, context); } -static union kvm_mmu_page_role -kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu) -{ - union kvm_mmu_page_role role = {0}; - bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); - bool smap = kvm_read_cr4_bits(vcpu, X86_CR4_SMAP); - - role.nxe = is_nx(vcpu); - role.cr4_pae = !!is_pae(vcpu); - role.cr0_wp = is_write_protection(vcpu); - role.smep_andnot_wp = smep && !is_write_protection(vcpu); - role.smap_andnot_wp = smap && !is_write_protection(vcpu); - role.guest_mode = is_guest_mode(vcpu); - role.smm = is_smm(vcpu); - role.direct = !is_paging(vcpu); - role.access = ACC_ALL; +static union kvm_mmu_role +kvm_calc_shadow_mmu_root_page_role(struct kvm_vcpu *vcpu, bool base_only) +{ + union kvm_mmu_role role = kvm_calc_mmu_role_common(vcpu, base_only); + + role.base.smep_andnot_wp = role.ext.cr4_smep && + !is_write_protection(vcpu); + role.base.smap_andnot_wp = role.ext.cr4_smap && + !is_write_protection(vcpu); + role.base.direct = !is_paging(vcpu); if (!is_long_mode(vcpu)) - role.level = PT32E_ROOT_LEVEL; + role.base.level = PT32E_ROOT_LEVEL; else if (is_la57_mode(vcpu)) - role.level = PT64_ROOT_5LEVEL; + role.base.level = PT64_ROOT_5LEVEL; else - role.level = PT64_ROOT_4LEVEL; + role.base.level = PT64_ROOT_4LEVEL; return role; } void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = &vcpu->arch.mmu; + struct kvm_mmu *context = vcpu->arch.mmu; + union kvm_mmu_role new_role = + kvm_calc_shadow_mmu_root_page_role(vcpu, false); + + new_role.base.word &= mmu_base_role_mask.word; + if (new_role.as_u64 == context->mmu_role.as_u64) + return; if (!is_paging(vcpu)) nonpaging_init_context(vcpu, context); @@ -4823,22 +4859,28 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu) else paging32_init_context(vcpu, context); - context->base_role.word = mmu_base_role_mask.word & - kvm_calc_shadow_mmu_root_page_role(vcpu).word; + context->mmu_role.as_u64 = new_role.as_u64; reset_shadow_zero_bits_mask(vcpu, context); } EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu); -static union kvm_mmu_page_role -kvm_calc_shadow_ept_root_page_role(struct kvm_vcpu *vcpu, bool accessed_dirty) +static union kvm_mmu_role +kvm_calc_shadow_ept_root_page_role(struct kvm_vcpu *vcpu, bool accessed_dirty, + bool execonly) { - union kvm_mmu_page_role role = vcpu->arch.mmu.base_role; + union kvm_mmu_role role; + + /* Base role is inherited from root_mmu */ + role.base.word = vcpu->arch.root_mmu.mmu_role.base.word; + role.ext = kvm_calc_mmu_role_ext(vcpu); - role.level = PT64_ROOT_4LEVEL; - role.direct = false; - role.ad_disabled = !accessed_dirty; - role.guest_mode = true; - role.access = ACC_ALL; + role.base.level = PT64_ROOT_4LEVEL; + role.base.direct = false; + role.base.ad_disabled = !accessed_dirty; + role.base.guest_mode = true; + role.base.access = ACC_ALL; + + role.ext.execonly = execonly; return role; } @@ -4846,11 +4888,17 @@ kvm_calc_shadow_ept_root_page_role(struct kvm_vcpu *vcpu, bool accessed_dirty) void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, bool accessed_dirty, gpa_t new_eptp) { - struct kvm_mmu *context = &vcpu->arch.mmu; - union kvm_mmu_page_role root_page_role = - kvm_calc_shadow_ept_root_page_role(vcpu, accessed_dirty); + struct kvm_mmu *context = vcpu->arch.mmu; + union kvm_mmu_role new_role = + kvm_calc_shadow_ept_root_page_role(vcpu, accessed_dirty, + execonly); + + __kvm_mmu_new_cr3(vcpu, new_eptp, new_role.base, false); + + new_role.base.word &= mmu_base_role_mask.word; + if (new_role.as_u64 == context->mmu_role.as_u64) + return; - __kvm_mmu_new_cr3(vcpu, new_eptp, root_page_role, false); context->shadow_root_level = PT64_ROOT_4LEVEL; context->nx = true; @@ -4862,7 +4910,8 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, context->update_pte = ept_update_pte; context->root_level = PT64_ROOT_4LEVEL; context->direct_map = false; - context->base_role.word = root_page_role.word & mmu_base_role_mask.word; + context->mmu_role.as_u64 = new_role.as_u64; + update_permission_bitmask(vcpu, context, true); update_pkru_bitmask(vcpu, context, true); update_last_nonleaf_level(vcpu, context); @@ -4873,7 +4922,7 @@ EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu); static void init_kvm_softmmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = &vcpu->arch.mmu; + struct kvm_mmu *context = vcpu->arch.mmu; kvm_init_shadow_mmu(vcpu); context->set_cr3 = kvm_x86_ops->set_cr3; @@ -4884,14 +4933,20 @@ static void init_kvm_softmmu(struct kvm_vcpu *vcpu) static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu) { + union kvm_mmu_role new_role = kvm_calc_mmu_role_common(vcpu, false); struct kvm_mmu *g_context = &vcpu->arch.nested_mmu; + new_role.base.word &= mmu_base_role_mask.word; + if (new_role.as_u64 == g_context->mmu_role.as_u64) + return; + + g_context->mmu_role.as_u64 = new_role.as_u64; g_context->get_cr3 = get_cr3; g_context->get_pdptr = kvm_pdptr_read; g_context->inject_page_fault = kvm_inject_page_fault; /* - * Note that arch.mmu.gva_to_gpa translates l2_gpa to l1_gpa using + * Note that arch.mmu->gva_to_gpa translates l2_gpa to l1_gpa using * L1's nested page tables (e.g. EPT12). The nested translation * of l2_gva to l1_gpa is done by arch.nested_mmu.gva_to_gpa using * L2's page tables as the first level of translation and L1's @@ -4930,10 +4985,10 @@ void kvm_init_mmu(struct kvm_vcpu *vcpu, bool reset_roots) if (reset_roots) { uint i; - vcpu->arch.mmu.root_hpa = INVALID_PAGE; + vcpu->arch.mmu->root_hpa = INVALID_PAGE; for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) - vcpu->arch.mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID; + vcpu->arch.mmu->prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID; } if (mmu_is_nested(vcpu)) @@ -4948,10 +5003,14 @@ EXPORT_SYMBOL_GPL(kvm_init_mmu); static union kvm_mmu_page_role kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu) { + union kvm_mmu_role role; + if (tdp_enabled) - return kvm_calc_tdp_mmu_root_page_role(vcpu); + role = kvm_calc_tdp_mmu_root_page_role(vcpu, true); else - return kvm_calc_shadow_mmu_root_page_role(vcpu); + role = kvm_calc_shadow_mmu_root_page_role(vcpu, true); + + return role.base; } void kvm_mmu_reset_context(struct kvm_vcpu *vcpu) @@ -4981,8 +5040,10 @@ EXPORT_SYMBOL_GPL(kvm_mmu_load); void kvm_mmu_unload(struct kvm_vcpu *vcpu) { - kvm_mmu_free_roots(vcpu, KVM_MMU_ROOTS_ALL); - WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa)); + kvm_mmu_free_roots(vcpu, &vcpu->arch.root_mmu, KVM_MMU_ROOTS_ALL); + WARN_ON(VALID_PAGE(vcpu->arch.root_mmu.root_hpa)); + kvm_mmu_free_roots(vcpu, &vcpu->arch.guest_mmu, KVM_MMU_ROOTS_ALL); + WARN_ON(VALID_PAGE(vcpu->arch.guest_mmu.root_hpa)); } EXPORT_SYMBOL_GPL(kvm_mmu_unload); @@ -4996,7 +5057,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, } ++vcpu->kvm->stat.mmu_pte_updated; - vcpu->arch.mmu.update_pte(vcpu, sp, spte, new); + vcpu->arch.mmu->update_pte(vcpu, sp, spte, new); } static bool need_remote_flush(u64 old, u64 new) @@ -5173,10 +5234,12 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, local_flush = true; while (npte--) { + u32 base_role = vcpu->arch.mmu->mmu_role.base.word; + entry = *spte; mmu_page_zap_pte(vcpu->kvm, sp, spte); if (gentry && - !((sp->role.word ^ vcpu->arch.mmu.base_role.word) + !((sp->role.word ^ base_role) & mmu_base_role_mask.word) && rmap_can_add(vcpu)) mmu_pte_write_new_pte(vcpu, sp, spte, &gentry); if (need_remote_flush(entry, *spte)) @@ -5194,7 +5257,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) gpa_t gpa; int r; - if (vcpu->arch.mmu.direct_map) + if (vcpu->arch.mmu->direct_map) return 0; gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL); @@ -5230,10 +5293,10 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, { int r, emulation_type = 0; enum emulation_result er; - bool direct = vcpu->arch.mmu.direct_map; + bool direct = vcpu->arch.mmu->direct_map; /* With shadow page tables, fault_address contains a GVA or nGPA. */ - if (vcpu->arch.mmu.direct_map) { + if (vcpu->arch.mmu->direct_map) { vcpu->arch.gpa_available = true; vcpu->arch.gpa_val = cr2; } @@ -5246,8 +5309,9 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, } if (r == RET_PF_INVALID) { - r = vcpu->arch.mmu.page_fault(vcpu, cr2, lower_32_bits(error_code), - false); + r = vcpu->arch.mmu->page_fault(vcpu, cr2, + lower_32_bits(error_code), + false); WARN_ON(r == RET_PF_INVALID); } @@ -5263,7 +5327,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, * paging in both guests. If true, we simply unprotect the page * and resume the guest. */ - if (vcpu->arch.mmu.direct_map && + if (vcpu->arch.mmu->direct_map && (error_code & PFERR_NESTED_GUEST_PAGE) == PFERR_NESTED_GUEST_PAGE) { kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(cr2)); return 1; @@ -5311,7 +5375,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_page_fault); void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) { - struct kvm_mmu *mmu = &vcpu->arch.mmu; + struct kvm_mmu *mmu = vcpu->arch.mmu; int i; /* INVLPG on a * non-canonical address is a NOP according to the SDM. */ @@ -5342,7 +5406,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_invlpg); void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid) { - struct kvm_mmu *mmu = &vcpu->arch.mmu; + struct kvm_mmu *mmu = vcpu->arch.mmu; bool tlb_flush = false; uint i; @@ -5386,8 +5450,8 @@ EXPORT_SYMBOL_GPL(kvm_disable_tdp); static void free_mmu_pages(struct kvm_vcpu *vcpu) { - free_page((unsigned long)vcpu->arch.mmu.pae_root); - free_page((unsigned long)vcpu->arch.mmu.lm_root); + free_page((unsigned long)vcpu->arch.mmu->pae_root); + free_page((unsigned long)vcpu->arch.mmu->lm_root); } static int alloc_mmu_pages(struct kvm_vcpu *vcpu) @@ -5407,9 +5471,9 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu) if (!page) return -ENOMEM; - vcpu->arch.mmu.pae_root = page_address(page); + vcpu->arch.mmu->pae_root = page_address(page); for (i = 0; i < 4; ++i) - vcpu->arch.mmu.pae_root[i] = INVALID_PAGE; + vcpu->arch.mmu->pae_root[i] = INVALID_PAGE; return 0; } @@ -5418,27 +5482,21 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu) { uint i; - vcpu->arch.walk_mmu = &vcpu->arch.mmu; - vcpu->arch.mmu.root_hpa = INVALID_PAGE; - vcpu->arch.mmu.translate_gpa = translate_gpa; - vcpu->arch.nested_mmu.translate_gpa = translate_nested_gpa; + vcpu->arch.mmu = &vcpu->arch.root_mmu; + vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; + vcpu->arch.root_mmu.root_hpa = INVALID_PAGE; + vcpu->arch.root_mmu.translate_gpa = translate_gpa; for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) - vcpu->arch.mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID; - - return alloc_mmu_pages(vcpu); -} + vcpu->arch.root_mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID; -void kvm_mmu_setup(struct kvm_vcpu *vcpu) -{ - MMU_WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa)); + vcpu->arch.guest_mmu.root_hpa = INVALID_PAGE; + vcpu->arch.guest_mmu.translate_gpa = translate_gpa; + for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) + vcpu->arch.guest_mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID; - /* - * kvm_mmu_setup() is called only on vCPU initialization. - * Therefore, no need to reset mmu roots as they are not yet - * initialized. - */ - kvm_init_mmu(vcpu, false); + vcpu->arch.nested_mmu.translate_gpa = translate_nested_gpa; + return alloc_mmu_pages(vcpu); } static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm, @@ -5621,7 +5679,7 @@ restart: if (sp->role.direct && !kvm_is_reserved_pfn(pfn) && PageTransCompoundMap(pfn_to_page(pfn))) { - drop_spte(kvm, sptep); + pte_list_remove(rmap_head, sptep); need_tlb_flush = 1; goto restart; } @@ -5878,6 +5936,16 @@ int kvm_mmu_module_init(void) { int ret = -ENOMEM; + /* + * MMU roles use union aliasing which is, generally speaking, an + * undefined behavior. However, we supposedly know how compilers behave + * and the current status quo is unlikely to change. Guardians below are + * supposed to let us know if the assumption becomes false. + */ + BUILD_BUG_ON(sizeof(union kvm_mmu_page_role) != sizeof(u32)); + BUILD_BUG_ON(sizeof(union kvm_mmu_extended_role) != sizeof(u32)); + BUILD_BUG_ON(sizeof(union kvm_mmu_role) != sizeof(u64)); + kvm_mmu_reset_all_pte_masks(); pte_list_desc_cache = kmem_cache_create("pte_list_desc", @@ -5907,7 +5975,7 @@ out: } /* - * Caculate mmu pages needed for kvm. + * Calculate mmu pages needed for kvm. */ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm) { diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 1fab69c0b2f3..c7b333147c4a 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -43,11 +43,6 @@ #define PT32_ROOT_LEVEL 2 #define PT32E_ROOT_LEVEL 3 -#define PT_PDPE_LEVEL 3 -#define PT_DIRECTORY_LEVEL 2 -#define PT_PAGE_TABLE_LEVEL 1 -#define PT_MAX_HUGEPAGE_LEVEL (PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES - 1) - static inline u64 rsvd_bits(int s, int e) { if (e < s) @@ -80,7 +75,7 @@ static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm) static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu) { - if (likely(vcpu->arch.mmu.root_hpa != INVALID_PAGE)) + if (likely(vcpu->arch.mmu->root_hpa != INVALID_PAGE)) return 0; return kvm_mmu_load(vcpu); @@ -102,9 +97,9 @@ static inline unsigned long kvm_get_active_pcid(struct kvm_vcpu *vcpu) static inline void kvm_mmu_load_cr3(struct kvm_vcpu *vcpu) { - if (VALID_PAGE(vcpu->arch.mmu.root_hpa)) - vcpu->arch.mmu.set_cr3(vcpu, vcpu->arch.mmu.root_hpa | - kvm_get_active_pcid(vcpu)); + if (VALID_PAGE(vcpu->arch.mmu->root_hpa)) + vcpu->arch.mmu->set_cr3(vcpu, vcpu->arch.mmu->root_hpa | + kvm_get_active_pcid(vcpu)); } /* diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index 1272861e77b9..abac7e208853 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c @@ -59,19 +59,19 @@ static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn) int i; struct kvm_mmu_page *sp; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return; - if (vcpu->arch.mmu.root_level >= PT64_ROOT_4LEVEL) { - hpa_t root = vcpu->arch.mmu.root_hpa; + if (vcpu->arch.mmu->root_level >= PT64_ROOT_4LEVEL) { + hpa_t root = vcpu->arch.mmu->root_hpa; sp = page_header(root); - __mmu_spte_walk(vcpu, sp, fn, vcpu->arch.mmu.root_level); + __mmu_spte_walk(vcpu, sp, fn, vcpu->arch.mmu->root_level); return; } for (i = 0; i < 4; ++i) { - hpa_t root = vcpu->arch.mmu.pae_root[i]; + hpa_t root = vcpu->arch.mmu->pae_root[i]; if (root && VALID_PAGE(root)) { root &= PT64_BASE_ADDR_MASK; @@ -122,7 +122,7 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) hpa = pfn << PAGE_SHIFT; if ((*sptep & PT64_BASE_ADDR_MASK) != hpa) audit_printk(vcpu->kvm, "levels %d pfn %llx hpa %llx " - "ent %llxn", vcpu->arch.mmu.root_level, pfn, + "ent %llxn", vcpu->arch.mmu->root_level, pfn, hpa, *sptep); } diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 14ffd973df54..7cf2185b7eb5 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -158,14 +158,15 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, u64 *spte, u64 gpte) { - if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL)) + if (is_rsvd_bits_set(vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL)) goto no_present; if (!FNAME(is_present_gpte)(gpte)) goto no_present; /* if accessed bit is not supported prefetch non accessed gpte */ - if (PT_HAVE_ACCESSED_DIRTY(&vcpu->arch.mmu) && !(gpte & PT_GUEST_ACCESSED_MASK)) + if (PT_HAVE_ACCESSED_DIRTY(vcpu->arch.mmu) && + !(gpte & PT_GUEST_ACCESSED_MASK)) goto no_present; return false; @@ -480,7 +481,7 @@ error: static int FNAME(walk_addr)(struct guest_walker *walker, struct kvm_vcpu *vcpu, gva_t addr, u32 access) { - return FNAME(walk_addr_generic)(walker, vcpu, &vcpu->arch.mmu, addr, + return FNAME(walk_addr_generic)(walker, vcpu, vcpu->arch.mmu, addr, access); } @@ -509,7 +510,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, gfn = gpte_to_gfn(gpte); pte_access = sp->role.access & FNAME(gpte_access)(gpte); - FNAME(protect_clean_gpte)(&vcpu->arch.mmu, &pte_access, gpte); + FNAME(protect_clean_gpte)(vcpu->arch.mmu, &pte_access, gpte); pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn, no_dirty_log && (pte_access & ACC_WRITE_MASK)); if (is_error_pfn(pfn)) @@ -604,7 +605,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, direct_access = gw->pte_access; - top_level = vcpu->arch.mmu.root_level; + top_level = vcpu->arch.mmu->root_level; if (top_level == PT32E_ROOT_LEVEL) top_level = PT32_ROOT_LEVEL; /* @@ -616,7 +617,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, if (FNAME(gpte_changed)(vcpu, gw, top_level)) goto out_gpte_changed; - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) goto out_gpte_changed; for (shadow_walk_init(&it, vcpu, addr); @@ -1004,7 +1005,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) gfn = gpte_to_gfn(gpte); pte_access = sp->role.access; pte_access &= FNAME(gpte_access)(gpte); - FNAME(protect_clean_gpte)(&vcpu->arch.mmu, &pte_access, gpte); + FNAME(protect_clean_gpte)(vcpu->arch.mmu, &pte_access, gpte); if (sync_mmio_spte(vcpu, &sp->spt[i], gfn, pte_access, &nr_present)) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 61ccfb13899e..0e21ccc46792 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -809,6 +809,8 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu) nested_svm_check_exception(svm, nr, has_error_code, error_code)) return; + kvm_deliver_exception_payload(&svm->vcpu); + if (nr == BP_VECTOR && !static_cpu_has(X86_FEATURE_NRIPS)) { unsigned long rip, old_rip = kvm_rip_read(&svm->vcpu); @@ -2922,18 +2924,18 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu) { WARN_ON(mmu_is_nested(vcpu)); kvm_init_shadow_mmu(vcpu); - vcpu->arch.mmu.set_cr3 = nested_svm_set_tdp_cr3; - vcpu->arch.mmu.get_cr3 = nested_svm_get_tdp_cr3; - vcpu->arch.mmu.get_pdptr = nested_svm_get_tdp_pdptr; - vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit; - vcpu->arch.mmu.shadow_root_level = get_npt_level(vcpu); - reset_shadow_zero_bits_mask(vcpu, &vcpu->arch.mmu); + vcpu->arch.mmu->set_cr3 = nested_svm_set_tdp_cr3; + vcpu->arch.mmu->get_cr3 = nested_svm_get_tdp_cr3; + vcpu->arch.mmu->get_pdptr = nested_svm_get_tdp_pdptr; + vcpu->arch.mmu->inject_page_fault = nested_svm_inject_npf_exit; + vcpu->arch.mmu->shadow_root_level = get_npt_level(vcpu); + reset_shadow_zero_bits_mask(vcpu, vcpu->arch.mmu); vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu; } static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu) { - vcpu->arch.walk_mmu = &vcpu->arch.mmu; + vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; } static int nested_svm_check_permissions(struct vcpu_svm *svm) @@ -2969,16 +2971,13 @@ static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, svm->vmcb->control.exit_info_1 = error_code; /* - * FIXME: we should not write CR2 when L1 intercepts an L2 #PF exception. - * The fix is to add the ancillary datum (CR2 or DR6) to structs - * kvm_queued_exception and kvm_vcpu_events, so that CR2 and DR6 can be - * written only when inject_pending_event runs (DR6 would written here - * too). This should be conditional on a new capability---if the - * capability is disabled, kvm_multiple_exception would write the - * ancillary information to CR2 or DR6, for backwards ABI-compatibility. + * EXITINFO2 is undefined for all exception intercepts other + * than #PF. */ if (svm->vcpu.arch.exception.nested_apf) svm->vmcb->control.exit_info_2 = svm->vcpu.arch.apf.nested_apf_token; + else if (svm->vcpu.arch.exception.has_payload) + svm->vmcb->control.exit_info_2 = svm->vcpu.arch.exception.payload; else svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2; @@ -5642,26 +5641,24 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) "mov %%r13, %c[r13](%[svm]) \n\t" "mov %%r14, %c[r14](%[svm]) \n\t" "mov %%r15, %c[r15](%[svm]) \n\t" -#endif /* * Clear host registers marked as clobbered to prevent * speculative use. */ - "xor %%" _ASM_BX ", %%" _ASM_BX " \n\t" - "xor %%" _ASM_CX ", %%" _ASM_CX " \n\t" - "xor %%" _ASM_DX ", %%" _ASM_DX " \n\t" - "xor %%" _ASM_SI ", %%" _ASM_SI " \n\t" - "xor %%" _ASM_DI ", %%" _ASM_DI " \n\t" -#ifdef CONFIG_X86_64 - "xor %%r8, %%r8 \n\t" - "xor %%r9, %%r9 \n\t" - "xor %%r10, %%r10 \n\t" - "xor %%r11, %%r11 \n\t" - "xor %%r12, %%r12 \n\t" - "xor %%r13, %%r13 \n\t" - "xor %%r14, %%r14 \n\t" - "xor %%r15, %%r15 \n\t" + "xor %%r8d, %%r8d \n\t" + "xor %%r9d, %%r9d \n\t" + "xor %%r10d, %%r10d \n\t" + "xor %%r11d, %%r11d \n\t" + "xor %%r12d, %%r12d \n\t" + "xor %%r13d, %%r13d \n\t" + "xor %%r14d, %%r14d \n\t" + "xor %%r15d, %%r15d \n\t" #endif + "xor %%ebx, %%ebx \n\t" + "xor %%ecx, %%ecx \n\t" + "xor %%edx, %%edx \n\t" + "xor %%esi, %%esi \n\t" + "xor %%edi, %%edi \n\t" "pop %%" _ASM_BP : : [svm]"a"(svm), @@ -7040,6 +7037,13 @@ failed: return ret; } +static int nested_enable_evmcs(struct kvm_vcpu *vcpu, + uint16_t *vmcs_version) +{ + /* Intel-only feature */ + return -ENODEV; +} + static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled, @@ -7169,6 +7173,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .mem_enc_op = svm_mem_enc_op, .mem_enc_reg_region = svm_register_enc_region, .mem_enc_unreg_region = svm_unregister_enc_region, + + .nested_enable_evmcs = nested_enable_evmcs, }; static int __init svm_init(void) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 0f997683404f..0659465a745c 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -1418,6 +1418,48 @@ TRACE_EVENT(kvm_hv_flush_tlb_ex, __entry->valid_bank_mask, __entry->format, __entry->address_space, __entry->flags) ); + +/* + * Tracepoints for kvm_hv_send_ipi. + */ +TRACE_EVENT(kvm_hv_send_ipi, + TP_PROTO(u32 vector, u64 processor_mask), + TP_ARGS(vector, processor_mask), + + TP_STRUCT__entry( + __field(u32, vector) + __field(u64, processor_mask) + ), + + TP_fast_assign( + __entry->vector = vector; + __entry->processor_mask = processor_mask; + ), + + TP_printk("vector %x processor_mask 0x%llx", + __entry->vector, __entry->processor_mask) +); + +TRACE_EVENT(kvm_hv_send_ipi_ex, + TP_PROTO(u32 vector, u64 format, u64 valid_bank_mask), + TP_ARGS(vector, format, valid_bank_mask), + + TP_STRUCT__entry( + __field(u32, vector) + __field(u64, format) + __field(u64, valid_bank_mask) + ), + + TP_fast_assign( + __entry->vector = vector; + __entry->format = format; + __entry->valid_bank_mask = valid_bank_mask; + ), + + TP_printk("vector %x format %llx valid_bank_mask 0x%llx", + __entry->vector, __entry->format, + __entry->valid_bank_mask) +); #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e665aa7167cf..4555077d69ce 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -20,6 +20,7 @@ #include "mmu.h" #include "cpuid.h" #include "lapic.h" +#include "hyperv.h" #include <linux/kvm_host.h> #include <linux/module.h> @@ -61,7 +62,7 @@ #define __ex(x) __kvm_handle_fault_on_reboot(x) #define __ex_clear(x, reg) \ - ____kvm_handle_fault_on_reboot(x, "xor " reg " , " reg) + ____kvm_handle_fault_on_reboot(x, "xor " reg ", " reg) MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); @@ -107,9 +108,12 @@ module_param_named(enable_shadow_vmcs, enable_shadow_vmcs, bool, S_IRUGO); * VMX and be a hypervisor for its own guests. If nested=0, guests may not * use VMX instructions. */ -static bool __read_mostly nested = 0; +static bool __read_mostly nested = 1; module_param(nested, bool, S_IRUGO); +static bool __read_mostly nested_early_check = 0; +module_param(nested_early_check, bool, S_IRUGO); + static u64 __read_mostly host_xss; static bool __read_mostly enable_pml = 1; @@ -131,7 +135,7 @@ static bool __read_mostly enable_preemption_timer = 1; module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO); #endif -#define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD) +#define KVM_VM_CR0_ALWAYS_OFF (X86_CR0_NW | X86_CR0_CD) #define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE #define KVM_VM_CR0_ALWAYS_ON \ (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | \ @@ -187,6 +191,7 @@ static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX; module_param(ple_window_max, uint, 0444); extern const ulong vmx_return; +extern const ulong vmx_early_consistency_check_return; static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond); @@ -827,14 +832,28 @@ struct nested_vmx { */ struct vmcs12 *cached_shadow_vmcs12; /* - * Indicates if the shadow vmcs must be updated with the - * data hold by vmcs12 + * Indicates if the shadow vmcs or enlightened vmcs must be updated + * with the data held by struct vmcs12. */ - bool sync_shadow_vmcs; + bool need_vmcs12_sync; bool dirty_vmcs12; + /* + * vmcs02 has been initialized, i.e. state that is constant for + * vmcs02 has been written to the backing VMCS. Initialization + * is delayed until L1 actually attempts to run a nested VM. + */ + bool vmcs02_initialized; + bool change_vmcs01_virtual_apic_mode; + /* + * Enlightened VMCS has been enabled. It does not mean that L1 has to + * use it. However, VMX features available to L1 will be limited based + * on what the enlightened VMCS supports. + */ + bool enlightened_vmcs_enabled; + /* L2 must run next, and mustn't decide to exit to L1. */ bool nested_run_pending; @@ -870,6 +889,10 @@ struct nested_vmx { /* in guest mode on SMM entry? */ bool guest_mode; } smm; + + gpa_t hv_evmcs_vmptr; + struct page *hv_evmcs_page; + struct hv_enlightened_vmcs *hv_evmcs; }; #define POSTED_INTR_ON 0 @@ -1381,6 +1404,49 @@ DEFINE_STATIC_KEY_FALSE(enable_evmcs); #define KVM_EVMCS_VERSION 1 +/* + * Enlightened VMCSv1 doesn't support these: + * + * POSTED_INTR_NV = 0x00000002, + * GUEST_INTR_STATUS = 0x00000810, + * APIC_ACCESS_ADDR = 0x00002014, + * POSTED_INTR_DESC_ADDR = 0x00002016, + * EOI_EXIT_BITMAP0 = 0x0000201c, + * EOI_EXIT_BITMAP1 = 0x0000201e, + * EOI_EXIT_BITMAP2 = 0x00002020, + * EOI_EXIT_BITMAP3 = 0x00002022, + * GUEST_PML_INDEX = 0x00000812, + * PML_ADDRESS = 0x0000200e, + * VM_FUNCTION_CONTROL = 0x00002018, + * EPTP_LIST_ADDRESS = 0x00002024, + * VMREAD_BITMAP = 0x00002026, + * VMWRITE_BITMAP = 0x00002028, + * + * TSC_MULTIPLIER = 0x00002032, + * PLE_GAP = 0x00004020, + * PLE_WINDOW = 0x00004022, + * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E, + * GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808, + * HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04, + * + * Currently unsupported in KVM: + * GUEST_IA32_RTIT_CTL = 0x00002814, + */ +#define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \ + PIN_BASED_VMX_PREEMPTION_TIMER) +#define EVMCS1_UNSUPPORTED_2NDEXEC \ + (SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | \ + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | \ + SECONDARY_EXEC_APIC_REGISTER_VIRT | \ + SECONDARY_EXEC_ENABLE_PML | \ + SECONDARY_EXEC_ENABLE_VMFUNC | \ + SECONDARY_EXEC_SHADOW_VMCS | \ + SECONDARY_EXEC_TSC_SCALING | \ + SECONDARY_EXEC_PAUSE_LOOP_EXITING) +#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) +#define EVMCS1_UNSUPPORTED_VMENTRY_CTRL (VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) +#define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING) + #if IS_ENABLED(CONFIG_HYPERV) static bool __read_mostly enlightened_vmcs = true; module_param(enlightened_vmcs, bool, 0444); @@ -1473,69 +1539,12 @@ static void evmcs_load(u64 phys_addr) static void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) { - /* - * Enlightened VMCSv1 doesn't support these: - * - * POSTED_INTR_NV = 0x00000002, - * GUEST_INTR_STATUS = 0x00000810, - * APIC_ACCESS_ADDR = 0x00002014, - * POSTED_INTR_DESC_ADDR = 0x00002016, - * EOI_EXIT_BITMAP0 = 0x0000201c, - * EOI_EXIT_BITMAP1 = 0x0000201e, - * EOI_EXIT_BITMAP2 = 0x00002020, - * EOI_EXIT_BITMAP3 = 0x00002022, - */ - vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR; - vmcs_conf->cpu_based_2nd_exec_ctrl &= - ~SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; - vmcs_conf->cpu_based_2nd_exec_ctrl &= - ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; - vmcs_conf->cpu_based_2nd_exec_ctrl &= - ~SECONDARY_EXEC_APIC_REGISTER_VIRT; - - /* - * GUEST_PML_INDEX = 0x00000812, - * PML_ADDRESS = 0x0000200e, - */ - vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_PML; - - /* VM_FUNCTION_CONTROL = 0x00002018, */ - vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_VMFUNC; - - /* - * EPTP_LIST_ADDRESS = 0x00002024, - * VMREAD_BITMAP = 0x00002026, - * VMWRITE_BITMAP = 0x00002028, - */ - vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_SHADOW_VMCS; - - /* - * TSC_MULTIPLIER = 0x00002032, - */ - vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_TSC_SCALING; + vmcs_conf->pin_based_exec_ctrl &= ~EVMCS1_UNSUPPORTED_PINCTRL; + vmcs_conf->cpu_based_2nd_exec_ctrl &= ~EVMCS1_UNSUPPORTED_2NDEXEC; - /* - * PLE_GAP = 0x00004020, - * PLE_WINDOW = 0x00004022, - */ - vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING; - - /* - * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E, - */ - vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER; - - /* - * GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808, - * HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04, - */ - vmcs_conf->vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; - vmcs_conf->vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; + vmcs_conf->vmexit_ctrl &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL; + vmcs_conf->vmentry_ctrl &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL; - /* - * Currently unsupported in KVM: - * GUEST_IA32_RTIT_CTL = 0x00002814, - */ } /* check_ept_pointer() should be under protection of ept_pointer_lock. */ @@ -1560,26 +1569,27 @@ static void check_ept_pointer_match(struct kvm *kvm) static int vmx_hv_remote_flush_tlb(struct kvm *kvm) { - int ret; + struct kvm_vcpu *vcpu; + int ret = -ENOTSUPP, i; spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock); if (to_kvm_vmx(kvm)->ept_pointers_match == EPT_POINTERS_CHECK) check_ept_pointer_match(kvm); - if (to_kvm_vmx(kvm)->ept_pointers_match != EPT_POINTERS_MATCH) { - ret = -ENOTSUPP; - goto out; - } - /* * FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE hypercall needs the address of the * base of EPT PML4 table, strip off EPT configuration information. */ - ret = hyperv_flush_guest_mapping( - to_vmx(kvm_get_vcpu(kvm, 0))->ept_pointer & PAGE_MASK); + if (to_kvm_vmx(kvm)->ept_pointers_match != EPT_POINTERS_MATCH) { + kvm_for_each_vcpu(i, vcpu, kvm) + ret |= hyperv_flush_guest_mapping( + to_vmx(kvm_get_vcpu(kvm, i))->ept_pointer & PAGE_MASK); + } else { + ret = hyperv_flush_guest_mapping( + to_vmx(kvm_get_vcpu(kvm, 0))->ept_pointer & PAGE_MASK); + } -out: spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock); return ret; } @@ -1595,6 +1605,35 @@ static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {} static inline void evmcs_touch_msr_bitmap(void) {} #endif /* IS_ENABLED(CONFIG_HYPERV) */ +static int nested_enable_evmcs(struct kvm_vcpu *vcpu, + uint16_t *vmcs_version) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + /* We don't support disabling the feature for simplicity. */ + if (vmx->nested.enlightened_vmcs_enabled) + return 0; + + vmx->nested.enlightened_vmcs_enabled = true; + + /* + * vmcs_version represents the range of supported Enlightened VMCS + * versions: lower 8 bits is the minimal version, higher 8 bits is the + * maximum supported version. KVM supports versions from 1 to + * KVM_EVMCS_VERSION. + */ + if (vmcs_version) + *vmcs_version = (KVM_EVMCS_VERSION << 8) | 1; + + vmx->nested.msrs.pinbased_ctls_high &= ~EVMCS1_UNSUPPORTED_PINCTRL; + vmx->nested.msrs.entry_ctls_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL; + vmx->nested.msrs.exit_ctls_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL; + vmx->nested.msrs.secondary_ctls_high &= ~EVMCS1_UNSUPPORTED_2NDEXEC; + vmx->nested.msrs.vmfunc_controls &= ~EVMCS1_UNSUPPORTED_VMFUNC; + + return 0; +} + static inline bool is_exception_n(u32 intr_info, u8 vector) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | @@ -1617,11 +1656,6 @@ static inline bool is_page_fault(u32 intr_info) return is_exception_n(intr_info, PF_VECTOR); } -static inline bool is_no_device(u32 intr_info) -{ - return is_exception_n(intr_info, NM_VECTOR); -} - static inline bool is_invalid_opcode(u32 intr_info) { return is_exception_n(intr_info, UD_VECTOR); @@ -1632,12 +1666,6 @@ static inline bool is_gp_fault(u32 intr_info) return is_exception_n(intr_info, GP_VECTOR); } -static inline bool is_external_interrupt(u32 intr_info) -{ - return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) - == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); -} - static inline bool is_machine_check(u32 intr_info) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK | @@ -2063,9 +2091,6 @@ static inline bool is_nmi(u32 intr_info) static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, u32 exit_intr_info, unsigned long exit_qualification); -static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12, - u32 reason, unsigned long qualification); static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr) { @@ -2077,7 +2102,7 @@ static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr) return -1; } -static inline void __invvpid(int ext, u16 vpid, gva_t gva) +static inline void __invvpid(unsigned long ext, u16 vpid, gva_t gva) { struct { u64 vpid : 16; @@ -2086,22 +2111,20 @@ static inline void __invvpid(int ext, u16 vpid, gva_t gva) } operand = { vpid, 0, gva }; bool error; - asm volatile (__ex(ASM_VMX_INVVPID) CC_SET(na) - : CC_OUT(na) (error) : "a"(&operand), "c"(ext) - : "memory"); + asm volatile (__ex("invvpid %2, %1") CC_SET(na) + : CC_OUT(na) (error) : "r"(ext), "m"(operand)); BUG_ON(error); } -static inline void __invept(int ext, u64 eptp, gpa_t gpa) +static inline void __invept(unsigned long ext, u64 eptp, gpa_t gpa) { struct { u64 eptp, gpa; } operand = {eptp, gpa}; bool error; - asm volatile (__ex(ASM_VMX_INVEPT) CC_SET(na) - : CC_OUT(na) (error) : "a" (&operand), "c" (ext) - : "memory"); + asm volatile (__ex("invept %2, %1") CC_SET(na) + : CC_OUT(na) (error) : "r"(ext), "m"(operand)); BUG_ON(error); } @@ -2120,9 +2143,8 @@ static void vmcs_clear(struct vmcs *vmcs) u64 phys_addr = __pa(vmcs); bool error; - asm volatile (__ex(ASM_VMX_VMCLEAR_RAX) CC_SET(na) - : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr) - : "memory"); + asm volatile (__ex("vmclear %1") CC_SET(na) + : CC_OUT(na) (error) : "m"(phys_addr)); if (unlikely(error)) printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n", vmcs, phys_addr); @@ -2145,9 +2167,8 @@ static void vmcs_load(struct vmcs *vmcs) if (static_branch_unlikely(&enable_evmcs)) return evmcs_load(phys_addr); - asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) CC_SET(na) - : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr) - : "memory"); + asm volatile (__ex("vmptrld %1") CC_SET(na) + : CC_OUT(na) (error) : "m"(phys_addr)); if (unlikely(error)) printk(KERN_ERR "kvm: vmptrld %p/%llx failed\n", vmcs, phys_addr); @@ -2323,8 +2344,8 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field) { unsigned long value; - asm volatile (__ex_clear(ASM_VMX_VMREAD_RDX_RAX, "%0") - : "=a"(value) : "d"(field) : "cc"); + asm volatile (__ex_clear("vmread %1, %0", "%k0") + : "=r"(value) : "r"(field)); return value; } @@ -2375,8 +2396,8 @@ static __always_inline void __vmcs_writel(unsigned long field, unsigned long val { bool error; - asm volatile (__ex(ASM_VMX_VMWRITE_RAX_RDX) CC_SET(na) - : CC_OUT(na) (error) : "a"(value), "d"(field)); + asm volatile (__ex("vmwrite %2, %1") CC_SET(na) + : CC_OUT(na) (error) : "r"(field), "rm"(value)); if (unlikely(error)) vmwrite_error(field, value); } @@ -2707,7 +2728,8 @@ static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx, u64 guest_val, u64 host_val) { vmcs_write64(guest_val_vmcs, guest_val); - vmcs_write64(host_val_vmcs, host_val); + if (host_val_vmcs != HOST_IA32_EFER) + vmcs_write64(host_val_vmcs, host_val); vm_entry_controls_setbit(vmx, entry); vm_exit_controls_setbit(vmx, exit); } @@ -2805,8 +2827,6 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) ignore_bits &= ~(u64)EFER_SCE; #endif - clear_atomic_switch_msr(vmx, MSR_EFER); - /* * On EPT, we can't emulate NX, so we must switch EFER atomically. * On CPUs that support "load IA32_EFER", always switch EFER @@ -2819,8 +2839,12 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) if (guest_efer != host_efer) add_atomic_switch_msr(vmx, MSR_EFER, guest_efer, host_efer, false); + else + clear_atomic_switch_msr(vmx, MSR_EFER); return false; } else { + clear_atomic_switch_msr(vmx, MSR_EFER); + guest_efer &= ~ignore_bits; guest_efer |= host_efer & ignore_bits; @@ -3272,34 +3296,30 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit { struct vmcs12 *vmcs12 = get_vmcs12(vcpu); unsigned int nr = vcpu->arch.exception.nr; + bool has_payload = vcpu->arch.exception.has_payload; + unsigned long payload = vcpu->arch.exception.payload; if (nr == PF_VECTOR) { if (vcpu->arch.exception.nested_apf) { *exit_qual = vcpu->arch.apf.nested_apf_token; return 1; } - /* - * FIXME: we must not write CR2 when L1 intercepts an L2 #PF exception. - * The fix is to add the ancillary datum (CR2 or DR6) to structs - * kvm_queued_exception and kvm_vcpu_events, so that CR2 and DR6 - * can be written only when inject_pending_event runs. This should be - * conditional on a new capability---if the capability is disabled, - * kvm_multiple_exception would write the ancillary information to - * CR2 or DR6, for backwards ABI-compatibility. - */ if (nested_vmx_is_page_fault_vmexit(vmcs12, vcpu->arch.exception.error_code)) { - *exit_qual = vcpu->arch.cr2; - return 1; - } - } else { - if (vmcs12->exception_bitmap & (1u << nr)) { - if (nr == DB_VECTOR) - *exit_qual = vcpu->arch.dr6; - else - *exit_qual = 0; + *exit_qual = has_payload ? payload : vcpu->arch.cr2; return 1; } + } else if (vmcs12->exception_bitmap & (1u << nr)) { + if (nr == DB_VECTOR) { + if (!has_payload) { + payload = vcpu->arch.dr6; + payload &= ~(DR6_FIXED_1 | DR6_BT); + payload ^= DR6_RTM; + } + *exit_qual = payload; + } else + *exit_qual = 0; + return 1; } return 0; @@ -3326,6 +3346,8 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu) u32 error_code = vcpu->arch.exception.error_code; u32 intr_info = nr | INTR_INFO_VALID_MASK; + kvm_deliver_exception_payload(vcpu); + if (has_error_code) { vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); intr_info |= INTR_INFO_DELIVER_CODE_MASK; @@ -4397,9 +4419,7 @@ static void kvm_cpu_vmxon(u64 addr) cr4_set_bits(X86_CR4_VMXE); intel_pt_handle_vmx(1); - asm volatile (ASM_VMX_VMXON_RAX - : : "a"(&addr), "m"(addr) - : "memory", "cc"); + asm volatile ("vmxon %0" : : "m"(addr)); } static int hardware_enable(void) @@ -4468,7 +4488,7 @@ static void vmclear_local_loaded_vmcss(void) */ static void kvm_cpu_vmxoff(void) { - asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc"); + asm volatile (__ex("vmxoff")); intel_pt_handle_vmx(0); cr4_clear_bits(X86_CR4_VMXE); @@ -5112,9 +5132,10 @@ static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid, bool invalidate_gpa) { if (enable_ept && (invalidate_gpa || !enable_vpid)) { - if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) return; - ept_sync_context(construct_eptp(vcpu, vcpu->arch.mmu.root_hpa)); + ept_sync_context(construct_eptp(vcpu, + vcpu->arch.mmu->root_hpa)); } else { vpid_sync_context(vpid); } @@ -5264,7 +5285,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) struct vcpu_vmx *vmx = to_vmx(vcpu); unsigned long hw_cr0; - hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK); + hw_cr0 = (cr0 & ~KVM_VM_CR0_ALWAYS_OFF); if (enable_unrestricted_guest) hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST; else { @@ -6339,6 +6360,9 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) rdmsr(MSR_IA32_CR_PAT, low32, high32); vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32)); } + + if (cpu_has_load_ia32_efer) + vmcs_write64(HOST_IA32_EFER, host_efer); } static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx) @@ -6666,7 +6690,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx) vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP); if (enable_pml) { - ASSERT(vmx->pml_pg); vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); } @@ -8067,35 +8090,39 @@ static int handle_monitor(struct kvm_vcpu *vcpu) /* * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(), - * set the success or error code of an emulated VMX instruction, as specified - * by Vol 2B, VMX Instruction Reference, "Conventions". + * set the success or error code of an emulated VMX instruction (as specified + * by Vol 2B, VMX Instruction Reference, "Conventions"), and skip the emulated + * instruction. */ -static void nested_vmx_succeed(struct kvm_vcpu *vcpu) +static int nested_vmx_succeed(struct kvm_vcpu *vcpu) { vmx_set_rflags(vcpu, vmx_get_rflags(vcpu) & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF)); + return kvm_skip_emulated_instruction(vcpu); } -static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu) +static int nested_vmx_failInvalid(struct kvm_vcpu *vcpu) { vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu) & ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF)) | X86_EFLAGS_CF); + return kvm_skip_emulated_instruction(vcpu); } -static void nested_vmx_failValid(struct kvm_vcpu *vcpu, - u32 vm_instruction_error) +static int nested_vmx_failValid(struct kvm_vcpu *vcpu, + u32 vm_instruction_error) { - if (to_vmx(vcpu)->nested.current_vmptr == -1ull) { - /* - * failValid writes the error number to the current VMCS, which - * can't be done there isn't a current VMCS. - */ - nested_vmx_failInvalid(vcpu); - return; - } + struct vcpu_vmx *vmx = to_vmx(vcpu); + + /* + * failValid writes the error number to the current VMCS, which + * can't be done if there isn't a current VMCS. + */ + if (vmx->nested.current_vmptr == -1ull && !vmx->nested.hv_evmcs) + return nested_vmx_failInvalid(vcpu); + vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu) & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_SF | X86_EFLAGS_OF)) @@ -8105,6 +8132,7 @@ static void nested_vmx_failValid(struct kvm_vcpu *vcpu, * We don't need to force a shadow sync because * VM_INSTRUCTION_ERROR is not shadowed */ + return kvm_skip_emulated_instruction(vcpu); } static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator) @@ -8292,6 +8320,7 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu) vmx->nested.vpid02 = allocate_vpid(); + vmx->nested.vmcs02_initialized = false; vmx->nested.vmxon = true; return 0; @@ -8345,10 +8374,9 @@ static int handle_vmon(struct kvm_vcpu *vcpu) return 1; } - if (vmx->nested.vmxon) { - nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION); - return kvm_skip_emulated_instruction(vcpu); - } + if (vmx->nested.vmxon) + return nested_vmx_failValid(vcpu, + VMXERR_VMXON_IN_VMX_ROOT_OPERATION); if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES) != VMXON_NEEDED_FEATURES) { @@ -8367,21 +8395,17 @@ static int handle_vmon(struct kvm_vcpu *vcpu) * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case; * which replaces physical address width with 32 */ - if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) + return nested_vmx_failInvalid(vcpu); page = kvm_vcpu_gpa_to_page(vcpu, vmptr); - if (is_error_page(page)) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } + if (is_error_page(page)) + return nested_vmx_failInvalid(vcpu); + if (*(u32 *)kmap(page) != VMCS12_REVISION) { kunmap(page); kvm_release_page_clean(page); - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_failInvalid(vcpu); } kunmap(page); kvm_release_page_clean(page); @@ -8391,8 +8415,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) if (ret) return ret; - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } /* @@ -8423,8 +8446,24 @@ static void vmx_disable_shadow_vmcs(struct vcpu_vmx *vmx) vmcs_write64(VMCS_LINK_POINTER, -1ull); } -static inline void nested_release_vmcs12(struct vcpu_vmx *vmx) +static inline void nested_release_evmcs(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + if (!vmx->nested.hv_evmcs) + return; + + kunmap(vmx->nested.hv_evmcs_page); + kvm_release_page_dirty(vmx->nested.hv_evmcs_page); + vmx->nested.hv_evmcs_vmptr = -1ull; + vmx->nested.hv_evmcs_page = NULL; + vmx->nested.hv_evmcs = NULL; +} + +static inline void nested_release_vmcs12(struct kvm_vcpu *vcpu) { + struct vcpu_vmx *vmx = to_vmx(vcpu); + if (vmx->nested.current_vmptr == -1ull) return; @@ -8432,16 +8471,18 @@ static inline void nested_release_vmcs12(struct vcpu_vmx *vmx) /* copy to memory all shadowed fields in case they were modified */ copy_shadow_to_vmcs12(vmx); - vmx->nested.sync_shadow_vmcs = false; + vmx->nested.need_vmcs12_sync = false; vmx_disable_shadow_vmcs(vmx); } vmx->nested.posted_intr_nv = -1; /* Flush VMCS12 to guest memory */ - kvm_vcpu_write_guest_page(&vmx->vcpu, + kvm_vcpu_write_guest_page(vcpu, vmx->nested.current_vmptr >> PAGE_SHIFT, vmx->nested.cached_vmcs12, 0, VMCS12_SIZE); + kvm_mmu_free_roots(vcpu, &vcpu->arch.guest_mmu, KVM_MMU_ROOTS_ALL); + vmx->nested.current_vmptr = -1ull; } @@ -8449,8 +8490,10 @@ static inline void nested_release_vmcs12(struct vcpu_vmx *vmx) * Free whatever needs to be freed from vmx->nested when L1 goes down, or * just stops using VMX. */ -static void free_nested(struct vcpu_vmx *vmx) +static void free_nested(struct kvm_vcpu *vcpu) { + struct vcpu_vmx *vmx = to_vmx(vcpu); + if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon) return; @@ -8483,6 +8526,10 @@ static void free_nested(struct vcpu_vmx *vmx) vmx->nested.pi_desc = NULL; } + kvm_mmu_free_roots(vcpu, &vcpu->arch.guest_mmu, KVM_MMU_ROOTS_ALL); + + nested_release_evmcs(vcpu); + free_loaded_vmcs(&vmx->nested.vmcs02); } @@ -8491,9 +8538,8 @@ static int handle_vmoff(struct kvm_vcpu *vcpu) { if (!nested_vmx_check_permission(vcpu)) return 1; - free_nested(to_vmx(vcpu)); - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + free_nested(vcpu); + return nested_vmx_succeed(vcpu); } /* Emulate the VMCLEAR instruction */ @@ -8509,25 +8555,28 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) if (nested_vmx_get_vmptr(vcpu, &vmptr)) return 1; - if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { - nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS); - return kvm_skip_emulated_instruction(vcpu); - } + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) + return nested_vmx_failValid(vcpu, + VMXERR_VMCLEAR_INVALID_ADDRESS); - if (vmptr == vmx->nested.vmxon_ptr) { - nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER); - return kvm_skip_emulated_instruction(vcpu); - } + if (vmptr == vmx->nested.vmxon_ptr) + return nested_vmx_failValid(vcpu, + VMXERR_VMCLEAR_VMXON_POINTER); - if (vmptr == vmx->nested.current_vmptr) - nested_release_vmcs12(vmx); + if (vmx->nested.hv_evmcs_page) { + if (vmptr == vmx->nested.hv_evmcs_vmptr) + nested_release_evmcs(vcpu); + } else { + if (vmptr == vmx->nested.current_vmptr) + nested_release_vmcs12(vcpu); - kvm_vcpu_write_guest(vcpu, - vmptr + offsetof(struct vmcs12, launch_state), - &zero, sizeof(zero)); + kvm_vcpu_write_guest(vcpu, + vmptr + offsetof(struct vmcs12, + launch_state), + &zero, sizeof(zero)); + } - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch); @@ -8610,6 +8659,395 @@ static inline int vmcs12_write_any(struct vmcs12 *vmcs12, } +static int copy_enlightened_to_vmcs12(struct vcpu_vmx *vmx) +{ + struct vmcs12 *vmcs12 = vmx->nested.cached_vmcs12; + struct hv_enlightened_vmcs *evmcs = vmx->nested.hv_evmcs; + + vmcs12->hdr.revision_id = evmcs->revision_id; + + /* HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE */ + vmcs12->tpr_threshold = evmcs->tpr_threshold; + vmcs12->guest_rip = evmcs->guest_rip; + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC))) { + vmcs12->guest_rsp = evmcs->guest_rsp; + vmcs12->guest_rflags = evmcs->guest_rflags; + vmcs12->guest_interruptibility_info = + evmcs->guest_interruptibility_info; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_PROC))) { + vmcs12->cpu_based_vm_exec_control = + evmcs->cpu_based_vm_exec_control; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_PROC))) { + vmcs12->exception_bitmap = evmcs->exception_bitmap; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_ENTRY))) { + vmcs12->vm_entry_controls = evmcs->vm_entry_controls; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT))) { + vmcs12->vm_entry_intr_info_field = + evmcs->vm_entry_intr_info_field; + vmcs12->vm_entry_exception_error_code = + evmcs->vm_entry_exception_error_code; + vmcs12->vm_entry_instruction_len = + evmcs->vm_entry_instruction_len; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1))) { + vmcs12->host_ia32_pat = evmcs->host_ia32_pat; + vmcs12->host_ia32_efer = evmcs->host_ia32_efer; + vmcs12->host_cr0 = evmcs->host_cr0; + vmcs12->host_cr3 = evmcs->host_cr3; + vmcs12->host_cr4 = evmcs->host_cr4; + vmcs12->host_ia32_sysenter_esp = evmcs->host_ia32_sysenter_esp; + vmcs12->host_ia32_sysenter_eip = evmcs->host_ia32_sysenter_eip; + vmcs12->host_rip = evmcs->host_rip; + vmcs12->host_ia32_sysenter_cs = evmcs->host_ia32_sysenter_cs; + vmcs12->host_es_selector = evmcs->host_es_selector; + vmcs12->host_cs_selector = evmcs->host_cs_selector; + vmcs12->host_ss_selector = evmcs->host_ss_selector; + vmcs12->host_ds_selector = evmcs->host_ds_selector; + vmcs12->host_fs_selector = evmcs->host_fs_selector; + vmcs12->host_gs_selector = evmcs->host_gs_selector; + vmcs12->host_tr_selector = evmcs->host_tr_selector; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1))) { + vmcs12->pin_based_vm_exec_control = + evmcs->pin_based_vm_exec_control; + vmcs12->vm_exit_controls = evmcs->vm_exit_controls; + vmcs12->secondary_vm_exec_control = + evmcs->secondary_vm_exec_control; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_IO_BITMAP))) { + vmcs12->io_bitmap_a = evmcs->io_bitmap_a; + vmcs12->io_bitmap_b = evmcs->io_bitmap_b; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP))) { + vmcs12->msr_bitmap = evmcs->msr_bitmap; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2))) { + vmcs12->guest_es_base = evmcs->guest_es_base; + vmcs12->guest_cs_base = evmcs->guest_cs_base; + vmcs12->guest_ss_base = evmcs->guest_ss_base; + vmcs12->guest_ds_base = evmcs->guest_ds_base; + vmcs12->guest_fs_base = evmcs->guest_fs_base; + vmcs12->guest_gs_base = evmcs->guest_gs_base; + vmcs12->guest_ldtr_base = evmcs->guest_ldtr_base; + vmcs12->guest_tr_base = evmcs->guest_tr_base; + vmcs12->guest_gdtr_base = evmcs->guest_gdtr_base; + vmcs12->guest_idtr_base = evmcs->guest_idtr_base; + vmcs12->guest_es_limit = evmcs->guest_es_limit; + vmcs12->guest_cs_limit = evmcs->guest_cs_limit; + vmcs12->guest_ss_limit = evmcs->guest_ss_limit; + vmcs12->guest_ds_limit = evmcs->guest_ds_limit; + vmcs12->guest_fs_limit = evmcs->guest_fs_limit; + vmcs12->guest_gs_limit = evmcs->guest_gs_limit; + vmcs12->guest_ldtr_limit = evmcs->guest_ldtr_limit; + vmcs12->guest_tr_limit = evmcs->guest_tr_limit; + vmcs12->guest_gdtr_limit = evmcs->guest_gdtr_limit; + vmcs12->guest_idtr_limit = evmcs->guest_idtr_limit; + vmcs12->guest_es_ar_bytes = evmcs->guest_es_ar_bytes; + vmcs12->guest_cs_ar_bytes = evmcs->guest_cs_ar_bytes; + vmcs12->guest_ss_ar_bytes = evmcs->guest_ss_ar_bytes; + vmcs12->guest_ds_ar_bytes = evmcs->guest_ds_ar_bytes; + vmcs12->guest_fs_ar_bytes = evmcs->guest_fs_ar_bytes; + vmcs12->guest_gs_ar_bytes = evmcs->guest_gs_ar_bytes; + vmcs12->guest_ldtr_ar_bytes = evmcs->guest_ldtr_ar_bytes; + vmcs12->guest_tr_ar_bytes = evmcs->guest_tr_ar_bytes; + vmcs12->guest_es_selector = evmcs->guest_es_selector; + vmcs12->guest_cs_selector = evmcs->guest_cs_selector; + vmcs12->guest_ss_selector = evmcs->guest_ss_selector; + vmcs12->guest_ds_selector = evmcs->guest_ds_selector; + vmcs12->guest_fs_selector = evmcs->guest_fs_selector; + vmcs12->guest_gs_selector = evmcs->guest_gs_selector; + vmcs12->guest_ldtr_selector = evmcs->guest_ldtr_selector; + vmcs12->guest_tr_selector = evmcs->guest_tr_selector; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2))) { + vmcs12->tsc_offset = evmcs->tsc_offset; + vmcs12->virtual_apic_page_addr = evmcs->virtual_apic_page_addr; + vmcs12->xss_exit_bitmap = evmcs->xss_exit_bitmap; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR))) { + vmcs12->cr0_guest_host_mask = evmcs->cr0_guest_host_mask; + vmcs12->cr4_guest_host_mask = evmcs->cr4_guest_host_mask; + vmcs12->cr0_read_shadow = evmcs->cr0_read_shadow; + vmcs12->cr4_read_shadow = evmcs->cr4_read_shadow; + vmcs12->guest_cr0 = evmcs->guest_cr0; + vmcs12->guest_cr3 = evmcs->guest_cr3; + vmcs12->guest_cr4 = evmcs->guest_cr4; + vmcs12->guest_dr7 = evmcs->guest_dr7; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER))) { + vmcs12->host_fs_base = evmcs->host_fs_base; + vmcs12->host_gs_base = evmcs->host_gs_base; + vmcs12->host_tr_base = evmcs->host_tr_base; + vmcs12->host_gdtr_base = evmcs->host_gdtr_base; + vmcs12->host_idtr_base = evmcs->host_idtr_base; + vmcs12->host_rsp = evmcs->host_rsp; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_XLAT))) { + vmcs12->ept_pointer = evmcs->ept_pointer; + vmcs12->virtual_processor_id = evmcs->virtual_processor_id; + } + + if (unlikely(!(evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1))) { + vmcs12->vmcs_link_pointer = evmcs->vmcs_link_pointer; + vmcs12->guest_ia32_debugctl = evmcs->guest_ia32_debugctl; + vmcs12->guest_ia32_pat = evmcs->guest_ia32_pat; + vmcs12->guest_ia32_efer = evmcs->guest_ia32_efer; + vmcs12->guest_pdptr0 = evmcs->guest_pdptr0; + vmcs12->guest_pdptr1 = evmcs->guest_pdptr1; + vmcs12->guest_pdptr2 = evmcs->guest_pdptr2; + vmcs12->guest_pdptr3 = evmcs->guest_pdptr3; + vmcs12->guest_pending_dbg_exceptions = + evmcs->guest_pending_dbg_exceptions; + vmcs12->guest_sysenter_esp = evmcs->guest_sysenter_esp; + vmcs12->guest_sysenter_eip = evmcs->guest_sysenter_eip; + vmcs12->guest_bndcfgs = evmcs->guest_bndcfgs; + vmcs12->guest_activity_state = evmcs->guest_activity_state; + vmcs12->guest_sysenter_cs = evmcs->guest_sysenter_cs; + } + + /* + * Not used? + * vmcs12->vm_exit_msr_store_addr = evmcs->vm_exit_msr_store_addr; + * vmcs12->vm_exit_msr_load_addr = evmcs->vm_exit_msr_load_addr; + * vmcs12->vm_entry_msr_load_addr = evmcs->vm_entry_msr_load_addr; + * vmcs12->cr3_target_value0 = evmcs->cr3_target_value0; + * vmcs12->cr3_target_value1 = evmcs->cr3_target_value1; + * vmcs12->cr3_target_value2 = evmcs->cr3_target_value2; + * vmcs12->cr3_target_value3 = evmcs->cr3_target_value3; + * vmcs12->page_fault_error_code_mask = + * evmcs->page_fault_error_code_mask; + * vmcs12->page_fault_error_code_match = + * evmcs->page_fault_error_code_match; + * vmcs12->cr3_target_count = evmcs->cr3_target_count; + * vmcs12->vm_exit_msr_store_count = evmcs->vm_exit_msr_store_count; + * vmcs12->vm_exit_msr_load_count = evmcs->vm_exit_msr_load_count; + * vmcs12->vm_entry_msr_load_count = evmcs->vm_entry_msr_load_count; + */ + + /* + * Read only fields: + * vmcs12->guest_physical_address = evmcs->guest_physical_address; + * vmcs12->vm_instruction_error = evmcs->vm_instruction_error; + * vmcs12->vm_exit_reason = evmcs->vm_exit_reason; + * vmcs12->vm_exit_intr_info = evmcs->vm_exit_intr_info; + * vmcs12->vm_exit_intr_error_code = evmcs->vm_exit_intr_error_code; + * vmcs12->idt_vectoring_info_field = evmcs->idt_vectoring_info_field; + * vmcs12->idt_vectoring_error_code = evmcs->idt_vectoring_error_code; + * vmcs12->vm_exit_instruction_len = evmcs->vm_exit_instruction_len; + * vmcs12->vmx_instruction_info = evmcs->vmx_instruction_info; + * vmcs12->exit_qualification = evmcs->exit_qualification; + * vmcs12->guest_linear_address = evmcs->guest_linear_address; + * + * Not present in struct vmcs12: + * vmcs12->exit_io_instruction_ecx = evmcs->exit_io_instruction_ecx; + * vmcs12->exit_io_instruction_esi = evmcs->exit_io_instruction_esi; + * vmcs12->exit_io_instruction_edi = evmcs->exit_io_instruction_edi; + * vmcs12->exit_io_instruction_eip = evmcs->exit_io_instruction_eip; + */ + + return 0; +} + +static int copy_vmcs12_to_enlightened(struct vcpu_vmx *vmx) +{ + struct vmcs12 *vmcs12 = vmx->nested.cached_vmcs12; + struct hv_enlightened_vmcs *evmcs = vmx->nested.hv_evmcs; + + /* + * Should not be changed by KVM: + * + * evmcs->host_es_selector = vmcs12->host_es_selector; + * evmcs->host_cs_selector = vmcs12->host_cs_selector; + * evmcs->host_ss_selector = vmcs12->host_ss_selector; + * evmcs->host_ds_selector = vmcs12->host_ds_selector; + * evmcs->host_fs_selector = vmcs12->host_fs_selector; + * evmcs->host_gs_selector = vmcs12->host_gs_selector; + * evmcs->host_tr_selector = vmcs12->host_tr_selector; + * evmcs->host_ia32_pat = vmcs12->host_ia32_pat; + * evmcs->host_ia32_efer = vmcs12->host_ia32_efer; + * evmcs->host_cr0 = vmcs12->host_cr0; + * evmcs->host_cr3 = vmcs12->host_cr3; + * evmcs->host_cr4 = vmcs12->host_cr4; + * evmcs->host_ia32_sysenter_esp = vmcs12->host_ia32_sysenter_esp; + * evmcs->host_ia32_sysenter_eip = vmcs12->host_ia32_sysenter_eip; + * evmcs->host_rip = vmcs12->host_rip; + * evmcs->host_ia32_sysenter_cs = vmcs12->host_ia32_sysenter_cs; + * evmcs->host_fs_base = vmcs12->host_fs_base; + * evmcs->host_gs_base = vmcs12->host_gs_base; + * evmcs->host_tr_base = vmcs12->host_tr_base; + * evmcs->host_gdtr_base = vmcs12->host_gdtr_base; + * evmcs->host_idtr_base = vmcs12->host_idtr_base; + * evmcs->host_rsp = vmcs12->host_rsp; + * sync_vmcs12() doesn't read these: + * evmcs->io_bitmap_a = vmcs12->io_bitmap_a; + * evmcs->io_bitmap_b = vmcs12->io_bitmap_b; + * evmcs->msr_bitmap = vmcs12->msr_bitmap; + * evmcs->ept_pointer = vmcs12->ept_pointer; + * evmcs->xss_exit_bitmap = vmcs12->xss_exit_bitmap; + * evmcs->vm_exit_msr_store_addr = vmcs12->vm_exit_msr_store_addr; + * evmcs->vm_exit_msr_load_addr = vmcs12->vm_exit_msr_load_addr; + * evmcs->vm_entry_msr_load_addr = vmcs12->vm_entry_msr_load_addr; + * evmcs->cr3_target_value0 = vmcs12->cr3_target_value0; + * evmcs->cr3_target_value1 = vmcs12->cr3_target_value1; + * evmcs->cr3_target_value2 = vmcs12->cr3_target_value2; + * evmcs->cr3_target_value3 = vmcs12->cr3_target_value3; + * evmcs->tpr_threshold = vmcs12->tpr_threshold; + * evmcs->virtual_processor_id = vmcs12->virtual_processor_id; + * evmcs->exception_bitmap = vmcs12->exception_bitmap; + * evmcs->vmcs_link_pointer = vmcs12->vmcs_link_pointer; + * evmcs->pin_based_vm_exec_control = vmcs12->pin_based_vm_exec_control; + * evmcs->vm_exit_controls = vmcs12->vm_exit_controls; + * evmcs->secondary_vm_exec_control = vmcs12->secondary_vm_exec_control; + * evmcs->page_fault_error_code_mask = + * vmcs12->page_fault_error_code_mask; + * evmcs->page_fault_error_code_match = + * vmcs12->page_fault_error_code_match; + * evmcs->cr3_target_count = vmcs12->cr3_target_count; + * evmcs->virtual_apic_page_addr = vmcs12->virtual_apic_page_addr; + * evmcs->tsc_offset = vmcs12->tsc_offset; + * evmcs->guest_ia32_debugctl = vmcs12->guest_ia32_debugctl; + * evmcs->cr0_guest_host_mask = vmcs12->cr0_guest_host_mask; + * evmcs->cr4_guest_host_mask = vmcs12->cr4_guest_host_mask; + * evmcs->cr0_read_shadow = vmcs12->cr0_read_shadow; + * evmcs->cr4_read_shadow = vmcs12->cr4_read_shadow; + * evmcs->vm_exit_msr_store_count = vmcs12->vm_exit_msr_store_count; + * evmcs->vm_exit_msr_load_count = vmcs12->vm_exit_msr_load_count; + * evmcs->vm_entry_msr_load_count = vmcs12->vm_entry_msr_load_count; + * + * Not present in struct vmcs12: + * evmcs->exit_io_instruction_ecx = vmcs12->exit_io_instruction_ecx; + * evmcs->exit_io_instruction_esi = vmcs12->exit_io_instruction_esi; + * evmcs->exit_io_instruction_edi = vmcs12->exit_io_instruction_edi; + * evmcs->exit_io_instruction_eip = vmcs12->exit_io_instruction_eip; + */ + + evmcs->guest_es_selector = vmcs12->guest_es_selector; + evmcs->guest_cs_selector = vmcs12->guest_cs_selector; + evmcs->guest_ss_selector = vmcs12->guest_ss_selector; + evmcs->guest_ds_selector = vmcs12->guest_ds_selector; + evmcs->guest_fs_selector = vmcs12->guest_fs_selector; + evmcs->guest_gs_selector = vmcs12->guest_gs_selector; + evmcs->guest_ldtr_selector = vmcs12->guest_ldtr_selector; + evmcs->guest_tr_selector = vmcs12->guest_tr_selector; + + evmcs->guest_es_limit = vmcs12->guest_es_limit; + evmcs->guest_cs_limit = vmcs12->guest_cs_limit; + evmcs->guest_ss_limit = vmcs12->guest_ss_limit; + evmcs->guest_ds_limit = vmcs12->guest_ds_limit; + evmcs->guest_fs_limit = vmcs12->guest_fs_limit; + evmcs->guest_gs_limit = vmcs12->guest_gs_limit; + evmcs->guest_ldtr_limit = vmcs12->guest_ldtr_limit; + evmcs->guest_tr_limit = vmcs12->guest_tr_limit; + evmcs->guest_gdtr_limit = vmcs12->guest_gdtr_limit; + evmcs->guest_idtr_limit = vmcs12->guest_idtr_limit; + + evmcs->guest_es_ar_bytes = vmcs12->guest_es_ar_bytes; + evmcs->guest_cs_ar_bytes = vmcs12->guest_cs_ar_bytes; + evmcs->guest_ss_ar_bytes = vmcs12->guest_ss_ar_bytes; + evmcs->guest_ds_ar_bytes = vmcs12->guest_ds_ar_bytes; + evmcs->guest_fs_ar_bytes = vmcs12->guest_fs_ar_bytes; + evmcs->guest_gs_ar_bytes = vmcs12->guest_gs_ar_bytes; + evmcs->guest_ldtr_ar_bytes = vmcs12->guest_ldtr_ar_bytes; + evmcs->guest_tr_ar_bytes = vmcs12->guest_tr_ar_bytes; + + evmcs->guest_es_base = vmcs12->guest_es_base; + evmcs->guest_cs_base = vmcs12->guest_cs_base; + evmcs->guest_ss_base = vmcs12->guest_ss_base; + evmcs->guest_ds_base = vmcs12->guest_ds_base; + evmcs->guest_fs_base = vmcs12->guest_fs_base; + evmcs->guest_gs_base = vmcs12->guest_gs_base; + evmcs->guest_ldtr_base = vmcs12->guest_ldtr_base; + evmcs->guest_tr_base = vmcs12->guest_tr_base; + evmcs->guest_gdtr_base = vmcs12->guest_gdtr_base; + evmcs->guest_idtr_base = vmcs12->guest_idtr_base; + + evmcs->guest_ia32_pat = vmcs12->guest_ia32_pat; + evmcs->guest_ia32_efer = vmcs12->guest_ia32_efer; + + evmcs->guest_pdptr0 = vmcs12->guest_pdptr0; + evmcs->guest_pdptr1 = vmcs12->guest_pdptr1; + evmcs->guest_pdptr2 = vmcs12->guest_pdptr2; + evmcs->guest_pdptr3 = vmcs12->guest_pdptr3; + + evmcs->guest_pending_dbg_exceptions = + vmcs12->guest_pending_dbg_exceptions; + evmcs->guest_sysenter_esp = vmcs12->guest_sysenter_esp; + evmcs->guest_sysenter_eip = vmcs12->guest_sysenter_eip; + + evmcs->guest_activity_state = vmcs12->guest_activity_state; + evmcs->guest_sysenter_cs = vmcs12->guest_sysenter_cs; + + evmcs->guest_cr0 = vmcs12->guest_cr0; + evmcs->guest_cr3 = vmcs12->guest_cr3; + evmcs->guest_cr4 = vmcs12->guest_cr4; + evmcs->guest_dr7 = vmcs12->guest_dr7; + + evmcs->guest_physical_address = vmcs12->guest_physical_address; + + evmcs->vm_instruction_error = vmcs12->vm_instruction_error; + evmcs->vm_exit_reason = vmcs12->vm_exit_reason; + evmcs->vm_exit_intr_info = vmcs12->vm_exit_intr_info; + evmcs->vm_exit_intr_error_code = vmcs12->vm_exit_intr_error_code; + evmcs->idt_vectoring_info_field = vmcs12->idt_vectoring_info_field; + evmcs->idt_vectoring_error_code = vmcs12->idt_vectoring_error_code; + evmcs->vm_exit_instruction_len = vmcs12->vm_exit_instruction_len; + evmcs->vmx_instruction_info = vmcs12->vmx_instruction_info; + + evmcs->exit_qualification = vmcs12->exit_qualification; + + evmcs->guest_linear_address = vmcs12->guest_linear_address; + evmcs->guest_rsp = vmcs12->guest_rsp; + evmcs->guest_rflags = vmcs12->guest_rflags; + + evmcs->guest_interruptibility_info = + vmcs12->guest_interruptibility_info; + evmcs->cpu_based_vm_exec_control = vmcs12->cpu_based_vm_exec_control; + evmcs->vm_entry_controls = vmcs12->vm_entry_controls; + evmcs->vm_entry_intr_info_field = vmcs12->vm_entry_intr_info_field; + evmcs->vm_entry_exception_error_code = + vmcs12->vm_entry_exception_error_code; + evmcs->vm_entry_instruction_len = vmcs12->vm_entry_instruction_len; + + evmcs->guest_rip = vmcs12->guest_rip; + + evmcs->guest_bndcfgs = vmcs12->guest_bndcfgs; + + return 0; +} + /* * Copy the writable VMCS shadow fields back to the VMCS12, in case * they have been modified by the L1 guest. Note that the "read-only" @@ -8683,20 +9121,6 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx) vmcs_load(vmx->loaded_vmcs->vmcs); } -/* - * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was - * used before) all generate the same failure when it is missing. - */ -static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu) -{ - struct vcpu_vmx *vmx = to_vmx(vcpu); - if (vmx->nested.current_vmptr == -1ull) { - nested_vmx_failInvalid(vcpu); - return 0; - } - return 1; -} - static int handle_vmread(struct kvm_vcpu *vcpu) { unsigned long field; @@ -8709,8 +9133,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; - if (!nested_vmx_check_vmcs12(vcpu)) - return kvm_skip_emulated_instruction(vcpu); + if (to_vmx(vcpu)->nested.current_vmptr == -1ull) + return nested_vmx_failInvalid(vcpu); if (!is_guest_mode(vcpu)) vmcs12 = get_vmcs12(vcpu); @@ -8719,20 +9143,18 @@ static int handle_vmread(struct kvm_vcpu *vcpu) * When vmcs->vmcs_link_pointer is -1ull, any VMREAD * to shadowed-field sets the ALU flags for VMfailInvalid. */ - if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } + if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) + return nested_vmx_failInvalid(vcpu); vmcs12 = get_shadow_vmcs12(vcpu); } /* Decode instruction info and find the field to read */ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); /* Read the field, zero-extended to a u64 field_value */ - if (vmcs12_read_any(vmcs12, field, &field_value) < 0) { - nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); - return kvm_skip_emulated_instruction(vcpu); - } + if (vmcs12_read_any(vmcs12, field, &field_value) < 0) + return nested_vmx_failValid(vcpu, + VMXERR_UNSUPPORTED_VMCS_COMPONENT); + /* * Now copy part of this value to register or memory, as requested. * Note that the number of bits actually copied is 32 or 64 depending @@ -8750,8 +9172,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu) (is_long_mode(vcpu) ? 8 : 4), NULL); } - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } @@ -8776,8 +9197,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; - if (!nested_vmx_check_vmcs12(vcpu)) - return kvm_skip_emulated_instruction(vcpu); + if (vmx->nested.current_vmptr == -1ull) + return nested_vmx_failInvalid(vcpu); if (vmx_instruction_info & (1u << 10)) field_value = kvm_register_readl(vcpu, @@ -8800,11 +9221,9 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) * VMCS," then the "read-only" fields are actually read/write. */ if (vmcs_field_readonly(field) && - !nested_cpu_has_vmwrite_any_field(vcpu)) { - nested_vmx_failValid(vcpu, + !nested_cpu_has_vmwrite_any_field(vcpu)) + return nested_vmx_failValid(vcpu, VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT); - return kvm_skip_emulated_instruction(vcpu); - } if (!is_guest_mode(vcpu)) vmcs12 = get_vmcs12(vcpu); @@ -8813,18 +9232,14 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) * When vmcs->vmcs_link_pointer is -1ull, any VMWRITE * to shadowed-field sets the ALU flags for VMfailInvalid. */ - if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } + if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) + return nested_vmx_failInvalid(vcpu); vmcs12 = get_shadow_vmcs12(vcpu); - } - if (vmcs12_write_any(vmcs12, field, field_value) < 0) { - nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); - return kvm_skip_emulated_instruction(vcpu); - } + if (vmcs12_write_any(vmcs12, field, field_value) < 0) + return nested_vmx_failValid(vcpu, + VMXERR_UNSUPPORTED_VMCS_COMPONENT); /* * Do not track vmcs12 dirty-state if in guest-mode @@ -8846,8 +9261,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) } } - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } static void set_current_vmptr(struct vcpu_vmx *vmx, gpa_t vmptr) @@ -8858,7 +9272,7 @@ static void set_current_vmptr(struct vcpu_vmx *vmx, gpa_t vmptr) SECONDARY_EXEC_SHADOW_VMCS); vmcs_write64(VMCS_LINK_POINTER, __pa(vmx->vmcs01.shadow_vmcs)); - vmx->nested.sync_shadow_vmcs = true; + vmx->nested.need_vmcs12_sync = true; } vmx->nested.dirty_vmcs12 = true; } @@ -8875,36 +9289,37 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) if (nested_vmx_get_vmptr(vcpu, &vmptr)) return 1; - if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) { - nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS); - return kvm_skip_emulated_instruction(vcpu); - } + if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) + return nested_vmx_failValid(vcpu, + VMXERR_VMPTRLD_INVALID_ADDRESS); - if (vmptr == vmx->nested.vmxon_ptr) { - nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER); - return kvm_skip_emulated_instruction(vcpu); - } + if (vmptr == vmx->nested.vmxon_ptr) + return nested_vmx_failValid(vcpu, + VMXERR_VMPTRLD_VMXON_POINTER); + + /* Forbid normal VMPTRLD if Enlightened version was used */ + if (vmx->nested.hv_evmcs) + return 1; if (vmx->nested.current_vmptr != vmptr) { struct vmcs12 *new_vmcs12; struct page *page; page = kvm_vcpu_gpa_to_page(vcpu, vmptr); - if (is_error_page(page)) { - nested_vmx_failInvalid(vcpu); - return kvm_skip_emulated_instruction(vcpu); - } + if (is_error_page(page)) + return nested_vmx_failInvalid(vcpu); + new_vmcs12 = kmap(page); if (new_vmcs12->hdr.revision_id != VMCS12_REVISION || (new_vmcs12->hdr.shadow_vmcs && !nested_cpu_has_vmx_shadow_vmcs(vcpu))) { kunmap(page); kvm_release_page_clean(page); - nested_vmx_failValid(vcpu, + return nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID); - return kvm_skip_emulated_instruction(vcpu); } - nested_release_vmcs12(vmx); + nested_release_vmcs12(vcpu); + /* * Load VMCS12 from guest memory since it is not already * cached. @@ -8916,8 +9331,71 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) set_current_vmptr(vmx, vmptr); } - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); +} + +/* + * This is an equivalent of the nested hypervisor executing the vmptrld + * instruction. + */ +static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu, + bool from_launch) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct hv_vp_assist_page assist_page; + + if (likely(!vmx->nested.enlightened_vmcs_enabled)) + return 1; + + if (unlikely(!kvm_hv_get_assist_page(vcpu, &assist_page))) + return 1; + + if (unlikely(!assist_page.enlighten_vmentry)) + return 1; + + if (unlikely(assist_page.current_nested_vmcs != + vmx->nested.hv_evmcs_vmptr)) { + + if (!vmx->nested.hv_evmcs) + vmx->nested.current_vmptr = -1ull; + + nested_release_evmcs(vcpu); + + vmx->nested.hv_evmcs_page = kvm_vcpu_gpa_to_page( + vcpu, assist_page.current_nested_vmcs); + + if (unlikely(is_error_page(vmx->nested.hv_evmcs_page))) + return 0; + + vmx->nested.hv_evmcs = kmap(vmx->nested.hv_evmcs_page); + + if (vmx->nested.hv_evmcs->revision_id != VMCS12_REVISION) { + nested_release_evmcs(vcpu); + return 0; + } + + vmx->nested.dirty_vmcs12 = true; + /* + * As we keep L2 state for one guest only 'hv_clean_fields' mask + * can't be used when we switch between them. Reset it here for + * simplicity. + */ + vmx->nested.hv_evmcs->hv_clean_fields &= + ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL; + vmx->nested.hv_evmcs_vmptr = assist_page.current_nested_vmcs; + + /* + * Unlike normal vmcs12, enlightened vmcs12 is not fully + * reloaded from guest's memory (read only fields, fields not + * present in struct hv_enlightened_vmcs, ...). Make sure there + * are no leftovers. + */ + if (from_launch) + memset(vmx->nested.cached_vmcs12, 0, + sizeof(*vmx->nested.cached_vmcs12)); + + } + return 1; } /* Emulate the VMPTRST instruction */ @@ -8932,6 +9410,9 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) if (!nested_vmx_check_permission(vcpu)) return 1; + if (unlikely(to_vmx(vcpu)->nested.hv_evmcs)) + return 1; + if (get_vmx_mem_address(vcpu, exit_qual, instr_info, true, &gva)) return 1; /* *_system ok, nested_vmx_check_permission has verified cpl=0 */ @@ -8940,8 +9421,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu) kvm_inject_page_fault(vcpu, &e); return 1; } - nested_vmx_succeed(vcpu); - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } /* Emulate the INVEPT instruction */ @@ -8971,11 +9451,9 @@ static int handle_invept(struct kvm_vcpu *vcpu) types = (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; - if (type >= 32 || !(types & (1 << type))) { - nested_vmx_failValid(vcpu, + if (type >= 32 || !(types & (1 << type))) + return nested_vmx_failValid(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); - return kvm_skip_emulated_instruction(vcpu); - } /* According to the Intel VMX instruction reference, the memory * operand is read even if it isn't needed (e.g., for type==global) @@ -8997,14 +9475,20 @@ static int handle_invept(struct kvm_vcpu *vcpu) case VMX_EPT_EXTENT_CONTEXT: kvm_mmu_sync_roots(vcpu); kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); - nested_vmx_succeed(vcpu); break; default: BUG_ON(1); break; } - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); +} + +static u16 nested_get_vpid02(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + return vmx->nested.vpid02 ? vmx->nested.vpid02 : vmx->vpid; } static int handle_invvpid(struct kvm_vcpu *vcpu) @@ -9018,6 +9502,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) u64 vpid; u64 gla; } operand; + u16 vpid02; if (!(vmx->nested.msrs.secondary_ctls_high & SECONDARY_EXEC_ENABLE_VPID) || @@ -9035,11 +9520,9 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) types = (vmx->nested.msrs.vpid_caps & VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8; - if (type >= 32 || !(types & (1 << type))) { - nested_vmx_failValid(vcpu, + if (type >= 32 || !(types & (1 << type))) + return nested_vmx_failValid(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); - return kvm_skip_emulated_instruction(vcpu); - } /* according to the intel vmx instruction reference, the memory * operand is read even if it isn't needed (e.g., for type==global) @@ -9051,47 +9534,39 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) kvm_inject_page_fault(vcpu, &e); return 1; } - if (operand.vpid >> 16) { - nested_vmx_failValid(vcpu, + if (operand.vpid >> 16) + return nested_vmx_failValid(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); - return kvm_skip_emulated_instruction(vcpu); - } + vpid02 = nested_get_vpid02(vcpu); switch (type) { case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: if (!operand.vpid || - is_noncanonical_address(operand.gla, vcpu)) { - nested_vmx_failValid(vcpu, + is_noncanonical_address(operand.gla, vcpu)) + return nested_vmx_failValid(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); - return kvm_skip_emulated_instruction(vcpu); - } - if (cpu_has_vmx_invvpid_individual_addr() && - vmx->nested.vpid02) { + if (cpu_has_vmx_invvpid_individual_addr()) { __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR, - vmx->nested.vpid02, operand.gla); + vpid02, operand.gla); } else - __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); + __vmx_flush_tlb(vcpu, vpid02, false); break; case VMX_VPID_EXTENT_SINGLE_CONTEXT: case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL: - if (!operand.vpid) { - nested_vmx_failValid(vcpu, + if (!operand.vpid) + return nested_vmx_failValid(vcpu, VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); - return kvm_skip_emulated_instruction(vcpu); - } - __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); + __vmx_flush_tlb(vcpu, vpid02, false); break; case VMX_VPID_EXTENT_ALL_CONTEXT: - __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); + __vmx_flush_tlb(vcpu, vpid02, false); break; default: WARN_ON_ONCE(1); return kvm_skip_emulated_instruction(vcpu); } - nested_vmx_succeed(vcpu); - - return kvm_skip_emulated_instruction(vcpu); + return nested_vmx_succeed(vcpu); } static int handle_invpcid(struct kvm_vcpu *vcpu) @@ -9162,11 +9637,11 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) } for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) - if (kvm_get_pcid(vcpu, vcpu->arch.mmu.prev_roots[i].cr3) + if (kvm_get_pcid(vcpu, vcpu->arch.mmu->prev_roots[i].cr3) == operand.pcid) roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i); - kvm_mmu_free_roots(vcpu, roots_to_free); + kvm_mmu_free_roots(vcpu, vcpu->arch.mmu, roots_to_free); /* * If neither the current cr3 nor any of the prev_roots use the * given PCID, then nothing needs to be done here because a @@ -9293,7 +9768,7 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu, kvm_mmu_unload(vcpu); mmu->ept_ad = accessed_dirty; - mmu->base_role.ad_disabled = !accessed_dirty; + mmu->mmu_role.base.ad_disabled = !accessed_dirty; vmcs12->ept_pointer = address; /* * TODO: Check what's the correct approach in case @@ -9652,9 +10127,6 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason) return false; else if (is_page_fault(intr_info)) return !vmx->vcpu.arch.apf.host_apf_reason && enable_ept; - else if (is_no_device(intr_info) && - !(vmcs12->guest_cr0 & X86_CR0_TS)) - return false; else if (is_debug(intr_info) && vcpu->guest_debug & (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) @@ -10676,9 +11148,25 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) vmcs_write32(PLE_WINDOW, vmx->ple_window); } - if (vmx->nested.sync_shadow_vmcs) { - copy_vmcs12_to_shadow(vmx); - vmx->nested.sync_shadow_vmcs = false; + if (vmx->nested.need_vmcs12_sync) { + /* + * hv_evmcs may end up being not mapped after migration (when + * L2 was running), map it here to make sure vmcs12 changes are + * properly reflected. + */ + if (vmx->nested.enlightened_vmcs_enabled && + !vmx->nested.hv_evmcs) + nested_vmx_handle_enlightened_vmptrld(vcpu, false); + + if (vmx->nested.hv_evmcs) { + copy_vmcs12_to_enlightened(vmx); + /* All fields are clean */ + vmx->nested.hv_evmcs->hv_clean_fields |= + HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL; + } else { + copy_vmcs12_to_shadow(vmx); + } + vmx->nested.need_vmcs12_sync = false; } if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty)) @@ -10745,7 +11233,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) "mov %%" _ASM_SP ", (%%" _ASM_SI ") \n\t" "jmp 1f \n\t" "2: \n\t" - __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t" + __ex("vmwrite %%" _ASM_SP ", %%" _ASM_DX) "\n\t" "1: \n\t" /* Reload cr2 if changed */ "mov %c[cr2](%0), %%" _ASM_AX " \n\t" @@ -10777,9 +11265,9 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) /* Enter guest mode */ "jne 1f \n\t" - __ex(ASM_VMX_VMLAUNCH) "\n\t" + __ex("vmlaunch") "\n\t" "jmp 2f \n\t" - "1: " __ex(ASM_VMX_VMRESUME) "\n\t" + "1: " __ex("vmresume") "\n\t" "2: " /* Save guest registers, load host registers, keep flags */ "mov %0, %c[wordsize](%%" _ASM_SP ") \n\t" @@ -10801,6 +11289,10 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) "mov %%r13, %c[r13](%0) \n\t" "mov %%r14, %c[r14](%0) \n\t" "mov %%r15, %c[r15](%0) \n\t" + /* + * Clear host registers marked as clobbered to prevent + * speculative use. + */ "xor %%r8d, %%r8d \n\t" "xor %%r9d, %%r9d \n\t" "xor %%r10d, %%r10d \n\t" @@ -10958,6 +11450,10 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs) vmx->loaded_vmcs = vmcs; vmx_vcpu_load(vcpu, cpu); put_cpu(); + + vm_entry_controls_reset_shadow(vmx); + vm_exit_controls_reset_shadow(vmx); + vmx_segment_cache_clear(vmx); } /* @@ -10966,12 +11462,10 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs) */ static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu) { - struct vcpu_vmx *vmx = to_vmx(vcpu); - - vcpu_load(vcpu); - vmx_switch_vmcs(vcpu, &vmx->vmcs01); - free_nested(vmx); - vcpu_put(vcpu); + vcpu_load(vcpu); + vmx_switch_vmcs(vcpu, &to_vmx(vcpu)->vmcs01); + free_nested(vcpu); + vcpu_put(vcpu); } static void vmx_free_vcpu(struct kvm_vcpu *vcpu) @@ -11334,28 +11828,28 @@ static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu) return get_vmcs12(vcpu)->ept_pointer; } -static int nested_ept_init_mmu_context(struct kvm_vcpu *vcpu) +static void nested_ept_init_mmu_context(struct kvm_vcpu *vcpu) { WARN_ON(mmu_is_nested(vcpu)); - if (!valid_ept_address(vcpu, nested_ept_get_cr3(vcpu))) - return 1; + vcpu->arch.mmu = &vcpu->arch.guest_mmu; kvm_init_shadow_ept_mmu(vcpu, to_vmx(vcpu)->nested.msrs.ept_caps & VMX_EPT_EXECUTE_ONLY_BIT, nested_ept_ad_enabled(vcpu), nested_ept_get_cr3(vcpu)); - vcpu->arch.mmu.set_cr3 = vmx_set_cr3; - vcpu->arch.mmu.get_cr3 = nested_ept_get_cr3; - vcpu->arch.mmu.inject_page_fault = nested_ept_inject_page_fault; + vcpu->arch.mmu->set_cr3 = vmx_set_cr3; + vcpu->arch.mmu->get_cr3 = nested_ept_get_cr3; + vcpu->arch.mmu->inject_page_fault = nested_ept_inject_page_fault; + vcpu->arch.mmu->get_pdptr = kvm_pdptr_read; vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu; - return 0; } static void nested_ept_uninit_mmu_context(struct kvm_vcpu *vcpu) { - vcpu->arch.walk_mmu = &vcpu->arch.mmu; + vcpu->arch.mmu = &vcpu->arch.root_mmu; + vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; } static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12, @@ -11716,7 +12210,7 @@ static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu, !nested_exit_intr_ack_set(vcpu) || (vmcs12->posted_intr_nv & 0xff00) || (vmcs12->posted_intr_desc_addr & 0x3f) || - (!page_address_valid(vcpu, vmcs12->posted_intr_desc_addr)))) + (vmcs12->posted_intr_desc_addr >> cpuid_maxphyaddr(vcpu)))) return -EINVAL; /* tpr shadow is needed by all apicv features. */ @@ -11772,15 +12266,12 @@ static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu, static int nested_vmx_check_pml_controls(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) { - u64 address = vmcs12->pml_address; - int maxphyaddr = cpuid_maxphyaddr(vcpu); + if (!nested_cpu_has_pml(vmcs12)) + return 0; - if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML)) { - if (!nested_cpu_has_ept(vmcs12) || - !IS_ALIGNED(address, 4096) || - address >> maxphyaddr) - return -EINVAL; - } + if (!nested_cpu_has_ept(vmcs12) || + !page_address_valid(vcpu, vmcs12->pml_address)) + return -EINVAL; return 0; } @@ -11960,112 +12451,87 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne return 0; } -static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) +/* + * Returns if KVM is able to config CPU to tag TLB entries + * populated by L2 differently than TLB entries populated + * by L1. + * + * If L1 uses EPT, then TLB entries are tagged with different EPTP. + * + * If L1 uses VPID and we allocated a vpid02, TLB entries are tagged + * with different VPID (L1 entries are tagged with vmx->vpid + * while L2 entries are tagged with vmx->nested.vpid02). + */ +static bool nested_has_guest_tlb_tag(struct kvm_vcpu *vcpu) { - struct vcpu_vmx *vmx = to_vmx(vcpu); + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); - vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector); - vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector); - vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector); - vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector); - vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector); - vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector); - vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector); - vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit); - vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit); - vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit); - vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit); - vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit); - vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit); - vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit); - vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit); - vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit); - vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes); - vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes); - vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes); - vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes); - vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes); - vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes); - vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes); - vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base); - vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base); - vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base); - vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base); - vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base); - vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base); - vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base); - vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base); - - vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs); - vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, - vmcs12->guest_pending_dbg_exceptions); - vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp); - vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip); + return nested_cpu_has_ept(vmcs12) || + (nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02); +} - if (nested_cpu_has_xsaves(vmcs12)) - vmcs_write64(XSS_EXIT_BITMAP, vmcs12->xss_exit_bitmap); - vmcs_write64(VMCS_LINK_POINTER, -1ull); +static u64 nested_vmx_calc_efer(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) +{ + if (vmx->nested.nested_run_pending && + (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) + return vmcs12->guest_ia32_efer; + else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) + return vmx->vcpu.arch.efer | (EFER_LMA | EFER_LME); + else + return vmx->vcpu.arch.efer & ~(EFER_LMA | EFER_LME); +} - if (cpu_has_vmx_posted_intr()) - vmcs_write16(POSTED_INTR_NV, POSTED_INTR_NESTED_VECTOR); +static void prepare_vmcs02_constant_state(struct vcpu_vmx *vmx) +{ + /* + * If vmcs02 hasn't been initialized, set the constant vmcs02 state + * according to L0's settings (vmcs12 is irrelevant here). Host + * fields that come from L0 and are not constant, e.g. HOST_CR3, + * will be set as needed prior to VMLAUNCH/VMRESUME. + */ + if (vmx->nested.vmcs02_initialized) + return; + vmx->nested.vmcs02_initialized = true; /* - * Whether page-faults are trapped is determined by a combination of - * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. - * If enable_ept, L0 doesn't care about page faults and we should - * set all of these to L1's desires. However, if !enable_ept, L0 does - * care about (at least some) page faults, and because it is not easy - * (if at all possible?) to merge L0 and L1's desires, we simply ask - * to exit on each and every L2 page fault. This is done by setting - * MASK=MATCH=0 and (see below) EB.PF=1. - * Note that below we don't need special code to set EB.PF beyond the - * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept, - * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when - * !enable_ept, EB.PF is 1, so the "or" will always be 1. + * We don't care what the EPTP value is we just need to guarantee + * it's valid so we don't get a false positive when doing early + * consistency checks. */ - vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, - enable_ept ? vmcs12->page_fault_error_code_mask : 0); - vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, - enable_ept ? vmcs12->page_fault_error_code_match : 0); + if (enable_ept && nested_early_check) + vmcs_write64(EPT_POINTER, construct_eptp(&vmx->vcpu, 0)); /* All VMFUNCs are currently emulated through L0 vmexits. */ if (cpu_has_vmx_vmfunc()) vmcs_write64(VM_FUNCTION_CONTROL, 0); - if (cpu_has_vmx_apicv()) { - vmcs_write64(EOI_EXIT_BITMAP0, vmcs12->eoi_exit_bitmap0); - vmcs_write64(EOI_EXIT_BITMAP1, vmcs12->eoi_exit_bitmap1); - vmcs_write64(EOI_EXIT_BITMAP2, vmcs12->eoi_exit_bitmap2); - vmcs_write64(EOI_EXIT_BITMAP3, vmcs12->eoi_exit_bitmap3); - } + if (cpu_has_vmx_posted_intr()) + vmcs_write16(POSTED_INTR_NV, POSTED_INTR_NESTED_VECTOR); - /* - * Set host-state according to L0's settings (vmcs12 is irrelevant here) - * Some constant fields are set here by vmx_set_constant_host_state(). - * Other fields are different per CPU, and will be set later when - * vmx_vcpu_load() is called, and when vmx_prepare_switch_to_guest() - * is called. - */ - vmx_set_constant_host_state(vmx); + if (cpu_has_vmx_msr_bitmap()) + vmcs_write64(MSR_BITMAP, __pa(vmx->nested.vmcs02.msr_bitmap)); + + if (enable_pml) + vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); /* - * Set the MSR load/store lists to match L0's settings. + * Set the MSR load/store lists to match L0's settings. Only the + * addresses are constant (for vmcs02), the counts can change based + * on L2's behavior, e.g. switching to/from long mode. */ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val)); - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val)); - set_cr4_guest_host_mask(vmx); + vmx_set_constant_host_state(vmx); +} - if (kvm_mpx_supported()) { - if (vmx->nested.nested_run_pending && - (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)) - vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs); - else - vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs); - } +static void prepare_vmcs02_early_full(struct vcpu_vmx *vmx, + struct vmcs12 *vmcs12) +{ + prepare_vmcs02_constant_state(vmx); + + vmcs_write64(VMCS_LINK_POINTER, -1ull); if (enable_vpid) { if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) @@ -12073,78 +12539,30 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) else vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); } - - /* - * L1 may access the L2's PDPTR, so save them to construct vmcs12 - */ - if (enable_ept) { - vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0); - vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1); - vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2); - vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3); - } - - if (cpu_has_vmx_msr_bitmap()) - vmcs_write64(MSR_BITMAP, __pa(vmx->nested.vmcs02.msr_bitmap)); } -/* - * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested - * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it - * with L0's requirements for its guest (a.k.a. vmcs01), so we can run the L2 - * guest in a way that will both be appropriate to L1's requests, and our - * needs. In addition to modifying the active vmcs (which is vmcs02), this - * function also has additional necessary side-effects, like setting various - * vcpu->arch fields. - * Returns 0 on success, 1 on failure. Invalid state exit qualification code - * is assigned to entry_failure_code on failure. - */ -static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, - u32 *entry_failure_code) +static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) { - struct vcpu_vmx *vmx = to_vmx(vcpu); u32 exec_control, vmcs12_exec_ctrl; + u64 guest_efer = nested_vmx_calc_efer(vmx, vmcs12); - if (vmx->nested.dirty_vmcs12) { - prepare_vmcs02_full(vcpu, vmcs12); - vmx->nested.dirty_vmcs12 = false; - } + if (vmx->nested.dirty_vmcs12 || vmx->nested.hv_evmcs) + prepare_vmcs02_early_full(vmx, vmcs12); /* - * First, the fields that are shadowed. This must be kept in sync - * with vmx_shadow_fields.h. + * HOST_RSP is normally set correctly in vmx_vcpu_run() just before + * entry, but only if the current (host) sp changed from the value + * we wrote last (vmx->host_rsp). This cache is no longer relevant + * if we switch vmcs, and rather than hold a separate cache per vmcs, + * here we just force the write to happen on entry. host_rsp will + * also be written unconditionally by nested_vmx_check_vmentry_hw() + * if we are doing early consistency checks via hardware. */ + vmx->host_rsp = 0; - vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector); - vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit); - vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes); - vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base); - vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base); - - if (vmx->nested.nested_run_pending && - (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) { - kvm_set_dr(vcpu, 7, vmcs12->guest_dr7); - vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl); - } else { - kvm_set_dr(vcpu, 7, vcpu->arch.dr7); - vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl); - } - if (vmx->nested.nested_run_pending) { - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, - vmcs12->vm_entry_intr_info_field); - vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, - vmcs12->vm_entry_exception_error_code); - vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, - vmcs12->vm_entry_instruction_len); - vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, - vmcs12->guest_interruptibility_info); - vmx->loaded_vmcs->nmi_known_unmasked = - !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI); - } else { - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); - } - vmx_set_rflags(vcpu, vmcs12->guest_rflags); - + /* + * PIN CONTROLS + */ exec_control = vmcs12->pin_based_vm_exec_control; /* Preemption timer setting is computed directly in vmx_vcpu_run. */ @@ -12159,13 +12577,43 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, } else { exec_control &= ~PIN_BASED_POSTED_INTR; } - vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, exec_control); - vmx->nested.preemption_timer_expired = false; - if (nested_cpu_has_preemption_timer(vmcs12)) - vmx_start_preemption_timer(vcpu); + /* + * EXEC CONTROLS + */ + exec_control = vmx_exec_control(vmx); /* L0's desires */ + exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING; + exec_control &= ~CPU_BASED_TPR_SHADOW; + exec_control |= vmcs12->cpu_based_vm_exec_control; + /* + * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR. Later, if + * nested_get_vmcs12_pages can't fix it up, the illegal value + * will result in a VM entry failure. + */ + if (exec_control & CPU_BASED_TPR_SHADOW) { + vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull); + vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold); + } else { +#ifdef CONFIG_X86_64 + exec_control |= CPU_BASED_CR8_LOAD_EXITING | + CPU_BASED_CR8_STORE_EXITING; +#endif + } + + /* + * A vmexit (to either L1 hypervisor or L0 userspace) is always needed + * for I/O port accesses. + */ + exec_control &= ~CPU_BASED_USE_IO_BITMAPS; + exec_control |= CPU_BASED_UNCOND_IO_EXITING; + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control); + + /* + * SECONDARY EXEC CONTROLS + */ if (cpu_has_secondary_exec_ctrls()) { exec_control = vmx->secondary_exec_control; @@ -12206,43 +12654,214 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, } /* - * HOST_RSP is normally set correctly in vmx_vcpu_run() just before - * entry, but only if the current (host) sp changed from the value - * we wrote last (vmx->host_rsp). This cache is no longer relevant - * if we switch vmcs, and rather than hold a separate cache per vmcs, - * here we just force the write to happen on entry. + * ENTRY CONTROLS + * + * vmcs12's VM_{ENTRY,EXIT}_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE + * are emulated by vmx_set_efer() in prepare_vmcs02(), but speculate + * on the related bits (if supported by the CPU) in the hope that + * we can avoid VMWrites during vmx_set_efer(). + */ + exec_control = (vmcs12->vm_entry_controls | vmcs_config.vmentry_ctrl) & + ~VM_ENTRY_IA32E_MODE & ~VM_ENTRY_LOAD_IA32_EFER; + if (cpu_has_load_ia32_efer) { + if (guest_efer & EFER_LMA) + exec_control |= VM_ENTRY_IA32E_MODE; + if (guest_efer != host_efer) + exec_control |= VM_ENTRY_LOAD_IA32_EFER; + } + vm_entry_controls_init(vmx, exec_control); + + /* + * EXIT CONTROLS + * + * L2->L1 exit controls are emulated - the hardware exit is to L0 so + * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER + * bits may be modified by vmx_set_efer() in prepare_vmcs02(). */ - vmx->host_rsp = 0; + exec_control = vmcs_config.vmexit_ctrl; + if (cpu_has_load_ia32_efer && guest_efer != host_efer) + exec_control |= VM_EXIT_LOAD_IA32_EFER; + vm_exit_controls_init(vmx, exec_control); - exec_control = vmx_exec_control(vmx); /* L0's desires */ - exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; - exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING; - exec_control &= ~CPU_BASED_TPR_SHADOW; - exec_control |= vmcs12->cpu_based_vm_exec_control; + /* + * Conceptually we want to copy the PML address and index from + * vmcs01 here, and then back to vmcs01 on nested vmexit. But, + * since we always flush the log on each vmexit and never change + * the PML address (once set), this happens to be equivalent to + * simply resetting the index in vmcs02. + */ + if (enable_pml) + vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); /* - * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR. Later, if - * nested_get_vmcs12_pages can't fix it up, the illegal value - * will result in a VM entry failure. + * Interrupt/Exception Fields */ - if (exec_control & CPU_BASED_TPR_SHADOW) { - vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull); - vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold); + if (vmx->nested.nested_run_pending) { + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, + vmcs12->vm_entry_intr_info_field); + vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, + vmcs12->vm_entry_exception_error_code); + vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, + vmcs12->vm_entry_instruction_len); + vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, + vmcs12->guest_interruptibility_info); + vmx->loaded_vmcs->nmi_known_unmasked = + !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI); } else { -#ifdef CONFIG_X86_64 - exec_control |= CPU_BASED_CR8_LOAD_EXITING | - CPU_BASED_CR8_STORE_EXITING; -#endif + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); } +} + +static void prepare_vmcs02_full(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12) +{ + struct hv_enlightened_vmcs *hv_evmcs = vmx->nested.hv_evmcs; + + 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); + vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector); + vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector); + vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector); + vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector); + vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector); + vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit); + vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit); + vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit); + vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit); + vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit); + vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit); + vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit); + vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit); + vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit); + vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit); + vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes); + vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes); + vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes); + vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes); + vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes); + vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes); + vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base); + vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base); + vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base); + vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base); + vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base); + vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base); + vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base); + vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base); + vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base); + vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base); + } + + if (!hv_evmcs || !(hv_evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1)) { + vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs); + vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, + vmcs12->guest_pending_dbg_exceptions); + vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp); + vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip); + + /* + * L1 may access the L2's PDPTR, so save them to construct + * vmcs12 + */ + if (enable_ept) { + vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0); + vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1); + vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2); + vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3); + } + } + + if (nested_cpu_has_xsaves(vmcs12)) + vmcs_write64(XSS_EXIT_BITMAP, vmcs12->xss_exit_bitmap); /* - * A vmexit (to either L1 hypervisor or L0 userspace) is always needed - * for I/O port accesses. + * Whether page-faults are trapped is determined by a combination of + * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. + * If enable_ept, L0 doesn't care about page faults and we should + * set all of these to L1's desires. However, if !enable_ept, L0 does + * care about (at least some) page faults, and because it is not easy + * (if at all possible?) to merge L0 and L1's desires, we simply ask + * to exit on each and every L2 page fault. This is done by setting + * MASK=MATCH=0 and (see below) EB.PF=1. + * Note that below we don't need special code to set EB.PF beyond the + * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept, + * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when + * !enable_ept, EB.PF is 1, so the "or" will always be 1. */ - exec_control &= ~CPU_BASED_USE_IO_BITMAPS; - exec_control |= CPU_BASED_UNCOND_IO_EXITING; + vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, + enable_ept ? vmcs12->page_fault_error_code_mask : 0); + vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, + enable_ept ? vmcs12->page_fault_error_code_match : 0); - vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control); + if (cpu_has_vmx_apicv()) { + vmcs_write64(EOI_EXIT_BITMAP0, vmcs12->eoi_exit_bitmap0); + vmcs_write64(EOI_EXIT_BITMAP1, vmcs12->eoi_exit_bitmap1); + vmcs_write64(EOI_EXIT_BITMAP2, vmcs12->eoi_exit_bitmap2); + vmcs_write64(EOI_EXIT_BITMAP3, vmcs12->eoi_exit_bitmap3); + } + + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); + + set_cr4_guest_host_mask(vmx); + + if (kvm_mpx_supported()) { + if (vmx->nested.nested_run_pending && + (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)) + vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs); + else + vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs); + } +} + +/* + * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested + * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it + * with L0's requirements for its guest (a.k.a. vmcs01), so we can run the L2 + * guest in a way that will both be appropriate to L1's requests, and our + * needs. In addition to modifying the active vmcs (which is vmcs02), this + * function also has additional necessary side-effects, like setting various + * vcpu->arch fields. + * Returns 0 on success, 1 on failure. Invalid state exit qualification code + * is assigned to entry_failure_code on failure. + */ +static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, + u32 *entry_failure_code) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct hv_enlightened_vmcs *hv_evmcs = vmx->nested.hv_evmcs; + + if (vmx->nested.dirty_vmcs12 || vmx->nested.hv_evmcs) { + prepare_vmcs02_full(vmx, vmcs12); + vmx->nested.dirty_vmcs12 = false; + } + + /* + * First, the fields that are shadowed. This must be kept in sync + * with vmx_shadow_fields.h. + */ + if (!hv_evmcs || !(hv_evmcs->hv_clean_fields & + HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2)) { + vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes); + vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes); + } + + if (vmx->nested.nested_run_pending && + (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) { + kvm_set_dr(vcpu, 7, vmcs12->guest_dr7); + vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl); + } else { + kvm_set_dr(vcpu, 7, vcpu->arch.dr7); + vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl); + } + vmx_set_rflags(vcpu, vmcs12->guest_rflags); + + vmx->nested.preemption_timer_expired = false; + if (nested_cpu_has_preemption_timer(vmcs12)) + vmx_start_preemption_timer(vcpu); /* EXCEPTION_BITMAP and CR0_GUEST_HOST_MASK should basically be the * bitwise-or of what L1 wants to trap for L2, and what we want to @@ -12252,20 +12871,6 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask; vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); - /* L2->L1 exit controls are emulated - the hardware exit is to L0 so - * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER - * bits are further modified by vmx_set_efer() below. - */ - vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl); - - /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are - * emulated by vmx_set_efer(), below. - */ - vm_entry_controls_init(vmx, - (vmcs12->vm_entry_controls & ~VM_ENTRY_LOAD_IA32_EFER & - ~VM_ENTRY_IA32E_MODE) | - (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE)); - if (vmx->nested.nested_run_pending && (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)) { vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat); @@ -12288,37 +12893,29 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, * influence global bitmap(for vpid01 and vpid02 allocation) * even if spawn a lot of nested vCPUs. */ - if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) { + if (nested_cpu_has_vpid(vmcs12) && nested_has_guest_tlb_tag(vcpu)) { if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) { vmx->nested.last_vpid = vmcs12->virtual_processor_id; - __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); + __vmx_flush_tlb(vcpu, nested_get_vpid02(vcpu), false); } } else { - vmx_flush_tlb(vcpu, true); + /* + * If L1 use EPT, then L0 needs to execute INVEPT on + * EPTP02 instead of EPTP01. Therefore, delay TLB + * flush until vmcs02->eptp is fully updated by + * KVM_REQ_LOAD_CR3. Note that this assumes + * KVM_REQ_TLB_FLUSH is evaluated after + * KVM_REQ_LOAD_CR3 in vcpu_enter_guest(). + */ + kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); } } - if (enable_pml) { - /* - * Conceptually we want to copy the PML address and index from - * vmcs01 here, and then back to vmcs01 on nested vmexit. But, - * since we always flush the log on each vmexit, this happens - * to be equivalent to simply resetting the fields in vmcs02. - */ - ASSERT(vmx->pml_pg); - vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); - vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); - } - - if (nested_cpu_has_ept(vmcs12)) { - if (nested_ept_init_mmu_context(vcpu)) { - *entry_failure_code = ENTRY_FAIL_DEFAULT; - return 1; - } - } else if (nested_cpu_has2(vmcs12, - SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) { + if (nested_cpu_has_ept(vmcs12)) + nested_ept_init_mmu_context(vcpu); + else if (nested_cpu_has2(vmcs12, + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) vmx_flush_tlb(vcpu, true); - } /* * This sets GUEST_CR0 to vmcs12->guest_cr0, possibly modifying those @@ -12334,14 +12931,8 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, vmx_set_cr4(vcpu, vmcs12->guest_cr4); vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12)); - if (vmx->nested.nested_run_pending && - (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) - vcpu->arch.efer = vmcs12->guest_ia32_efer; - else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) - vcpu->arch.efer |= (EFER_LMA | EFER_LME); - else - vcpu->arch.efer &= ~(EFER_LMA | EFER_LME); - /* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */ + vcpu->arch.efer = nested_vmx_calc_efer(vmx, vmcs12); + /* Note: may modify VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */ vmx_set_efer(vcpu, vcpu->arch.efer); /* @@ -12383,6 +12974,7 @@ static int nested_vmx_check_nmi_controls(struct vmcs12 *vmcs12) static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) { struct vcpu_vmx *vmx = to_vmx(vcpu); + bool ia32e; if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE && vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT) @@ -12457,6 +13049,21 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD; /* + * If the load IA32_EFER VM-exit control is 1, bits reserved in the + * IA32_EFER MSR must be 0 in the field for that register. In addition, + * the values of the LMA and LME bits in the field must each be that of + * the host address-space size VM-exit control. + */ + if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) { + ia32e = (vmcs12->vm_exit_controls & + VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0; + if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) || + ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) || + ia32e != !!(vmcs12->host_ia32_efer & EFER_LME)) + return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD; + } + + /* * From the Intel SDM, volume 3: * Fields relevant to VM-entry event injection must be set properly. * These fields are the VM-entry interruption-information field, the @@ -12512,6 +13119,10 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) } } + if (nested_cpu_has_ept(vmcs12) && + !valid_ept_address(vcpu, vmcs12->ept_pointer)) + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; + return 0; } @@ -12577,21 +13188,6 @@ static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, return 1; } - /* - * If the load IA32_EFER VM-exit control is 1, bits reserved in the - * IA32_EFER MSR must be 0 in the field for that register. In addition, - * the values of the LMA and LME bits in the field must each be that of - * the host address-space size VM-exit control. - */ - if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) { - ia32e = (vmcs12->vm_exit_controls & - VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0; - if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) || - ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) || - ia32e != !!(vmcs12->host_ia32_efer & EFER_LME)) - return 1; - } - if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS) && (is_noncanonical_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu) || (vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD))) @@ -12600,26 +13196,139 @@ static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, return 0; } +static int __noclone nested_vmx_check_vmentry_hw(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + unsigned long cr3, cr4; + + if (!nested_early_check) + return 0; + + if (vmx->msr_autoload.host.nr) + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0); + if (vmx->msr_autoload.guest.nr) + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0); + + preempt_disable(); + + vmx_prepare_switch_to_guest(vcpu); + + /* + * Induce a consistency check VMExit by clearing bit 1 in GUEST_RFLAGS, + * which is reserved to '1' by hardware. GUEST_RFLAGS is guaranteed to + * be written (by preparve_vmcs02()) before the "real" VMEnter, i.e. + * there is no need to preserve other bits or save/restore the field. + */ + vmcs_writel(GUEST_RFLAGS, 0); + + vmcs_writel(HOST_RIP, vmx_early_consistency_check_return); + + cr3 = __get_current_cr3_fast(); + if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) { + vmcs_writel(HOST_CR3, cr3); + vmx->loaded_vmcs->host_state.cr3 = cr3; + } + + cr4 = cr4_read_shadow(); + if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) { + vmcs_writel(HOST_CR4, cr4); + vmx->loaded_vmcs->host_state.cr4 = cr4; + } + + vmx->__launched = vmx->loaded_vmcs->launched; + + asm( + /* Set HOST_RSP */ + __ex("vmwrite %%" _ASM_SP ", %%" _ASM_DX) "\n\t" + "mov %%" _ASM_SP ", %c[host_rsp](%0)\n\t" + + /* Check if vmlaunch of vmresume is needed */ + "cmpl $0, %c[launched](%0)\n\t" + "je 1f\n\t" + __ex("vmresume") "\n\t" + "jmp 2f\n\t" + "1: " __ex("vmlaunch") "\n\t" + "jmp 2f\n\t" + "2: " + + /* Set vmx->fail accordingly */ + "setbe %c[fail](%0)\n\t" + + ".pushsection .rodata\n\t" + ".global vmx_early_consistency_check_return\n\t" + "vmx_early_consistency_check_return: " _ASM_PTR " 2b\n\t" + ".popsection" + : + : "c"(vmx), "d"((unsigned long)HOST_RSP), + [launched]"i"(offsetof(struct vcpu_vmx, __launched)), + [fail]"i"(offsetof(struct vcpu_vmx, fail)), + [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)) + : "rax", "cc", "memory" + ); + + vmcs_writel(HOST_RIP, vmx_return); + + preempt_enable(); + + if (vmx->msr_autoload.host.nr) + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); + if (vmx->msr_autoload.guest.nr) + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); + + if (vmx->fail) { + WARN_ON_ONCE(vmcs_read32(VM_INSTRUCTION_ERROR) != + VMXERR_ENTRY_INVALID_CONTROL_FIELD); + vmx->fail = 0; + return 1; + } + + /* + * VMExit clears RFLAGS.IF and DR7, even on a consistency check. + */ + local_irq_enable(); + if (hw_breakpoint_active()) + set_debugreg(__this_cpu_read(cpu_dr7), 7); + + /* + * A non-failing VMEntry means we somehow entered guest mode with + * an illegal RIP, and that's just the tip of the iceberg. There + * is no telling what memory has been modified or what state has + * been exposed to unknown code. Hitting this all but guarantees + * a (very critical) hardware issue. + */ + WARN_ON(!(vmcs_read32(VM_EXIT_REASON) & + VMX_EXIT_REASONS_FAILED_VMENTRY)); + + return 0; +} +STACK_FRAME_NON_STANDARD(nested_vmx_check_vmentry_hw); + +static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12); + /* - * If exit_qual is NULL, this is being called from state restore (either RSM + * If from_vmentry is false, this is being called from state restore (either RSM * or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume. ++ * ++ * Returns: ++ * 0 - success, i.e. proceed with actual VMEnter ++ * 1 - consistency check VMExit ++ * -1 - consistency check VMFail */ -static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual) +static int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, + bool from_vmentry) { struct vcpu_vmx *vmx = to_vmx(vcpu); struct vmcs12 *vmcs12 = get_vmcs12(vcpu); - bool from_vmentry = !!exit_qual; - u32 dummy_exit_qual; bool evaluate_pending_interrupts; - int r = 0; + u32 exit_reason = EXIT_REASON_INVALID_STATE; + u32 exit_qual; evaluate_pending_interrupts = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) & (CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_VIRTUAL_NMI_PENDING); if (likely(!evaluate_pending_interrupts) && kvm_vcpu_apicv_active(vcpu)) evaluate_pending_interrupts |= vmx_has_apicv_interrupt(vcpu); - enter_guest_mode(vcpu); - if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL); if (kvm_mpx_supported() && @@ -12627,24 +13336,35 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual) vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS); vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02); - vmx_segment_cache_clear(vmx); + prepare_vmcs02_early(vmx, vmcs12); + + if (from_vmentry) { + nested_get_vmcs12_pages(vcpu); + + if (nested_vmx_check_vmentry_hw(vcpu)) { + vmx_switch_vmcs(vcpu, &vmx->vmcs01); + return -1; + } + + if (check_vmentry_postreqs(vcpu, vmcs12, &exit_qual)) + goto vmentry_fail_vmexit; + } + + enter_guest_mode(vcpu); if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING) vcpu->arch.tsc_offset += vmcs12->tsc_offset; - r = EXIT_REASON_INVALID_STATE; - if (prepare_vmcs02(vcpu, vmcs12, from_vmentry ? exit_qual : &dummy_exit_qual)) - goto fail; + if (prepare_vmcs02(vcpu, vmcs12, &exit_qual)) + goto vmentry_fail_vmexit_guest_mode; if (from_vmentry) { - nested_get_vmcs12_pages(vcpu); - - r = EXIT_REASON_MSR_LOAD_FAIL; - *exit_qual = nested_vmx_load_msr(vcpu, - vmcs12->vm_entry_msr_load_addr, - vmcs12->vm_entry_msr_load_count); - if (*exit_qual) - goto fail; + exit_reason = EXIT_REASON_MSR_LOAD_FAIL; + exit_qual = nested_vmx_load_msr(vcpu, + vmcs12->vm_entry_msr_load_addr, + vmcs12->vm_entry_msr_load_count); + if (exit_qual) + goto vmentry_fail_vmexit_guest_mode; } else { /* * The MMU is not initialized to point at the right entities yet and @@ -12681,12 +13401,28 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual) */ return 0; -fail: + /* + * A failed consistency check that leads to a VMExit during L1's + * VMEnter to L2 is a variation of a normal VMexit, as explained in + * 26.7 "VM-entry failures during or after loading guest state". + */ +vmentry_fail_vmexit_guest_mode: if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING) vcpu->arch.tsc_offset -= vmcs12->tsc_offset; leave_guest_mode(vcpu); + +vmentry_fail_vmexit: vmx_switch_vmcs(vcpu, &vmx->vmcs01); - return r; + + if (!from_vmentry) + return 1; + + load_vmcs12_host_state(vcpu, vmcs12); + vmcs12->vm_exit_reason = exit_reason | VMX_EXIT_REASONS_FAILED_VMENTRY; + vmcs12->exit_qualification = exit_qual; + if (enable_shadow_vmcs || vmx->nested.hv_evmcs) + vmx->nested.need_vmcs12_sync = true; + return 1; } /* @@ -12698,14 +13434,16 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) struct vmcs12 *vmcs12; struct vcpu_vmx *vmx = to_vmx(vcpu); u32 interrupt_shadow = vmx_get_interrupt_shadow(vcpu); - u32 exit_qual; int ret; if (!nested_vmx_check_permission(vcpu)) return 1; - if (!nested_vmx_check_vmcs12(vcpu)) - goto out; + if (!nested_vmx_handle_enlightened_vmptrld(vcpu, true)) + return 1; + + if (!vmx->nested.hv_evmcs && vmx->nested.current_vmptr == -1ull) + return nested_vmx_failInvalid(vcpu); vmcs12 = get_vmcs12(vcpu); @@ -12715,13 +13453,16 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) * rather than RFLAGS.ZF, and no error number is stored to the * VM-instruction error field. */ - if (vmcs12->hdr.shadow_vmcs) { - nested_vmx_failInvalid(vcpu); - goto out; - } + if (vmcs12->hdr.shadow_vmcs) + return nested_vmx_failInvalid(vcpu); - if (enable_shadow_vmcs) + if (vmx->nested.hv_evmcs) { + copy_enlightened_to_vmcs12(vmx); + /* Enlightened VMCS doesn't have launch state */ + vmcs12->launch_state = !launch; + } else if (enable_shadow_vmcs) { copy_shadow_to_vmcs12(vmx); + } /* * The nested entry process starts with enforcing various prerequisites @@ -12733,59 +13474,37 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) * for misconfigurations which will anyway be caught by the processor * when using the merged vmcs02. */ - if (interrupt_shadow & KVM_X86_SHADOW_INT_MOV_SS) { - nested_vmx_failValid(vcpu, - VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS); - goto out; - } + if (interrupt_shadow & KVM_X86_SHADOW_INT_MOV_SS) + return nested_vmx_failValid(vcpu, + VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS); - if (vmcs12->launch_state == launch) { - nested_vmx_failValid(vcpu, + if (vmcs12->launch_state == launch) + return nested_vmx_failValid(vcpu, launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS : VMXERR_VMRESUME_NONLAUNCHED_VMCS); - goto out; - } ret = check_vmentry_prereqs(vcpu, vmcs12); - if (ret) { - nested_vmx_failValid(vcpu, ret); - goto out; - } - - /* - * After this point, the trap flag no longer triggers a singlestep trap - * on the vm entry instructions; don't call kvm_skip_emulated_instruction. - * This is not 100% correct; for performance reasons, we delegate most - * of the checks on host state to the processor. If those fail, - * the singlestep trap is missed. - */ - skip_emulated_instruction(vcpu); - - ret = check_vmentry_postreqs(vcpu, vmcs12, &exit_qual); - if (ret) { - nested_vmx_entry_failure(vcpu, vmcs12, - EXIT_REASON_INVALID_STATE, exit_qual); - return 1; - } + if (ret) + return nested_vmx_failValid(vcpu, ret); /* * We're finally done with prerequisite checking, and can start with * the nested entry. */ - vmx->nested.nested_run_pending = 1; - ret = enter_vmx_non_root_mode(vcpu, &exit_qual); - if (ret) { - nested_vmx_entry_failure(vcpu, vmcs12, ret, exit_qual); - vmx->nested.nested_run_pending = 0; + ret = nested_vmx_enter_non_root_mode(vcpu, true); + vmx->nested.nested_run_pending = !ret; + if (ret > 0) return 1; - } + else if (ret) + return nested_vmx_failValid(vcpu, + VMXERR_ENTRY_INVALID_CONTROL_FIELD); /* Hide L1D cache contents from the nested guest. */ vmx->vcpu.arch.l1tf_flush_l1d = true; /* - * Must happen outside of enter_vmx_non_root_mode() as it will + * Must happen outside of nested_vmx_enter_non_root_mode() as it will * also be used as part of restoring nVMX state for * snapshot restore (migration). * @@ -12806,9 +13525,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) return kvm_vcpu_halt(vcpu); } return 1; - -out: - return kvm_skip_emulated_instruction(vcpu); } /* @@ -13122,24 +13838,6 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, kvm_clear_interrupt_queue(vcpu); } -static void load_vmcs12_mmu_host_state(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12) -{ - u32 entry_failure_code; - - nested_ept_uninit_mmu_context(vcpu); - - /* - * Only PDPTE load can fail as the value of cr3 was checked on entry and - * couldn't have changed. - */ - if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code)) - nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL); - - if (!enable_ept) - vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault; -} - /* * A part of what we need to when the nested L2 guest exits and we want to * run its L1 parent, is to reset L1's guest state to the host state specified @@ -13153,6 +13851,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) { struct kvm_segment seg; + u32 entry_failure_code; if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) vcpu->arch.efer = vmcs12->host_ia32_efer; @@ -13165,6 +13864,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp); kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip); vmx_set_rflags(vcpu, X86_EFLAGS_FIXED); + vmx_set_interrupt_shadow(vcpu, 0); + /* * Note that calling vmx_set_cr0 is important, even if cr0 hasn't * actually changed, because vmx_set_cr0 refers to efer set above. @@ -13179,23 +13880,35 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK); vmx_set_cr4(vcpu, vmcs12->host_cr4); - load_vmcs12_mmu_host_state(vcpu, vmcs12); + nested_ept_uninit_mmu_context(vcpu); /* - * If vmcs01 don't use VPID, CPU flushes TLB on every + * Only PDPTE load can fail as the value of cr3 was checked on entry and + * couldn't have changed. + */ + if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code)) + nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL); + + if (!enable_ept) + vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault; + + /* + * If vmcs01 doesn't use VPID, CPU flushes TLB on every * VMEntry/VMExit. Thus, no need to flush TLB. * - * If vmcs12 uses VPID, TLB entries populated by L2 are - * tagged with vmx->nested.vpid02 while L1 entries are tagged - * with vmx->vpid. Thus, no need to flush TLB. + * If vmcs12 doesn't use VPID, L1 expects TLB to be + * flushed on every VMEntry/VMExit. + * + * Otherwise, we can preserve TLB entries as long as we are + * able to tag L1 TLB entries differently than L2 TLB entries. * - * Therefore, flush TLB only in case vmcs01 uses VPID and - * vmcs12 don't use VPID as in this case L1 & L2 TLB entries - * are both tagged with vmx->vpid. + * If vmcs12 uses EPT, we need to execute this flush on EPTP01 + * and therefore we request the TLB flush to happen only after VMCS EPTP + * has been set by KVM_REQ_LOAD_CR3. */ if (enable_vpid && - !(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02)) { - vmx_flush_tlb(vcpu, true); + (!nested_cpu_has_vpid(vmcs12) || !nested_has_guest_tlb_tag(vcpu))) { + kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); } vmcs_write32(GUEST_SYSENTER_CS, vmcs12->host_ia32_sysenter_cs); @@ -13275,6 +13988,140 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL); } +static inline u64 nested_vmx_get_vmcs01_guest_efer(struct vcpu_vmx *vmx) +{ + struct shared_msr_entry *efer_msr; + unsigned int i; + + if (vm_entry_controls_get(vmx) & VM_ENTRY_LOAD_IA32_EFER) + return vmcs_read64(GUEST_IA32_EFER); + + if (cpu_has_load_ia32_efer) + return host_efer; + + for (i = 0; i < vmx->msr_autoload.guest.nr; ++i) { + if (vmx->msr_autoload.guest.val[i].index == MSR_EFER) + return vmx->msr_autoload.guest.val[i].value; + } + + efer_msr = find_msr_entry(vmx, MSR_EFER); + if (efer_msr) + return efer_msr->data; + + return host_efer; +} + +static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu) +{ + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct vmx_msr_entry g, h; + struct msr_data msr; + gpa_t gpa; + u32 i, j; + + vcpu->arch.pat = vmcs_read64(GUEST_IA32_PAT); + + if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) { + /* + * L1's host DR7 is lost if KVM_GUESTDBG_USE_HW_BP is set + * as vmcs01.GUEST_DR7 contains a userspace defined value + * and vcpu->arch.dr7 is not squirreled away before the + * nested VMENTER (not worth adding a variable in nested_vmx). + */ + if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) + kvm_set_dr(vcpu, 7, DR7_FIXED_1); + else + WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7))); + } + + /* + * Note that calling vmx_set_{efer,cr0,cr4} is important as they + * handle a variety of side effects to KVM's software model. + */ + vmx_set_efer(vcpu, nested_vmx_get_vmcs01_guest_efer(vmx)); + + vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS; + vmx_set_cr0(vcpu, vmcs_readl(CR0_READ_SHADOW)); + + vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK); + vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW)); + + nested_ept_uninit_mmu_context(vcpu); + vcpu->arch.cr3 = vmcs_readl(GUEST_CR3); + __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail); + + /* + * Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs + * from vmcs01 (if necessary). The PDPTRs are not loaded on + * VMFail, like everything else we just need to ensure our + * software model is up-to-date. + */ + ept_save_pdptrs(vcpu); + + kvm_mmu_reset_context(vcpu); + + if (cpu_has_vmx_msr_bitmap()) + vmx_update_msr_bitmap(vcpu); + + /* + * This nasty bit of open coding is a compromise between blindly + * loading L1's MSRs using the exit load lists (incorrect emulation + * of VMFail), leaving the nested VM's MSRs in the software model + * (incorrect behavior) and snapshotting the modified MSRs (too + * expensive since the lists are unbound by hardware). For each + * MSR that was (prematurely) loaded from the nested VMEntry load + * list, reload it from the exit load list if it exists and differs + * from the guest value. The intent is to stuff host state as + * silently as possible, not to fully process the exit load list. + */ + msr.host_initiated = false; + for (i = 0; i < vmcs12->vm_entry_msr_load_count; i++) { + gpa = vmcs12->vm_entry_msr_load_addr + (i * sizeof(g)); + if (kvm_vcpu_read_guest(vcpu, gpa, &g, sizeof(g))) { + pr_debug_ratelimited( + "%s read MSR index failed (%u, 0x%08llx)\n", + __func__, i, gpa); + goto vmabort; + } + + for (j = 0; j < vmcs12->vm_exit_msr_load_count; j++) { + gpa = vmcs12->vm_exit_msr_load_addr + (j * sizeof(h)); + if (kvm_vcpu_read_guest(vcpu, gpa, &h, sizeof(h))) { + pr_debug_ratelimited( + "%s read MSR failed (%u, 0x%08llx)\n", + __func__, j, gpa); + goto vmabort; + } + if (h.index != g.index) + continue; + if (h.value == g.value) + break; + + if (nested_vmx_load_msr_check(vcpu, &h)) { + pr_debug_ratelimited( + "%s check failed (%u, 0x%x, 0x%x)\n", + __func__, j, h.index, h.reserved); + goto vmabort; + } + + msr.index = h.index; + msr.data = h.value; + if (kvm_set_msr(vcpu, &msr)) { + pr_debug_ratelimited( + "%s WRMSR failed (%u, 0x%x, 0x%llx)\n", + __func__, j, h.index, h.value); + goto vmabort; + } + } + } + + return; + +vmabort: + nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL); +} + /* * Emulate an exit from nested guest (L2) to L1, i.e., prepare to run L1 * and modify vmcs12 to make it see what it would expect to see there if @@ -13290,14 +14137,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, /* trying to cancel vmlaunch/vmresume is a bug */ WARN_ON_ONCE(vmx->nested.nested_run_pending); - /* - * The only expected VM-instruction error is "VM entry with - * invalid control field(s)." Anything else indicates a - * problem with L0. - */ - WARN_ON_ONCE(vmx->fail && (vmcs_read32(VM_INSTRUCTION_ERROR) != - VMXERR_ENTRY_INVALID_CONTROL_FIELD)); - leave_guest_mode(vcpu); if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING) @@ -13324,12 +14163,19 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, if (nested_vmx_store_msr(vcpu, vmcs12->vm_exit_msr_store_addr, vmcs12->vm_exit_msr_store_count)) nested_vmx_abort(vcpu, VMX_ABORT_SAVE_GUEST_MSR_FAIL); + } else { + /* + * The only expected VM-instruction error is "VM entry with + * invalid control field(s)." Anything else indicates a + * problem with L0. And we should never get here with a + * VMFail of any type if early consistency checks are enabled. + */ + WARN_ON_ONCE(vmcs_read32(VM_INSTRUCTION_ERROR) != + VMXERR_ENTRY_INVALID_CONTROL_FIELD); + WARN_ON_ONCE(nested_early_check); } vmx_switch_vmcs(vcpu, &vmx->vmcs01); - vm_entry_controls_reset_shadow(vmx); - vm_exit_controls_reset_shadow(vmx); - vmx_segment_cache_clear(vmx); /* Update any VMCS fields that might have changed while L2 ran */ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); @@ -13373,8 +14219,8 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, */ kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); - if (enable_shadow_vmcs && exit_reason != -1) - vmx->nested.sync_shadow_vmcs = true; + if ((exit_reason != -1) && (enable_shadow_vmcs || vmx->nested.hv_evmcs)) + vmx->nested.need_vmcs12_sync = true; /* in case we halted in L2 */ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; @@ -13409,24 +14255,24 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, return; } - + /* * After an early L2 VM-entry failure, we're now back * in L1 which thinks it just finished a VMLAUNCH or * VMRESUME instruction, so we need to set the failure * flag and the VM-instruction error field of the VMCS - * accordingly. + * accordingly, and skip the emulated instruction. */ - nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); - - load_vmcs12_mmu_host_state(vcpu, vmcs12); + (void)nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); /* - * The emulated instruction was already skipped in - * nested_vmx_run, but the updated RIP was never - * written back to the vmcs01. + * Restore L1's host state to KVM's software model. We're here + * because a consistency check was caught by hardware, which + * means some amount of guest state has been propagated to KVM's + * model and needs to be unwound to the host's state. */ - skip_emulated_instruction(vcpu); + nested_vmx_restore_host_state(vcpu); + vmx->fail = 0; } @@ -13439,26 +14285,7 @@ static void vmx_leave_nested(struct kvm_vcpu *vcpu) to_vmx(vcpu)->nested.nested_run_pending = 0; nested_vmx_vmexit(vcpu, -1, 0, 0); } - free_nested(to_vmx(vcpu)); -} - -/* - * L1's failure to enter L2 is a subset of a normal exit, as explained in - * 23.7 "VM-entry failures during or after loading guest state" (this also - * lists the acceptable exit-reason and exit-qualification parameters). - * It should only be called before L2 actually succeeded to run, and when - * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). - */ -static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12, - u32 reason, unsigned long qualification) -{ - load_vmcs12_host_state(vcpu, vmcs12); - vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; - vmcs12->exit_qualification = qualification; - nested_vmx_succeed(vcpu); - if (enable_shadow_vmcs) - to_vmx(vcpu)->nested.sync_shadow_vmcs = true; + free_nested(vcpu); } static int vmx_check_intercept(struct kvm_vcpu *vcpu, @@ -13884,7 +14711,7 @@ static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase) if (vmx->nested.smm.guest_mode) { vcpu->arch.hflags &= ~HF_SMM_MASK; - ret = enter_vmx_non_root_mode(vcpu, NULL); + ret = nested_vmx_enter_non_root_mode(vcpu, false); vcpu->arch.hflags |= HF_SMM_MASK; if (ret) return ret; @@ -13899,6 +14726,20 @@ static int enable_smi_window(struct kvm_vcpu *vcpu) return 0; } +static inline int vmx_has_valid_vmcs12(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + /* + * In case we do two consecutive get/set_nested_state()s while L2 was + * running hv_evmcs may end up not being mapped (we map it from + * nested_vmx_run()/vmx_vcpu_run()). Check is_guest_mode() as we always + * have vmcs12 if it is true. + */ + return is_guest_mode(vcpu) || vmx->nested.current_vmptr != -1ull || + vmx->nested.hv_evmcs; +} + static int vmx_get_nested_state(struct kvm_vcpu *vcpu, struct kvm_nested_state __user *user_kvm_nested_state, u32 user_data_size) @@ -13918,12 +14759,16 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu, vmx = to_vmx(vcpu); vmcs12 = get_vmcs12(vcpu); + + if (nested_vmx_allowed(vcpu) && vmx->nested.enlightened_vmcs_enabled) + kvm_state.flags |= KVM_STATE_NESTED_EVMCS; + if (nested_vmx_allowed(vcpu) && (vmx->nested.vmxon || vmx->nested.smm.vmxon)) { kvm_state.vmx.vmxon_pa = vmx->nested.vmxon_ptr; kvm_state.vmx.vmcs_pa = vmx->nested.current_vmptr; - if (vmx->nested.current_vmptr != -1ull) { + if (vmx_has_valid_vmcs12(vcpu)) { kvm_state.size += VMCS12_SIZE; if (is_guest_mode(vcpu) && @@ -13952,20 +14797,24 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu, if (copy_to_user(user_kvm_nested_state, &kvm_state, sizeof(kvm_state))) return -EFAULT; - if (vmx->nested.current_vmptr == -1ull) + if (!vmx_has_valid_vmcs12(vcpu)) goto out; /* * When running L2, the authoritative vmcs12 state is in the * vmcs02. When running L1, the authoritative vmcs12 state is - * in the shadow vmcs linked to vmcs01, unless - * sync_shadow_vmcs is set, in which case, the authoritative + * in the shadow or enlightened vmcs linked to vmcs01, unless + * need_vmcs12_sync is set, in which case, the authoritative * vmcs12 state is in the vmcs12 already. */ - if (is_guest_mode(vcpu)) + if (is_guest_mode(vcpu)) { sync_vmcs12(vcpu, vmcs12); - else if (enable_shadow_vmcs && !vmx->nested.sync_shadow_vmcs) - copy_shadow_to_vmcs12(vmx); + } else if (!vmx->nested.need_vmcs12_sync) { + if (vmx->nested.hv_evmcs) + copy_enlightened_to_vmcs12(vmx); + else if (enable_shadow_vmcs) + copy_shadow_to_vmcs12(vmx); + } if (copy_to_user(user_kvm_nested_state->data, vmcs12, sizeof(*vmcs12))) return -EFAULT; @@ -13993,6 +14842,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, if (kvm_state->format != 0) return -EINVAL; + if (kvm_state->flags & KVM_STATE_NESTED_EVMCS) + nested_enable_evmcs(vcpu, NULL); + if (!nested_vmx_allowed(vcpu)) return kvm_state->vmx.vmxon_pa == -1ull ? 0 : -EINVAL; @@ -14010,13 +14862,6 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, if (!page_address_valid(vcpu, kvm_state->vmx.vmxon_pa)) return -EINVAL; - if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) - return -EINVAL; - - if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa || - !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa)) - return -EINVAL; - if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) && (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) return -EINVAL; @@ -14046,7 +14891,25 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, if (ret) return ret; - set_current_vmptr(vmx, kvm_state->vmx.vmcs_pa); + /* Empty 'VMXON' state is permitted */ + if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) + return 0; + + if (kvm_state->vmx.vmcs_pa != -1ull) { + if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa || + !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa)) + return -EINVAL; + + set_current_vmptr(vmx, kvm_state->vmx.vmcs_pa); + } else if (kvm_state->flags & KVM_STATE_NESTED_EVMCS) { + /* + * Sync eVMCS upon entry as we may not have + * HV_X64_MSR_VP_ASSIST_PAGE set up yet. + */ + vmx->nested.need_vmcs12_sync = true; + } else { + return -EINVAL; + } if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON) { vmx->nested.smm.vmxon = true; @@ -14090,7 +14953,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, return -EINVAL; vmx->nested.dirty_vmcs12 = true; - ret = enter_vmx_non_root_mode(vcpu, NULL); + ret = nested_vmx_enter_non_root_mode(vcpu, false); if (ret) return -EINVAL; @@ -14242,6 +15105,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = { .pre_enter_smm = vmx_pre_enter_smm, .pre_leave_smm = vmx_pre_leave_smm, .enable_smi_window = enable_smi_window, + + .nested_enable_evmcs = nested_enable_evmcs, }; static void vmx_cleanup_l1d_flush(void) diff --git a/arch/x86/kvm/vmx_shadow_fields.h b/arch/x86/kvm/vmx_shadow_fields.h index cd0c75f6d037..132432f375c2 100644 --- a/arch/x86/kvm/vmx_shadow_fields.h +++ b/arch/x86/kvm/vmx_shadow_fields.h @@ -28,7 +28,6 @@ */ /* 16-bits */ -SHADOW_FIELD_RW(GUEST_CS_SELECTOR) SHADOW_FIELD_RW(GUEST_INTR_STATUS) SHADOW_FIELD_RW(GUEST_PML_INDEX) SHADOW_FIELD_RW(HOST_FS_SELECTOR) @@ -47,8 +46,8 @@ SHADOW_FIELD_RW(VM_ENTRY_EXCEPTION_ERROR_CODE) SHADOW_FIELD_RW(VM_ENTRY_INTR_INFO_FIELD) SHADOW_FIELD_RW(VM_ENTRY_INSTRUCTION_LEN) SHADOW_FIELD_RW(TPR_THRESHOLD) -SHADOW_FIELD_RW(GUEST_CS_LIMIT) SHADOW_FIELD_RW(GUEST_CS_AR_BYTES) +SHADOW_FIELD_RW(GUEST_SS_AR_BYTES) SHADOW_FIELD_RW(GUEST_INTERRUPTIBILITY_INFO) SHADOW_FIELD_RW(VMX_PREEMPTION_TIMER_VALUE) @@ -61,8 +60,6 @@ SHADOW_FIELD_RW(GUEST_CR0) SHADOW_FIELD_RW(GUEST_CR3) SHADOW_FIELD_RW(GUEST_CR4) SHADOW_FIELD_RW(GUEST_RFLAGS) -SHADOW_FIELD_RW(GUEST_CS_BASE) -SHADOW_FIELD_RW(GUEST_ES_BASE) SHADOW_FIELD_RW(CR0_GUEST_HOST_MASK) SHADOW_FIELD_RW(CR0_READ_SHADOW) SHADOW_FIELD_RW(CR4_READ_SHADOW) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ca717737347e..66d66d77caee 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -136,7 +136,7 @@ static u32 __read_mostly tsc_tolerance_ppm = 250; module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR); /* lapic timer advance (tscdeadline mode only) in nanoseconds */ -unsigned int __read_mostly lapic_timer_advance_ns = 0; +unsigned int __read_mostly lapic_timer_advance_ns = 1000; module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR); EXPORT_SYMBOL_GPL(lapic_timer_advance_ns); @@ -400,9 +400,51 @@ static int exception_type(int vector) return EXCPT_FAULT; } +void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu) +{ + unsigned nr = vcpu->arch.exception.nr; + bool has_payload = vcpu->arch.exception.has_payload; + unsigned long payload = vcpu->arch.exception.payload; + + if (!has_payload) + return; + + switch (nr) { + case DB_VECTOR: + /* + * "Certain debug exceptions may clear bit 0-3. The + * remaining contents of the DR6 register are never + * cleared by the processor". + */ + vcpu->arch.dr6 &= ~DR_TRAP_BITS; + /* + * DR6.RTM is set by all #DB exceptions that don't clear it. + */ + vcpu->arch.dr6 |= DR6_RTM; + vcpu->arch.dr6 |= payload; + /* + * Bit 16 should be set in the payload whenever the #DB + * exception should clear DR6.RTM. This makes the payload + * compatible with the pending debug exceptions under VMX. + * Though not currently documented in the SDM, this also + * makes the payload compatible with the exit qualification + * for #DB exceptions under VMX. + */ + vcpu->arch.dr6 ^= payload & DR6_RTM; + break; + case PF_VECTOR: + vcpu->arch.cr2 = payload; + break; + } + + vcpu->arch.exception.has_payload = false; + vcpu->arch.exception.payload = 0; +} +EXPORT_SYMBOL_GPL(kvm_deliver_exception_payload); + static void kvm_multiple_exception(struct kvm_vcpu *vcpu, unsigned nr, bool has_error, u32 error_code, - bool reinject) + bool has_payload, unsigned long payload, bool reinject) { u32 prev_nr; int class1, class2; @@ -424,6 +466,14 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, */ WARN_ON_ONCE(vcpu->arch.exception.pending); vcpu->arch.exception.injected = true; + if (WARN_ON_ONCE(has_payload)) { + /* + * A reinjected event has already + * delivered its payload. + */ + has_payload = false; + payload = 0; + } } else { vcpu->arch.exception.pending = true; vcpu->arch.exception.injected = false; @@ -431,6 +481,22 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, vcpu->arch.exception.has_error_code = has_error; vcpu->arch.exception.nr = nr; vcpu->arch.exception.error_code = error_code; + vcpu->arch.exception.has_payload = has_payload; + vcpu->arch.exception.payload = payload; + /* + * In guest mode, payload delivery should be deferred, + * so that the L1 hypervisor can intercept #PF before + * CR2 is modified (or intercept #DB before DR6 is + * modified under nVMX). However, for ABI + * compatibility with KVM_GET_VCPU_EVENTS and + * KVM_SET_VCPU_EVENTS, we can't delay payload + * delivery unless userspace has enabled this + * functionality via the per-VM capability, + * KVM_CAP_EXCEPTION_PAYLOAD. + */ + if (!vcpu->kvm->arch.exception_payload_enabled || + !is_guest_mode(vcpu)) + kvm_deliver_exception_payload(vcpu); return; } @@ -455,6 +521,8 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, vcpu->arch.exception.has_error_code = true; vcpu->arch.exception.nr = DF_VECTOR; vcpu->arch.exception.error_code = 0; + vcpu->arch.exception.has_payload = false; + vcpu->arch.exception.payload = 0; } else /* replace previous exception with a new one in a hope that instruction re-execution will regenerate lost @@ -464,16 +532,29 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu, void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr) { - kvm_multiple_exception(vcpu, nr, false, 0, false); + kvm_multiple_exception(vcpu, nr, false, 0, false, 0, false); } EXPORT_SYMBOL_GPL(kvm_queue_exception); void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr) { - kvm_multiple_exception(vcpu, nr, false, 0, true); + kvm_multiple_exception(vcpu, nr, false, 0, false, 0, true); } EXPORT_SYMBOL_GPL(kvm_requeue_exception); +static void kvm_queue_exception_p(struct kvm_vcpu *vcpu, unsigned nr, + unsigned long payload) +{ + kvm_multiple_exception(vcpu, nr, false, 0, true, payload, false); +} + +static void kvm_queue_exception_e_p(struct kvm_vcpu *vcpu, unsigned nr, + u32 error_code, unsigned long payload) +{ + kvm_multiple_exception(vcpu, nr, true, error_code, + true, payload, false); +} + int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err) { if (err) @@ -490,11 +571,13 @@ void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault) ++vcpu->stat.pf_guest; vcpu->arch.exception.nested_apf = is_guest_mode(vcpu) && fault->async_page_fault; - if (vcpu->arch.exception.nested_apf) + if (vcpu->arch.exception.nested_apf) { vcpu->arch.apf.nested_apf_token = fault->address; - else - vcpu->arch.cr2 = fault->address; - kvm_queue_exception_e(vcpu, PF_VECTOR, fault->error_code); + kvm_queue_exception_e(vcpu, PF_VECTOR, fault->error_code); + } else { + kvm_queue_exception_e_p(vcpu, PF_VECTOR, fault->error_code, + fault->address); + } } EXPORT_SYMBOL_GPL(kvm_inject_page_fault); @@ -503,7 +586,7 @@ static bool kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fau if (mmu_is_nested(vcpu) && !fault->nested_page_fault) vcpu->arch.nested_mmu.inject_page_fault(vcpu, fault); else - vcpu->arch.mmu.inject_page_fault(vcpu, fault); + vcpu->arch.mmu->inject_page_fault(vcpu, fault); return fault->nested_page_fault; } @@ -517,13 +600,13 @@ EXPORT_SYMBOL_GPL(kvm_inject_nmi); void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) { - kvm_multiple_exception(vcpu, nr, true, error_code, false); + kvm_multiple_exception(vcpu, nr, true, error_code, false, 0, false); } EXPORT_SYMBOL_GPL(kvm_queue_exception_e); void kvm_requeue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) { - kvm_multiple_exception(vcpu, nr, true, error_code, true); + kvm_multiple_exception(vcpu, nr, true, error_code, false, 0, true); } EXPORT_SYMBOL_GPL(kvm_requeue_exception_e); @@ -602,7 +685,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3) for (i = 0; i < ARRAY_SIZE(pdpte); ++i) { if ((pdpte[i] & PT_PRESENT_MASK) && (pdpte[i] & - vcpu->arch.mmu.guest_rsvd_check.rsvd_bits_mask[0][2])) { + vcpu->arch.mmu->guest_rsvd_check.rsvd_bits_mask[0][2])) { ret = 0; goto out; } @@ -2477,7 +2560,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_KVM_PV_EOI_EN: - if (kvm_lapic_enable_pv_eoi(vcpu, data)) + if (kvm_lapic_enable_pv_eoi(vcpu, data, sizeof(u8))) return 1; break; @@ -2912,6 +2995,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_HYPERV_VP_INDEX: case KVM_CAP_HYPERV_EVENTFD: case KVM_CAP_HYPERV_TLBFLUSH: + case KVM_CAP_HYPERV_SEND_IPI: + case KVM_CAP_HYPERV_ENLIGHTENED_VMCS: case KVM_CAP_PCI_SEGMENT: case KVM_CAP_DEBUGREGS: case KVM_CAP_X86_ROBUST_SINGLESTEP: @@ -2930,6 +3015,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_IMMEDIATE_EXIT: case KVM_CAP_GET_MSR_FEATURES: case KVM_CAP_MSR_PLATFORM_INFO: + case KVM_CAP_EXCEPTION_PAYLOAD: r = 1; break; case KVM_CAP_SYNC_REGS: @@ -3362,19 +3448,33 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, struct kvm_vcpu_events *events) { process_nmi(vcpu); + /* - * FIXME: pass injected and pending separately. This is only - * needed for nested virtualization, whose state cannot be - * migrated yet. For now we can combine them. + * The API doesn't provide the instruction length for software + * exceptions, so don't report them. As long as the guest RIP + * isn't advanced, we should expect to encounter the exception + * again. */ - events->exception.injected = - (vcpu->arch.exception.pending || - vcpu->arch.exception.injected) && - !kvm_exception_is_soft(vcpu->arch.exception.nr); + if (kvm_exception_is_soft(vcpu->arch.exception.nr)) { + events->exception.injected = 0; + events->exception.pending = 0; + } else { + events->exception.injected = vcpu->arch.exception.injected; + events->exception.pending = vcpu->arch.exception.pending; + /* + * For ABI compatibility, deliberately conflate + * pending and injected exceptions when + * KVM_CAP_EXCEPTION_PAYLOAD isn't enabled. + */ + if (!vcpu->kvm->arch.exception_payload_enabled) + events->exception.injected |= + vcpu->arch.exception.pending; + } events->exception.nr = vcpu->arch.exception.nr; events->exception.has_error_code = vcpu->arch.exception.has_error_code; - events->exception.pad = 0; events->exception.error_code = vcpu->arch.exception.error_code; + events->exception_has_payload = vcpu->arch.exception.has_payload; + events->exception_payload = vcpu->arch.exception.payload; events->interrupt.injected = vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft; @@ -3398,6 +3498,9 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SHADOW | KVM_VCPUEVENT_VALID_SMM); + if (vcpu->kvm->arch.exception_payload_enabled) + events->flags |= KVM_VCPUEVENT_VALID_PAYLOAD; + memset(&events->reserved, 0, sizeof(events->reserved)); } @@ -3409,12 +3512,24 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, if (events->flags & ~(KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR | KVM_VCPUEVENT_VALID_SHADOW - | KVM_VCPUEVENT_VALID_SMM)) + | KVM_VCPUEVENT_VALID_SMM + | KVM_VCPUEVENT_VALID_PAYLOAD)) return -EINVAL; - if (events->exception.injected && - (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR || - is_guest_mode(vcpu))) + if (events->flags & KVM_VCPUEVENT_VALID_PAYLOAD) { + if (!vcpu->kvm->arch.exception_payload_enabled) + return -EINVAL; + if (events->exception.pending) + events->exception.injected = 0; + else + events->exception_has_payload = 0; + } else { + events->exception.pending = 0; + events->exception_has_payload = 0; + } + + if ((events->exception.injected || events->exception.pending) && + (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR)) return -EINVAL; /* INITs are latched while in SMM */ @@ -3424,11 +3539,13 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, return -EINVAL; process_nmi(vcpu); - vcpu->arch.exception.injected = false; - vcpu->arch.exception.pending = events->exception.injected; + vcpu->arch.exception.injected = events->exception.injected; + vcpu->arch.exception.pending = events->exception.pending; vcpu->arch.exception.nr = events->exception.nr; vcpu->arch.exception.has_error_code = events->exception.has_error_code; vcpu->arch.exception.error_code = events->exception.error_code; + vcpu->arch.exception.has_payload = events->exception_has_payload; + vcpu->arch.exception.payload = events->exception_payload; vcpu->arch.interrupt.injected = events->interrupt.injected; vcpu->arch.interrupt.nr = events->interrupt.nr; @@ -3694,6 +3811,10 @@ static int kvm_set_guest_paused(struct kvm_vcpu *vcpu) static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, struct kvm_enable_cap *cap) { + int r; + uint16_t vmcs_version; + void __user *user_ptr; + if (cap->flags) return -EINVAL; @@ -3706,6 +3827,16 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, return -EINVAL; return kvm_hv_activate_synic(vcpu, cap->cap == KVM_CAP_HYPERV_SYNIC2); + case KVM_CAP_HYPERV_ENLIGHTENED_VMCS: + r = kvm_x86_ops->nested_enable_evmcs(vcpu, &vmcs_version); + if (!r) { + user_ptr = (void __user *)(uintptr_t)cap->args[0]; + if (copy_to_user(user_ptr, &vmcs_version, + sizeof(vmcs_version))) + r = -EFAULT; + } + return r; + default: return -EINVAL; } @@ -4047,11 +4178,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp, break; if (kvm_state.flags & - ~(KVM_STATE_NESTED_RUN_PENDING | KVM_STATE_NESTED_GUEST_MODE)) + ~(KVM_STATE_NESTED_RUN_PENDING | KVM_STATE_NESTED_GUEST_MODE + | KVM_STATE_NESTED_EVMCS)) break; /* nested_run_pending implies guest_mode. */ - if (kvm_state.flags == KVM_STATE_NESTED_RUN_PENDING) + if ((kvm_state.flags & KVM_STATE_NESTED_RUN_PENDING) + && !(kvm_state.flags & KVM_STATE_NESTED_GUEST_MODE)) break; r = kvm_x86_ops->set_nested_state(vcpu, user_kvm_nested_state, &kvm_state); @@ -4363,6 +4496,10 @@ split_irqchip_unlock: kvm->arch.guest_can_read_msr_platform_info = cap->args[0]; r = 0; break; + case KVM_CAP_EXCEPTION_PAYLOAD: + kvm->arch.exception_payload_enabled = cap->args[0]; + r = 0; + break; default: r = -EINVAL; break; @@ -4803,7 +4940,7 @@ gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access, /* NPT walks are always user-walks */ access |= PFERR_USER_MASK; - t_gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gpa, access, exception); + t_gpa = vcpu->arch.mmu->gva_to_gpa(vcpu, gpa, access, exception); return t_gpa; } @@ -5889,7 +6026,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2, if (WARN_ON_ONCE(is_guest_mode(vcpu))) return false; - if (!vcpu->arch.mmu.direct_map) { + if (!vcpu->arch.mmu->direct_map) { /* * Write permission should be allowed since only * write access need to be emulated. @@ -5922,7 +6059,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2, kvm_release_pfn_clean(pfn); /* The instructions are well-emulated on direct mmu. */ - if (vcpu->arch.mmu.direct_map) { + if (vcpu->arch.mmu->direct_map) { unsigned int indirect_shadow_pages; spin_lock(&vcpu->kvm->mmu_lock); @@ -5989,7 +6126,7 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt, vcpu->arch.last_retry_eip = ctxt->eip; vcpu->arch.last_retry_addr = cr2; - if (!vcpu->arch.mmu.direct_map) + if (!vcpu->arch.mmu->direct_map) gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2, NULL); kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa)); @@ -6049,14 +6186,7 @@ static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r) kvm_run->exit_reason = KVM_EXIT_DEBUG; *r = EMULATE_USER_EXIT; } else { - /* - * "Certain debug exceptions may clear bit 0-3. The - * remaining contents of the DR6 register are never - * cleared by the processor". - */ - vcpu->arch.dr6 &= ~15; - vcpu->arch.dr6 |= DR6_BS | DR6_RTM; - kvm_queue_exception(vcpu, DB_VECTOR); + kvm_queue_exception_p(vcpu, DB_VECTOR, DR6_BS); } } @@ -6995,10 +7125,22 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win) __kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) | X86_EFLAGS_RF); - if (vcpu->arch.exception.nr == DB_VECTOR && - (vcpu->arch.dr7 & DR7_GD)) { - vcpu->arch.dr7 &= ~DR7_GD; - kvm_update_dr7(vcpu); + if (vcpu->arch.exception.nr == DB_VECTOR) { + /* + * This code assumes that nSVM doesn't use + * check_nested_events(). If it does, the + * DR6/DR7 changes should happen before L1 + * gets a #VMEXIT for an intercepted #DB in + * L2. (Under VMX, on the other hand, the + * DR6/DR7 changes should not happen in the + * event of a VM-exit to L1 for an intercepted + * #DB in L2.) + */ + kvm_deliver_exception_payload(vcpu); + if (vcpu->arch.dr7 & DR7_GD) { + vcpu->arch.dr7 &= ~DR7_GD; + kvm_update_dr7(vcpu); + } } kvm_x86_ops->queue_exception(vcpu); @@ -8478,7 +8620,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) kvm_vcpu_mtrr_init(vcpu); vcpu_load(vcpu); kvm_vcpu_reset(vcpu, false); - kvm_mmu_setup(vcpu); + kvm_init_mmu(vcpu, false); vcpu_put(vcpu); return 0; } @@ -9327,7 +9469,7 @@ void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work) { int r; - if ((vcpu->arch.mmu.direct_map != work->arch.direct_map) || + if ((vcpu->arch.mmu->direct_map != work->arch.direct_map) || work->wakeup_all) return; @@ -9335,11 +9477,11 @@ void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work) if (unlikely(r)) return; - if (!vcpu->arch.mmu.direct_map && - work->arch.cr3 != vcpu->arch.mmu.get_cr3(vcpu)) + if (!vcpu->arch.mmu->direct_map && + work->arch.cr3 != vcpu->arch.mmu->get_cr3(vcpu)) return; - vcpu->arch.mmu.page_fault(vcpu, work->gva, 0, true); + vcpu->arch.mmu->page_fault(vcpu, work->gva, 0, true); } static inline u32 kvm_async_pf_hash_fn(gfn_t gfn) @@ -9463,6 +9605,8 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, vcpu->arch.exception.nr = 0; vcpu->arch.exception.has_error_code = false; vcpu->arch.exception.error_code = 0; + vcpu->arch.exception.has_payload = false; + vcpu->arch.exception.payload = 0; } else if (!apf_put_user(vcpu, KVM_PV_REASON_PAGE_READY)) { fault.vector = PF_VECTOR; fault.error_code_valid = true; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 67b9568613f3..224cd0a47568 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -266,6 +266,8 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, int handle_ud(struct kvm_vcpu *vcpu); +void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu); + void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu); u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn); bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data); diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2b1519bc5381..b24eb4eb9984 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -157,79 +157,6 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr) return prefetch; } -/* - * A protection key fault means that the PKRU value did not allow - * access to some PTE. Userspace can figure out what PKRU was - * from the XSAVE state, and this function fills out a field in - * siginfo so userspace can discover which protection key was set - * on the PTE. - * - * If we get here, we know that the hardware signaled a X86_PF_PK - * fault and that there was a VMA once we got in the fault - * handler. It does *not* guarantee that the VMA we find here - * was the one that we faulted on. - * - * 1. T1 : mprotect_key(foo, PAGE_SIZE, pkey=4); - * 2. T1 : set PKRU 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_sem, etc... - * 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really - * faulted on a pte with its pkey=4. - */ -static void fill_sig_info_pkey(int si_signo, int si_code, siginfo_t *info, - u32 *pkey) -{ - /* This is effectively an #ifdef */ - if (!boot_cpu_has(X86_FEATURE_OSPKE)) - return; - - /* Fault not from Protection Keys: nothing to do */ - if ((si_code != SEGV_PKUERR) || (si_signo != SIGSEGV)) - return; - /* - * force_sig_info_fault() is called from a number of - * contexts, some of which have a VMA and some of which - * do not. The X86_PF_PK handing happens after we have a - * valid VMA, so we should never reach this without a - * valid VMA. - */ - if (!pkey) { - WARN_ONCE(1, "PKU fault with no VMA passed in"); - info->si_pkey = 0; - return; - } - /* - * si_pkey should be thought of as a strong hint, but not - * absolutely guranteed to be 100% accurate because of - * the race explained above. - */ - info->si_pkey = *pkey; -} - -static void -force_sig_info_fault(int si_signo, int si_code, unsigned long address, - struct task_struct *tsk, u32 *pkey, int fault) -{ - unsigned lsb = 0; - siginfo_t info; - - clear_siginfo(&info); - info.si_signo = si_signo; - info.si_errno = 0; - info.si_code = si_code; - info.si_addr = (void __user *)address; - if (fault & VM_FAULT_HWPOISON_LARGE) - lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); - if (fault & VM_FAULT_HWPOISON) - lsb = PAGE_SHIFT; - info.si_addr_lsb = lsb; - - fill_sig_info_pkey(si_signo, si_code, &info, pkey); - - force_sig_info(si_signo, &info, tsk); -} - DEFINE_SPINLOCK(pgd_lock); LIST_HEAD(pgd_list); @@ -734,8 +661,8 @@ no_context(struct pt_regs *regs, unsigned long error_code, tsk->thread.cr2 = address; /* XXX: hwpoison faults will set the wrong code. */ - force_sig_info_fault(signal, si_code, address, - tsk, NULL, 0); + force_sig_fault(signal, si_code, (void __user *)address, + tsk); } /* @@ -862,7 +789,7 @@ static bool is_vsyscall_vaddr(unsigned long vaddr) static void __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, - unsigned long address, u32 *pkey, int si_code) + unsigned long address, u32 pkey, int si_code) { struct task_struct *tsk = current; @@ -898,7 +825,10 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_PF; - force_sig_info_fault(SIGSEGV, si_code, address, tsk, pkey, 0); + if (si_code == SEGV_PKUERR) + force_sig_pkuerr((void __user *)address, pkey); + + force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk); return; } @@ -911,35 +841,29 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, static noinline void bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, - unsigned long address, u32 *pkey) + unsigned long address) { - __bad_area_nosemaphore(regs, error_code, address, pkey, SEGV_MAPERR); + __bad_area_nosemaphore(regs, error_code, address, 0, SEGV_MAPERR); } static void __bad_area(struct pt_regs *regs, unsigned long error_code, - unsigned long address, struct vm_area_struct *vma, int si_code) + unsigned long address, u32 pkey, int si_code) { struct mm_struct *mm = current->mm; - u32 pkey; - - if (vma) - pkey = vma_pkey(vma); - /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ up_read(&mm->mmap_sem); - __bad_area_nosemaphore(regs, error_code, address, - (vma) ? &pkey : NULL, si_code); + __bad_area_nosemaphore(regs, error_code, address, pkey, si_code); } static noinline void bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address) { - __bad_area(regs, error_code, address, NULL, SEGV_MAPERR); + __bad_area(regs, error_code, address, 0, SEGV_MAPERR); } static inline bool bad_area_access_from_pkeys(unsigned long error_code, @@ -968,18 +892,40 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code, * But, doing it this way allows compiler optimizations * if pkeys are compiled out. */ - if (bad_area_access_from_pkeys(error_code, vma)) - __bad_area(regs, error_code, address, vma, SEGV_PKUERR); - else - __bad_area(regs, error_code, address, vma, SEGV_ACCERR); + if (bad_area_access_from_pkeys(error_code, vma)) { + /* + * A protection key fault means that the PKRU value did not allow + * access to some PTE. Userspace can figure out what PKRU was + * from the XSAVE state. This function captures the pkey from + * the vma and passes it to userspace so userspace can discover + * which protection key was set on the PTE. + * + * If we get here, we know that the hardware signaled a X86_PF_PK + * fault and that there was a VMA once we got in the fault + * handler. It does *not* guarantee that the VMA we find here + * was the one that we faulted on. + * + * 1. T1 : mprotect_key(foo, PAGE_SIZE, pkey=4); + * 2. T1 : set PKRU 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_sem, etc... + * 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really + * faulted on a pte with its pkey=4. + */ + u32 pkey = vma_pkey(vma); + + __bad_area(regs, error_code, address, pkey, SEGV_PKUERR); + } else { + __bad_area(regs, error_code, address, 0, SEGV_ACCERR); + } } static void do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, - u32 *pkey, unsigned int fault) + unsigned int fault) { struct task_struct *tsk = current; - int code = BUS_ADRERR; /* Kernel mode? Handle exceptions or die: */ if (!(error_code & X86_PF_USER)) { @@ -997,18 +943,25 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, #ifdef CONFIG_MEMORY_FAILURE if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { - printk(KERN_ERR + unsigned lsb = 0; + + pr_err( "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", tsk->comm, tsk->pid, address); - code = BUS_MCEERR_AR; + if (fault & VM_FAULT_HWPOISON_LARGE) + lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); + if (fault & VM_FAULT_HWPOISON) + lsb = PAGE_SHIFT; + force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, tsk); + return; } #endif - force_sig_info_fault(SIGBUS, code, address, tsk, pkey, fault); + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk); } static noinline void mm_fault_error(struct pt_regs *regs, unsigned long error_code, - unsigned long address, u32 *pkey, vm_fault_t fault) + unsigned long address, vm_fault_t fault) { if (fatal_signal_pending(current) && !(error_code & X86_PF_USER)) { no_context(regs, error_code, address, 0, 0); @@ -1032,9 +985,9 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, } else { if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| VM_FAULT_HWPOISON_LARGE)) - do_sigbus(regs, error_code, address, pkey, fault); + do_sigbus(regs, error_code, address, fault); else if (fault & VM_FAULT_SIGSEGV) - bad_area_nosemaphore(regs, error_code, address, pkey); + bad_area_nosemaphore(regs, error_code, address); else BUG(); } @@ -1267,7 +1220,7 @@ do_kern_addr_fault(struct pt_regs *regs, unsigned long hw_error_code, * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock: */ - bad_area_nosemaphore(regs, hw_error_code, address, NULL); + bad_area_nosemaphore(regs, hw_error_code, address); } NOKPROBE_SYMBOL(do_kern_addr_fault); @@ -1283,7 +1236,6 @@ void do_user_addr_fault(struct pt_regs *regs, struct mm_struct *mm; vm_fault_t fault, major = 0; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; - u32 pkey; tsk = current; mm = tsk->mm; @@ -1304,7 +1256,7 @@ void do_user_addr_fault(struct pt_regs *regs, * pages in the user address space. */ if (unlikely(smap_violation(hw_error_code, regs))) { - bad_area_nosemaphore(regs, hw_error_code, address, NULL); + bad_area_nosemaphore(regs, hw_error_code, address); return; } @@ -1313,7 +1265,7 @@ void do_user_addr_fault(struct pt_regs *regs, * in a region with pagefaults disabled then we must not take the fault */ if (unlikely(faulthandler_disabled() || !mm)) { - bad_area_nosemaphore(regs, hw_error_code, address, NULL); + bad_area_nosemaphore(regs, hw_error_code, address); return; } @@ -1403,7 +1355,7 @@ void do_user_addr_fault(struct pt_regs *regs, * Fault from code in kernel from * which we do not expect faults. */ - bad_area_nosemaphore(regs, sw_error_code, address, NULL); + bad_area_nosemaphore(regs, sw_error_code, address); return; } retry: @@ -1467,10 +1419,7 @@ good_area: * (potentially after handling any pending signal during the return to * userland). The return to userland is identified whenever * FAULT_FLAG_USER|FAULT_FLAG_KILLABLE are both set in flags. - * Thus we have to be careful about not touching vma after handling the - * fault, so we read the pkey beforehand. */ - pkey = vma_pkey(vma); fault = handle_mm_fault(vma, address, flags); major |= fault & VM_FAULT_MAJOR; @@ -1499,7 +1448,7 @@ good_area: up_read(&mm->mmap_sem); if (unlikely(fault & VM_FAULT_ERROR)) { - mm_fault_error(regs, sw_error_code, address, &pkey, fault); + mm_fault_error(regs, sw_error_code, address, fault); return; } diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index e500949bae24..2385538e8065 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -118,14 +118,11 @@ bad_opcode: * anything it wants in to the instructions. We can not * trust anything about it. They might not be valid * instructions or might encode invalid registers, etc... - * - * The caller is expected to kfree() the returned siginfo_t. */ -siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) +int mpx_fault_info(struct mpx_fault_info *info, struct pt_regs *regs) { const struct mpx_bndreg_state *bndregs; const struct mpx_bndreg *bndreg; - siginfo_t *info = NULL; struct insn insn; uint8_t bndregno; int err; @@ -153,11 +150,6 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) /* now go select the individual register in the set of 4 */ bndreg = &bndregs->bndreg[bndregno]; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) { - err = -ENOMEM; - goto err_out; - } /* * The registers are always 64-bit, but the upper 32 * bits are ignored in 32-bit mode. Also, note that the @@ -168,27 +160,23 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) * complains when casting from integers to different-size * pointers. */ - info->si_lower = (void __user *)(unsigned long)bndreg->lower_bound; - info->si_upper = (void __user *)(unsigned long)~bndreg->upper_bound; - info->si_addr_lsb = 0; - info->si_signo = SIGSEGV; - info->si_errno = 0; - info->si_code = SEGV_BNDERR; - info->si_addr = insn_get_addr_ref(&insn, regs); + info->lower = (void __user *)(unsigned long)bndreg->lower_bound; + info->upper = (void __user *)(unsigned long)~bndreg->upper_bound; + info->addr = insn_get_addr_ref(&insn, regs); + /* * We were not able to extract an address from the instruction, * probably because there was something invalid in it. */ - if (info->si_addr == (void __user *)-1) { + if (info->addr == (void __user *)-1) { err = -EINVAL; goto err_out; } - trace_mpx_bounds_register_exception(info->si_addr, bndreg); - return info; + trace_mpx_bounds_register_exception(info->addr, bndreg); + return 0; err_out: /* info might be NULL, but kfree() handles that */ - kfree(info); - return ERR_PTR(err); + return err; } static __user void *mpx_get_bounds_dir(void) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 5559dcaddd5e..948656069cdd 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -356,7 +356,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) } else { struct pci_root_info *info; - info = kzalloc_node(sizeof(*info), GFP_KERNEL, node); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) dev_err(&root->device->dev, "pci_bus %04x:%02x: ignored (out of memory)\n", diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 13f4485ca388..30a5111ae5fd 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -629,17 +629,11 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff); static void quirk_no_aersid(struct pci_dev *pdev) { /* VMD Domain */ - if (is_vmd(pdev->bus)) + if (is_vmd(pdev->bus) && pci_is_root_bus(pdev->bus)) pdev->bus->bus_flags |= PCI_BUS_FLAGS_NO_AERSID; } -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334a, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334b, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334c, quirk_no_aersid); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334d, quirk_no_aersid); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, + PCI_CLASS_BRIDGE_PCI, 8, quirk_no_aersid); #ifdef CONFIG_PHYS_ADDR_T_64BIT diff --git a/arch/x86/platform/intel/iosf_mbi.c b/arch/x86/platform/intel/iosf_mbi.c index 6f37a2137a79..2e569d10f2d0 100644 --- a/arch/x86/platform/intel/iosf_mbi.c +++ b/arch/x86/platform/intel/iosf_mbi.c @@ -18,24 +18,26 @@ * enumerate the device using PCI. */ +#include <linux/delay.h> #include <linux/module.h> #include <linux/init.h> #include <linux/spinlock.h> #include <linux/pci.h> #include <linux/debugfs.h> #include <linux/capability.h> +#include <linux/pm_qos.h> #include <asm/iosf_mbi.h> -#define PCI_DEVICE_ID_BAYTRAIL 0x0F00 -#define PCI_DEVICE_ID_BRASWELL 0x2280 -#define PCI_DEVICE_ID_QUARK_X1000 0x0958 -#define PCI_DEVICE_ID_TANGIER 0x1170 +#define PCI_DEVICE_ID_INTEL_BAYTRAIL 0x0F00 +#define PCI_DEVICE_ID_INTEL_BRASWELL 0x2280 +#define PCI_DEVICE_ID_INTEL_QUARK_X1000 0x0958 +#define PCI_DEVICE_ID_INTEL_TANGIER 0x1170 static struct pci_dev *mbi_pdev; static DEFINE_SPINLOCK(iosf_mbi_lock); -static DEFINE_MUTEX(iosf_mbi_punit_mutex); -static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier); + +/**************** Generic iosf_mbi access helpers ****************/ static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) { @@ -192,6 +194,30 @@ bool iosf_mbi_available(void) } EXPORT_SYMBOL(iosf_mbi_available); +/* + **************** P-Unit/kernel shared I2C bus arbritration **************** + * + * Some Bay Trail and Cherry Trail devices have the P-Unit and us (the kernel) + * share a single I2C bus to the PMIC. Below are helpers to arbitrate the + * accesses between the kernel and the P-Unit. + * + * See arch/x86/include/asm/iosf_mbi.h for kernel-doc text for each function. + */ + +#define SEMAPHORE_TIMEOUT 500 +#define PUNIT_SEMAPHORE_BYT 0x7 +#define PUNIT_SEMAPHORE_CHT 0x10e +#define PUNIT_SEMAPHORE_BIT BIT(0) +#define PUNIT_SEMAPHORE_ACQUIRE BIT(1) + +static DEFINE_MUTEX(iosf_mbi_punit_mutex); +static DEFINE_MUTEX(iosf_mbi_block_punit_i2c_access_count_mutex); +static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier); +static u32 iosf_mbi_block_punit_i2c_access_count; +static u32 iosf_mbi_sem_address; +static unsigned long iosf_mbi_sem_acquired; +static struct pm_qos_request iosf_mbi_pm_qos; + void iosf_mbi_punit_acquire(void) { mutex_lock(&iosf_mbi_punit_mutex); @@ -204,6 +230,159 @@ void iosf_mbi_punit_release(void) } EXPORT_SYMBOL(iosf_mbi_punit_release); +static int iosf_mbi_get_sem(u32 *sem) +{ + int ret; + + ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, + iosf_mbi_sem_address, sem); + if (ret) { + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore read failed\n"); + return ret; + } + + *sem &= PUNIT_SEMAPHORE_BIT; + return 0; +} + +static void iosf_mbi_reset_semaphore(void) +{ + if (iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, + iosf_mbi_sem_address, 0, PUNIT_SEMAPHORE_BIT)) + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore reset failed\n"); + + pm_qos_update_request(&iosf_mbi_pm_qos, PM_QOS_DEFAULT_VALUE); + + blocking_notifier_call_chain(&iosf_mbi_pmic_bus_access_notifier, + MBI_PMIC_BUS_ACCESS_END, NULL); +} + +/* + * This function blocks P-Unit accesses to the PMIC I2C bus, so that kernel + * I2C code, such as e.g. a fuel-gauge driver, can access it safely. + * + * This function may be called by I2C controller code while an I2C driver has + * already blocked P-Unit accesses because it wants them blocked over multiple + * i2c-transfers, for e.g. read-modify-write of an I2C client register. + * + * The P-Unit accesses already being blocked is tracked through the + * iosf_mbi_block_punit_i2c_access_count variable which is protected by the + * iosf_mbi_block_punit_i2c_access_count_mutex this mutex is hold for the + * entire duration of the function. + * + * If access is not blocked yet, this function takes the following steps: + * + * 1) Some code sends request to the P-Unit which make it access the PMIC + * I2C bus. Testing has shown that the P-Unit does not check its internal + * PMIC bus semaphore for these requests. Callers of these requests call + * iosf_mbi_punit_acquire()/_release() around their P-Unit accesses, these + * functions lock/unlock the iosf_mbi_punit_mutex. + * As the first step we lock the iosf_mbi_punit_mutex, to wait for any in + * flight requests to finish and to block any new requests. + * + * 2) Some code makes such P-Unit requests from atomic contexts where it + * cannot call iosf_mbi_punit_acquire() as that may sleep. + * As the second step we call a notifier chain which allows any code + * needing P-Unit resources from atomic context to acquire them before + * we take control over the PMIC I2C bus. + * + * 3) When CPU cores enter C6 or C7 the P-Unit needs to talk to the PMIC + * if this happens while the kernel itself is accessing the PMIC I2C bus + * the SoC hangs. + * As the third step we call pm_qos_update_request() to disallow the CPU + * to enter C6 or C7. + * + * 4) The P-Unit has a PMIC bus semaphore which we can request to stop + * autonomous P-Unit tasks from accessing the PMIC I2C bus while we hold it. + * As the fourth and final step we request this semaphore and wait for our + * request to be acknowledged. + */ +int iosf_mbi_block_punit_i2c_access(void) +{ + unsigned long start, end; + int ret = 0; + u32 sem; + + if (WARN_ON(!mbi_pdev || !iosf_mbi_sem_address)) + return -ENXIO; + + mutex_lock(&iosf_mbi_block_punit_i2c_access_count_mutex); + + if (iosf_mbi_block_punit_i2c_access_count > 0) + goto success; + + mutex_lock(&iosf_mbi_punit_mutex); + blocking_notifier_call_chain(&iosf_mbi_pmic_bus_access_notifier, + MBI_PMIC_BUS_ACCESS_BEGIN, NULL); + + /* + * Disallow the CPU to enter C6 or C7 state, entering these states + * requires the P-Unit to talk to the PMIC and if this happens while + * we're holding the semaphore, the SoC hangs. + */ + pm_qos_update_request(&iosf_mbi_pm_qos, 0); + + /* host driver writes to side band semaphore register */ + ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, + iosf_mbi_sem_address, PUNIT_SEMAPHORE_ACQUIRE); + if (ret) { + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore request failed\n"); + goto error; + } + + /* host driver waits for bit 0 to be set in semaphore register */ + start = jiffies; + end = start + msecs_to_jiffies(SEMAPHORE_TIMEOUT); + do { + ret = iosf_mbi_get_sem(&sem); + if (!ret && sem) { + iosf_mbi_sem_acquired = jiffies; + dev_dbg(&mbi_pdev->dev, "P-Unit semaphore acquired after %ums\n", + jiffies_to_msecs(jiffies - start)); + /* + * Success, keep iosf_mbi_punit_mutex locked till + * iosf_mbi_unblock_punit_i2c_access() gets called. + */ + goto success; + } + + usleep_range(1000, 2000); + } while (time_before(jiffies, end)); + + ret = -ETIMEDOUT; + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore timed out, resetting\n"); +error: + iosf_mbi_reset_semaphore(); + mutex_unlock(&iosf_mbi_punit_mutex); + + if (!iosf_mbi_get_sem(&sem)) + dev_err(&mbi_pdev->dev, "P-Unit semaphore: %d\n", sem); +success: + if (!WARN_ON(ret)) + iosf_mbi_block_punit_i2c_access_count++; + + mutex_unlock(&iosf_mbi_block_punit_i2c_access_count_mutex); + + return ret; +} +EXPORT_SYMBOL(iosf_mbi_block_punit_i2c_access); + +void iosf_mbi_unblock_punit_i2c_access(void) +{ + mutex_lock(&iosf_mbi_block_punit_i2c_access_count_mutex); + + iosf_mbi_block_punit_i2c_access_count--; + if (iosf_mbi_block_punit_i2c_access_count == 0) { + iosf_mbi_reset_semaphore(); + mutex_unlock(&iosf_mbi_punit_mutex); + dev_dbg(&mbi_pdev->dev, "punit semaphore held for %ums\n", + jiffies_to_msecs(jiffies - iosf_mbi_sem_acquired)); + } + + mutex_unlock(&iosf_mbi_block_punit_i2c_access_count_mutex); +} +EXPORT_SYMBOL(iosf_mbi_unblock_punit_i2c_access); + int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb) { int ret; @@ -241,19 +420,14 @@ int iosf_mbi_unregister_pmic_bus_access_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier); -int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) -{ - return blocking_notifier_call_chain( - &iosf_mbi_pmic_bus_access_notifier, val, v); -} -EXPORT_SYMBOL(iosf_mbi_call_pmic_bus_access_notifier_chain); - void iosf_mbi_assert_punit_acquired(void) { WARN_ON(!mutex_is_locked(&iosf_mbi_punit_mutex)); } EXPORT_SYMBOL(iosf_mbi_assert_punit_acquired); +/**************** iosf_mbi debug code ****************/ + #ifdef CONFIG_IOSF_MBI_DEBUG static u32 dbg_mdr; static u32 dbg_mcr; @@ -338,7 +512,7 @@ static inline void iosf_debugfs_remove(void) { } #endif /* CONFIG_IOSF_MBI_DEBUG */ static int iosf_mbi_probe(struct pci_dev *pdev, - const struct pci_device_id *unused) + const struct pci_device_id *dev_id) { int ret; @@ -349,14 +523,16 @@ static int iosf_mbi_probe(struct pci_dev *pdev, } mbi_pdev = pci_dev_get(pdev); + iosf_mbi_sem_address = dev_id->driver_data; + return 0; } static const struct pci_device_id iosf_mbi_pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BRASWELL) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_TANGIER) }, + { PCI_DEVICE_DATA(INTEL, BAYTRAIL, PUNIT_SEMAPHORE_BYT) }, + { PCI_DEVICE_DATA(INTEL, BRASWELL, PUNIT_SEMAPHORE_CHT) }, + { PCI_DEVICE_DATA(INTEL, QUARK_X1000, 0) }, + { PCI_DEVICE_DATA(INTEL, TANGIER, 0) }, { 0, }, }; MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); @@ -371,6 +547,9 @@ static int __init iosf_mbi_init(void) { iosf_debugfs_init(); + pm_qos_add_request(&iosf_mbi_pm_qos, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + return pci_register_driver(&iosf_mbi_pci_driver); } @@ -381,6 +560,8 @@ static void __exit iosf_mbi_exit(void) pci_unregister_driver(&iosf_mbi_pci_driver); pci_dev_put(mbi_pdev); mbi_pdev = NULL; + + pm_qos_remove_request(&iosf_mbi_pm_qos); } module_init(iosf_mbi_init); diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index d67e30faff9c..be060dfb1cc3 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -80,28 +80,18 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) head-y := arch/xtensa/kernel/head.o core-y += arch/xtensa/kernel/ arch/xtensa/mm/ core-y += $(buildvar) $(buildplf) +core-y += arch/xtensa/boot/dts/ libs-y += arch/xtensa/lib/ $(LIBGCC) drivers-$(CONFIG_OPROFILE) += arch/xtensa/oprofile/ -ifneq ($(CONFIG_BUILTIN_DTB),"") -core-$(CONFIG_OF) += arch/xtensa/boot/dts/ -endif - boot := arch/xtensa/boot all Image zImage uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -%.dtb: - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - -dtbs: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts - define archhelp @echo '* Image - Kernel ELF image with reset vector' @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)' @echo '* uImage - U-Boot wrapped image' - @echo ' dtbs - Build device tree blobs for enabled boards' endef diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 82c756431b49..3310adecafb0 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -26,5 +26,6 @@ generic-y += rwsem.h generic-y += sections.h generic-y += topology.h generic-y += trace_clock.h +generic-y += vga.h generic-y += word-at-a-time.h generic-y += xor.h diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index ed66db3bc9bb..574e5520968c 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -5,9 +5,9 @@ #define __ARCH_WANT_SYS_CLONE #include <uapi/asm/unistd.h> +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_GETPGRP /* diff --git a/arch/xtensa/include/asm/vga.h b/arch/xtensa/include/asm/vga.h deleted file mode 100644 index 1fd8cab3a297..000000000000 --- a/arch/xtensa/include/asm/vga.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * include/asm-xtensa/vga.h - * - * 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) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_VGA_H -#define _XTENSA_VGA_H - -#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) - -#define vga_readb(x) (*(x)) -#define vga_writeb(x,y) (*(y) = (x)) - -#endif diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index ec43609cbfc5..6d4a87296c95 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -107,6 +107,8 @@ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ #define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */ +#define TIOCGISO7816 _IOR('T', 0x42, struct serial_iso7816) +#define TIOCSISO7816 _IOWR('T', 0x43, struct serial_iso7816) #define TIOCSERCONFIG _IO('T', 83) #define TIOCSERGWILD _IOR('T', 84, int) diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index a1c3edb8ad56..b727b18a68ac 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -197,7 +197,6 @@ SECTIONS INIT_SETUP(XCHAL_ICACHE_LINESIZE) INIT_CALLS CON_INITCALL - SECURITY_INITCALL INIT_RAM_FS } diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 42285f35d313..820e8738af11 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -94,7 +94,7 @@ static void __init xtfpga_clk_setup(struct device_node *np) u32 freq; if (!base) { - pr_err("%s: invalid address\n", np->name); + pr_err("%pOFn: invalid address\n", np); return; } @@ -103,12 +103,12 @@ static void __init xtfpga_clk_setup(struct device_node *np) clk = clk_register_fixed_rate(NULL, np->name, NULL, 0, freq); if (IS_ERR(clk)) { - pr_err("%s: clk registration failed\n", np->name); + pr_err("%pOFn: clk registration failed\n", np); return; } if (of_clk_add_provider(np, of_clk_src_simple_get, clk)) { - pr_err("%s: clk provider registration failed\n", np->name); + pr_err("%pOFn: clk provider registration failed\n", np); return; } } |